aboutsummaryrefslogtreecommitdiffstats
path: root/main
diff options
context:
space:
mode:
authordvossel <dvossel@f38db490-d61c-443f-a65b-d21fe96a405b>2009-08-26 16:36:42 +0000
committerdvossel <dvossel@f38db490-d61c-443f-a65b-d21fe96a405b>2009-08-26 16:36:42 +0000
commitb43a76769eadd05423677aa14298643ec6d387cb (patch)
treedd2b65cd298c94c296f95915f2bab7abf474999b /main
parent3518843ecf69d1ddc633db9fb301b414aafd4b37 (diff)
ast_write() ignores ast_audiohook_write() results
In ast_write(), if a channel has a list of audiohooks, those lists are written to and the resulting frame is what ast_write() should continue with. The problem was the returned audiohook frame was not being handled at all, and the original frame passed into it did not contain the mixed audio, so essentially audio was being lost. One result of this was chan_spy's whisper mode no longer worked. To complicate the issue, frames passed into ast_write may either be a single frame, or a list of frames. So, as the list of frames is processed in the audiohook_write, the returned frames had to be added to a new list. (closes issue #15660) Reported by: corruptor Tested by: dvossel git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.4@214194 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'main')
-rw-r--r--main/channel.c27
1 files changed, 25 insertions, 2 deletions
diff --git a/main/channel.c b/main/channel.c
index 5e0dc8d55..3499b99a6 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -2933,13 +2933,36 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr)
}
if (chan->audiohooks) {
- struct ast_frame *new_frame, *cur;
+ struct ast_frame *prev = NULL, *new_frame, *cur, *dup;
+ /* Since ast_audiohook_write may return a new frame, and the cur frame is
+ * an item in a list of frames, create a new list adding each cur frame back to it
+ * regardless if the cur frame changes or not. */
for (cur = f; cur; cur = AST_LIST_NEXT(cur, frame_list)) {
new_frame = ast_audiohook_write_list(chan, chan->audiohooks, AST_AUDIOHOOK_DIRECTION_WRITE, cur);
+
+ /* if this frame is different than cur, preserve the end of the list,
+ * free the old frames, and set cur to be the new frame */
if (new_frame != cur) {
- ast_frfree(new_frame);
+ /* doing an ast_frisolate here seems silly, but we are not guaranteed the new_frame
+ * isn't part of local storage, meaning if ast_audiohook_write is called multiple
+ * times it may override the previous frame we got from it unless we dup it */
+ if ((dup = ast_frisolate(new_frame))) {
+ AST_LIST_NEXT(dup, frame_list) = AST_LIST_NEXT(cur, frame_list);
+ ast_frfree(new_frame);
+ ast_frfree(cur);
+ cur = dup;
+ }
+ }
+
+ /* now, regardless if cur is new or not, add it to the new list,
+ * if the new list has not started, cur will become the first item. */
+ if (prev) {
+ AST_LIST_NEXT(prev, frame_list) = cur;
+ } else {
+ f = cur; /* set f to be the beginning of our new list */
}
+ prev = cur;
}
}