diff options
Diffstat (limited to 'main/file.c')
-rw-r--r-- | main/file.c | 124 |
1 files changed, 96 insertions, 28 deletions
diff --git a/main/file.c b/main/file.c index dda1b3d63..d64e9cd94 100644 --- a/main/file.c +++ b/main/file.c @@ -603,39 +603,68 @@ struct ast_frame *ast_readframe(struct ast_filestream *s) return f; } -static int ast_readaudio_callback(void *data) +enum fsread_res { + FSREAD_FAILURE, + FSREAD_SUCCESS_SCHED, + FSREAD_SUCCESS_NOSCHED, +}; + +static int ast_fsread_audio(void *data); + +static enum fsread_res ast_readaudio_callback(struct ast_filestream *s) { - struct ast_filestream *s = data; int whennext = 0; while (!whennext) { - struct ast_frame *fr = s->fmt->read(s, &whennext); + struct ast_frame *fr; + + if (s->orig_chan_name && strcasecmp(s->owner->name, s->orig_chan_name)) + goto return_failure; + + fr = s->fmt->read(s, &whennext); if (!fr /* stream complete */ || ast_write(s->owner, fr) /* error writing */) { if (fr) ast_log(LOG_WARNING, "Failed to write frame\n"); - s->owner->streamid = -1; -#ifdef HAVE_ZAPTEL - ast_settimeout(s->owner, 0, NULL, NULL); -#endif - return 0; + goto return_failure; } } if (whennext != s->lasttimeout) { #ifdef HAVE_ZAPTEL if (s->owner->timingfd > -1) - ast_settimeout(s->owner, whennext, ast_readaudio_callback, s); + ast_settimeout(s->owner, whennext, ast_fsread_audio, s); else #endif - s->owner->streamid = ast_sched_add(s->owner->sched, whennext/8, ast_readaudio_callback, s); + s->owner->streamid = ast_sched_add(s->owner->sched, whennext/8, ast_fsread_audio, s); s->lasttimeout = whennext; - return 0; + return FSREAD_SUCCESS_NOSCHED; } - return 1; + return FSREAD_SUCCESS_SCHED; + +return_failure: + s->owner->streamid = -1; +#ifdef HAVE_ZAPTEL + ast_settimeout(s->owner, 0, NULL, NULL); +#endif + return FSREAD_FAILURE; } -static int ast_readvideo_callback(void *data) +static int ast_fsread_audio(void *data) +{ + struct ast_filestream *fs = data; + enum fsread_res res; + + res = ast_readaudio_callback(fs); + + if (res == FSREAD_SUCCESS_SCHED) + return 1; + + return 0; +} + +static int ast_fsread_video(void *data); + +static enum fsread_res ast_readvideo_callback(struct ast_filestream *s) { - struct ast_filestream *s = data; int whennext = 0; while (!whennext) { @@ -644,15 +673,31 @@ static int ast_readvideo_callback(void *data) if (fr) ast_log(LOG_WARNING, "Failed to write frame\n"); s->owner->vstreamid = -1; - return 0; + return FSREAD_FAILURE; } } + if (whennext != s->lasttimeout) { - s->owner->vstreamid = ast_sched_add(s->owner->sched, whennext/8, ast_readvideo_callback, s); + s->owner->vstreamid = ast_sched_add(s->owner->sched, whennext / 8, + ast_fsread_video, s); s->lasttimeout = whennext; - return 0; + return FSREAD_SUCCESS_NOSCHED; } - return 1; + + return FSREAD_SUCCESS_SCHED; +} + +static int ast_fsread_video(void *data) +{ + struct ast_filestream *fs = data; + enum fsread_res res; + + res = ast_readvideo_callback(fs); + + if (res == FSREAD_SUCCESS_SCHED) + return 1; + + return 0; } int ast_applystream(struct ast_channel *chan, struct ast_filestream *s) @@ -663,11 +708,14 @@ int ast_applystream(struct ast_channel *chan, struct ast_filestream *s) int ast_playstream(struct ast_filestream *s) { + enum fsread_res res; + if (s->fmt->format < AST_FORMAT_MAX_AUDIO) - ast_readaudio_callback(s); + res = ast_readaudio_callback(s); else - ast_readvideo_callback(s); - return 0; + res = ast_readvideo_callback(s); + + return (res == FSREAD_FAILURE) ? -1 : 0; } int ast_seekstream(struct ast_filestream *fs, off_t sample_offset, int whence) @@ -737,6 +785,8 @@ int ast_closestream(struct ast_filestream *f) fclose(f->f); if (f->vfs) ast_closestream(f->vfs); + if (f->orig_chan_name) + free((void *) f->orig_chan_name); ast_module_unref(f->fmt->module); ast_free(f); return 0; @@ -788,16 +838,19 @@ int ast_streamfile(struct ast_channel *chan, const char *filename, const char *p ast_debug(1, "Ooh, found a video stream, too, format %s\n", ast_getformatname(vfs->fmt->format)); } if (fs){ + int res; + if (ast_test_flag(chan, AST_FLAG_MASQ_NOSTREAM)) + fs->orig_chan_name = ast_strdup(chan->name); if (ast_applystream(chan, fs)) return -1; if (vfs && ast_applystream(chan, vfs)) return -1; - ast_playstream(fs); - if (vfs) - ast_playstream(vfs); + res = ast_playstream(fs); + if (!res && vfs) + res = ast_playstream(vfs); ast_verb(3, "<%s> Playing '%s.%s' (language '%s')\n", chan->name, filename, ast_getformatname(chan->writeformat), preflang ? preflang : "default"); - return 0; + return res; } ast_log(LOG_WARNING, "Unable to open %s (format %s): %s\n", filename, ast_getformatname_multiple(fmt, sizeof(fmt), chan->nativeformats), strerror(errno)); return -1; @@ -980,6 +1033,9 @@ static int waitstream_core(struct ast_channel *c, const char *breakon, const char *forward, const char *rewind, int skip_ms, int audiofd, int cmdfd, const char *context) { + const char *orig_chan_name = NULL; + int err = 0; + if (!breakon) breakon = ""; if (!forward) @@ -989,10 +1045,22 @@ static int waitstream_core(struct ast_channel *c, const char *breakon, /* Switch the channel to end DTMF frame only. waitstream_core doesn't care about the start of DTMF. */ ast_set_flag(c, AST_FLAG_END_DTMF_ONLY); - + + if (ast_test_flag(c, AST_FLAG_MASQ_NOSTREAM)) + orig_chan_name = ast_strdupa(c->name); + while (c->stream) { int res; - int ms = ast_sched_wait(c->sched); + int ms; + + if (orig_chan_name && strcasecmp(orig_chan_name, c->name)) { + ast_stopstream(c); + err = 1; + break; + } + + ms = ast_sched_wait(c->sched); + if (ms < 0 && !c->timingfunc) { ast_stopstream(c); break; @@ -1087,7 +1155,7 @@ static int waitstream_core(struct ast_channel *c, const char *breakon, ast_clear_flag(c, AST_FLAG_END_DTMF_ONLY); - return (c->_softhangup ? -1 : 0); + return (err || c->_softhangup) ? -1 : 0; } int ast_waitstream_fr(struct ast_channel *c, const char *breakon, const char *forward, const char *rewind, int ms) |