diff --git a/src/include/switch_core.h b/src/include/switch_core.h index cb07dd2ebb..826b88ebd1 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -136,6 +136,19 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_bug_add(switch_core_session_t */ SWITCH_DECLARE(void *) switch_core_media_bug_get_user_data(switch_media_bug_t *bug); +/*! + \brief Obtain a replace frame from a media bug + \param bug the bug to get the data from +*/ +SWITCH_DECLARE(switch_frame_t *) switch_core_media_bug_get_replace_frame(switch_media_bug_t *bug); + +/*! + \brief Set a return replace frame + \param bug the bug to set the frame on + \param frame the frame to set +*/ +SWITCH_DECLARE(void) switch_core_media_bug_set_replace_frame(switch_media_bug_t *bug, switch_frame_t *frame); + /*! \brief Remove a media bug from the session \param session the session to remove the bug from diff --git a/src/include/switch_types.h b/src/include/switch_types.h index b49d74cbc3..9264e2a437 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -140,6 +140,7 @@ typedef enum { SWITCH_ABC_TYPE_INIT, SWITCH_ABC_TYPE_READ, SWITCH_ABC_TYPE_WRITE, + SWITCH_ABC_TYPE_WRITE_REPLACE, SWITCH_ABC_TYPE_CLOSE, } switch_abc_type_t; @@ -654,12 +655,14 @@ typedef enum {
 SMBF_READ_STREAM - Include the Read Stream
 SMBF_WRITE_STREAM - Include the Write Stream
+SMBF_WRITE_STREAM - Replace the Write Stream
 
*/ typedef enum { SMBF_BOTH = 0, SMBF_READ_STREAM = (1 << 0), - SMBF_WRITE_STREAM = (1 << 1) + SMBF_WRITE_STREAM = (1 << 1), + SMBF_WRITE_REPLACE = (1 << 2) } switch_media_bug_flag_t; /*! diff --git a/src/mod/applications/mod_ivrtest/mod_ivrtest.c b/src/mod/applications/mod_ivrtest/mod_ivrtest.c index 688eacfebd..4f9496467e 100644 --- a/src/mod/applications/mod_ivrtest/mod_ivrtest.c +++ b/src/mod/applications/mod_ivrtest/mod_ivrtest.c @@ -231,6 +231,39 @@ static void tts_function(switch_core_session_t *session, char *data) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Done\n"); } +static void bug_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type) +{ + switch_frame_t *frame; + + switch(type) { + case SWITCH_ABC_TYPE_WRITE_REPLACE: + frame = switch_core_media_bug_get_replace_frame(bug); + switch_core_media_bug_set_replace_frame(bug, frame); + printf("W00t\n"); + break; + default: + break; + } + +} + +static void bugtest_function(switch_core_session_t *session, char *data) +{ + switch_media_bug_t *bug; + switch_channel_t *channel = switch_core_session_get_channel(session); + switch_status_t status; + + if ((status = switch_core_media_bug_add(session, + bug_callback, + NULL, + SMBF_WRITE_REPLACE, + &bug)) != SWITCH_STATUS_SUCCESS) { + switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); + return; + } + switch_ivr_play_file(session, NULL, data, NULL); +} + #if 1 static void asrtest_function(switch_core_session_t *session, char *data) { @@ -423,11 +456,18 @@ static const switch_state_handler_table_t state_handlers = { +static const switch_application_interface_t bug_application_interface = { + /*.interface_name */ "bugtest", + /*.application_function */ bugtest_function, + NULL, NULL, NULL, + /*.next*/ NULL +}; + static const switch_application_interface_t ivr_application_interface = { /*.interface_name */ "ivrmenu", /*.application_function */ ivr_application_function, NULL, NULL, NULL, - /*.next*/ NULL + /*.next*/ &bug_application_interface }; static const switch_application_interface_t xml_application_interface = { diff --git a/src/switch_core.c b/src/switch_core.c index 16dd598247..f57648086f 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -59,6 +59,8 @@ struct switch_media_bug { switch_buffer_t *raw_write_buffer; switch_buffer_t *raw_read_buffer; + switch_frame_t *replace_frame_in; + switch_frame_t *replace_frame_out; switch_media_bug_callback_t callback; switch_mutex_t *read_mutex; switch_mutex_t *write_mutex; @@ -176,6 +178,17 @@ static void switch_core_media_bug_destroy(switch_media_bug_t *bug) switch_buffer_destroy(&bug->raw_write_buffer); } + +SWITCH_DECLARE(switch_frame_t *) switch_core_media_bug_get_replace_frame(switch_media_bug_t *bug) +{ + return bug->replace_frame_in; +} + +SWITCH_DECLARE(void) switch_core_media_bug_set_replace_frame(switch_media_bug_t *bug, switch_frame_t *frame) +{ + bug->replace_frame_out = frame; +} + SWITCH_DECLARE(void *) switch_core_media_bug_get_user_data(switch_media_bug_t *bug) { return bug->user_data; @@ -277,9 +290,21 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_bug_add(switch_core_session_t switch_media_bug_t **new_bug) { - switch_media_bug_t *bug; + switch_media_bug_t *bug, *bp; switch_size_t bytes; + if (flags & SMBF_WRITE_REPLACE) { + switch_thread_rwlock_wrlock(session->bug_rwlock); + for (bp = session->bugs; bp; bp = bp->next) { + if (switch_test_flag(bp, SMBF_WRITE_REPLACE)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Only one bug of this type allowed!\n"); + switch_thread_rwlock_unlock(session->bug_rwlock); + return SWITCH_STATUS_GENERR; + } + } + switch_thread_rwlock_unlock(session->bug_rwlock); + } + if (!(bug = switch_core_session_alloc(session, sizeof(*bug)))) { return SWITCH_STATUS_MEMERR; } @@ -2087,6 +2112,7 @@ static switch_status_t perform_write(switch_core_session_t *session, switch_fram switch_status_t status = SWITCH_STATUS_FALSE; if (session->endpoint_interface->io_routines->write_frame) { + if ((status = session->endpoint_interface->io_routines->write_frame(session, frame, timeout, flags, stream_id)) == SWITCH_STATUS_SUCCESS) { @@ -2230,15 +2256,25 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_frame(switch_core_sess if (bp->callback) { bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_WRITE); } + } else if (switch_test_flag(bp, SMBF_WRITE_REPLACE)) { + do_bugs = 0; + if (bp->callback) { + bp->replace_frame_in = frame; + bp->replace_frame_out = NULL; + bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_WRITE_REPLACE); + write_frame = bp->replace_frame_out; + } } } switch_thread_rwlock_unlock(session->bug_rwlock); } + if (do_bugs) { - do_write = 1; - write_frame = frame; - goto done; + do_write = 1; + write_frame = frame; + goto done; } + if (session->write_codec) { if (write_frame->datalen == session->write_codec->implementation->bytes_per_frame) { perfect = TRUE; diff --git a/src/switch_ivr.c b/src/switch_ivr.c index 92d1455b21..0e08a3bf51 100644 --- a/src/switch_ivr.c +++ b/src/switch_ivr.c @@ -563,6 +563,7 @@ static void record_callback(switch_media_bug_t *bug, void *user_data, switch_abc } break; case SWITCH_ABC_TYPE_WRITE: + default: break; } } @@ -787,6 +788,7 @@ static void speech_callback(switch_media_bug_t *bug, void *user_data, switch_abc } break; case SWITCH_ABC_TYPE_WRITE: + default: break; } }