From 2450722f52401b8537e9c0ffb1192f38b7dd146d Mon Sep 17 00:00:00 2001 From: "David M. Lee" Date: Mon, 15 Apr 2013 16:22:03 +0000 Subject: DTMF events are now published on a channel's stasis_topic. AMI was refactored to use these events rather than producing the events directly in channel.c. Finally, the code was added to app_stasis to produce DTMF events on the WebSocket. The AMI events are completely backward compatible, including sending events on transmitted DTMF, and sending DTMF start events. The Stasis-HTTP events are somewhat simplified. Since DTMF start and DTMF send events are generally less useful, Stasis-HTTP will only send events on received DTMF end. (closes issue ASTERISK-21282) (closes issue ASTERISK-21359) Review: https://reviewboard.asterisk.org/r/2439 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@385734 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- main/channel.c | 92 ++++++++++++++++++++++++++++--------------------- main/manager_channels.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 143 insertions(+), 41 deletions(-) (limited to 'main') diff --git a/main/channel.c b/main/channel.c index a9bcf4481..415af35e2 100644 --- a/main/channel.c +++ b/main/channel.c @@ -3714,42 +3714,56 @@ int ast_waitfordigit_full(struct ast_channel *c, int timeout_ms, int audiofd, in return 0; /* Time is up */ } -static void send_dtmf_event(struct ast_channel *chan, const char *direction, const char digit, const char *begin, const char *end) +enum DtmfDirection { + DTMF_RECEIVED, + DTMF_SENT +}; + +static const char *dtmf_direction_to_string(enum DtmfDirection direction) { - /*** DOCUMENTATION - - Raised when a DTMF digit has started or ended on a channel. - - - - - - - - - - - - - - - - - - - - - - ***/ - ast_manager_event(chan, EVENT_FLAG_DTMF, - "DTMF", - "Channel: %s\r\n" - "Uniqueid: %s\r\n" - "Digit: %c\r\n" - "Direction: %s\r\n" - "Begin: %s\r\n" - "End: %s\r\n", - ast_channel_name(chan), ast_channel_uniqueid(chan), digit, direction, begin, end); + switch (direction) { + case DTMF_RECEIVED: + return "Received"; + case DTMF_SENT: + return "Sent"; + } + + return "?"; +} + +static void send_dtmf_begin_event(struct ast_channel *chan, + enum DtmfDirection direction, const char digit) +{ + RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref); + char digit_str[] = { digit, '\0' }; + + blob = ast_json_pack("{ s: s, s: s, s: s }", + "type", "dtmf_begin", + "digit", digit_str, + "direction", dtmf_direction_to_string(direction)); + if (!blob) { + return; + } + + publish_channel_blob(chan, blob); +} + +static void send_dtmf_end_event(struct ast_channel *chan, + enum DtmfDirection direction, const char digit, long duration_ms) +{ + RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref); + char digit_str[] = { digit, '\0' }; + + blob = ast_json_pack("{ s: s, s: s, s: s, s: i }", + "type", "dtmf_end", + "digit", digit_str, + "direction", dtmf_direction_to_string(direction), + "duration_ms", duration_ms); + if (!blob) { + return; + } + + publish_channel_blob(chan, blob); } static void ast_read_generator_actions(struct ast_channel *chan, struct ast_frame *f) @@ -4104,7 +4118,7 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio) } break; case AST_FRAME_DTMF_END: - send_dtmf_event(chan, "Received", f->subclass.integer, "No", "Yes"); + send_dtmf_end_event(chan, DTMF_RECEIVED, f->subclass.integer, f->len); ast_log(LOG_DTMF, "DTMF end '%c' received on %s, duration %ld ms\n", f->subclass.integer, ast_channel_name(chan), f->len); /* Queue it up if DTMF is deferred, or if DTMF emulation is forced. */ if (ast_test_flag(ast_channel_flags(chan), AST_FLAG_DEFER_DTMF) || ast_test_flag(ast_channel_flags(chan), AST_FLAG_EMULATE_DTMF)) { @@ -4190,7 +4204,7 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio) } break; case AST_FRAME_DTMF_BEGIN: - send_dtmf_event(chan, "Received", f->subclass.integer, "Yes", "No"); + send_dtmf_begin_event(chan, DTMF_RECEIVED, f->subclass.integer); ast_log(LOG_DTMF, "DTMF begin '%c' received on %s\n", f->subclass.integer, ast_channel_name(chan)); if (ast_test_flag(ast_channel_flags(chan), AST_FLAG_DEFER_DTMF | AST_FLAG_END_DTMF_ONLY | AST_FLAG_EMULATE_DTMF) || (!ast_tvzero(*ast_channel_dtmf_tv(chan)) && @@ -5042,7 +5056,7 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr) if (old_frame != fr) f = fr; } - send_dtmf_event(chan, "Sent", fr->subclass.integer, "Yes", "No"); + send_dtmf_begin_event(chan, DTMF_SENT, fr->subclass.integer); ast_clear_flag(ast_channel_flags(chan), AST_FLAG_BLOCKING); ast_channel_unlock(chan); res = ast_senddigit_begin(chan, fr->subclass.integer); @@ -5058,7 +5072,7 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr) ast_frfree(new_frame); } } - send_dtmf_event(chan, "Sent", fr->subclass.integer, "No", "Yes"); + send_dtmf_end_event(chan, DTMF_SENT, fr->subclass.integer, fr->len); ast_clear_flag(ast_channel_flags(chan), AST_FLAG_BLOCKING); ast_channel_unlock(chan); res = ast_senddigit_end(chan, fr->subclass.integer, fr->len); diff --git a/main/manager_channels.c b/main/manager_channels.c index ce306e4bb..03cf71fd8 100644 --- a/main/manager_channels.c +++ b/main/manager_channels.c @@ -275,8 +275,8 @@ struct ast_str *ast_manager_build_channel_state_string_suffix( struct ast_var_t *var; AST_LIST_TRAVERSE(snapshot->manager_vars, var, entries) { ast_str_append(&out, 0, "ChanVariable%s: %s=%s\r\n", - suffix, - var->name, var->value); + suffix, + var->name, var->value); } } @@ -657,6 +657,90 @@ static void channel_hangup_request(struct ast_channel_blob *obj) ast_str_buffer(extra)); } +static void channel_dtmf_begin(struct ast_channel_blob *obj) +{ + RAII_VAR(struct ast_str *, channel_event_string, NULL, ast_free); + const char *digit = + ast_json_string_get(ast_json_object_get(obj->blob, "digit")); + const char *direction = + ast_json_string_get(ast_json_object_get(obj->blob, "direction")); + + channel_event_string = manager_build_channel_state_string(obj->snapshot); + + if (!channel_event_string) { + return; + } + + /*** DOCUMENTATION + + Raised when a DTMF digit has started on a channel. + + + + DTMF digit received or transmitted (0-9, A-E, # or * + + + + + + + + + + ***/ + manager_event(EVENT_FLAG_DTMF, "DTMFBegin", + "%s" + "Digit: %s\r\n" + "Direction: %s\r\n", + ast_str_buffer(channel_event_string), + digit, direction); +} + +static void channel_dtmf_end(struct ast_channel_blob *obj) +{ + RAII_VAR(struct ast_str *, channel_event_string, NULL, ast_free); + const char *digit = + ast_json_string_get(ast_json_object_get(obj->blob, "digit")); + const char *direction = + ast_json_string_get(ast_json_object_get(obj->blob, "direction")); + long duration_ms = + ast_json_integer_get(ast_json_object_get(obj->blob, "duration_ms")); + + channel_event_string = manager_build_channel_state_string(obj->snapshot); + + if (!channel_event_string) { + return; + } + + /*** DOCUMENTATION + + Raised when a DTMF digit has ended on a channel. + + + + DTMF digit received or transmitted (0-9, A-E, # or * + + + Duration (in milliseconds) DTMF was sent/received + + + + + + + + + + ***/ + manager_event(EVENT_FLAG_DTMF, "DTMFEnd", + "%s" + "Digit: %s\r\n" + "DurationMs: %ld\r\n" + "Direction: %s\r\n", + ast_str_buffer(channel_event_string), + digit, duration_ms, direction); +} + /*! * \brief Callback processing messages on the channel topic. */ @@ -672,6 +756,10 @@ static void channel_blob_cb(void *data, struct stasis_subscription *sub, channel_userevent(obj); } else if (strcmp("hangup_request", ast_channel_blob_json_type(obj)) == 0) { channel_hangup_request(obj); + } else if (strcmp("dtmf_begin", ast_channel_blob_json_type(obj)) == 0) { + channel_dtmf_begin(obj); + } else if (strcmp("dtmf_end", ast_channel_blob_json_type(obj)) == 0) { + channel_dtmf_end(obj); } } -- cgit v1.2.3