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