diff --git a/configs/samples/cel.conf.sample b/configs/samples/cel.conf.sample index 755fcd3eda..f6f90cf108 100644 --- a/configs/samples/cel.conf.sample +++ b/configs/samples/cel.conf.sample @@ -59,6 +59,12 @@ apps=dial,park ; USER_DEFINED -- Triggered from the dialplan, and has a name given by the ; user ; LOCAL_OPTIMIZE -- A local channel pair is optimizing away. +; STREAM_BEGIN -- A stream started playing: it can be a standalone sound file +; playing back, or a music-on-hold class started +; STREAM_END -- A playing stream ended +; DTMF -- A DTMF digit was processed: these events are dispatched at the +; end, when the button is released and the duration is present in +; the extra field ; ; Default value: none ; (Track no events) diff --git a/include/asterisk/cel.h b/include/asterisk/cel.h index 7444938ce6..8a1e8b884f 100644 --- a/include/asterisk/cel.h +++ b/include/asterisk/cel.h @@ -77,6 +77,12 @@ enum ast_cel_event_type { AST_CEL_LOCAL_OPTIMIZE = 17, /*! \brief A local channel optimization has begun */ AST_CEL_LOCAL_OPTIMIZE_BEGIN = 18, + /*! \brief A stream started */ + AST_CEL_STREAM_BEGIN = 19, + /*! \brief A stream ended */ + AST_CEL_STREAM_END = 20, + /*! \brief A DTMF digit was processed */ + AST_CEL_DTMF = 21, }; /*! diff --git a/main/cel.c b/main/cel.c index 26440f4a4b..4e99f63242 100644 --- a/main/cel.c +++ b/main/cel.c @@ -118,6 +118,9 @@ + + + @@ -338,6 +341,9 @@ static const char * const cel_event_types[CEL_MAX_EVENT_IDS] = { [AST_CEL_LINKEDID_END] = "LINKEDID_END", [AST_CEL_LOCAL_OPTIMIZE] = "LOCAL_OPTIMIZE", [AST_CEL_LOCAL_OPTIMIZE_BEGIN] = "LOCAL_OPTIMIZE_BEGIN", + [AST_CEL_STREAM_BEGIN] = "STREAM_BEGIN", + [AST_CEL_STREAM_END] = "STREAM_END", + [AST_CEL_DTMF] = "DTMF", }; struct cel_backend { @@ -849,12 +855,8 @@ int ast_cel_fill_record(const struct ast_event *e, struct ast_cel_event_record * r->event_time.tv_usec = ast_event_get_ie_uint(e, AST_EVENT_IE_CEL_EVENT_TIME_USEC); r->event_name = ast_cel_get_type_name(r->event_type); - if (r->event_type == AST_CEL_USER_DEFINED) { - r->user_defined_name = ast_event_get_ie_str(e, AST_EVENT_IE_CEL_USEREVENT_NAME); - } else { - r->user_defined_name = ""; - } + r->user_defined_name= S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_USEREVENT_NAME), ""); r->caller_id_name = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_CIDNAME), ""); r->caller_id_num = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_CIDNUM), ""); r->caller_id_ani = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_CIDANI), ""); @@ -1282,6 +1284,8 @@ static void cel_generic_cb( switch (event_type) { case AST_CEL_USER_DEFINED: + case AST_CEL_DTMF: + case AST_CEL_STREAM_BEGIN: { const char *event = ast_json_string_get(ast_json_object_get(event_details, "event")); struct ast_json *extra = ast_json_object_get(event_details, "extra"); @@ -1289,6 +1293,13 @@ static void cel_generic_cb( event, extra, NULL); break; } + case AST_CEL_STREAM_END: + { + const char *event = ast_json_string_get(ast_json_object_get(event_details, "event")); + cel_report_event(obj->snapshot, event_type, stasis_message_timestamp(message), + event, NULL, NULL); + break; + } default: ast_log(LOG_ERROR, "Unhandled %s event blob\n", ast_cel_get_type_name(event_type)); break; diff --git a/main/channel.c b/main/channel.c index 5513934d07..89b2867960 100644 --- a/main/channel.c +++ b/main/channel.c @@ -42,6 +42,7 @@ #include "asterisk/mod_format.h" #include "asterisk/sched.h" #include "asterisk/channel.h" +#include "asterisk/cel.h" #include "asterisk/musiconhold.h" #include "asterisk/say.h" #include "asterisk/file.h" @@ -3343,34 +3344,45 @@ static const char *dtmf_direction_to_string(enum DtmfDirection direction) 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); + RAII_VAR(struct ast_json *, channel_blob, NULL, ast_json_unref); char digit_str[] = { digit, '\0' }; - blob = ast_json_pack("{ s: s, s: s }", + channel_blob = ast_json_pack("{ s: s, s: s }", "digit", digit_str, "direction", dtmf_direction_to_string(direction)); - if (!blob) { - return; - } - ast_channel_publish_blob(chan, ast_channel_dtmf_begin_type(), blob); + if (channel_blob) { + ast_channel_publish_blob(chan, ast_channel_dtmf_begin_type(), channel_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); + RAII_VAR(struct ast_json *, channel_blob, NULL, ast_json_unref); + RAII_VAR(struct ast_json *, cel_blob, NULL, ast_json_unref); char digit_str[] = { digit, '\0' }; - blob = ast_json_pack("{ s: s, s: s, s: I }", + channel_blob = ast_json_pack("{ s: s, s: s, s: I }", "digit", digit_str, "direction", dtmf_direction_to_string(direction), "duration_ms", (ast_json_int_t)duration_ms); - if (!blob) { - return; + + if (channel_blob) { + ast_channel_publish_blob(chan, ast_channel_dtmf_end_type(), channel_blob); } - ast_channel_publish_blob(chan, ast_channel_dtmf_end_type(), blob); + cel_blob = ast_json_pack("{ s: s, s: { s: s, s: I }}", + "event", dtmf_direction_to_string(direction), + "extra", + "digit", digit_str, + "duration_ms", (ast_json_int_t)duration_ms); + + if (cel_blob) { + ast_cel_publish_event(chan, AST_CEL_DTMF, cel_blob); + } else { + ast_log(LOG_WARNING, "Unable to build extradata for DTMF CEL event on channel %s", ast_channel_name(chan)); + } } static void send_flash_event(struct ast_channel *chan) diff --git a/main/file.c b/main/file.c index 039e33b19a..eb45911d54 100644 --- a/main/file.c +++ b/main/file.c @@ -39,6 +39,7 @@ #include "asterisk/mod_format.h" #include "asterisk/cli.h" #include "asterisk/channel.h" +#include "asterisk/cel.h" #include "asterisk/sched.h" #include "asterisk/translate.h" #include "asterisk/utils.h" @@ -221,15 +222,25 @@ int ast_file_fdtemp(const char *path, char **filename, const char *template_name int ast_stopstream(struct ast_channel *tmp) { + struct ast_json * cel_event = NULL; + ast_channel_lock(tmp); /* Stop a running stream if there is one */ if (ast_channel_stream(tmp)) { ast_closestream(ast_channel_stream(tmp)); ast_channel_stream_set(tmp, NULL); + + cel_event = ast_json_pack("{ s: s }", "event", "FILE_STREAM_END"); + if (cel_event) { + ast_cel_publish_event(tmp, AST_CEL_STREAM_END, cel_event); + } + if (ast_channel_oldwriteformat(tmp) && ast_set_write_format(tmp, ast_channel_oldwriteformat(tmp))) ast_log(LOG_WARNING, "Unable to restore format back to %s\n", ast_format_get_name(ast_channel_oldwriteformat(tmp))); } + ast_json_unref(cel_event); + /* Stop the video stream too */ if (ast_channel_vstream(tmp) != NULL) { ast_closestream(ast_channel_vstream(tmp)); @@ -1301,6 +1312,7 @@ int ast_file_read_dirs(const char *dir_name, ast_file_on_file on_file, void *obj int ast_streamfile(struct ast_channel *chan, const char *filename, const char *preflang) { + struct ast_json * cel_event = NULL; struct ast_filestream *fs = NULL; struct ast_filestream *vfs = NULL; off_t pos; @@ -1367,6 +1379,20 @@ int ast_streamfile(struct ast_channel *chan, const char *filename, if (!res && vfs) res = ast_playstream(vfs); + cel_event = ast_json_pack("{ s: s, s: {s: s, s: s, s: s}}", + "event", "FILE_STREAM_BEGIN", + "extra", + "sound", tmp_filename, + "format", ast_format_get_name(ast_channel_writeformat(chan)), + "language", preflang ? preflang : "default" + ); + if (cel_event) { + ast_cel_publish_event(chan, AST_CEL_STREAM_BEGIN, cel_event); + } else { + ast_log(LOG_WARNING, "Unable to build extradata for sound file STREAM_BEGIN event on channel %s", ast_channel_name(chan)); + } + ast_json_unref(cel_event); + if (VERBOSITY_ATLEAST(3)) { ast_channel_lock(chan); ast_verb(3, "<%s> Playing '%s.%s' (language '%s')\n", ast_channel_name(chan), tmp_filename, ast_format_get_name(ast_channel_writeformat(chan)), preflang ? preflang : "default"); diff --git a/res/res_musiconhold.c b/res/res_musiconhold.c index b53c7e29ae..e57a238129 100644 --- a/res/res_musiconhold.c +++ b/res/res_musiconhold.c @@ -54,6 +54,7 @@ #include "asterisk/lock.h" #include "asterisk/file.h" #include "asterisk/channel.h" +#include "asterisk/cel.h" #include "asterisk/pbx.h" #include "asterisk/app.h" #include "asterisk/module.h" @@ -253,10 +254,23 @@ static void moh_post_start(struct ast_channel *chan, const char *moh_class_name) { struct stasis_message *message; struct ast_json *json_object; + struct ast_json *cel_event; ast_verb(3, "Started music on hold, class '%s', on channel '%s'\n", moh_class_name, ast_channel_name(chan)); + cel_event = ast_json_pack("{ s: s, s: {s: s }}", + "event", "MOH_STREAM_BEGIN", + "extra", + "class", moh_class_name + ); + if (cel_event) { + ast_cel_publish_event(chan, AST_CEL_STREAM_BEGIN, cel_event); + } else { + ast_log(LOG_WARNING, "Unable to build extradata for music on hold STREAM_BEGIN event on channel %s", ast_channel_name(chan)); + } + ast_json_unref(cel_event); + json_object = ast_json_pack("{s: s}", "class", moh_class_name); if (!json_object) { return; @@ -277,9 +291,16 @@ static void moh_post_start(struct ast_channel *chan, const char *moh_class_name) static void moh_post_stop(struct ast_channel *chan) { struct stasis_message *message; + struct ast_json *cel_event; ast_verb(3, "Stopped music on hold on %s\n", ast_channel_name(chan)); + cel_event = ast_json_pack("{ s: s }", "event", "MOH_STREAM_END"); + if (cel_event) { + ast_cel_publish_event(chan, AST_CEL_STREAM_END, cel_event); + } + ast_json_unref(cel_event); + message = ast_channel_blob_create_from_cache(ast_channel_uniqueid(chan), ast_channel_moh_stop_type(), NULL); if (message) {