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