From 5c5758095540cbceae0d19fcd95266e1cd431285 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 8 Jun 2006 19:22:54 +0000 Subject: [PATCH] ivr stuff (part 1) git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@1573 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- src/include/switch_core.h | 8 + src/include/switch_module_interfaces.h | 4 + src/include/switch_types.h | 2 + src/mod/applications/mod_rss/mod_rss.c | 200 ------------------- src/mod/applications/mod_rss/mod_rss.vcproj | 209 -------------------- src/mod/asr_tts/mod_cepstral/mod_cepstral.c | 91 ++++++++- src/mod/endpoints/mod_wanpipe/mod_wanpipe.c | 4 +- src/switch_core.c | 14 +- src/switch_ivr.c | 67 +++++-- 9 files changed, 161 insertions(+), 438 deletions(-) delete mode 100644 src/mod/applications/mod_rss/mod_rss.c delete mode 100644 src/mod/applications/mod_rss/mod_rss.vcproj diff --git a/src/include/switch_core.h b/src/include/switch_core.h index ff8b47276d..a4a72e9045 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -917,6 +917,14 @@ SWITCH_DECLARE(void) switch_core_speech_text_param_tts(switch_speech_handle_t *s */ SWITCH_DECLARE(void) switch_core_speech_numeric_param_tts(switch_speech_handle_t *sh, char *param, int val); +/*! + \brief Set a float parameter on a TTS handle + \param sh the speech handle + \param param the parameter + \param val the value +*/ +SWITCH_DECLARE(void) switch_core_speech_float_param_tts(switch_speech_handle_t *sh, char *param, double val); + /*! \brief Read rendered audio from the TTS module \param sh the speech handle to read diff --git a/src/include/switch_module_interfaces.h b/src/include/switch_module_interfaces.h index 7f6920e6a4..2dadbf8ca6 100644 --- a/src/include/switch_module_interfaces.h +++ b/src/include/switch_module_interfaces.h @@ -330,6 +330,7 @@ struct switch_speech_interface { void (*speech_flush_tts)(switch_speech_handle_t *sh); void (*speech_text_param_tts)(switch_speech_handle_t *sh, char *param, char *val); void (*speech_numeric_param_tts)(switch_speech_handle_t *sh, char *param, int val); + void (*speech_float_param_tts)(switch_speech_handle_t *sh, char *param, double val); const struct switch_speech_interface *next; }; @@ -345,6 +346,9 @@ struct switch_speech_handle { char *name; /*! The Rate*/ uint32_t rate; + uint32_t speed; + char voice[80]; + char engine[80]; /*! the handle's memory pool */ switch_memory_pool_t *memory_pool; /*! private data for the format module to store handle specific info */ diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 4380b21a58..51b8bbd0ef 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -424,6 +424,7 @@ SWITCH_SPEECH_FLAG_HASTEXT = (1 << 2) - Interface is has text to read. SWITCH_SPEECH_FLAG_PEEK = (1 << 3) - Read data but do not erase it. SWITCH_SPEECH_FLAG_FREE_POOL = (1 << 4) - Free interface's pool on destruction. SWITCH_SPEECH_FLAG_BLOCKING = (1 << 5) - Indicate that a blocking call is desired +SWITCH_SPEECH_FLAG_PAUSE = (1 << 6) - Pause toggle for playback */ typedef enum { @@ -433,6 +434,7 @@ typedef enum { SWITCH_SPEECH_FLAG_PEEK = (1 << 3), SWITCH_SPEECH_FLAG_FREE_POOL = (1 << 4), SWITCH_SPEECH_FLAG_BLOCKING = (1 << 5), + SWITCH_SPEECH_FLAG_PAUSE = (1 << 6) } switch_speech_flag_t; diff --git a/src/mod/applications/mod_rss/mod_rss.c b/src/mod/applications/mod_rss/mod_rss.c deleted file mode 100644 index a13ba6453b..0000000000 --- a/src/mod/applications/mod_rss/mod_rss.c +++ /dev/null @@ -1,200 +0,0 @@ -/* - * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application - * Copyright (C) 2005/2006, Anthony Minessale II - * - * Version: MPL 1.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application - * - * The Initial Developer of the Original Code is - * Anthony Minessale II - * Portions created by the Initial Developer are Copyright (C) - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Anthony Minessale II - * - * - * mod_rss.c -- RSS Browser - * - */ -#include - -static const char modname[] = "mod_rss"; - - -/* helper object */ -struct dtmf_buffer { - char *data; - char *front; - uint32_t len; - uint32_t size; - switch_file_handle_t fh; -}; - -/* - dtmf handler function you can hook up to be executed when a digit is dialed during playback - if you return anything but SWITCH_STATUS_SUCCESS the playback will stop. -*/ -static switch_status_t on_dtmf(switch_core_session_t *session, char *dtmf, void *buf, unsigned int buflen) -{ - - struct dtmf_buffer *dtb; - uint32_t len, slen; - uint32_t samps = 0, pos = 0; - dtb = (struct dtmf_buffer *) buf; - - if (*dtmf == '#') { - return SWITCH_STATUS_FALSE; - } - - len = dtb->size - dtb->len; - slen = (uint32_t)strlen(dtmf); - - if (slen > len) { - slen = len; - } - - switch_copy_string(dtb->front, dtmf, len); - dtb->front += slen; - dtb->len += slen; - - if (dtb->len == 2) { - if (*dtb->data == '*') { - dtb->front = dtb->data; - dtb->len = 0; - *dtb->data = '\0'; - switch(*(dtb->data+1)) { - case '0': - dtb->fh.speed = 0; - break; - case '2': - dtb->fh.speed++; - break; - case '1': - dtb->fh.speed--; - break; - case '5': - { - switch_codec_t *codec = switch_core_session_get_read_codec(session); - samps = 5000 * (codec->implementation->samples_per_second / 1000); - switch_core_file_seek(&dtb->fh, &pos, samps, SEEK_CUR); - } - break; - case '4': - { - int32_t lpos = 0; - switch_codec_t *codec = switch_core_session_get_read_codec(session); - - samps = 5000 * (codec->implementation->samples_per_second / 1000); - lpos = (int) dtb->fh.pos - samps; - if (lpos < 0) { - lpos = 0; - } - switch_core_file_seek(&dtb->fh, &pos, lpos, SEEK_SET); - } - break; - case '*': - if (switch_test_flag(&dtb->fh, SWITCH_FILE_PAUSE)) { - switch_clear_flag(&dtb->fh, SWITCH_FILE_PAUSE); - } else { - switch_set_flag(&dtb->fh, SWITCH_FILE_PAUSE); - } - break; - } - - return SWITCH_STATUS_SUCCESS; - } - return SWITCH_STATUS_BREAK; - } - - return SWITCH_STATUS_SUCCESS; -} - - -static void rss_function(switch_core_session_t *session, char *data) -{ - switch_channel_t *channel; - uint8_t index = 0; - char fname[512]; - switch_status_t status; - char buf[10]; - struct dtmf_buffer dtb; - - - dtb.data = buf; - dtb.front = buf; - dtb.len = 0; - dtb.size = sizeof(buf); - - channel = switch_core_session_get_channel(session); - assert(channel != NULL); - - if (switch_strlen_zero(data)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "No Path Specified!\n"); - return; - } - - switch_channel_answer(channel); - - while(switch_channel_ready(channel)) { - snprintf(fname, sizeof(fname), "%s/%.2u.raw", data, index); - memset(&dtb.fh, 0, sizeof(dtb.fh)); - if ((status = switch_ivr_play_file(session, &dtb.fh, fname, NULL, on_dtmf, &dtb, sizeof(dtb))) == SWITCH_STATUS_FALSE) { - break; - } - - index = (uint8_t)atoi(buf); - - /* reset for next loop */ - *buf = '\0'; - dtb.front = buf; - dtb.len = 0; - } - - - -} - -static const switch_application_interface_t rss_application_interface = { - /*.interface_name */ "rss", - /*.application_function */ rss_function, - NULL, NULL, NULL, - /*.next*/ NULL -}; - - -static switch_loadable_module_interface_t rss_module_interface = { - /*.module_name */ modname, - /*.endpoint_interface */ NULL, - /*.timer_interface */ NULL, - /*.dialplan_interface */ NULL, - /*.codec_interface */ NULL, - /*.application_interface */ &rss_application_interface, - /*.api_interface */ NULL, - /*.file_interface */ NULL, - /*.speech_interface */ NULL, - /*.directory_interface */ NULL -}; - - -SWITCH_MOD_DECLARE(switch_status_t) switch_module_load(const switch_loadable_module_interface_t **module_interface, char *filename) -{ - /* connect my internal structure to the blank pointer passed to me */ - *module_interface = &rss_module_interface; - - /* indicate that the module should continue to be loaded */ - return SWITCH_STATUS_SUCCESS; -} - diff --git a/src/mod/applications/mod_rss/mod_rss.vcproj b/src/mod/applications/mod_rss/mod_rss.vcproj deleted file mode 100644 index 0bc51c71c7..0000000000 --- a/src/mod/applications/mod_rss/mod_rss.vcproj +++ /dev/null @@ -1,209 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/mod/asr_tts/mod_cepstral/mod_cepstral.c b/src/mod/asr_tts/mod_cepstral/mod_cepstral.c index ded36faac8..5698cb7f0e 100644 --- a/src/mod/asr_tts/mod_cepstral/mod_cepstral.c +++ b/src/mod/asr_tts/mod_cepstral/mod_cepstral.c @@ -36,7 +36,7 @@ #include #include -#define MY_BUF_LEN 1024 * 512 +#define MY_BUF_LEN 1024 * 256 static const char modname[] = "mod_cepstral"; @@ -152,8 +152,14 @@ static switch_status_t cepstral_speech_open(switch_speech_handle_t *sh, char *vo switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to set voice.\n"); goto all_done; } + + voice_name = (char *) swift_voice_get_attribute(cepstral->voice, "name"); } + if (voice_name) { + switch_copy_string(sh->voice, voice_name, sizeof(sh->voice)); + } + swift_port_set_callback(cepstral->port, &write_audio, SWIFT_EVENT_AUDIO, cepstral); sh->private_info = cepstral; @@ -175,7 +181,6 @@ static switch_status_t cepstral_speech_close(switch_speech_handle_t *sh, switch_ cepstral->done = 1; cepstral->done_gen = 1; - printf("CLOSE!!!\n"); swift_port_stop(cepstral->port, SWIFT_ASYNC_ANY, SWIFT_EVENT_NOW); /* Close the Swift Port and Engine */ if (NULL != cepstral->port) swift_port_close(cepstral->port); @@ -294,6 +299,83 @@ static switch_status_t cepstral_speech_read_tts(switch_speech_handle_t *sh, return status; } +static void cepstral_text_param_tts(switch_speech_handle_t *sh, char *param, char *val) +{ + cepstral_t *cepstral; + + cepstral = sh->private_info; + assert(cepstral != NULL); + + if (!strcasecmp(param, "voice")) { + char *voice_name = val; + if (!strcasecmp(voice_name, "next")) { + if ((cepstral->voice = swift_port_find_next_voice(cepstral->port))) { + if ( SWIFT_FAILED(swift_port_set_voice(cepstral->port, cepstral->voice)) ) { + cepstral->done = cepstral->done_gen = 1; + return; + } + voice_name = (char *) swift_voice_get_attribute(cepstral->voice, "name"); + } else { + voice_name = NULL; + } + } else { + if (voice_name && SWIFT_FAILED(swift_port_set_voice_by_name(cepstral->port, voice_name))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid voice %s!\n", voice_name); + voice_name = NULL; + } + } + + if (!voice_name) { + /* Find the first voice on the system */ + if ((cepstral->voice = swift_port_find_first_voice(cepstral->port, NULL, NULL)) == NULL) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to find any voices!\n"); + cepstral->done = cepstral->done_gen = 1; + return; + } + + /* Set the voice found by find_first_voice() as the port's current voice */ + if ( SWIFT_FAILED(swift_port_set_voice(cepstral->port, cepstral->voice)) ) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to set voice.\n"); + cepstral->done = cepstral->done_gen = 1; + return; + } + + voice_name = (char *) swift_voice_get_attribute(cepstral->voice, "name"); + } + + if (voice_name) { + switch_copy_string(sh->voice, voice_name, sizeof(sh->voice)); + } + + return; + } + + swift_port_set_param_string(cepstral->port, param, val, NULL); +} + +static void cepstral_numeric_param_tts(switch_speech_handle_t *sh, char *param, int val) +{ + cepstral_t *cepstral; + + cepstral = sh->private_info; + assert(cepstral != NULL); + + swift_port_set_param_int(cepstral->port, param, val, NULL); + +} + + +static void cepstral_float_param_tts(switch_speech_handle_t *sh, char *param, double val) +{ + cepstral_t *cepstral; + + cepstral = sh->private_info; + assert(cepstral != NULL); + + swift_port_set_param_float(cepstral->port, param, val, NULL); + +} + static const switch_speech_interface_t cepstral_speech_interface = { /*.interface_name*/ "cepstral", /*.speech_open*/ cepstral_speech_open, @@ -302,7 +384,10 @@ static const switch_speech_interface_t cepstral_speech_interface = { /*.speech_interpret_asr*/ NULL, /*.speech_feed_tts*/ cepstral_speech_feed_tts, /*.speech_read_tts*/ cepstral_speech_read_tts, - /*.speech_flush_tts*/ cepstral_speech_flush_tts + /*.speech_flush_tts*/ cepstral_speech_flush_tts, + /*.speech_text_param_tts*/ cepstral_text_param_tts, + /*.speech_numeric_param_tts*/ cepstral_numeric_param_tts, + /*.speech_numeric_param_tts*/ cepstral_float_param_tts }; static const switch_loadable_module_interface_t cepstral_module_interface = { diff --git a/src/mod/endpoints/mod_wanpipe/mod_wanpipe.c b/src/mod/endpoints/mod_wanpipe/mod_wanpipe.c index 2a4d233c95..df056b981e 100644 --- a/src/mod/endpoints/mod_wanpipe/mod_wanpipe.c +++ b/src/mod/endpoints/mod_wanpipe/mod_wanpipe.c @@ -566,8 +566,8 @@ static switch_status_t wanpipe_write_frame(switch_core_session_t *session, switc while (bytes > 0) { unsigned int towrite; -#if 0 - if (sangoma_socket_waitfor(tech_pvt->socket, -1, POLLOUT | POLLERR | POLLHUP) <= 0) { +#if 1 + if (sangoma_socket_waitfor(tech_pvt->socket, 1000, POLLOUT | POLLERR | POLLHUP) <= 0) { return SWITCH_STATUS_GENERR; } #endif diff --git a/src/switch_core.c b/src/switch_core.c index 1c768c0e13..511245a748 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -578,6 +578,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_speech_open(switch_speech_handle_t * return SWITCH_STATUS_GENERR; } + switch_copy_string(sh->engine, module_name, sizeof(sh->engine)); sh->flags = *flags; if (pool) { sh->memory_pool = pool; @@ -640,6 +641,15 @@ SWITCH_DECLARE(void) switch_core_speech_numeric_param_tts(switch_speech_handle_t } } +SWITCH_DECLARE(void) switch_core_speech_float_param_tts(switch_speech_handle_t *sh, char *param, double val) +{ + assert(sh != NULL); + + if (sh->speech_interface->speech_float_param_tts) { + sh->speech_interface->speech_float_param_tts(sh, param, val); + } +} + SWITCH_DECLARE(switch_status_t) switch_core_speech_read_tts(switch_speech_handle_t *sh, void *data, switch_size_t *datalen, @@ -736,15 +746,13 @@ static void *switch_core_service_thread(switch_thread_t *thread, void *obj) while (data->running > 0) { switch (switch_core_session_read_frame(session, &read_frame, -1, stream_id)) { case SWITCH_STATUS_SUCCESS: - break; case SWITCH_STATUS_TIMEOUT: + case SWITCH_STATUS_BREAK: break; default: data->running = -1; continue; } - - switch_yield(10000); } data->running = 0; diff --git a/src/switch_ivr.c b/src/switch_ivr.c index c5f859f458..44bf1baa98 100644 --- a/src/switch_ivr.c +++ b/src/switch_ivr.c @@ -554,6 +554,52 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text_handle(switch_core_session ilen = len; while(switch_channel_ready(channel)) { + + if (dtmf_callback || buf) { + /* + dtmf handler function you can hook up to be executed when a digit is dialed during playback + if you return anything but SWITCH_STATUS_SUCCESS the playback will stop. + */ + if (switch_channel_has_dtmf(channel)) { + if (buf && !strcasecmp(buf, "_break_")) { + status = SWITCH_STATUS_BREAK; + } else { + switch_channel_dequeue_dtmf(channel, dtmf, sizeof(dtmf)); + if (dtmf_callback) { + status = dtmf_callback(session, dtmf, buf, buflen); + } else { + switch_copy_string((char *)buf, dtmf, buflen); + status = SWITCH_STATUS_BREAK; + } + } + } + + if (status != SWITCH_STATUS_SUCCESS) { + done = 1; + break; + } + } + + if (switch_test_flag(sh, SWITCH_SPEECH_FLAG_PAUSE)) { + if (timer) { + if ((x = switch_core_timer_next(timer)) < 0) { + break; + } + } else { + switch_frame_t *read_frame; + switch_status_t status = switch_core_session_read_frame(session, &read_frame, -1, 0); + + while (switch_channel_test_flag(channel, CF_HOLD)) { + switch_yield(10000); + } + + if (!SWITCH_READ_ACCEPTABLE(status)) { + break; + } + } + continue; + } + flags = SWITCH_SPEECH_FLAG_BLOCKING; status = switch_core_speech_read_tts(sh, abuf, @@ -596,27 +642,6 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text_handle(switch_core_session } } - if (dtmf_callback || buf) { - /* - dtmf handler function you can hook up to be executed when a digit is dialed during playback - if you return anything but SWITCH_STATUS_SUCCESS the playback will stop. - */ - if (switch_channel_has_dtmf(channel)) { - switch_channel_dequeue_dtmf(channel, dtmf, sizeof(dtmf)); - if (dtmf_callback) { - status = dtmf_callback(session, dtmf, buf, buflen); - } else { - switch_copy_string((char *)buf, dtmf, buflen); - status = SWITCH_STATUS_BREAK; - } - } - - if (status != SWITCH_STATUS_SUCCESS) { - done = 1; - break; - } - } - if (timer) { if ((x = switch_core_timer_next(timer)) < 0) { break;