diff --git a/main/channel.c b/main/channel.c index b30bb1de792f333d334aceebc3398ab4bd6236db..6317f6f20caf4b5a8dc2ac257ac4c6470d7b1bb2 100644 --- a/main/channel.c +++ b/main/channel.c @@ -10283,15 +10283,9 @@ int ast_channel_connected_line_macro(struct ast_channel *autoservice_chan, struc ast_party_connected_line_copy(ast_channel_connected(macro_chan), connected); } - ast_channel_start_defer_frames(macro_chan); ast_channel_unlock(macro_chan); retval = ast_app_run_macro(autoservice_chan, macro_chan, macro, macro_args); - - ast_channel_lock(macro_chan); - ast_channel_stop_defer_frames(macro_chan); - ast_channel_unlock(macro_chan); - if (!retval) { struct ast_party_connected_line saved_connected; @@ -10339,15 +10333,9 @@ int ast_channel_redirecting_macro(struct ast_channel *autoservice_chan, struct a ast_party_redirecting_copy(ast_channel_redirecting(macro_chan), redirecting); } - ast_channel_start_defer_frames(macro_chan); ast_channel_unlock(macro_chan); retval = ast_app_run_macro(autoservice_chan, macro_chan, macro, macro_args); - - ast_channel_lock(macro_chan); - ast_channel_stop_defer_frames(macro_chan); - ast_channel_unlock(macro_chan); - if (!retval) { struct ast_party_redirecting saved_redirecting; @@ -10388,15 +10376,9 @@ int ast_channel_connected_line_sub(struct ast_channel *autoservice_chan, struct ast_party_connected_line_copy(ast_channel_connected(sub_chan), connected); } - ast_channel_start_defer_frames(sub_chan); ast_channel_unlock(sub_chan); retval = ast_app_run_sub(autoservice_chan, sub_chan, sub, sub_args, 0); - - ast_channel_lock(sub_chan); - ast_channel_stop_defer_frames(sub_chan); - ast_channel_unlock(sub_chan); - if (!retval) { struct ast_party_connected_line saved_connected; @@ -10437,15 +10419,9 @@ int ast_channel_redirecting_sub(struct ast_channel *autoservice_chan, struct ast ast_party_redirecting_copy(ast_channel_redirecting(sub_chan), redirecting); } - ast_channel_start_defer_frames(sub_chan); ast_channel_unlock(sub_chan); retval = ast_app_run_sub(autoservice_chan, sub_chan, sub, sub_args, 0); - - ast_channel_lock(sub_chan); - ast_channel_stop_defer_frames(sub_chan); - ast_channel_unlock(sub_chan); - if (!retval) { struct ast_party_redirecting saved_redirecting; diff --git a/res/res_agi.c b/res/res_agi.c index 5e047d4c3dce2d5168883560719e8970b1cd31dd..06e8a03e2513e8f9abf362342e9bd5cc7e6ce3c4 100644 --- a/res/res_agi.c +++ b/res/res_agi.c @@ -4091,6 +4091,23 @@ static enum agi_result agi_handle_command(struct ast_channel *chan, AGI *agi, ch return AGI_RESULT_SUCCESS; } +AST_LIST_HEAD_NOLOCK(deferred_frames, ast_frame); + +static void queue_deferred_frames(struct deferred_frames *deferred_frames, + struct ast_channel *chan) +{ + struct ast_frame *f; + + if (!AST_LIST_EMPTY(deferred_frames)) { + ast_channel_lock(chan); + while ((f = AST_LIST_REMOVE_HEAD(deferred_frames, frame_list))) { + ast_queue_frame_head(chan, f); + ast_frfree(f); + } + ast_channel_unlock(chan); + } +} + static enum agi_result run_agi(struct ast_channel *chan, char *request, AGI *agi, int pid, int *status, int dead, int argc, char *argv[]) { struct ast_channel *c; @@ -4109,6 +4126,9 @@ static enum agi_result run_agi(struct ast_channel *chan, char *request, AGI *agi const char *sighup_str; const char *exit_on_hangup_str; int exit_on_hangup; + struct deferred_frames deferred_frames; + + AST_LIST_HEAD_INIT_NOLOCK(&deferred_frames); ast_channel_lock(chan); sighup_str = pbx_builtin_getvar_helper(chan, "AGISIGHUP"); @@ -4170,8 +4190,20 @@ static enum agi_result run_agi(struct ast_channel *chan, char *request, AGI *agi /* Write, ignoring errors */ if (write(agi->audio, f->data.ptr, f->datalen) < 0) { } + ast_frfree(f); + } else if (ast_is_deferrable_frame(f)) { + struct ast_frame *dup_f; + + if ((dup_f = ast_frisolate(f))) { + AST_LIST_INSERT_HEAD(&deferred_frames, dup_f, frame_list); + } + + if (dup_f != f) { + ast_frfree(f); + } + } else { + ast_frfree(f); } - ast_frfree(f); } } else if (outfd > -1) { size_t len = sizeof(buf); @@ -4219,6 +4251,8 @@ static enum agi_result run_agi(struct ast_channel *chan, char *request, AGI *agi buf[buflen - 1] = '\0'; } + queue_deferred_frames(&deferred_frames, chan); + if (agidebug) ast_verbose("<%s>AGI Rx << %s\n", ast_channel_name(chan), buf); cmd_status = agi_handle_command(chan, agi, buf, dead); @@ -4241,6 +4275,8 @@ static enum agi_result run_agi(struct ast_channel *chan, char *request, AGI *agi } } + queue_deferred_frames(&deferred_frames, chan); + if (agi->speech) { ast_speech_destroy(agi->speech); }