diff options
author | David M. Lee <dlee@digium.com> | 2013-04-15 16:22:03 +0000 |
---|---|---|
committer | David M. Lee <dlee@digium.com> | 2013-04-15 16:22:03 +0000 |
commit | 2450722f52401b8537e9c0ffb1192f38b7dd146d (patch) | |
tree | 2a798888a6601082b150a2eada805b0b82aadaa4 /main | |
parent | c6cf12408edc133c229b323a9039e04f3c12c248 (diff) |
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
Diffstat (limited to 'main')
-rw-r--r-- | main/channel.c | 92 | ||||
-rw-r--r-- | main/manager_channels.c | 92 |
2 files changed, 143 insertions, 41 deletions
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 - <managerEventInstance> - <synopsis>Raised when a DTMF digit has started or ended on a channel.</synopsis> - <syntax> - <parameter name="Direction"> - <enumlist> - <enum name="Received"/> - <enum name="Sent"/> - </enumlist> - </parameter> - <parameter name="Begin"> - <enumlist> - <enum name="Yes"/> - <enum name="No"/> - </enumlist> - </parameter> - <parameter name="End"> - <enumlist> - <enum name="Yes"/> - <enum name="No"/> - </enumlist> - </parameter> - </syntax> - </managerEventInstance> - ***/ - 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 + <managerEventInstance> + <synopsis>Raised when a DTMF digit has started on a channel.</synopsis> + <syntax> + <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" /> + <parameter name="Digit"> + <para>DTMF digit received or transmitted (0-9, A-E, # or *</para> + </parameter> + <parameter name="Direction"> + <enumlist> + <enum name="Received"/> + <enum name="Sent"/> + </enumlist> + </parameter> + </syntax> + </managerEventInstance> + ***/ + 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 + <managerEventInstance> + <synopsis>Raised when a DTMF digit has ended on a channel.</synopsis> + <syntax> + <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" /> + <parameter name="Digit"> + <para>DTMF digit received or transmitted (0-9, A-E, # or *</para> + </parameter> + <parameter name="DurationMs"> + <para>Duration (in milliseconds) DTMF was sent/received</para> + </parameter> + <parameter name="Direction"> + <enumlist> + <enum name="Received"/> + <enum name="Sent"/> + </enumlist> + </parameter> + </syntax> + </managerEventInstance> + ***/ + 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); } } |