diff --git a/src/include/switch_ivr.h b/src/include/switch_ivr.h index 52b7f6f9e6..f45f1fa327 100644 --- a/src/include/switch_ivr.h +++ b/src/include/switch_ivr.h @@ -267,6 +267,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_tone_detect_session(switch_core_sessi */ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *session, switch_file_handle_t *fh, char *file, switch_input_args_t *args); +SWITCH_DECLARE(switch_status_t) switch_ivr_gentones(switch_core_session_t *session, char *script, int32_t loops, switch_input_args_t *args); /*! \brief record a file from the session to a file diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c index 6e37c6de90..1586690cd3 100644 --- a/src/mod/applications/mod_dptools/mod_dptools.c +++ b/src/mod/applications/mod_dptools/mod_dptools.c @@ -820,6 +820,35 @@ static void playback_function(switch_core_session_t *session, char *data) } +static void gentones_function(switch_core_session_t *session, char *data) +{ + switch_channel_t *channel; + char *tone_script = NULL; + switch_input_args_t args = { 0 }; + char *l; + int32_t loops = 0; + + tone_script = switch_core_session_strdup(session, data); + + channel = switch_core_session_get_channel(session); + assert(channel != NULL); + + switch_channel_pre_answer(channel); + + if ((l = strchr(tone_script, '|'))) { + *l++ = '\0'; + loops = atoi(l); + + if (loops < 0) { + loops = -1; + } + } + + args.input_callback = on_dtmf; + switch_ivr_gentones(session, tone_script, loops, &args); + +} + static void displace_session_function(switch_core_session_t *session, char *data) { switch_channel_t *channel; @@ -1124,6 +1153,17 @@ static switch_application_interface_t playback_application_interface = { /* flags */ SAF_NONE, /*.next */ &stop_record_session_application_interface }; + +static switch_application_interface_t gentones_application_interface = { + /*.interface_name */ "gentones", + /*.application_function */ gentones_function, + /* long_desc */ "Generate tones to the channel", + /* short_desc */ "Generate Tones", + /* syntax */ "[|]", + /* flags */ SAF_NONE, + /*.next */ &playback_application_interface +}; + static switch_application_interface_t park_application_interface = { /*.interface_name */ "park", /*.application_function */ park_function, @@ -1131,7 +1171,7 @@ static switch_application_interface_t park_application_interface = { /* short_desc */ NULL, /* syntax */ NULL, /* flags */ SAF_NONE, - /*.next */ &playback_application_interface + /*.next */ &gentones_application_interface }; static switch_application_interface_t echo_application_interface = { diff --git a/src/switch_ivr_originate.c b/src/switch_ivr_originate.c index 42085e5e96..9d33cf1609 100644 --- a/src/switch_ivr_originate.c +++ b/src/switch_ivr_originate.c @@ -663,6 +663,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess } else { teletone_init_session(&ringback.ts, 0, teletone_handler, &ringback); + ringback.ts.rate = read_codec->implementation->samples_per_second; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Play Ringback Tone [%s]\n", ringback_data); //ringback.ts.debug = 1; //ringback.ts.debug_stream = switch_core_get_console(); diff --git a/src/switch_ivr_play_say.c b/src/switch_ivr_play_say.c index ea33923c44..91ecfcb61e 100644 --- a/src/switch_ivr_play_say.c +++ b/src/switch_ivr_play_say.c @@ -477,6 +477,94 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se return status; } +static int teletone_handler(teletone_generation_session_t * ts, teletone_tone_map_t * map) +{ + switch_buffer_t *audio_buffer = ts->user_data; + int wrote; + + if (!audio_buffer) { + return -1; + } + + wrote = teletone_mux_tones(ts, map); + switch_buffer_write(audio_buffer, ts->buffer, wrote * 2); + + return 0; +} + +SWITCH_DECLARE(switch_status_t) switch_ivr_gentones(switch_core_session_t *session, char *script, int32_t loops, switch_input_args_t *args) +{ + teletone_generation_session_t ts; + switch_buffer_t *audio_buffer; + switch_frame_t *read_frame = NULL; + switch_codec_t *read_codec = NULL, write_codec; + switch_frame_t write_frame; + switch_byte_t data[1024]; + switch_channel_t *channel; + + assert(session != NULL); + + channel = switch_core_session_get_channel(session); + assert(channel != NULL); + + switch_channel_pre_answer(channel); + read_codec = switch_core_session_get_read_codec(session); + + if (switch_core_codec_init(&write_codec, + "L16", + NULL, + read_codec->implementation->samples_per_second, + read_codec->implementation->microseconds_per_frame / 1000, + 1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, + NULL, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) { + + return SWITCH_STATUS_FALSE; + } + + write_frame.codec = &write_codec; + write_frame.data = data; + + switch_buffer_create_dynamic(&audio_buffer, 512, 1024, 0); + teletone_init_session(&ts, 0, teletone_handler, audio_buffer); + ts.rate = read_codec->implementation->samples_per_second; + + teletone_run(&ts, script); + + if (loops) { + switch_buffer_set_loops(audio_buffer, loops); + } + + while(switch_channel_ready(channel)) { + switch_status_t status = switch_core_session_read_frame(session, &read_frame, 1000, 0); + + if (!SWITCH_READ_ACCEPTABLE(status)) { + break; + } + + if (read_frame->datalen < 2 || switch_test_flag(read_frame, SFF_CNG)) { + continue; + } + + if ((write_frame.datalen = (uint32_t) switch_buffer_read_loop(audio_buffer, write_frame.data, + read_frame->codec->implementation->bytes_per_frame)) <= 0) { + break; + } + + write_frame.samples = write_frame.datalen / 2; + + if (switch_core_session_write_frame(session, &write_frame, 1000, 0) != SWITCH_STATUS_SUCCESS) { + break; + } + } + + switch_core_codec_destroy(&write_codec); + switch_buffer_destroy(&audio_buffer); + teletone_destroy_session(&ts); + + return SWITCH_STATUS_SUCCESS; +} + + #define FILE_STARTSAMPLES 1024 * 32 #define FILE_BLOCKSIZE 1024 * 8 #define FILE_BUFSIZE 1024 * 64