diff --git a/src/include/switch_core.h b/src/include/switch_core.h index e6a98fd128..153e582037 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -826,11 +826,23 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_exec(_In_ switch_core_sessio \param session the current session \param app the application's name \param arg application arguments - \warning Has to be called from the session's thread + \param flags pointer to a flags variable to set the applications flags to \return the application's return value */ -SWITCH_DECLARE(switch_status_t) switch_core_session_execute_application(_In_ switch_core_session_t *session, - _In_ const char *app, _In_opt_z_ const char *arg); +SWITCH_DECLARE(switch_status_t) switch_core_session_execute_application_get_flags(_In_ switch_core_session_t *session, + _In_ const char *app, _In_opt_z_ const char *arg, _Out_ int32_t *flags); + +SWITCH_DECLARE(switch_status_t) switch_core_session_get_app_flags(const char *app, int32_t *flags); + +/*! + \brief Execute an application on a session + \param session the current session + \param app the application's name + \param arg application arguments + \return the application's return value +*/ +#define switch_core_session_execute_application(_a, _b, _c) switch_core_session_execute_application_get_flags(_a, _b, _c, NULL) + /*! \brief Run a dialplan and execute an extension \param session the current session diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 34d51fac06..1f7f0db97d 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -943,6 +943,7 @@ typedef enum { CF_MEDIA_BRIDGE_TTL, CF_BYPASS_MEDIA_AFTER_BRIDGE, CF_LEG_HOLDING, + CF_BROADCAST_DROP_MEDIA, /* WARNING: DO NOT ADD ANY FLAGS BELOW THIS LINE */ CF_FLAG_MAX } switch_channel_flag_t; @@ -983,7 +984,8 @@ typedef uint32_t switch_frame_flag_t; typedef enum { SAF_NONE = 0, SAF_SUPPORT_NOMEDIA = (1 << 0), - SAF_ROUTING_EXEC = (1 << 1) + SAF_ROUTING_EXEC = (1 << 1), + SAF_MEDIA_TAP = (1 << 2) } switch_application_flag_enum_t; typedef uint32_t switch_application_flag_t; diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c index 0d7f92cbcc..0b8f50a9b5 100644 --- a/src/mod/applications/mod_dptools/mod_dptools.c +++ b/src/mod/applications/mod_dptools/mod_dptools.c @@ -2999,18 +2999,18 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load) SWITCH_ADD_APP(app_interface, "unbind_meta_app", "Unbind a key from an application", "Unbind a key from an application", dtmf_unbind_function, UNBIND_SYNTAX, SAF_SUPPORT_NOMEDIA); SWITCH_ADD_APP(app_interface, "intercept", "intercept", "intercept", intercept_function, INTERCEPT_SYNTAX, SAF_NONE); - SWITCH_ADD_APP(app_interface, "eavesdrop", "eavesdrop on a uuid", "eavesdrop on a uuid", eavesdrop_function, eavesdrop_SYNTAX, SAF_NONE); - SWITCH_ADD_APP(app_interface, "three_way", "three way call with a uuid", "three way call with a uuid", three_way_function, threeway_SYNTAX, SAF_NONE); + SWITCH_ADD_APP(app_interface, "eavesdrop", "eavesdrop on a uuid", "eavesdrop on a uuid", eavesdrop_function, eavesdrop_SYNTAX, SAF_MEDIA_TAP); + SWITCH_ADD_APP(app_interface, "three_way", "three way call with a uuid", "three way call with a uuid", three_way_function, threeway_SYNTAX, SAF_MEDIA_TAP); SWITCH_ADD_APP(app_interface, "set_user", "Set a User", "Set a User", set_user_function, SET_USER_SYNTAX, SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC ); SWITCH_ADD_APP(app_interface, "stop_dtmf", "stop inband dtmf", "Stop detecting inband dtmf.", stop_dtmf_session_function, "", SAF_NONE); - SWITCH_ADD_APP(app_interface, "start_dtmf", "Detect dtmf", "Detect inband dtmf on the session", dtmf_session_function, "", SAF_NONE); + SWITCH_ADD_APP(app_interface, "start_dtmf", "Detect dtmf", "Detect inband dtmf on the session", dtmf_session_function, "", SAF_MEDIA_TAP); SWITCH_ADD_APP(app_interface, "stop_dtmf_generate", "stop inband dtmf generation", "Stop generating inband dtmf.", stop_dtmf_session_generate_function, "[write]", SAF_NONE); SWITCH_ADD_APP(app_interface, "start_dtmf_generate", "Generate dtmf", "Generate inband dtmf on the session", dtmf_session_generate_function, "", SAF_NONE); SWITCH_ADD_APP(app_interface, "stop_tone_detect", "stop detecting tones", "Stop detecting tones", stop_fax_detect_session_function, "", SAF_NONE); - SWITCH_ADD_APP(app_interface, "fax_detect", "Detect faxes", "Detect fax send tone", fax_detect_session_function, "", SAF_NONE); - SWITCH_ADD_APP(app_interface, "tone_detect", "Detect tones", "Detect tones", tone_detect_session_function, "", SAF_NONE); + SWITCH_ADD_APP(app_interface, "fax_detect", "Detect faxes", "Detect fax send tone", fax_detect_session_function, "", SAF_MEDIA_TAP); + SWITCH_ADD_APP(app_interface, "tone_detect", "Detect tones", "Detect tones", tone_detect_session_function, "", SAF_MEDIA_TAP); SWITCH_ADD_APP(app_interface, "echo", "Echo", "Perform an echo test against the calling channel", echo_function, "", SAF_NONE); SWITCH_ADD_APP(app_interface, "park", "Park", "Park", park_function, "", SAF_NONE); SWITCH_ADD_APP(app_interface, "park_state", "Park State", "Park State", park_state_function, "", SAF_NONE); @@ -3023,14 +3023,14 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load) SWITCH_ADD_APP(app_interface, "play_and_get_digits", "Play and get Digits", "Play and get Digits", play_and_get_digits_function, " ", SAF_NONE); SWITCH_ADD_APP(app_interface, "stop_record_session", "Stop Record Session", STOP_SESS_REC_DESC, stop_record_session_function, "", SAF_NONE); - SWITCH_ADD_APP(app_interface, "record_session", "Record Session", SESS_REC_DESC, record_session_function, " [+]", SAF_NONE); + SWITCH_ADD_APP(app_interface, "record_session", "Record Session", SESS_REC_DESC, record_session_function, " [+]", SAF_MEDIA_TAP); SWITCH_ADD_APP(app_interface, "record", "Record File", "Record a file from the channels input", record_function, " [] [] []", SAF_NONE); SWITCH_ADD_APP(app_interface, "preprocess", "pre-process", "pre-process", preprocess_session_function, "", SAF_NONE); SWITCH_ADD_APP(app_interface, "stop_displace_session", "Stop Displace File", "Stop Displacing to a file", stop_displace_session_function, "", SAF_NONE); SWITCH_ADD_APP(app_interface, "displace_session", "Displace File", DISPLACE_DESC, displace_session_function, " [] [+time_limit_ms]", - SAF_NONE); + SAF_MEDIA_TAP); SWITCH_ADD_APP(app_interface, "speak", "Speak text", SPEAK_DESC, speak_function, "||", SAF_NONE); SWITCH_ADD_APP(app_interface, "clear_speech_cache", "Clear Speech Handle Cache", "Clear Speech Handle Cache", clear_speech_cache_function, "", SAF_NONE); diff --git a/src/switch_core_session.c b/src/switch_core_session.c index 6cf9bad11e..cfdb420adb 100644 --- a/src/switch_core_session.c +++ b/src/switch_core_session.c @@ -865,15 +865,27 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_queue_private_event(switch_c return status; } +#define check_media(session) \ + { \ + if (switch_channel_test_flag(session->channel, CF_BROADCAST_DROP_MEDIA)) { \ + switch_channel_clear_flag(session->channel, CF_BROADCAST_DROP_MEDIA); \ + switch_ivr_nomedia(session->uuid_str, SMF_REBRIDGE); \ + } \ + } \ + SWITCH_DECLARE(uint32_t) switch_core_session_private_event_count(switch_core_session_t *session) { switch_channel_t *channel = switch_core_session_get_channel(session); - + uint32_t count = 0; + if (!switch_channel_test_flag(channel, CF_EVENT_LOCK) && session->private_event_queue) { - return switch_queue_size(session->private_event_queue); + count = switch_queue_size(session->private_event_queue); + if (count == 0) { + check_media(session); + } } - return 0; + return count; } SWITCH_DECLARE(switch_status_t) switch_core_session_dequeue_private_event(switch_core_session_t *session, switch_event_t **event) @@ -889,6 +901,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_dequeue_private_event(switch if (session->private_event_queue) { if ((status = (switch_status_t) switch_queue_trypop(session->private_event_queue, &pop)) == SWITCH_STATUS_SUCCESS) { *event = (switch_event_t *) pop; + } else { + check_media(session); } } @@ -905,6 +919,7 @@ SWITCH_DECLARE(uint32_t) switch_core_session_flush_private_events(switch_core_se while ((status = (switch_status_t) switch_queue_trypop(session->private_event_queue, &pop)) == SWITCH_STATUS_SUCCESS) { x++; } + check_media(session); } return x; @@ -1420,7 +1435,28 @@ SWITCH_DECLARE(switch_app_log_t *) switch_core_session_get_app_log(switch_core_s return session->app_log; } -SWITCH_DECLARE(switch_status_t) switch_core_session_execute_application(switch_core_session_t *session, const char *app, const char *arg) +SWITCH_DECLARE(switch_status_t) switch_core_session_get_app_flags(const char *app, int32_t *flags) +{ + switch_application_interface_t *application_interface; + switch_status_t status = SWITCH_STATUS_FALSE; + + switch_assert(flags); + + *flags = 0; + + if ((application_interface = switch_loadable_module_get_application_interface(app)) == 0) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Application %s\n", app); + } else if (application_interface->flags) { + *flags = application_interface->flags; + status = SWITCH_STATUS_SUCCESS; + } + + return status; + +} + +SWITCH_DECLARE(switch_status_t) switch_core_session_execute_application_get_flags(switch_core_session_t *session, const char *app, + const char *arg, int32_t *flags) { switch_application_interface_t *application_interface; switch_status_t status = SWITCH_STATUS_SUCCESS; @@ -1442,6 +1478,10 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_execute_application(switch_c switch_goto_status(SWITCH_STATUS_FALSE, done); } + if (flags && application_interface->flags) { + *flags = application_interface->flags; + } + if (switch_channel_test_flag(session->channel, CF_PROXY_MODE) && !switch_test_flag(application_interface, SAF_SUPPORT_NOMEDIA)) { switch_ivr_media(session->uuid_str, SMF_NONE); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Application %s Requires media on channel %s!\n", diff --git a/src/switch_ivr_async.c b/src/switch_ivr_async.c index 6d2327d30b..0cf4c17984 100644 --- a/src/switch_ivr_async.c +++ b/src/switch_ivr_async.c @@ -2662,7 +2662,6 @@ SWITCH_DECLARE(uint32_t) switch_ivr_schedule_broadcast(time_t runtime, const cha SWITCH_DECLARE(switch_status_t) switch_ivr_broadcast(const char *uuid, const char *path, switch_media_flag_t flags) { switch_channel_t *channel; - int nomedia; switch_core_session_t *session, *master; switch_event_t *event; switch_core_session_t *other_session = NULL; @@ -2671,7 +2670,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_broadcast(const char *uuid, const cha char *cause = NULL; char *mypath; char *p; - int custom = 0; + int app_flags = 0, nomedia = 1; switch_assert(path); @@ -2689,19 +2688,10 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_broadcast(const char *uuid, const cha *p++ = '\0'; *p++ = '\0'; path = p; - custom++; } - if (!custom && (switch_channel_test_flag(channel, CF_EVENT_PARSE))) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Channel [%s][%s] already broadcasting...broadcast aborted\n", - switch_channel_get_name(channel), path); - switch_core_session_rwunlock(session); - switch_safe_free(mypath); - return SWITCH_STATUS_FALSE; - } - - - if ((nomedia = switch_channel_test_flag(channel, CF_PROXY_MODE))) { + if (switch_channel_test_flag(channel, CF_PROXY_MODE)) { + nomedia = 1; switch_ivr_media(uuid, SMF_REBRIDGE); } @@ -2715,9 +2705,10 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_broadcast(const char *uuid, const cha if ((flags & SMF_ECHO_BLEG) && (other_uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE)) && (other_session = switch_core_session_locate(other_uuid))) { if ((flags & SMF_EXEC_INLINE)) { - switch_core_session_execute_application(other_session, app, path); + switch_core_session_execute_application_get_flags(other_session, app, path, &app_flags); nomedia = 0; } else { + switch_core_session_get_app_flags(app, &app_flags); if (switch_event_create(&event, SWITCH_EVENT_COMMAND) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-command", "execute"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "execute-app-name", app); @@ -2735,21 +2726,20 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_broadcast(const char *uuid, const cha switch_core_session_queue_private_event(other_session, &event); } } - + switch_core_session_rwunlock(other_session); master = other_session; other_session = NULL; } - if (switch_stristr("record", app)) { + if ((app_flags & SAF_MEDIA_TAP)) { nomedia = 0; } - if ((flags & SMF_ECHO_ALEG)) { if ((flags & SMF_EXEC_INLINE)) { - switch_core_session_execute_application(session, app, path); nomedia = 0; + switch_core_session_execute_application(session, app, path); } else { if (switch_event_create(&event, SWITCH_EVENT_COMMAND) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-command", "execute"); @@ -2764,20 +2754,12 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_broadcast(const char *uuid, const cha switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "hold-bleg", "true"); } switch_core_session_queue_private_event(session, &event); + if (nomedia) switch_channel_set_flag(channel, CF_BROADCAST_DROP_MEDIA); } } master = session; } - if (nomedia) { - if (switch_event_create(&event, SWITCH_EVENT_COMMAND) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-command", "nomedia"); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "nomedia-uuid", uuid); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event-lock", "true"); - switch_core_session_queue_private_event(master, &event); - } - } - if (cause) { if (switch_event_create(&event, SWITCH_EVENT_COMMAND) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-command", "execute");