Merged revisions 43695 via svnmerge from
authorJoshua Colp <jcolp@digium.com>
Tue, 26 Sep 2006 20:11:44 +0000 (20:11 +0000)
committerJoshua Colp <jcolp@digium.com>
Tue, 26 Sep 2006 20:11:44 +0000 (20:11 +0000)
https://origsvn.digium.com/svn/asterisk/branches/1.4

........
r43695 | file | 2006-09-26 16:09:41 -0400 (Tue, 26 Sep 2006) | 2 lines

Slight overhaul of the whisper support. 1. We need to duplicate the frame from ast_translate 2. We need to ensure we always have signed linear coming in for signed linear combining. 3. We need to ensure we are always feeding signed linear out. 4. Properly store and restore write format when beeping on the channel we are whispering on. 5. Properly discontinue the stream on the channel for the beep. (issue #8019 reported by timkelly1980)

........

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@43696 65c4cc65-6c06-0410-ace0-fbb531ad65f3

apps/app_chanspy.c
main/channel.c
main/slinfactory.c

index 01adbac..e001b4b 100644 (file)
@@ -277,8 +277,10 @@ static int channel_spy(struct ast_channel *chan, struct ast_channel *spyee, int
 
        if (ast_test_flag(flags, OPTION_WHISPER)) {
                struct ast_filestream *beepstream;
 
        if (ast_test_flag(flags, OPTION_WHISPER)) {
                struct ast_filestream *beepstream;
+               int old_write_format = 0;
 
                ast_channel_whisper_start(csth.spy.chan);
 
                ast_channel_whisper_start(csth.spy.chan);
+               old_write_format = chan->writeformat;
                if ((beepstream = ast_openstream_full(chan, "beep", chan->language, 1))) {
                        struct ast_frame *f;
 
                if ((beepstream = ast_openstream_full(chan, "beep", chan->language, 1))) {
                        struct ast_frame *f;
 
@@ -288,7 +290,10 @@ static int channel_spy(struct ast_channel *chan, struct ast_channel *spyee, int
                        }
 
                        ast_closestream(beepstream);
                        }
 
                        ast_closestream(beepstream);
+                       chan->stream = NULL;
                }
                }
+               if (old_write_format)
+                       ast_set_write_format(chan, old_write_format);
        }
 
        if (ast_test_flag(flags, OPTION_PRIVATE))
        }
 
        if (ast_test_flag(flags, OPTION_PRIVATE))
index 421bbee..27a2ef8 100644 (file)
@@ -84,6 +84,7 @@ struct ast_channel_whisper_buffer {
        ast_mutex_t lock;
        struct ast_slinfactory sf;
        unsigned int original_format;
        ast_mutex_t lock;
        struct ast_slinfactory sf;
        unsigned int original_format;
+       struct ast_trans_pvt *path;
 };
 
 /* uncomment if you have problems with 'monitoring' synchronized files */
 };
 
 /* uncomment if you have problems with 'monitoring' synchronized files */
@@ -2506,66 +2507,93 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr)
                if (chan->tech->write == NULL)
                        break;  /*! \todo XXX should return 0 maybe ? */
 
                if (chan->tech->write == NULL)
                        break;  /*! \todo XXX should return 0 maybe ? */
 
-               /* Bypass translator if we're writing format in the raw write format.  This
-                  allows mixing of native / non-native formats */
-               if (fr->subclass == chan->rawwriteformat)
-                       f = fr;
-               else
-                       f = (chan->writetrans) ? ast_translate(chan->writetrans, fr, 0) : fr;
+               /* If someone is whispering on this channel then we must ensure that we are always getting signed linear frames */
+               if (ast_test_flag(chan, AST_FLAG_WHISPER)) {
+                       if (fr->subclass == AST_FORMAT_SLINEAR)
+                               f = fr;
+                       else {
+                               ast_mutex_lock(&chan->whisper->lock);
+                               if (chan->writeformat != AST_FORMAT_SLINEAR) {
+                                       /* Rebuild the translation path and set our write format back to signed linear */
+                                       chan->whisper->original_format = chan->writeformat;
+                                       ast_set_write_format(chan, AST_FORMAT_SLINEAR);
+                                       if (chan->whisper->path)
+                                               ast_translator_free_path(chan->whisper->path);
+                                       chan->whisper->path = ast_translator_build_path(AST_FORMAT_SLINEAR, chan->whisper->original_format);
+                               }
+                               /* Translate frame using the above translation path */
+                               f = (chan->whisper->path) ? ast_translate(chan->whisper->path, fr, 0) : fr;
+                               ast_mutex_unlock(&chan->whisper->lock);
+                       }
+               } else {
+                       /* If the frame is in the raw write format, then it's easy... just use the frame - otherwise we will have to translate */
+                       if (fr->subclass == chan->rawwriteformat)
+                               f = fr;
+                       else
+                               f = (chan->writetrans) ? ast_translate(chan->writetrans, fr, 0) : fr;
+               }
+
+               /* If we have no frame of audio, then we have to bail out */
                if (f == NULL) {
                        res = 0;
                if (f == NULL) {
                        res = 0;
-               } else {
-                       if (chan->spies)
-                               queue_frame_to_spies(chan, f, SPY_WRITE);
+                       break;
+               }
 
 
-                       if (chan->monitor && chan->monitor->write_stream) {
-                               /* XXX must explain this code */
+               /* If spies are on the channel then queue the frame out to them */
+               if (chan->spies)
+                       queue_frame_to_spies(chan, f, SPY_WRITE);
+
+               /* If Monitor is running on this channel, then we have to write frames out there too */
+               if (chan->monitor && chan->monitor->write_stream) {
+                       /* XXX must explain this code */
 #ifndef MONITOR_CONSTANT_DELAY
 #ifndef MONITOR_CONSTANT_DELAY
-                               int jump = chan->insmpl - chan->outsmpl - 4 * f->samples;
-                               if (jump >= 0) {
-                                       if (ast_seekstream(chan->monitor->write_stream, jump + f->samples, SEEK_FORCECUR) == -1)
-                                               ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n");
-                                       chan->outsmpl += jump + 4 * f->samples;
-                               } else
-                                       chan->outsmpl += f->samples;
+                       int jump = chan->insmpl - chan->outsmpl - 4 * f->samples;
+                       if (jump >= 0) {
+                               if (ast_seekstream(chan->monitor->write_stream, jump + f->samples, SEEK_FORCECUR) == -1)
+                                       ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n");
+                               chan->outsmpl += jump + 4 * f->samples;
+                       } else
+                               chan->outsmpl += f->samples;
 #else
 #else
-                               int jump = chan->insmpl - chan->outsmpl;
-                               if (jump - MONITOR_DELAY >= 0) {
-                                       if (ast_seekstream(chan->monitor->write_stream, jump - f->samples, SEEK_FORCECUR) == -1)
-                                               ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n");
-                                       chan->outsmpl += jump;
-                               } else
-                                       chan->outsmpl += f->samples;
+                       int jump = chan->insmpl - chan->outsmpl;
+                       if (jump - MONITOR_DELAY >= 0) {
+                               if (ast_seekstream(chan->monitor->write_stream, jump - f->samples, SEEK_FORCECUR) == -1)
+                                       ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n");
+                               chan->outsmpl += jump;
+                       } else
+                               chan->outsmpl += f->samples;
 #endif
 #endif
-                               if (chan->monitor->state == AST_MONITOR_RUNNING) {
-                                       if (ast_writestream(chan->monitor->write_stream, f) < 0)
-                                               ast_log(LOG_WARNING, "Failed to write data to channel monitor write stream\n");
-                               }
+                       if (chan->monitor->state == AST_MONITOR_RUNNING) {
+                               if (ast_writestream(chan->monitor->write_stream, f) < 0)
+                                       ast_log(LOG_WARNING, "Failed to write data to channel monitor write stream\n");
                        }
                        }
+               }
 
 
-                       if (ast_test_flag(chan, AST_FLAG_WHISPER)) {
-                               /* frame is assumed to be in SLINEAR, since that is
-                                  required for whisper mode */
-                               ast_frame_adjust_volume(f, -2);
-                               if (ast_slinfactory_available(&chan->whisper->sf) >= f->samples) {
-                                       short buf[f->samples];
-                                       struct ast_frame whisper = {
-                                               .frametype = AST_FRAME_VOICE,
-                                               .subclass = AST_FORMAT_SLINEAR,
-                                               .data = buf,
-                                               .datalen = sizeof(buf),
-                                               .samples = f->samples,
-                                       };
-
-                                       ast_mutex_lock(&chan->whisper->lock);
-                                       if (ast_slinfactory_read(&chan->whisper->sf, buf, f->samples))
-                                               ast_frame_slinear_sum(f, &whisper);
-                                       ast_mutex_unlock(&chan->whisper->lock);
-                               }
+               /* Finally the good part! Write this out to the channel */
+               if (ast_test_flag(chan, AST_FLAG_WHISPER)) {
+                       /* frame is assumed to be in SLINEAR, since that is
+                          required for whisper mode */
+                       ast_frame_adjust_volume(f, -2);
+                       if (ast_slinfactory_available(&chan->whisper->sf) >= f->samples) {
+                               short buf[f->samples];
+                               struct ast_frame whisper = {
+                                       .frametype = AST_FRAME_VOICE,
+                                       .subclass = AST_FORMAT_SLINEAR,
+                                       .data = buf,
+                                       .datalen = sizeof(buf),
+                                       .samples = f->samples,
+                               };
+                               
+                               ast_mutex_lock(&chan->whisper->lock);
+                               if (ast_slinfactory_read(&chan->whisper->sf, buf, f->samples))
+                                       ast_frame_slinear_sum(f, &whisper);
+                               ast_mutex_unlock(&chan->whisper->lock);
                        }
                        }
-
-                       res = chan->tech->write(chan, f);
+                       /* and now put it through the regular translator */
+                       f = (chan->writetrans) ? ast_translate(chan->writetrans, f, 0) : f;
                }
                }
+               
+               res = chan->tech->write(chan, f);
                break;
        case AST_FRAME_NULL:
        case AST_FRAME_IAX:
                break;
        case AST_FRAME_NULL:
        case AST_FRAME_IAX:
@@ -4606,7 +4634,6 @@ int ast_channel_whisper_start(struct ast_channel *chan)
 
        ast_mutex_init(&chan->whisper->lock);
        ast_slinfactory_init(&chan->whisper->sf);
 
        ast_mutex_init(&chan->whisper->lock);
        ast_slinfactory_init(&chan->whisper->sf);
-       chan->whisper->original_format = ast_set_write_format(chan, AST_FORMAT_SLINEAR);
        ast_set_flag(chan, AST_FLAG_WHISPER);
 
        return 0;
        ast_set_flag(chan, AST_FLAG_WHISPER);
 
        return 0;
@@ -4630,7 +4657,10 @@ void ast_channel_whisper_stop(struct ast_channel *chan)
                return;
 
        ast_clear_flag(chan, AST_FLAG_WHISPER);
                return;
 
        ast_clear_flag(chan, AST_FLAG_WHISPER);
-       ast_set_write_format(chan, chan->whisper->original_format);
+       if (chan->whisper->path)
+               ast_translator_free_path(chan->whisper->path);
+       if (chan->whisper->original_format && chan->writeformat == AST_FORMAT_SLINEAR)
+               ast_set_write_format(chan, chan->whisper->original_format);
        ast_slinfactory_destroy(&chan->whisper->sf);
        ast_mutex_destroy(&chan->whisper->lock);
        free(chan->whisper);
        ast_slinfactory_destroy(&chan->whisper->sf);
        ast_mutex_destroy(&chan->whisper->lock);
        free(chan->whisper);
index 0520dbc..a07798b 100644 (file)
@@ -74,12 +74,7 @@ int ast_slinfactory_feed(struct ast_slinfactory *sf, struct ast_frame *f)
                }
        }
 
                }
        }
 
-       if (sf->trans)
-               frame = ast_translate(sf->trans, f, 0);
-       else
-               frame = ast_frdup(f);
-
-       if (!frame)
+       if (!(frame = ast_frdup( (sf->trans) ? ast_translate(sf->trans, f, 0) : f )))
                return 0;
 
        x = 0;
                return 0;
 
        x = 0;