00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
#include <sys/types.h>
00015
#include <asterisk/frame.h>
00016
#include <asterisk/file.h>
00017
#include <asterisk/logger.h>
00018
#include <asterisk/channel.h>
00019
#include <asterisk/sched.h>
00020
#include <asterisk/options.h>
00021
#include <asterisk/translate.h>
00022
#include <asterisk/utils.h>
00023
#include <errno.h>
00024
#include <unistd.h>
00025
#include <stdlib.h>
00026
#include <string.h>
00027
#include <pthread.h>
00028
#include <stdio.h>
00029
#include <fcntl.h>
00030
#include <dirent.h>
00031
#include <sys/stat.h>
00032
#include "asterisk.h"
00033
#include "astconf.h"
00034
00035 struct ast_format {
00036
00037 char name[80];
00038
00039
00040 char exts[80];
00041
00042 int format;
00043
00044
struct ast_filestream * (*open)(
int fd);
00045
00046
struct ast_filestream * (*rewrite)(
int fd,
char *comment);
00047
00048 int (*write)(
struct ast_filestream *,
struct ast_frame *);
00049
00050 int (*seek)(
struct ast_filestream *,
long offset,
int whence);
00051
00052 int (*trunc)(
struct ast_filestream *fs);
00053
00054 long (*tell)(
struct ast_filestream *fs);
00055
00056
00057
struct ast_frame * (*read)(
struct ast_filestream *,
int *whennext);
00058
00059 void (*close)(
struct ast_filestream *);
00060
00061
char * (*getcomment)(
struct ast_filestream *);
00062
00063 struct ast_format *
next;
00064 };
00065
00066 struct ast_filestream {
00067
00068 struct ast_format *
fmt;
00069 int flags;
00070 mode_t
mode;
00071 char *
filename;
00072
00073 struct ast_filestream *
vfs;
00074
00075 struct ast_trans_pvt *
trans;
00076 struct ast_tranlator_pvt *
tr;
00077 int lastwriteformat;
00078 int lasttimeout;
00079 struct ast_channel *
owner;
00080 };
00081
00082
AST_MUTEX_DEFINE_STATIC(formatlock);
00083
00084
static struct ast_format *formats = NULL;
00085
00086 int ast_format_register(
char *name,
char *exts,
int format,
00087
struct ast_filestream * (*open)(
int fd),
00088
struct ast_filestream * (*rewrite)(
int fd,
char *comment),
00089
int (*write)(
struct ast_filestream *,
struct ast_frame *),
00090
int (*seek)(
struct ast_filestream *,
long sample_offset,
int whence),
00091
int (*trunc)(
struct ast_filestream *),
00092
long (*tell)(
struct ast_filestream *),
00093
struct ast_frame * (*read)(
struct ast_filestream *,
int *whennext),
00094
void (*close)(
struct ast_filestream *),
00095
char * (*getcomment)(
struct ast_filestream *))
00096 {
00097
struct ast_format *tmp;
00098
if (
ast_mutex_lock(&formatlock)) {
00099
ast_log(
LOG_WARNING,
"Unable to lock format list\n");
00100
return -1;
00101 }
00102 tmp = formats;
00103
while(tmp) {
00104
if (!strcasecmp(name, tmp->name)) {
00105
ast_mutex_unlock(&formatlock);
00106
ast_log(
LOG_WARNING,
"Tried to register '%s' format, already registered\n", name);
00107
return -1;
00108 }
00109 tmp = tmp->next;
00110 }
00111 tmp =
malloc(
sizeof(
struct ast_format));
00112
if (!tmp) {
00113
ast_log(
LOG_WARNING,
"Out of memory\n");
00114
ast_mutex_unlock(&formatlock);
00115
return -1;
00116 }
00117 strncpy(tmp->name, name,
sizeof(tmp->name)-1);
00118 strncpy(tmp->exts, exts,
sizeof(tmp->exts)-1);
00119 tmp->open = open;
00120 tmp->rewrite = rewrite;
00121 tmp->read = read;
00122 tmp->write = write;
00123 tmp->seek = seek;
00124 tmp->trunc = trunc;
00125 tmp->tell = tell;
00126 tmp->close = close;
00127 tmp->format = format;
00128 tmp->getcomment = getcomment;
00129 tmp->
next = formats;
00130 formats = tmp;
00131
ast_mutex_unlock(&formatlock);
00132
if (
option_verbose > 1)
00133
ast_verbose(
VERBOSE_PREFIX_2 "Registered file format %s, extension(s) %s\n", name, exts);
00134
return 0;
00135 }
00136
00137 int ast_format_unregister(
char *name)
00138 {
00139
struct ast_format *tmp, *tmpl = NULL;
00140
if (
ast_mutex_lock(&formatlock)) {
00141
ast_log(
LOG_WARNING,
"Unable to lock format list\n");
00142
return -1;
00143 }
00144 tmp = formats;
00145
while(tmp) {
00146
if (!strcasecmp(name, tmp->name)) {
00147
if (tmpl)
00148 tmpl->
next = tmp->
next;
00149
else
00150 formats = tmp->
next;
00151
free(tmp);
00152
ast_mutex_unlock(&formatlock);
00153
if (
option_verbose > 1)
00154
ast_verbose(
VERBOSE_PREFIX_2 "Unregistered format %s\n", name);
00155
return 0;
00156 }
00157 tmpl = tmp;
00158 tmp = tmp->next;
00159 }
00160
ast_log(
LOG_WARNING,
"Tried to unregister format %s, already unregistered\n", name);
00161
return -1;
00162 }
00163
00164 int ast_stopstream(
struct ast_channel *tmp)
00165 {
00166
00167
if (tmp->
vstream)
00168
ast_closestream(tmp->
vstream);
00169
if (tmp->
stream) {
00170
ast_closestream(tmp->
stream);
00171
if (tmp->
oldwriteformat &&
ast_set_write_format(tmp, tmp->
oldwriteformat))
00172
ast_log(
LOG_WARNING,
"Unable to restore format back to %d\n", tmp->
oldwriteformat);
00173 }
00174
return 0;
00175 }
00176
00177 int ast_writestream(
struct ast_filestream *fs,
struct ast_frame *f)
00178 {
00179
struct ast_frame *trf;
00180
int res = -1;
00181
int alt=0;
00182
if (f->
frametype ==
AST_FRAME_VIDEO) {
00183
if (fs->
fmt->
format <
AST_FORMAT_MAX_AUDIO) {
00184
00185
if (!fs->
vfs && fs->
filename) {
00186
00187
char *
type =
"h263";
00188 fs->
vfs =
ast_writefile(fs->
filename,
type, NULL, fs->
flags, 0, fs->
mode);
00189
ast_log(
LOG_DEBUG,
"Opened video output file\n");
00190 }
00191
if (fs->
vfs)
00192
return ast_writestream(fs->
vfs, f);
00193
00194
return 0;
00195 }
else {
00196
00197 alt = 1;
00198 }
00199 }
else if (f->
frametype !=
AST_FRAME_VOICE) {
00200
ast_log(
LOG_WARNING,
"Tried to write non-voice frame\n");
00201
return -1;
00202 }
00203
if (((fs->
fmt->
format | alt) & f->
subclass) == f->
subclass) {
00204 res = fs->
fmt->
write(fs, f);
00205
if (res < 0)
00206
ast_log(
LOG_WARNING,
"Natural write failed\n");
00207
if (res > 0)
00208
ast_log(
LOG_WARNING,
"Huh??\n");
00209
return res;
00210 }
else {
00211
00212
00213
if (fs->
trans && (f->
subclass != fs->
lastwriteformat)) {
00214
ast_translator_free_path(fs->
trans);
00215 fs->
trans = NULL;
00216 }
00217
if (!fs->
trans)
00218 fs->
trans =
ast_translator_build_path(fs->
fmt->
format, f->
subclass);
00219
if (!fs->
trans)
00220
ast_log(
LOG_WARNING,
"Unable to translate to format %s, source format %s\n", fs->
fmt->
name,
ast_getformatname(f->
subclass));
00221
else {
00222 fs->
lastwriteformat = f->
subclass;
00223 res = 0;
00224
00225 trf =
ast_translate(fs->
trans, f, 0);
00226
if (trf) {
00227 res = fs->
fmt->
write(fs, trf);
00228
if (res)
00229
ast_log(
LOG_WARNING,
"Translated frame write failed\n");
00230 }
else
00231 res = 0;
00232 }
00233
return res;
00234 }
00235 }
00236
00237
static int copy(
char *infile,
char *outfile)
00238 {
00239
int ifd;
00240
int ofd;
00241
int res;
00242
int len;
00243
char buf[4096];
00244
if ((ifd = open(infile, O_RDONLY)) < 0) {
00245
ast_log(LOG_WARNING,
"Unable to open %s in read-only mode\n", infile);
00246
return -1;
00247 }
00248
if ((ofd = open(outfile, O_WRONLY | O_TRUNC | O_CREAT, 0600)) < 0) {
00249
ast_log(LOG_WARNING,
"Unable to open %s in write-only mode\n", outfile);
00250 close(ifd);
00251
return -1;
00252 }
00253
do {
00254 len = read(ifd, buf,
sizeof(buf));
00255
if (len < 0) {
00256
ast_log(LOG_WARNING,
"Read failed on %s: %s\n", infile, strerror(errno));
00257 close(ifd);
00258 close(ofd);
00259 unlink(outfile);
00260 }
00261
if (len) {
00262 res = write(ofd, buf, len);
00263
if (res != len) {
00264
ast_log(LOG_WARNING,
"Write failed on %s (%d of %d): %s\n", outfile, res, len, strerror(errno));
00265 close(ifd);
00266 close(ofd);
00267 unlink(outfile);
00268 }
00269 }
00270 }
while(len);
00271 close(ifd);
00272 close(ofd);
00273
return 0;
00274 }
00275
00276
static char *build_filename(
char *filename,
char *ext)
00277 {
00278
char *fn;
00279
char tmp[
AST_CONFIG_MAX_PATH]=
"";
00280 snprintf(tmp,
sizeof(tmp)-1,
"%s/%s",(
char *)ast_config_AST_VAR_DIR,
"sounds");
00281 fn =
malloc(strlen(tmp) + strlen(filename) + strlen(ext) + 10);
00282
if (fn) {
00283
if (filename[0] ==
'/')
00284 sprintf(fn,
"%s.%s", filename, ext);
00285
else
00286 sprintf(fn,
"%s/%s.%s", (
char *)tmp, filename, ext);
00287 }
00288
return fn;
00289
00290 }
00291
00292
static int exts_compare(
char *exts,
char *type)
00293 {
00294
char *stringp = NULL, *ext;
00295
char tmp[256];
00296
00297 strncpy(tmp, exts,
sizeof(tmp) - 1);
00298 stringp = tmp;
00299
while ((ext = strsep(&stringp,
"|"))) {
00300
if (!strcmp(ext, type)) {
00301
return 1;
00302 }
00303 }
00304
00305
return 0;
00306 }
00307
00308 #define ACTION_EXISTS 1
00309 #define ACTION_DELETE 2
00310 #define ACTION_RENAME 3
00311 #define ACTION_OPEN 4
00312 #define ACTION_COPY 5
00313
00314
static int ast_filehelper(
char *filename,
char *filename2,
char *fmt,
int action)
00315 {
00316
struct stat st;
00317
struct ast_format *f;
00318
struct ast_filestream *
s;
00319
int res=0, ret = 0;
00320
char *ext=NULL, *exts, *fn, *nfn;
00321
struct ast_channel *chan = (
struct ast_channel *)filename2;
00322
00323
00324
if (action ==
ACTION_EXISTS)
00325 res = 0;
00326
else
00327 res = -1;
00328
if (action ==
ACTION_OPEN)
00329 ret = -1;
00330
00331
if (
ast_mutex_lock(&formatlock)) {
00332
ast_log(
LOG_WARNING,
"Unable to lock format list\n");
00333
if (action ==
ACTION_EXISTS)
00334
return 0;
00335
else
00336
return -1;
00337 }
00338 f = formats;
00339
while(f) {
00340
if (!fmt || exts_compare(f->exts, fmt)) {
00341
char *stringp=NULL;
00342 exts =
strdup(f->exts);
00343
00344 stringp=exts;
00345 ext = strsep(&stringp,
"|");
00346
do {
00347 fn = build_filename(filename, ext);
00348
if (fn) {
00349 res = stat(fn, &st);
00350
if (!res) {
00351
switch(action) {
00352
case ACTION_EXISTS:
00353 ret |= f->format;
00354
break;
00355
case ACTION_DELETE:
00356 res = unlink(fn);
00357
if (res)
00358
ast_log(
LOG_WARNING,
"unlink(%s) failed: %s\n", fn, strerror(errno));
00359
break;
00360
case ACTION_RENAME:
00361 nfn = build_filename(filename2, ext);
00362
if (nfn) {
00363 res = rename(fn, nfn);
00364
if (res)
00365
ast_log(
LOG_WARNING,
"rename(%s,%s) failed: %s\n", fn, nfn, strerror(errno));
00366
free(nfn);
00367 }
else
00368
ast_log(
LOG_WARNING,
"Out of memory\n");
00369
break;
00370
case ACTION_COPY:
00371 nfn = build_filename(filename2, ext);
00372
if (nfn) {
00373 res = copy(fn, nfn);
00374
if (res)
00375
ast_log(
LOG_WARNING,
"copy(%s,%s) failed: %s\n", fn, nfn, strerror(errno));
00376
free(nfn);
00377 }
else
00378
ast_log(
LOG_WARNING,
"Out of memory\n");
00379
break;
00380
case ACTION_OPEN:
00381
if ((ret < 0) && ((chan->writeformat & f->format) ||
00382 ((f->format >=
AST_FORMAT_MAX_AUDIO) && fmt))) {
00383 ret = open(fn, O_RDONLY);
00384
if (ret >= 0) {
00385
s = f->open(ret);
00386
if (
s) {
00387
s->lasttimeout = -1;
00388
s->fmt = f;
00389
s->trans = NULL;
00390
s->filename = NULL;
00391
if (
s->fmt->format <
AST_FORMAT_MAX_AUDIO)
00392 chan->stream =
s;
00393
else
00394 chan->vstream =
s;
00395 }
else {
00396 close(ret);
00397
ast_log(
LOG_WARNING,
"Unable to open fd on %s\n", fn);
00398 }
00399 }
else
00400
ast_log(
LOG_WARNING,
"Couldn't open file %s\n", fn);
00401 }
00402
break;
00403
default:
00404
ast_log(
LOG_WARNING,
"Unknown helper %d\n", action);
00405 }
00406
00407
if (res)
00408
break;
00409 }
00410
free(fn);
00411 }
00412 ext = strsep(&stringp,
"|");
00413 }
while(ext);
00414
free(exts);
00415 }
00416 f = f->next;
00417 }
00418
ast_mutex_unlock(&formatlock);
00419
if ((action ==
ACTION_EXISTS) || (action ==
ACTION_OPEN))
00420 res = ret ? ret : -1;
00421
return res;
00422 }
00423
00424 struct ast_filestream *
ast_openstream(
struct ast_channel *chan,
char *filename,
char *preflang)
00425 {
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
int fd = -1;
00439
int fmts = -1;
00440
char filename2[256]=
"";
00441
char filename3[256]=
"";
00442
char *endpart;
00443
int res;
00444
ast_stopstream(chan);
00445
00446
if (chan->
generator)
00447
ast_deactivate_generator(chan);
00448
if (preflang && !ast_strlen_zero(preflang)) {
00449 strncpy(filename3, filename,
sizeof(filename3) - 1);
00450 endpart = strrchr(filename3,
'/');
00451
if (endpart) {
00452 *endpart =
'\0';
00453 endpart++;
00454 snprintf(filename2,
sizeof(filename2),
"%s/%s/%s", filename3, preflang, endpart);
00455 }
else
00456 snprintf(filename2,
sizeof(filename2),
"%s/%s", preflang, filename);
00457 fmts =
ast_fileexists(filename2, NULL, NULL);
00458 }
00459
if (fmts < 1) {
00460 strncpy(filename2, filename,
sizeof(filename2)-1);
00461 fmts =
ast_fileexists(filename2, NULL, NULL);
00462 }
00463
if (fmts < 1) {
00464
ast_log(
LOG_WARNING,
"File %s does not exist in any format\n", filename);
00465
return NULL;
00466 }
00467 chan->
oldwriteformat = chan->
writeformat;
00468
00469 res =
ast_set_write_format(chan, fmts);
00470
00471 fd = ast_filehelper(filename2, (
char *)chan, NULL,
ACTION_OPEN);
00472
if(fd >= 0)
00473
return chan->stream;
00474
return NULL;
00475 }
00476
00477 struct ast_filestream *
ast_openvstream(
struct ast_channel *chan,
char *filename,
char *preflang)
00478 {
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
int fd = -1;
00492
int fmts = -1;
00493
char filename2[256];
00494
char lang2[
MAX_LANGUAGE];
00495
00496
char *fmt =
"h263";
00497
if (preflang && !ast_strlen_zero(preflang)) {
00498 snprintf(filename2,
sizeof(filename2),
"%s/%s", preflang, filename);
00499 fmts =
ast_fileexists(filename2, fmt, NULL);
00500
if (fmts < 1) {
00501 strncpy(lang2, preflang,
sizeof(lang2)-1);
00502 snprintf(filename2,
sizeof(filename2),
"%s/%s", lang2, filename);
00503 fmts =
ast_fileexists(filename2, fmt, NULL);
00504 }
00505 }
00506
if (fmts < 1) {
00507 strncpy(filename2, filename,
sizeof(filename2)-1);
00508 fmts =
ast_fileexists(filename2, fmt, NULL);
00509 }
00510
if (fmts < 1) {
00511
return NULL;
00512 }
00513 fd = ast_filehelper(filename2, (
char *)chan, fmt,
ACTION_OPEN);
00514
if(fd >= 0)
00515
return chan->vstream;
00516
ast_log(
LOG_WARNING,
"File %s has video but couldn't be opened\n", filename);
00517
return NULL;
00518 }
00519
00520 struct ast_frame *
ast_readframe(
struct ast_filestream *s)
00521 {
00522
struct ast_frame *f = NULL;
00523
int whennext = 0;
00524
if (
s &&
s->fmt)
00525 f =
s->fmt->read(
s, &whennext);
00526
return f;
00527 }
00528
00529
static int ast_readaudio_callback(
void *data)
00530 {
00531
struct ast_filestream *
s = data;
00532
struct ast_frame *fr;
00533
int whennext = 0;
00534
00535
while(!whennext) {
00536 fr =
s->fmt->read(s, &whennext);
00537
if (fr) {
00538
if (
ast_write(
s->owner, fr)) {
00539
ast_log(LOG_WARNING,
"Failed to write frame\n");
00540
s->owner->streamid = -1;
00541
#ifdef ZAPTEL_OPTIMIZATIONS
00542
ast_settimeout(
s->owner, 0, NULL, NULL);
00543
#endif
00544
return 0;
00545 }
00546 }
else {
00547
00548
s->owner->streamid = -1;
00549
#ifdef ZAPTEL_OPTIMIZATIONS
00550
ast_settimeout(
s->owner, 0, NULL, NULL);
00551
#endif
00552
return 0;
00553 }
00554 }
00555
if (whennext !=
s->lasttimeout) {
00556
#ifdef ZAPTEL_OPTIMIZATIONS
00557
if (
s->owner->timingfd > -1)
00558
ast_settimeout(
s->owner, whennext, ast_readaudio_callback, s);
00559
else
00560
#endif
00561
s->owner->streamid =
ast_sched_add(
s->owner->sched, whennext/8, ast_readaudio_callback, s);
00562
s->lasttimeout = whennext;
00563
return 0;
00564 }
00565
return 1;
00566 }
00567
00568
static int ast_readvideo_callback(
void *data)
00569 {
00570
struct ast_filestream *
s = data;
00571
struct ast_frame *fr;
00572
int whennext = 0;
00573
00574
while(!whennext) {
00575 fr =
s->fmt->read(s, &whennext);
00576
if (fr) {
00577
if (
ast_write(
s->owner, fr)) {
00578
ast_log(LOG_WARNING,
"Failed to write frame\n");
00579
s->owner->vstreamid = -1;
00580
return 0;
00581 }
00582 }
else {
00583
00584
s->owner->vstreamid = -1;
00585
return 0;
00586 }
00587 }
00588
if (whennext !=
s->lasttimeout) {
00589
s->owner->vstreamid =
ast_sched_add(
s->owner->sched, whennext/8, ast_readvideo_callback, s);
00590
s->lasttimeout = whennext;
00591
return 0;
00592 }
00593
return 1;
00594 }
00595
00596 int ast_applystream(
struct ast_channel *chan,
struct ast_filestream *s)
00597 {
00598
s->owner = chan;
00599
return 0;
00600 }
00601
00602 int ast_playstream(
struct ast_filestream *s)
00603 {
00604
if (
s->fmt->format <
AST_FORMAT_MAX_AUDIO)
00605 ast_readaudio_callback(
s);
00606
else
00607 ast_readvideo_callback(
s);
00608
return 0;
00609 }
00610
00611 int ast_seekstream(
struct ast_filestream *fs,
long sample_offset,
int whence)
00612 {
00613
return fs->
fmt->
seek(fs, sample_offset, whence);
00614 }
00615
00616 int ast_truncstream(
struct ast_filestream *fs)
00617 {
00618
return fs->
fmt->
trunc(fs);
00619 }
00620
00621 long ast_tellstream(
struct ast_filestream *fs)
00622 {
00623
return fs->
fmt->
tell(fs);
00624 }
00625
00626 int ast_stream_fastforward(
struct ast_filestream *fs,
long ms)
00627 {
00628
00629
00630
long samples = ms * 8;
00631
return ast_seekstream(fs, samples, SEEK_CUR);
00632 }
00633
00634 int ast_stream_rewind(
struct ast_filestream *fs,
long ms)
00635 {
00636
long samples = ms * 8;
00637 samples = samples * -1;
00638
return ast_seekstream(fs, samples, SEEK_CUR);
00639 }
00640
00641 int ast_closestream(
struct ast_filestream *f)
00642 {
00643
00644
if (f->
owner) {
00645
if (f->
fmt->
format <
AST_FORMAT_MAX_AUDIO) {
00646 f->
owner->
stream = NULL;
00647
if (f->
owner->
streamid > -1)
00648
ast_sched_del(f->
owner->
sched, f->
owner->
streamid);
00649 f->
owner->
streamid = -1;
00650
#ifdef ZAPTEL_OPTIMIZATIONS
00651
ast_settimeout(f->
owner, 0, NULL, NULL);
00652
#endif
00653
}
else {
00654 f->
owner->
vstream = NULL;
00655
if (f->
owner->
vstreamid > -1)
00656
ast_sched_del(f->
owner->
sched, f->
owner->
vstreamid);
00657 f->
owner->
vstreamid = -1;
00658 }
00659 }
00660
00661
if (f->
trans) {
00662
ast_translator_free_path(f->
trans);
00663 f->
trans = NULL;
00664 }
00665
if (f->
filename)
00666
free(f->
filename);
00667 f->
filename = NULL;
00668 f->
fmt->
close(f);
00669
return 0;
00670 }
00671
00672
00673 int ast_fileexists(
char *filename,
char *fmt,
char *preflang)
00674 {
00675
char filename2[256];
00676
char tmp[256];
00677
char *postfix;
00678
char *prefix;
00679
char *c;
00680
char lang2[
MAX_LANGUAGE];
00681
int res = -1;
00682
if (preflang && !ast_strlen_zero(preflang)) {
00683
00684 strncpy(tmp, filename,
sizeof(tmp) - 1);
00685 c = strrchr(tmp,
'/');
00686
if (c) {
00687 *c =
'\0';
00688 postfix = c+1;
00689 prefix = tmp;
00690 }
else {
00691 postfix = tmp;
00692 prefix=
"";
00693 }
00694 snprintf(filename2,
sizeof(filename2),
"%s/%s/%s", prefix, preflang, postfix);
00695 res = ast_filehelper(filename2, NULL, fmt,
ACTION_EXISTS);
00696
if (res < 1) {
00697
char *stringp=NULL;
00698 strncpy(lang2, preflang,
sizeof(lang2)-1);
00699 stringp=lang2;
00700 strsep(&stringp,
"_");
00701
if (strcmp(lang2, preflang)) {
00702 snprintf(filename2,
sizeof(filename2),
"%s/%s/%s", prefix, lang2, postfix);
00703 res = ast_filehelper(filename2, NULL, fmt,
ACTION_EXISTS);
00704 }
00705 }
00706 }
00707
if (res < 1) {
00708 res = ast_filehelper(filename, NULL, fmt,
ACTION_EXISTS);
00709 }
00710
return res;
00711 }
00712
00713 int ast_filedelete(
char *filename,
char *fmt)
00714 {
00715
return ast_filehelper(filename, NULL, fmt,
ACTION_DELETE);
00716 }
00717
00718 int ast_filerename(
char *filename,
char *filename2,
char *fmt)
00719 {
00720
return ast_filehelper(filename, filename2, fmt,
ACTION_RENAME);
00721 }
00722
00723 int ast_filecopy(
char *filename,
char *filename2,
char *fmt)
00724 {
00725
return ast_filehelper(filename, filename2, fmt,
ACTION_COPY);
00726 }
00727
00728 int ast_streamfile(
struct ast_channel *chan,
char *filename,
char *preflang)
00729 {
00730
struct ast_filestream *fs;
00731
struct ast_filestream *vfs;
00732
00733 fs =
ast_openstream(chan, filename, preflang);
00734 vfs =
ast_openvstream(chan, filename, preflang);
00735
if (vfs)
00736
ast_log(
LOG_DEBUG,
"Ooh, found a video stream, too\n");
00737
if(fs){
00738
if(
ast_applystream(chan, fs))
00739
return -1;
00740
if(vfs &&
ast_applystream(chan, vfs))
00741
return -1;
00742
if(
ast_playstream(fs))
00743
return -1;
00744
if(vfs &&
ast_playstream(vfs))
00745
return -1;
00746
#if 1
00747
if (
option_verbose > 2)
00748
ast_verbose(
VERBOSE_PREFIX_3 "Playing '%s' (language '%s')\n", filename, preflang ? preflang :
"default");
00749
#endif
00750
return 0;
00751 }
00752
ast_log(
LOG_WARNING,
"Unable to open %s (format %s): %s\n", filename,
ast_getformatname(chan->
nativeformats), strerror(errno));
00753
return -1;
00754 }
00755
00756 struct ast_filestream *
ast_readfile(
char *filename,
char *type,
char *comment,
int flags,
int check, mode_t mode)
00757 {
00758
int fd,myflags = 0;
00759
struct ast_format *f;
00760
struct ast_filestream *fs=NULL;
00761
char *fn;
00762
char *ext;
00763
if (
ast_mutex_lock(&formatlock)) {
00764
ast_log(
LOG_WARNING,
"Unable to lock format list\n");
00765
return NULL;
00766 }
00767 f = formats;
00768
while(f) {
00769
if (exts_compare(f->exts,
type)) {
00770
char *stringp=NULL;
00771
00772 ext =
strdup(f->exts);
00773 stringp=ext;
00774 ext = strsep(&stringp,
"|");
00775 fn = build_filename(filename, ext);
00776 fd = open(fn, flags | myflags);
00777
if (fd >= 0) {
00778 errno = 0;
00779
if ((fs = f->open(fd))) {
00780 fs->trans = NULL;
00781 fs->fmt = f;
00782 fs->flags = flags;
00783 fs->mode = mode;
00784 fs->filename =
strdup(filename);
00785 fs->vfs = NULL;
00786 }
else {
00787
ast_log(
LOG_WARNING,
"Unable to open %s\n", fn);
00788 close(fd);
00789 unlink(fn);
00790 }
00791 }
else if (errno != EEXIST)
00792
ast_log(
LOG_WARNING,
"Unable to open file %s: %s\n", fn, strerror(errno));
00793
free(fn);
00794
free(ext);
00795
break;
00796 }
00797 f = f->next;
00798 }
00799
ast_mutex_unlock(&formatlock);
00800
if (!f)
00801
ast_log(
LOG_WARNING,
"No such format '%s'\n",
type);
00802
return fs;
00803 }
00804
00805 struct ast_filestream *
ast_writefile(
char *filename,
char *type,
char *comment,
int flags,
int check, mode_t mode)
00806 {
00807
int fd,myflags = 0;
00808
struct ast_format *f;
00809
struct ast_filestream *fs=NULL;
00810
char *fn;
00811
char *ext;
00812
if (
ast_mutex_lock(&formatlock)) {
00813
ast_log(
LOG_WARNING,
"Unable to lock format list\n");
00814
return NULL;
00815 }
00816
00817
if (!(flags & O_APPEND))
00818 myflags = O_TRUNC;
00819
00820 myflags |= O_WRONLY | O_CREAT;
00821
00822 f = formats;
00823
while(f) {
00824
if (exts_compare(f->exts,
type)) {
00825
char *stringp=NULL;
00826
00827 ext =
strdup(f->exts);
00828 stringp=ext;
00829 ext = strsep(&stringp,
"|");
00830 fn = build_filename(filename, ext);
00831 fd = open(fn, flags | myflags, mode);
00832
if (fd >= 0) {
00833 errno = 0;
00834
if ((fs = f->rewrite(fd, comment))) {
00835 fs->trans = NULL;
00836 fs->fmt = f;
00837 fs->flags = flags;
00838 fs->mode = mode;
00839 fs->filename =
strdup(filename);
00840 fs->vfs = NULL;
00841 }
else {
00842
ast_log(
LOG_WARNING,
"Unable to rewrite %s\n", fn);
00843 close(fd);
00844 unlink(fn);
00845 }
00846 }
else if (errno != EEXIST)
00847
ast_log(
LOG_WARNING,
"Unable to open file %s: %s\n", fn, strerror(errno));
00848
free(fn);
00849
free(ext);
00850
break;
00851 }
00852 f = f->next;
00853 }
00854
ast_mutex_unlock(&formatlock);
00855
if (!f)
00856
ast_log(
LOG_WARNING,
"No such format '%s'\n",
type);
00857
return fs;
00858 }
00859
00860 char ast_waitstream(
struct ast_channel *c,
char *breakon)
00861 {
00862
00863
int res;
00864
struct ast_frame *fr;
00865
while(c->
stream) {
00866 res =
ast_sched_wait(c->
sched);
00867
if ((res < 0) && !c->
timingfunc) {
00868
ast_stopstream(c);
00869
break;
00870 }
00871
if (res < 0)
00872 res = 1000;
00873 res =
ast_waitfor(c, res);
00874
if (res < 0) {
00875
ast_log(
LOG_WARNING,
"Select failed (%s)\n", strerror(errno));
00876
return res;
00877 }
else if (res > 0) {
00878 fr =
ast_read(c);
00879
if (!fr) {
00880
#if 0
00881
ast_log(
LOG_DEBUG,
"Got hung up\n");
00882
#endif
00883
return -1;
00884 }
00885
00886
switch(fr->frametype) {
00887
case AST_FRAME_DTMF:
00888 res = fr->subclass;
00889
if (strchr(breakon, res)) {
00890
ast_frfree(fr);
00891
return res;
00892 }
00893
break;
00894
case AST_FRAME_CONTROL:
00895
switch(fr->subclass) {
00896
case AST_CONTROL_HANGUP:
00897
ast_frfree(fr);
00898
return -1;
00899
case AST_CONTROL_RINGING:
00900
case AST_CONTROL_ANSWER:
00901
00902
break;
00903
default:
00904
ast_log(
LOG_WARNING,
"Unexpected control subclass '%d'\n", fr->subclass);
00905 }
00906 }
00907
00908
ast_frfree(fr);
00909 }
00910
ast_sched_runq(c->
sched);
00911 }
00912
return (c->
_softhangup ? -1 : 0);
00913 }
00914
00915 char ast_waitstream_fr(
struct ast_channel *c,
char *breakon,
char *forward,
char *rewind,
int ms)
00916 {
00917
int res;
00918
struct ast_frame *fr;
00919
while(c->
stream) {
00920 res =
ast_sched_wait(c->
sched);
00921
if ((res < 0) && !c->
timingfunc) {
00922
ast_stopstream(c);
00923
break;
00924 }
00925
if (res < 0)
00926 res = 1000;
00927 res =
ast_waitfor(c, res);
00928
if (res < 0) {
00929
ast_log(
LOG_WARNING,
"Select failed (%s)\n", strerror(errno));
00930
return res;
00931 }
else
00932
if (res > 0) {
00933 fr =
ast_read(c);
00934
if (!fr) {
00935
#if 0
00936
ast_log(
LOG_DEBUG,
"Got hung up\n");
00937
#endif
00938
return -1;
00939 }
00940
00941
switch(fr->frametype) {
00942
case AST_FRAME_DTMF:
00943 res = fr->subclass;
00944
if (strchr(forward,res)) {
00945
ast_stream_fastforward(c->
stream, ms);
00946 }
else if (strchr(rewind,res)) {
00947
ast_stream_rewind(c->
stream, ms);
00948 }
else if (strchr(breakon, res)) {
00949
ast_frfree(fr);
00950
return res;
00951 }
00952
break;
00953
case AST_FRAME_CONTROL:
00954
switch(fr->subclass) {
00955
case AST_CONTROL_HANGUP:
00956
ast_frfree(fr);
00957
return -1;
00958
case AST_CONTROL_RINGING:
00959
case AST_CONTROL_ANSWER:
00960
00961
break;
00962
default:
00963
ast_log(
LOG_WARNING,
"Unexpected control subclass '%d'\n", fr->subclass);
00964 }
00965 }
00966
00967
ast_frfree(fr);
00968 }
else
00969
ast_sched_runq(c->
sched);
00970
00971
00972 }
00973
return (c->
_softhangup ? -1 : 0);
00974 }
00975
00976 char ast_waitstream_full(
struct ast_channel *c,
char *breakon,
int audiofd,
int cmdfd)
00977 {
00978
int res;
00979
int ms;
00980
int outfd;
00981
struct ast_frame *fr;
00982
struct ast_channel *rchan;
00983
00984
while(c->
stream) {
00985 ms =
ast_sched_wait(c->
sched);
00986
if ((ms < 0) && !c->
timingfunc) {
00987
ast_stopstream(c);
00988
break;
00989 }
00990
if (ms < 0)
00991 ms = 1000;
00992 rchan =
ast_waitfor_nandfds(&c, 1, &cmdfd, (cmdfd > -1) ? 1 : 0, NULL, &outfd, &ms);
00993
if (!rchan && (outfd < 0) && (ms)) {
00994
ast_log(
LOG_WARNING,
"Wait failed (%s)\n", strerror(errno));
00995
return -1;
00996 }
else if (outfd > -1) {
00997
00998
return 1;
00999 }
else if (rchan) {
01000 fr =
ast_read(c);
01001
if (!fr) {
01002
#if 0
01003
ast_log(
LOG_DEBUG,
"Got hung up\n");
01004
#endif
01005
return -1;
01006 }
01007
01008
switch(fr->frametype) {
01009
case AST_FRAME_DTMF:
01010 res = fr->subclass;
01011
if (strchr(breakon, res)) {
01012
ast_frfree(fr);
01013
return res;
01014 }
01015
break;
01016
case AST_FRAME_CONTROL:
01017
switch(fr->subclass) {
01018
case AST_CONTROL_HANGUP:
01019
ast_frfree(fr);
01020
return -1;
01021
case AST_CONTROL_RINGING:
01022
case AST_CONTROL_ANSWER:
01023
01024
break;
01025
default:
01026
ast_log(
LOG_WARNING,
"Unexpected control subclass '%d'\n", fr->subclass);
01027 }
01028
case AST_FRAME_VOICE:
01029
01030
if (audiofd > -1)
01031 write(audiofd, fr->data, fr->datalen);
01032 }
01033
01034
ast_frfree(fr);
01035 }
01036
ast_sched_runq(c->
sched);
01037
01038
01039 }
01040
return (c->
_softhangup ? -1 : 0);
01041 }