aboutsummaryrefslogtreecommitdiffstats
path: root/main/file.c
diff options
context:
space:
mode:
authorrussell <russell@f38db490-d61c-443f-a65b-d21fe96a405b>2007-09-05 20:58:19 +0000
committerrussell <russell@f38db490-d61c-443f-a65b-d21fe96a405b>2007-09-05 20:58:19 +0000
commit300442eaee26a2691722fcd134462e9ebbc51374 (patch)
treea7f23b0e5e3f8d490abe51d42907b7b86adf7c21 /main/file.c
parent8ad2435cee5ea871a18303ae22ccf6ab0f4cdb07 (diff)
Merged revisions 81599 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r81599 | russell | 2007-09-05 15:53:41 -0500 (Wed, 05 Sep 2007) | 11 lines Fix an issue that can occur when you do an attended transfer to parking. If you complete the transfer before the announcement of the parking spot finishes, then the channel being parked will hear the remainder of the announcement. These changes make it so that will not happen anymore. Basically, res_features sets a flag on the channel is playing the announcement to so that the file streaming core knows that it needs to watch out for a channel masquerade, and if it occurs, to abort the announcement. (closes BE-182) ........ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@81600 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'main/file.c')
-rw-r--r--main/file.c124
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)