2006-06-08 19:26:39 +00:00
|
|
|
/*
|
|
|
|
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
|
|
|
* Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
|
|
|
|
*
|
|
|
|
* 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 <anthmct@yahoo.com>
|
|
|
|
* Portions created by the Initial Developer are Copyright (C)
|
|
|
|
* the Initial Developer. All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s):
|
|
|
|
*
|
|
|
|
* Anthony Minessale II <anthmct@yahoo.com>
|
2007-11-01 13:29:06 +00:00
|
|
|
* Bret McDanel <trixter AT 0xdecafbad.com>
|
2006-06-08 19:26:39 +00:00
|
|
|
*
|
|
|
|
*
|
|
|
|
* mod_rss.c -- RSS Browser
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
#include <switch.h>
|
|
|
|
|
2007-06-13 16:00:14 +00:00
|
|
|
SWITCH_MODULE_LOAD_FUNCTION(mod_rss_load);
|
|
|
|
SWITCH_MODULE_DEFINITION(mod_rss, mod_rss_load, NULL, NULL);
|
2006-06-08 19:26:39 +00:00
|
|
|
|
|
|
|
typedef enum {
|
|
|
|
SFLAG_INSTRUCT = (1 << 0),
|
|
|
|
SFLAG_INFO = (1 << 1),
|
|
|
|
SFLAG_MAIN = (1 << 2)
|
|
|
|
} SFLAGS;
|
|
|
|
|
|
|
|
/* helper object */
|
|
|
|
struct dtmf_buffer {
|
|
|
|
int32_t index;
|
|
|
|
uint32_t flags;
|
|
|
|
int32_t speed;
|
|
|
|
char voice[80];
|
|
|
|
switch_speech_handle_t *sh;
|
|
|
|
};
|
|
|
|
|
|
|
|
#define TTS_MEAN_SPEED 170
|
|
|
|
#define TTS_MAX_ENTRIES 99
|
|
|
|
#define TTS_DEFAULT_ENGINE "cepstral"
|
|
|
|
#define TTS_DEFAULT_VOICE "david"
|
|
|
|
|
2006-06-14 16:52:24 +00:00
|
|
|
#define MATCH_COUNT
|
|
|
|
|
2006-06-11 03:21:00 +00:00
|
|
|
struct rss_entry {
|
2006-06-08 19:26:39 +00:00
|
|
|
uint8_t inuse;
|
|
|
|
char *title_txt;
|
|
|
|
char *description_txt;
|
|
|
|
char *subject_txt;
|
|
|
|
char *dept_txt;
|
|
|
|
};
|
|
|
|
|
2006-06-10 20:57:15 +00:00
|
|
|
#ifdef MATCH_COUNT
|
|
|
|
static uint32_t match_count(char *str, uint32_t max)
|
|
|
|
{
|
|
|
|
char tstr[80] = "";
|
|
|
|
uint32_t matches = 0, x = 0;
|
2007-03-29 22:31:56 +00:00
|
|
|
uint32_t len = (uint32_t) strlen(str);
|
2006-06-23 20:14:29 +00:00
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
for (x = 0; x < max; x++) {
|
2007-12-12 21:53:32 +00:00
|
|
|
switch_snprintf(tstr, sizeof(tstr), "%u", x);
|
2006-06-10 20:57:15 +00:00
|
|
|
if (!strncasecmp(str, tstr, len)) {
|
|
|
|
matches++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return matches;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2006-06-08 19:26:39 +00:00
|
|
|
/*
|
|
|
|
dtmf handler function you can hook up to be executed when a digit is dialed during playback
|
2006-06-11 03:21:00 +00:00
|
|
|
if you return anything but SWITCH_STATUS_SUCCESS the playback will stop.
|
2006-06-08 19:26:39 +00:00
|
|
|
*/
|
2007-03-30 00:13:31 +00:00
|
|
|
static switch_status_t on_dtmf(switch_core_session_t *session, void *input, switch_input_type_t itype, void *buf, unsigned int buflen)
|
2006-07-12 18:39:19 +00:00
|
|
|
{
|
|
|
|
switch (itype) {
|
2007-03-29 22:31:56 +00:00
|
|
|
case SWITCH_INPUT_TYPE_DTMF:{
|
2008-05-27 04:54:52 +00:00
|
|
|
switch_dtmf_t *dtmf = (switch_dtmf_t *) input;
|
2007-03-29 22:31:56 +00:00
|
|
|
struct dtmf_buffer *dtb;
|
|
|
|
dtb = (struct dtmf_buffer *) buf;
|
|
|
|
|
2007-12-22 00:32:20 +00:00
|
|
|
switch (dtmf->digit) {
|
2007-03-29 22:31:56 +00:00
|
|
|
case '#':
|
|
|
|
switch_set_flag(dtb, SFLAG_MAIN);
|
|
|
|
return SWITCH_STATUS_BREAK;
|
|
|
|
case '6':
|
|
|
|
dtb->index++;
|
|
|
|
return SWITCH_STATUS_BREAK;
|
|
|
|
case '4':
|
|
|
|
dtb->index--;
|
|
|
|
return SWITCH_STATUS_BREAK;
|
|
|
|
case '*':
|
|
|
|
if (switch_test_flag(dtb->sh, SWITCH_SPEECH_FLAG_PAUSE)) {
|
|
|
|
switch_clear_flag(dtb->sh, SWITCH_SPEECH_FLAG_PAUSE);
|
|
|
|
} else {
|
|
|
|
switch_set_flag(dtb->sh, SWITCH_SPEECH_FLAG_PAUSE);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case '5':
|
|
|
|
switch_core_speech_text_param_tts(dtb->sh, "voice", "next");
|
2006-07-12 18:39:19 +00:00
|
|
|
switch_set_flag(dtb, SFLAG_INFO);
|
|
|
|
return SWITCH_STATUS_BREAK;
|
2007-03-29 22:31:56 +00:00
|
|
|
case '9':
|
|
|
|
switch_core_speech_text_param_tts(dtb->sh, "voice", dtb->voice);
|
|
|
|
switch_set_flag(dtb, SFLAG_INFO);
|
|
|
|
return SWITCH_STATUS_BREAK;
|
|
|
|
case '2':
|
|
|
|
if (dtb->speed < 260) {
|
|
|
|
dtb->speed += 30;
|
|
|
|
switch_core_speech_numeric_param_tts(dtb->sh, "speech/rate", dtb->speed);
|
|
|
|
switch_set_flag(dtb, SFLAG_INFO);
|
|
|
|
return SWITCH_STATUS_BREAK;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case '7':
|
|
|
|
dtb->speed = TTS_MEAN_SPEED;
|
2006-07-12 18:39:19 +00:00
|
|
|
switch_core_speech_numeric_param_tts(dtb->sh, "speech/rate", dtb->speed);
|
|
|
|
switch_set_flag(dtb, SFLAG_INFO);
|
|
|
|
return SWITCH_STATUS_BREAK;
|
2007-03-29 22:31:56 +00:00
|
|
|
case '8':
|
|
|
|
if (dtb->speed > 80) {
|
|
|
|
dtb->speed -= 30;
|
|
|
|
switch_core_speech_numeric_param_tts(dtb->sh, "speech/rate", dtb->speed);
|
|
|
|
switch_set_flag(dtb, SFLAG_INFO);
|
|
|
|
return SWITCH_STATUS_BREAK;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case '0':
|
|
|
|
switch_set_flag(dtb, SFLAG_INSTRUCT);
|
|
|
|
return SWITCH_STATUS_BREAK;
|
2006-07-12 18:39:19 +00:00
|
|
|
}
|
2006-06-08 19:26:39 +00:00
|
|
|
}
|
2006-07-12 18:39:19 +00:00
|
|
|
break;
|
|
|
|
default:
|
2006-06-08 19:26:39 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2007-06-20 06:05:31 +00:00
|
|
|
SWITCH_STANDARD_APP(rss_function)
|
2006-06-08 19:26:39 +00:00
|
|
|
{
|
2008-01-28 07:26:10 +00:00
|
|
|
switch_channel_t *channel = switch_core_session_get_channel(session);
|
2006-06-08 19:26:39 +00:00
|
|
|
switch_status_t status;
|
|
|
|
const char *err = NULL;
|
2007-03-29 22:31:56 +00:00
|
|
|
struct dtmf_buffer dtb = { 0 };
|
2006-06-08 19:26:39 +00:00
|
|
|
switch_xml_t xml = NULL, item, xchannel = NULL;
|
2007-03-29 22:31:56 +00:00
|
|
|
struct rss_entry entries[TTS_MAX_ENTRIES] = { {0} };
|
2006-06-08 19:26:39 +00:00
|
|
|
uint32_t i = 0;
|
|
|
|
char *title_txt = "", *description_txt = "", *rights_txt = "";
|
|
|
|
switch_codec_t speech_codec, *codec = switch_core_session_get_read_codec(session);
|
|
|
|
char *engine = TTS_DEFAULT_ENGINE;
|
|
|
|
char *voice = TTS_DEFAULT_VOICE;
|
|
|
|
char *timer_name = NULL;
|
|
|
|
switch_speech_handle_t sh;
|
2007-03-29 22:31:56 +00:00
|
|
|
switch_speech_flag_t flags = SWITCH_SPEECH_FLAG_NONE;
|
2006-06-08 19:26:39 +00:00
|
|
|
switch_core_thread_session_t thread_session;
|
2006-06-08 19:41:14 +00:00
|
|
|
uint32_t rate, interval = 20;
|
2007-03-29 22:31:56 +00:00
|
|
|
switch_timer_t timer = { 0 }, *timerp = NULL;
|
2006-06-08 19:26:39 +00:00
|
|
|
uint32_t last;
|
|
|
|
char *mydata = NULL;
|
|
|
|
char *filename = NULL;
|
2008-05-27 04:54:52 +00:00
|
|
|
char *argv[3], *feed_list[TTS_MAX_ENTRIES] = { 0 }, *feed_names[TTS_MAX_ENTRIES] = {
|
|
|
|
0};
|
2006-06-08 19:26:39 +00:00
|
|
|
int argc, feed_index = 0;
|
2007-11-16 18:54:40 +00:00
|
|
|
const char *cf = "rss.conf";
|
2007-03-29 22:31:56 +00:00
|
|
|
switch_xml_t cfg, cxml, feeds, feed;
|
2007-12-15 05:50:21 +00:00
|
|
|
char buf[1024] = "";
|
2006-06-08 19:41:14 +00:00
|
|
|
int32_t jumpto = -1;
|
2006-06-10 20:57:15 +00:00
|
|
|
uint32_t matches = 0;
|
2007-03-29 22:31:56 +00:00
|
|
|
switch_input_args_t args = { 0 };
|
2007-11-16 18:54:40 +00:00
|
|
|
const char *vcf = NULL;
|
2008-01-28 07:26:10 +00:00
|
|
|
char *chanvars = switch_channel_build_param_string(channel, NULL, NULL);
|
2006-06-08 22:03:23 +00:00
|
|
|
|
2007-11-16 18:54:40 +00:00
|
|
|
if ((vcf = switch_channel_get_variable(channel, "rss_alt_config"))) {
|
|
|
|
cf = vcf;
|
|
|
|
}
|
2006-06-08 22:03:23 +00:00
|
|
|
|
2006-06-08 19:26:39 +00:00
|
|
|
if (!(cxml = switch_xml_open_cfg(cf, &cfg, NULL))) {
|
2007-03-29 22:31:56 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "open of %s failed\n", cf);
|
|
|
|
return;
|
|
|
|
}
|
2007-11-20 03:44:19 +00:00
|
|
|
switch_safe_free(chanvars);
|
2006-06-08 19:26:39 +00:00
|
|
|
|
|
|
|
if ((feeds = switch_xml_child(cfg, "feeds"))) {
|
|
|
|
for (feed = switch_xml_child(feeds, "feed"); feed; feed = feed->next) {
|
|
|
|
char *name = (char *) switch_xml_attr_soft(feed, "name");
|
2007-11-07 20:12:26 +00:00
|
|
|
char *expanded = NULL;
|
|
|
|
char *idx = feed->txt;
|
|
|
|
|
|
|
|
if ((expanded = switch_channel_expand_variables(channel, idx)) == idx) {
|
|
|
|
expanded = NULL;
|
|
|
|
} else {
|
|
|
|
idx = expanded;
|
|
|
|
}
|
2006-06-08 19:26:39 +00:00
|
|
|
|
|
|
|
if (!name) {
|
|
|
|
name = "Error No Name.";
|
|
|
|
}
|
|
|
|
|
2007-11-07 20:12:26 +00:00
|
|
|
feed_list[feed_index] = switch_core_session_strdup(session, idx);
|
|
|
|
switch_safe_free(expanded);
|
|
|
|
|
|
|
|
if ((expanded = switch_channel_expand_variables(channel, name)) == name) {
|
|
|
|
expanded = NULL;
|
|
|
|
} else {
|
|
|
|
name = expanded;
|
|
|
|
}
|
2006-06-08 19:26:39 +00:00
|
|
|
feed_names[feed_index] = switch_core_session_strdup(session, name);
|
2007-11-07 20:12:26 +00:00
|
|
|
switch_safe_free(expanded);
|
2006-06-08 19:26:39 +00:00
|
|
|
feed_index++;
|
2007-11-07 20:12:26 +00:00
|
|
|
|
2006-06-08 19:26:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
switch_xml_free(cxml);
|
2007-03-29 22:31:56 +00:00
|
|
|
|
2006-06-08 22:03:23 +00:00
|
|
|
switch_channel_answer(channel);
|
|
|
|
|
2006-06-08 19:26:39 +00:00
|
|
|
if (!switch_strlen_zero(data)) {
|
|
|
|
if ((mydata = switch_core_session_strdup(session, data))) {
|
2007-03-29 22:31:56 +00:00
|
|
|
argc = switch_separate_string(mydata, ' ', argv, sizeof(argv) / sizeof(argv[0]));
|
2006-06-08 19:26:39 +00:00
|
|
|
|
|
|
|
if (argv[0]) {
|
|
|
|
engine = argv[0];
|
|
|
|
if (argv[1]) {
|
|
|
|
voice = argv[1];
|
|
|
|
if (argv[2]) {
|
|
|
|
jumpto = atoi(argv[2]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!feed_index) {
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "No Feeds Specified!\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (codec) {
|
2007-10-19 03:42:02 +00:00
|
|
|
rate = codec->implementation->actual_samples_per_second;
|
2006-06-08 19:26:39 +00:00
|
|
|
} else {
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Codec Error!\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(&sh, 0, sizeof(sh));
|
2007-08-25 21:33:26 +00:00
|
|
|
if (switch_core_speech_open(&sh, engine, voice, rate, interval, &flags, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
|
2006-06-08 19:26:39 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid TTS module!\n");
|
|
|
|
return;
|
|
|
|
}
|
2007-03-29 22:31:56 +00:00
|
|
|
|
2006-06-08 19:26:39 +00:00
|
|
|
if (switch_core_codec_init(&speech_codec,
|
|
|
|
"L16",
|
2006-10-09 02:24:43 +00:00
|
|
|
NULL,
|
2007-03-29 22:31:56 +00:00
|
|
|
(int) rate,
|
2006-06-08 19:26:39 +00:00
|
|
|
interval,
|
2007-03-30 00:15:25 +00:00
|
|
|
1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL,
|
|
|
|
switch_core_session_get_pool(session)) == SWITCH_STATUS_SUCCESS) {
|
2006-06-08 19:26:39 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Raw Codec Activated\n");
|
|
|
|
} else {
|
2007-03-30 00:13:31 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Raw Codec Activation Failed L16@%uhz 1 channel %dms\n", rate, interval);
|
2006-06-08 19:26:39 +00:00
|
|
|
flags = 0;
|
|
|
|
switch_core_speech_close(&sh, &flags);
|
|
|
|
return;
|
|
|
|
}
|
2007-03-29 22:31:56 +00:00
|
|
|
|
2006-06-08 19:26:39 +00:00
|
|
|
if (timer_name) {
|
2007-03-30 00:13:31 +00:00
|
|
|
if (switch_core_timer_init(&timer, timer_name, interval, (int) (rate / 50), switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
|
2006-06-08 19:26:39 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "setup timer failed!\n");
|
|
|
|
switch_core_codec_destroy(&speech_codec);
|
|
|
|
flags = 0;
|
|
|
|
switch_core_speech_close(&sh, &flags);
|
|
|
|
return;
|
|
|
|
}
|
2007-03-30 00:13:31 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "setup timer success %u bytes per %d ms!\n", (rate / 50) * 2, interval);
|
2006-06-08 19:26:39 +00:00
|
|
|
|
|
|
|
/* start a thread to absorb incoming audio */
|
2008-05-08 19:19:47 +00:00
|
|
|
switch_core_service_session(session, &thread_session, 0);
|
2006-06-08 19:26:39 +00:00
|
|
|
timerp = &timer;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (switch_channel_ready(channel)) {
|
|
|
|
int32_t len = 0, idx = 0;
|
|
|
|
char cmd[3];
|
2007-03-29 22:31:56 +00:00
|
|
|
main_menu:
|
2006-06-08 19:26:39 +00:00
|
|
|
filename = NULL;
|
|
|
|
len = idx = 0;
|
|
|
|
*cmd = '\0';
|
2006-06-11 03:11:04 +00:00
|
|
|
title_txt = description_txt = rights_txt = "";
|
2006-06-08 19:26:39 +00:00
|
|
|
|
|
|
|
if (jumpto > -1) {
|
2007-12-12 21:53:32 +00:00
|
|
|
switch_snprintf(cmd, sizeof(cmd), "%d", jumpto);
|
2006-06-23 20:14:29 +00:00
|
|
|
jumpto = -1;
|
2006-06-08 19:26:39 +00:00
|
|
|
} else {
|
|
|
|
switch_core_speech_flush_tts(&sh);
|
2006-06-14 16:52:24 +00:00
|
|
|
#ifdef MATCH_COUNT
|
2007-12-15 05:50:21 +00:00
|
|
|
switch_snprintf(buf + len, sizeof(buf) - len, "%s",
|
2008-05-27 04:54:52 +00:00
|
|
|
",<break time=\"500ms\"/>Main Menu. <break time=\"600ms\"/> "
|
|
|
|
"Select one of the following news sources, or press 0 to exit. " ",<break time=\"600ms\"/>");
|
2006-06-14 16:52:24 +00:00
|
|
|
#else
|
2007-12-15 05:50:21 +00:00
|
|
|
switch_snprintf(buf + len, sizeof(buf) - len, "%s",
|
2008-05-27 04:54:52 +00:00
|
|
|
",<break time=\"500ms\"/>Main Menu. <break time=\"600ms\"/> "
|
|
|
|
"Select one of the following news sources, followed by the pound key or press 0 to exit. " ",<break time=\"600ms\"/>");
|
2006-06-14 16:52:24 +00:00
|
|
|
#endif
|
2007-03-29 22:31:56 +00:00
|
|
|
len = (int32_t) strlen(buf);
|
2006-06-08 19:26:39 +00:00
|
|
|
|
|
|
|
for (idx = 0; idx < feed_index; idx++) {
|
2007-12-12 21:53:32 +00:00
|
|
|
switch_snprintf(buf + len, sizeof(buf) - len, "%d: %s. <break time=\"600ms\"/>", idx + 1, feed_names[idx]);
|
2007-03-29 22:31:56 +00:00
|
|
|
len = (int32_t) strlen(buf);
|
2006-06-08 19:26:39 +00:00
|
|
|
}
|
|
|
|
|
2007-12-15 05:50:21 +00:00
|
|
|
switch_snprintf(buf + len, sizeof(buf) - len, "%s", "<break time=\"2000ms\"/>");
|
2007-03-29 22:31:56 +00:00
|
|
|
len = (int32_t) strlen(buf);
|
2006-06-08 19:26:39 +00:00
|
|
|
|
2006-12-24 02:24:16 +00:00
|
|
|
args.input_callback = NULL;
|
|
|
|
args.buf = cmd;
|
|
|
|
args.buflen = sizeof(cmd);
|
2007-03-29 22:31:56 +00:00
|
|
|
status = switch_ivr_speak_text_handle(session, &sh, &speech_codec, timerp, buf, &args);
|
2006-06-08 19:26:39 +00:00
|
|
|
if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_BREAK) {
|
|
|
|
goto finished;
|
|
|
|
}
|
|
|
|
}
|
2007-11-01 13:29:06 +00:00
|
|
|
if (*cmd != '\0') {
|
2007-12-15 05:50:21 +00:00
|
|
|
int32_t x;
|
2006-06-10 20:57:15 +00:00
|
|
|
char *p;
|
2006-06-08 19:26:39 +00:00
|
|
|
|
2006-06-10 20:57:15 +00:00
|
|
|
if (strchr(cmd, '0')) {
|
2006-06-08 19:26:39 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
if ((p = strchr(cmd, '#'))) {
|
2006-06-10 20:57:15 +00:00
|
|
|
*p = '\0';
|
|
|
|
#ifdef MATCH_COUNT
|
|
|
|
/* Hmmm... I know there are no more matches so I don't *need* them to press pound but
|
|
|
|
I already told them to press it. Will this confuse people or not? Let's make em press
|
|
|
|
pound unless this define is enabled for now.
|
2007-03-29 22:31:56 +00:00
|
|
|
*/
|
2006-06-10 20:57:15 +00:00
|
|
|
} else if (match_count(cmd, feed_index) > 1) {
|
|
|
|
#else
|
|
|
|
} else {
|
|
|
|
#endif
|
|
|
|
char term;
|
|
|
|
char *cp;
|
2007-10-12 20:14:41 +00:00
|
|
|
switch_size_t blen = sizeof(cmd) - strlen(cmd);
|
2006-06-10 20:57:15 +00:00
|
|
|
|
|
|
|
cp = cmd + blen;
|
2008-01-07 16:49:46 +00:00
|
|
|
switch_ivr_collect_digits_count(session, cp, blen, blen, "#", &term, 5000, 0, 0);
|
2006-06-10 20:57:15 +00:00
|
|
|
}
|
2007-03-29 22:31:56 +00:00
|
|
|
|
2007-12-15 05:50:21 +00:00
|
|
|
x = atoi(cmd) - 1;
|
2006-06-09 19:54:53 +00:00
|
|
|
|
2007-12-15 05:50:21 +00:00
|
|
|
if (x > -1 && x < feed_index) {
|
2006-06-08 19:26:39 +00:00
|
|
|
filename = feed_list[i];
|
2006-06-10 20:57:15 +00:00
|
|
|
} else if (matches > 1) {
|
2007-03-29 22:31:56 +00:00
|
|
|
|
2006-06-09 19:54:53 +00:00
|
|
|
} else {
|
2006-12-24 02:24:16 +00:00
|
|
|
args.input_callback = NULL;
|
|
|
|
args.buf = NULL;
|
|
|
|
args.buflen = 0;
|
2007-03-30 00:13:31 +00:00
|
|
|
status = switch_ivr_speak_text_handle(session, &sh, &speech_codec, timerp, "I'm sorry. That is an Invalid Selection. ", &args);
|
2006-06-09 19:54:53 +00:00
|
|
|
if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_BREAK) {
|
|
|
|
goto finished;
|
|
|
|
}
|
2006-06-08 19:26:39 +00:00
|
|
|
}
|
|
|
|
}
|
2007-03-29 22:31:56 +00:00
|
|
|
|
2006-06-08 19:26:39 +00:00
|
|
|
if (!filename) {
|
|
|
|
continue;
|
|
|
|
}
|
2007-03-29 22:31:56 +00:00
|
|
|
|
2006-06-08 19:26:39 +00:00
|
|
|
if (!(xml = switch_xml_parse_file(filename))) {
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "open of %s failed\n", filename);
|
|
|
|
goto finished;
|
|
|
|
}
|
|
|
|
|
|
|
|
err = switch_xml_error(xml);
|
|
|
|
|
|
|
|
if (!switch_strlen_zero(err)) {
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Error [%s]\n", err);
|
|
|
|
goto finished;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((xchannel = switch_xml_child(xml, "channel"))) {
|
|
|
|
switch_xml_t title, description, rights;
|
|
|
|
|
|
|
|
if ((title = switch_xml_child(xchannel, "title"))) {
|
|
|
|
title_txt = title->txt;
|
|
|
|
}
|
2007-03-29 22:31:56 +00:00
|
|
|
|
2006-06-08 19:26:39 +00:00
|
|
|
if ((description = switch_xml_child(xchannel, "description"))) {
|
|
|
|
description_txt = description->txt;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((rights = switch_xml_child(xchannel, "dc:rights"))) {
|
|
|
|
rights_txt = rights->txt;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!(item = switch_xml_child(xml, "item"))) {
|
|
|
|
if (xchannel) {
|
|
|
|
item = switch_xml_child(xchannel, "item");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-06-11 03:11:04 +00:00
|
|
|
memset(entries, 0, sizeof(entries));
|
|
|
|
|
2006-06-08 19:26:39 +00:00
|
|
|
for (i = 0; item; item = item->next) {
|
|
|
|
switch_xml_t title, description, subject, dept;
|
|
|
|
char *p;
|
|
|
|
|
|
|
|
entries[i].inuse = 1;
|
|
|
|
entries[i].title_txt = NULL;
|
|
|
|
entries[i].description_txt = NULL;
|
|
|
|
entries[i].subject_txt = NULL;
|
|
|
|
entries[i].dept_txt = NULL;
|
|
|
|
|
|
|
|
if ((title = switch_xml_child(item, "title"))) {
|
|
|
|
entries[i].title_txt = title->txt;
|
|
|
|
}
|
2007-03-29 22:31:56 +00:00
|
|
|
|
2006-06-08 19:26:39 +00:00
|
|
|
if ((description = switch_xml_child(item, "description"))) {
|
|
|
|
char *t, *e;
|
|
|
|
entries[i].description_txt = description->txt;
|
2007-03-29 22:31:56 +00:00
|
|
|
for (;;) {
|
2006-06-08 19:26:39 +00:00
|
|
|
if (!(t = strchr(entries[i].description_txt, '<'))) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (!(e = strchr(t, '>'))) {
|
|
|
|
break;
|
|
|
|
}
|
2007-03-29 22:31:56 +00:00
|
|
|
|
|
|
|
memset(t, 32, ++e - t);
|
2006-06-08 19:26:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((subject = switch_xml_child(item, "dc:subject"))) {
|
|
|
|
entries[i].subject_txt = subject->txt;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((dept = switch_xml_child(item, "slash:department"))) {
|
|
|
|
entries[i].dept_txt = dept->txt;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (entries[i].description_txt && (p = strchr(entries[i].description_txt, '<'))) {
|
|
|
|
*p = '\0';
|
|
|
|
}
|
|
|
|
#ifdef _STRIP_SOME_CHARS_
|
2007-03-29 22:31:56 +00:00
|
|
|
for (p = entries[i].description_txt; *p; p++) {
|
2006-06-08 19:26:39 +00:00
|
|
|
if (*p == '\'' || *p == '"' || *p == ':') {
|
|
|
|
*p = ' ';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (switch_channel_ready(channel)) {
|
|
|
|
switch_time_exp_t tm;
|
|
|
|
char date[80] = "";
|
|
|
|
switch_size_t retsize;
|
2007-12-15 05:50:21 +00:00
|
|
|
char dtmf[5] = "";
|
2006-06-08 19:26:39 +00:00
|
|
|
|
2008-01-11 00:43:49 +00:00
|
|
|
switch_time_exp_lt(&tm, switch_timestamp_now());
|
2006-06-14 14:54:43 +00:00
|
|
|
switch_strftime(date, &retsize, sizeof(date), "%I:%M %p", &tm);
|
2006-06-08 19:26:39 +00:00
|
|
|
|
|
|
|
|
2007-12-12 21:53:32 +00:00
|
|
|
switch_snprintf(buf, sizeof(buf),
|
2008-05-27 04:54:52 +00:00
|
|
|
",<break time=\"500ms\"/>%s. %s. %s. local time: %s, Press 0 for options, 5 to change voice, or pound to return to the main menu. ",
|
|
|
|
title_txt, description_txt, rights_txt, date);
|
2006-12-24 02:24:16 +00:00
|
|
|
args.input_callback = NULL;
|
2007-12-15 05:50:21 +00:00
|
|
|
args.buf = dtmf;
|
|
|
|
args.buflen = sizeof(dtmf);
|
2007-03-29 22:31:56 +00:00
|
|
|
status = switch_ivr_speak_text_handle(session, &sh, &speech_codec, timerp, buf, &args);
|
2006-06-08 19:26:39 +00:00
|
|
|
if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_BREAK) {
|
|
|
|
goto finished;
|
|
|
|
}
|
2007-12-15 05:50:21 +00:00
|
|
|
if (*dtmf != '\0') {
|
|
|
|
switch (*dtmf) {
|
2006-06-08 19:26:39 +00:00
|
|
|
case '0':
|
|
|
|
switch_set_flag(&dtb, SFLAG_INSTRUCT);
|
|
|
|
break;
|
2006-06-08 22:03:23 +00:00
|
|
|
case '#':
|
|
|
|
goto main_menu;
|
2006-06-08 19:26:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
for (last = 0; last < TTS_MAX_ENTRIES; last++) {
|
2006-06-08 19:26:39 +00:00
|
|
|
if (!entries[last].inuse) {
|
|
|
|
last--;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
dtb.index = 0;
|
|
|
|
dtb.sh = &sh;
|
|
|
|
dtb.speed = TTS_MEAN_SPEED;
|
|
|
|
switch_set_flag(&dtb, SFLAG_INFO);
|
|
|
|
switch_copy_string(dtb.voice, voice, sizeof(dtb.voice));
|
2007-03-29 22:31:56 +00:00
|
|
|
while (entries[0].inuse && switch_channel_ready(channel)) {
|
|
|
|
while (switch_channel_ready(channel)) {
|
2006-06-08 19:26:39 +00:00
|
|
|
uint8_t cont = 0;
|
|
|
|
|
|
|
|
if (dtb.index >= TTS_MAX_ENTRIES) {
|
|
|
|
dtb.index = 0;
|
|
|
|
}
|
|
|
|
if (dtb.index < 0) {
|
|
|
|
dtb.index = last;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!entries[dtb.index].inuse) {
|
|
|
|
dtb.index = 0;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (switch_channel_ready(channel)) {
|
2007-12-15 05:50:21 +00:00
|
|
|
char tmpbuf[1024] = "";
|
|
|
|
uint32_t tmplen = 0;
|
2006-06-08 19:26:39 +00:00
|
|
|
|
|
|
|
if (switch_test_flag(&dtb, SFLAG_MAIN)) {
|
|
|
|
switch_clear_flag(&dtb, SFLAG_MAIN);
|
|
|
|
goto main_menu;
|
|
|
|
}
|
|
|
|
if (switch_test_flag(&dtb, SFLAG_INFO)) {
|
|
|
|
switch_clear_flag(&dtb, SFLAG_INFO);
|
2008-05-27 04:54:52 +00:00
|
|
|
switch_snprintf(tmpbuf + tmplen, sizeof(tmpbuf) - tmplen, "%s %s. I am speaking at %u words per minute. ", sh.engine, sh.voice,
|
|
|
|
dtb.speed);
|
2007-12-15 05:50:21 +00:00
|
|
|
tmplen = (uint32_t) strlen(tmpbuf);
|
2006-06-08 19:26:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (switch_test_flag(&dtb, SFLAG_INSTRUCT)) {
|
|
|
|
switch_clear_flag(&dtb, SFLAG_INSTRUCT);
|
|
|
|
cont = 1;
|
2007-12-15 05:50:21 +00:00
|
|
|
switch_snprintf(tmpbuf + tmplen, sizeof(tmpbuf) - tmplen, "%s",
|
2008-05-27 04:54:52 +00:00
|
|
|
"Press star to pause or resume speech. "
|
|
|
|
"To go to the next item, press six. "
|
|
|
|
"To go back, press 4. "
|
|
|
|
"Press two to go faster, eight to slow down, or 7 to resume normal speed. "
|
|
|
|
"To change voices, press five. To restore the original voice press 9. "
|
|
|
|
"To hear these options again, press zero or press pound to return to the main menu. ");
|
2006-06-08 19:26:39 +00:00
|
|
|
} else {
|
2007-12-15 05:50:21 +00:00
|
|
|
switch_snprintf(tmpbuf + tmplen, sizeof(tmpbuf) - tmplen, "Story %d. ", dtb.index + 1);
|
|
|
|
tmplen = (uint32_t) strlen(tmpbuf);
|
2006-06-08 19:26:39 +00:00
|
|
|
|
|
|
|
if (entries[dtb.index].subject_txt) {
|
2007-12-15 05:50:21 +00:00
|
|
|
switch_snprintf(tmpbuf + tmplen, sizeof(tmpbuf) - tmplen, "Subject: %s. ", entries[dtb.index].subject_txt);
|
|
|
|
tmplen = (uint32_t) strlen(tmpbuf);
|
2006-06-08 19:26:39 +00:00
|
|
|
}
|
2007-03-29 22:31:56 +00:00
|
|
|
|
2006-06-08 19:26:39 +00:00
|
|
|
if (entries[dtb.index].dept_txt) {
|
2007-12-15 05:50:21 +00:00
|
|
|
switch_snprintf(tmpbuf + tmplen, sizeof(tmpbuf) - tmplen, "From the %s department. ", entries[dtb.index].dept_txt);
|
|
|
|
tmplen = (uint32_t) strlen(tmpbuf);
|
2006-06-08 19:26:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (entries[dtb.index].title_txt) {
|
2007-12-15 05:50:21 +00:00
|
|
|
switch_snprintf(tmpbuf + tmplen, sizeof(tmpbuf) - tmplen, "%s", entries[dtb.index].title_txt);
|
|
|
|
tmplen = (uint32_t) strlen(tmpbuf);
|
2006-06-08 19:26:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
switch_core_speech_flush_tts(&sh);
|
2006-12-24 02:24:16 +00:00
|
|
|
args.input_callback = on_dtmf;
|
|
|
|
args.buf = &dtb;
|
|
|
|
args.buflen = sizeof(dtb);
|
2007-12-15 05:50:21 +00:00
|
|
|
status = switch_ivr_speak_text_handle(session, &sh, &speech_codec, timerp, tmpbuf, &args);
|
2006-06-08 19:26:39 +00:00
|
|
|
if (status == SWITCH_STATUS_BREAK) {
|
|
|
|
continue;
|
|
|
|
} else if (status != SWITCH_STATUS_SUCCESS) {
|
|
|
|
goto finished;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cont) {
|
|
|
|
cont = 0;
|
|
|
|
continue;
|
|
|
|
}
|
2007-03-29 22:31:56 +00:00
|
|
|
|
2006-07-06 22:12:15 +00:00
|
|
|
if (entries[dtb.index].description_txt) {
|
2006-12-24 02:24:16 +00:00
|
|
|
args.input_callback = on_dtmf;
|
|
|
|
args.buf = &dtb;
|
|
|
|
args.buflen = sizeof(dtb);
|
2007-03-30 00:13:31 +00:00
|
|
|
status = switch_ivr_speak_text_handle(session, &sh, &speech_codec, timerp, entries[dtb.index].description_txt, &args);
|
2006-07-06 22:12:15 +00:00
|
|
|
}
|
2006-06-08 19:26:39 +00:00
|
|
|
if (status == SWITCH_STATUS_BREAK) {
|
|
|
|
continue;
|
|
|
|
} else if (status != SWITCH_STATUS_SUCCESS) {
|
|
|
|
goto finished;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
dtb.index++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
finished:
|
2006-06-08 19:26:39 +00:00
|
|
|
switch_core_speech_close(&sh, &flags);
|
|
|
|
switch_core_codec_destroy(&speech_codec);
|
|
|
|
|
|
|
|
if (timerp) {
|
|
|
|
/* End the audio absorbing thread */
|
|
|
|
switch_core_thread_session_end(&thread_session);
|
|
|
|
switch_core_timer_destroy(&timer);
|
|
|
|
}
|
|
|
|
|
|
|
|
switch_xml_free(xml);
|
2008-01-13 18:39:51 +00:00
|
|
|
switch_core_session_reset(session, SWITCH_TRUE);
|
2006-06-08 19:26:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-06-13 16:00:14 +00:00
|
|
|
SWITCH_MODULE_LOAD_FUNCTION(mod_rss_load)
|
2006-06-08 19:26:39 +00:00
|
|
|
{
|
2007-06-20 06:05:31 +00:00
|
|
|
switch_application_interface_t *app_interface;
|
|
|
|
|
2006-06-08 19:26:39 +00:00
|
|
|
/* connect my internal structure to the blank pointer passed to me */
|
2007-06-20 06:05:31 +00:00
|
|
|
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
|
|
|
|
SWITCH_ADD_APP(app_interface, "rss", NULL, NULL, rss_function, NULL, SAF_NONE);
|
2006-06-08 19:26:39 +00:00
|
|
|
|
|
|
|
/* indicate that the module should continue to be loaded */
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2006-11-27 22:30:48 +00:00
|
|
|
/* For Emacs:
|
|
|
|
* Local Variables:
|
|
|
|
* mode:c
|
2008-02-03 22:14:57 +00:00
|
|
|
* indent-tabs-mode:t
|
2006-11-27 22:30:48 +00:00
|
|
|
* tab-width:4
|
|
|
|
* c-basic-offset:4
|
|
|
|
* End:
|
|
|
|
* For VIM:
|
|
|
|
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 expandtab:
|
|
|
|
*/
|