diff --git a/libs/freetdm/mod_freetdm/tdm.c b/libs/freetdm/mod_freetdm/tdm.c index 1b401d364c..30cc3e4307 100644 --- a/libs/freetdm/mod_freetdm/tdm.c +++ b/libs/freetdm/mod_freetdm/tdm.c @@ -40,6 +40,8 @@ void ctdm_init(switch_loadable_module_interface_t *module_interface); #define kCHAN_ID "chan" #define kSPAN_NAME "span_name" #define kPREBUFFER_LEN "prebuffer_len" +#define kECHOCANCEL "echo_cancel" + static struct { switch_memory_pool_t *pool; @@ -373,6 +375,10 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to set channel pre buffer size.\n"); return SWITCH_STATUS_GENERR; } + + if (FTDM_SUCCESS != ftdm_channel_command(tech_pvt->ftdm_channel, FTDM_COMMAND_ENABLE_ECHOCANCEL, NULL)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Failed to set enable echo cancellation.\n"); + } switch(codec) { case FTDM_CODEC_ULAW: @@ -476,6 +482,10 @@ static switch_status_t channel_on_destroy(switch_core_session_t *session) ctdm_private_t *tech_pvt = switch_core_session_get_private(session); if ((tech_pvt = switch_core_session_get_private(session))) { + + if (FTDM_SUCCESS != ftdm_channel_command(tech_pvt->ftdm_channel, FTDM_COMMAND_ENABLE_ECHOCANCEL, NULL)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Failed to enable echo cancellation.\n"); + } if (tech_pvt->read_codec.implementation) { switch_core_codec_destroy(&tech_pvt->read_codec); @@ -639,20 +649,28 @@ static switch_status_t channel_receive_event(switch_core_session_t *session, swi const char *command = switch_event_get_header(event, "command"); ctdm_private_t *tech_pvt = switch_core_session_get_private(session); - if (!zstr(command) && !strcasecmp(command, kPREBUFFER_LEN)) { - const char *szval = switch_event_get_header(event, kPREBUFFER_LEN); - int val = !zstr(szval) ? atoi(szval) : 0; + if (!zstr(command)) { + if (!strcasecmp(command, kPREBUFFER_LEN)) { + const char *szval = switch_event_get_header(event, kPREBUFFER_LEN); + int val = !zstr(szval) ? atoi(szval) : 0; - if (tech_pvt->prebuffer_len == val) { - tech_pvt->prebuffer_len = val; - if (FTDM_SUCCESS != ftdm_channel_command(tech_pvt->ftdm_channel, FTDM_COMMAND_SET_PRE_BUFFER_SIZE, &tech_pvt->prebuffer_len)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to set channel pre buffer size.\n"); - return SWITCH_STATUS_GENERR; - } - } + if (tech_pvt->prebuffer_len == val) { + tech_pvt->prebuffer_len = val; + if (FTDM_SUCCESS != ftdm_channel_command(tech_pvt->ftdm_channel, FTDM_COMMAND_SET_PRE_BUFFER_SIZE, &tech_pvt->prebuffer_len)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to set channel pre buffer size.\n"); + return SWITCH_STATUS_GENERR; + } + } + } else if (!strcasecmp(command, kECHOCANCEL)) { + const char *szval = switch_event_get_header(event, kECHOCANCEL); + int enabled = !!switch_true(szval); + + if (FTDM_SUCCESS != ftdm_channel_command(tech_pvt->ftdm_channel, enabled ? FTDM_COMMAND_ENABLE_ECHOCANCEL : FTDM_COMMAND_DISABLE_ECHOCANCEL, NULL)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to %s echo cancellation.\n", enable ? "enable" : "disable"); + } + } } - return SWITCH_STATUS_SUCCESS; } diff --git a/src/mod/endpoints/mod_media_gateway/media_gateway.c b/src/mod/endpoints/mod_media_gateway/media_gateway.c index f1abe47bb7..aedf4e0abc 100644 --- a/src/mod/endpoints/mod_media_gateway/media_gateway.c +++ b/src/mod/endpoints/mod_media_gateway/media_gateway.c @@ -761,6 +761,34 @@ void mg_term_set_pre_buffer_size(mg_termination_t *term, int newval) switch_event_destroy(&event); } + +void mg_term_set_ec(mg_termination_t *term, int enable) +{ + switch_event_t *event = NULL, *event2 = NULL; + switch_core_session_t *session, *session2; + + if (!zstr(term->uuid) && (session = switch_core_session_locate(term->uuid))) { + switch_event_create(&event, SWITCH_EVENT_CLONE); + + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "command", kECHOCANCEL); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, kECHOCANCEL, enable ? "true" : "false"); + + /* Propagate event to bridged session if there is one */ + if (switch_core_session_get_partner(session, &session2) == SWITCH_STATUS_SUCCESS) { + switch_event_dup(&event2, event); + switch_core_session_receive_event(session2, &event2); + switch_core_session_rwunlock(session2); + } + + switch_core_session_receive_event(session, &event); + switch_core_session_rwunlock(session); + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Sent echo_cancel event to [%s] to [%s]\n", term->uuid, enable ? "enable" : "disable"); + } + + switch_event_destroy(&event); +} + /* For Emacs: * Local Variables: * mode:c diff --git a/src/mod/endpoints/mod_media_gateway/mod_media_gateway.c b/src/mod/endpoints/mod_media_gateway/mod_media_gateway.c index a905a445e1..bc50ddc165 100644 --- a/src/mod/endpoints/mod_media_gateway/mod_media_gateway.c +++ b/src/mod/endpoints/mod_media_gateway/mod_media_gateway.c @@ -35,13 +35,17 @@ SWITCH_STANDARD_APP(mg_notify_function) switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "mg_notify called on a non-supported channel.\n"); return; } - + if (!strcmp(data, "cng")) { mg_send_t38_cng_notify(term->profile, term->name); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Sent CNG notify\n"); + /* Disable echo cancellation */ + mg_term_set_ec(term, 0); } else if (!strcmp(data, "ced")) { - mg_send_t38_ans_notify(term->profile, term->name); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Sent CED notify\n"); + mg_send_t38_ans_notify(term->profile, term->name); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Sent CED notify\n"); + /* Disable echo cancellation */ + mg_term_set_ec(term, 0); } } diff --git a/src/mod/endpoints/mod_media_gateway/mod_media_gateway.h b/src/mod/endpoints/mod_media_gateway/mod_media_gateway.h index 15f1cf7bed..a3d8c2fc04 100644 --- a/src/mod/endpoints/mod_media_gateway/mod_media_gateway.h +++ b/src/mod/endpoints/mod_media_gateway/mod_media_gateway.h @@ -88,6 +88,7 @@ typedef struct mg_context_s mg_context_t; #define kCHAN_ID "chan" #define kSPAN_NAME "span_name" #define kPREBUFFER_LEN "prebuffer_len" +#define kECHOCANCEL "echo_cancel" typedef struct mg_termination_s mg_termination_t; @@ -269,6 +270,7 @@ switch_status_t megaco_profile_destroy(megaco_profile_t **profile); uint32_t mg_rtp_request_id(megaco_profile_t *profile); void mg_rtp_release_id(megaco_profile_t *profile, uint32_t id); void mg_term_set_pre_buffer_size(mg_termination_t *term, int newval); +void mg_term_set_ec(mg_termination_t *term, int enable); mg_context_t *megaco_get_context(megaco_profile_t *profile, uint32_t context_id); mg_context_t *megaco_choose_context(megaco_profile_t *profile);