+++ /dev/null
-/*
- * 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>
- *
- *
- * mod_lumenvox.cpp -- Lumenvox Interface
- *
- *
- */
-#ifdef __ICC
-#pragma warning (disable:188)
-#endif
-
-#include <LVSpeechPort.h>
-#include <switch.h>
-#include <sstream>
-
-SWITCH_MODULE_LOAD_FUNCTION(mod_lumenvox_load);
-SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_lumenvox_shutdown);
-SWITCH_MODULE_DEFINITION(mod_lumenvox, mod_lumenvox_load, mod_lumenvox_shutdown, NULL);
-
-typedef enum {
- LVFLAG_HAS_TEXT = (1 << 0),
- LVFLAG_BARGE = (1 << 1),
- LVFLAG_READY = (1 << 2)
-} lvflag_t;
-
-typedef struct {
- LVSpeechPort port;
- uint32_t flags;
- int sound_format;
- int channel;
- switch_mutex_t *flag_mutex;
-} lumenvox_t;
-
-static void log_callback(const char *message, void *userdata)
-{
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s\n", message);
-}
-
-static const char *state_names[] = {
- "NOT_READY",
- "READY",
- "BARGE_IN",
- "END_SPEECH",
- "STOPPED",
- "BARGE_IN_TIMEOUT",
- "END_SPEECH_TIMEOUT",
- "BEEP"
-};
-
-std::ostream & operator <<(std::ostream & os, const LVSemanticData & Data)
-{
- int i;
- LVSemanticObject Obj;
- switch (Data.Type()) {
- case SI_TYPE_BOOL:
- os << Data.GetBool();
- break;
- case SI_TYPE_INT:
- os << Data.GetInt();
- break;
- case SI_TYPE_DOUBLE:
- os << Data.GetDouble();
- break;
- case SI_TYPE_STRING:
- os << Data.GetString();
- break;
- case SI_TYPE_OBJECT:
- Obj = Data.GetSemanticObject();
- for (i = 0; i < Obj.NumberOfProperties(); ++i) {
- os << "<" << Obj.PropertyName(i) << ">";
- os << Obj.PropertyValue(i);
- os << "</" << Obj.PropertyName(i) << ">";
- }
- break;
- case SI_TYPE_ARRAY:
- for (i = 0; i < Data.GetSemanticArray().Size(); ++i) {
- os << Data.GetArray().At(i);
- }
- break;
- }
- return os;
-}
-
-//==============================================================================================
-// code to plug LVInterpretation into any standard stream
-std::ostream & operator <<(std::ostream & os, const LVInterpretation & Interp)
-{
- os << "<interpretation grammar=\"" << Interp.GrammarLabel()
- << "\" score=\"" << Interp.Score() << "\">";
- os << "<result name=\"" << Interp.ResultName() << "\">";
- os << Interp.ResultData();
- os << "</result>";
- os << "<input>";
- os << Interp.InputSentence();
- os << "</input>";
- os << "</interpretation>";
- return os;
-}
-
-
-static void state_change_callback(long new_state, unsigned long total_bytes, unsigned long recorded_bytes, void *user_data)
-{
- lumenvox_t *lv = (lumenvox_t *) user_data;
-
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "State: [%s] total bytes: [%ld] recorded bytes: [%ld]\n",
- state_names[new_state], total_bytes, recorded_bytes);
-
- switch (new_state) {
- case STREAM_STATUS_READY:
- break;
- case STREAM_STATUS_STOPPED:
- switch_clear_flag_locked(lv, LVFLAG_READY);
- break;
- case STREAM_STATUS_END_SPEECH:
- switch_set_flag_locked(lv, LVFLAG_HAS_TEXT);
- break;
- case STREAM_STATUS_BARGE_IN:
- switch_set_flag_locked(lv, LVFLAG_BARGE);
- break;
- }
-}
-
-static switch_status_t lumenvox_asr_pause(switch_asr_handle_t *ah)
-{
- lumenvox_t *lv = (lumenvox_t *) ah->private_info;
-
- if (switch_test_flag(lv, LVFLAG_READY)) {
- lv->port.StreamStop();
- switch_clear_flag_locked(lv, LVFLAG_READY);
- return SWITCH_STATUS_SUCCESS;
- }
-
- return SWITCH_STATUS_GENERR;
-}
-
-static switch_status_t lumenvox_asr_resume(switch_asr_handle_t *ah)
-{
- lumenvox_t *lv = (lumenvox_t *) ah->private_info;
-
- switch_clear_flag_locked(lv, LVFLAG_HAS_TEXT);
-
- if (!switch_test_flag(lv, LVFLAG_READY)) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Manually Resuming\n");
- if (lv->port.StreamStart()) {
- lv->port.ClosePort();
- return SWITCH_STATUS_GENERR;
- }
- switch_set_flag_locked(lv, LVFLAG_READY);
- return SWITCH_STATUS_SUCCESS;
- }
-
- return SWITCH_STATUS_GENERR;
-}
-
-/*! function to open the asr interface */
-static switch_status_t lumenvox_asr_open(switch_asr_handle_t *ah, const char *codec, int rate, const char *dest, switch_asr_flag_t *flags)
-{
-
- lumenvox_t *lv;
- int error_code;
-
- if (!(lv = (lumenvox_t *) switch_core_alloc(ah->memory_pool, sizeof(*lv)))) {
- return SWITCH_STATUS_MEMERR;
- }
-
- if (rate != 8000 && rate != 16000) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Rate: Pick 8000 or 16000\n");
- return SWITCH_STATUS_FALSE;
- }
-
- if (!strcasecmp(codec, "PCMU")) {
- switch (rate) {
- case 8000:
- lv->sound_format = ULAW_8KHZ;
- break;
- }
- } else if (!strcasecmp(codec, "PCMA")) {
- switch (rate) {
- case 8000:
- lv->sound_format = ULAW_8KHZ;
- break;
- }
- } else if (!strcasecmp(codec, "speex")) {
- switch (rate) {
- case 8000:
- lv->sound_format = SPX_8KHZ;
- break;
- case 16000:
- lv->sound_format = SPX_16KHZ;
- break;
- }
- }
-
- if (!lv->sound_format) {
- codec = "L16";
- switch (rate) {
- case 8000:
- lv->sound_format = PCM_8KHZ;
- break;
- case 16000:
- lv->sound_format = PCM_16KHZ;
- break;
- }
- }
-
- if (!lv->sound_format) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot negotiate sound format.\n");
- return SWITCH_STATUS_FALSE;
- }
-
- ah->rate = rate;
- ah->codec = switch_core_strdup(ah->memory_pool, codec);
-
- lv->port.OpenPort(log_callback, NULL, 5);
- error_code = lv->port.GetOpenPortStatus();
-
- switch (error_code) {
- case LV_FAILURE:
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Licenses Exceeded!\n");
- return SWITCH_STATUS_GENERR;
- case LV_OPEN_PORT_FAILED__PRIMARY_SERVER_NOT_RESPONDING:
- case LV_NO_SERVER_RESPONDING:
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SRE Server Unavailable!\n");
- return SWITCH_STATUS_GENERR;
- case LV_SUCCESS:
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Port Opened %d %dkhz.\n", lv->sound_format, rate);
- break;
- }
-
-
- // turn on sound and response file logging
- /*
- int save_sound_files = 1;
- lv->port.SetPropertyEx(PROP_EX_SAVE_SOUND_FILES,
- PROP_EX_VALUE_TYPE_INT_PTR,
- &save_sound_files);
- */
- lv->channel = 1;
- lv->flags = *flags;
- lv->port.StreamSetParameter(STREAM_PARM_DETECT_BARGE_IN, 1);
- lv->port.StreamSetParameter(STREAM_PARM_DETECT_END_OF_SPEECH, 1);
- lv->port.StreamSetParameter(STREAM_PARM_AUTO_DECODE, 1);
- lv->port.StreamSetParameter(STREAM_PARM_DECODE_FLAGS, LV_DECODE_SEMANTIC_INTERPRETATION);
- lv->port.StreamSetParameter(STREAM_PARM_VOICE_CHANNEL, lv->channel);
- lv->port.StreamSetParameter(STREAM_PARM_GRAMMAR_SET, (long unsigned int) LV_ACTIVE_GRAMMAR_SET);
-
-
- lv->port.StreamSetStateChangeCallBack(state_change_callback, lv);
- lv->port.StreamSetParameter(STREAM_PARM_SOUND_FORMAT, lv->sound_format);
-
- if (dest) {
- lv->port.SetClientPropertyEx(PROP_EX_SRE_SERVERS, PROP_EX_VALUE_TYPE_STRING, (void *) dest);
- }
-
- switch_mutex_init(&lv->flag_mutex, SWITCH_MUTEX_NESTED, ah->memory_pool);
-
- switch_set_flag_locked(lv, LVFLAG_READY);
- if (lv->port.StreamStart()) {
- lv->port.ClosePort();
- return SWITCH_STATUS_GENERR;
- }
-
- ah->private_info = lv;
-
- return SWITCH_STATUS_SUCCESS;
-}
-
-/*! function to load a grammar to the asr interface */
-static switch_status_t lumenvox_asr_load_grammar(switch_asr_handle_t *ah, const char *grammar, const char *path)
-{
- lumenvox_t *lv = (lumenvox_t *) ah->private_info;
-
- if (path) {
- if (!lv->port.LoadGrammar(grammar, path)) {
- if (!lv->port.ActivateGrammar(grammar)) {
- return SWITCH_STATUS_SUCCESS;
- }
- }
- } else {
- if (lv->port.ActivateGrammar(grammar)) {
- return SWITCH_STATUS_GENERR;
- }
- }
-
- return SWITCH_STATUS_GENERR;
-}
-
-
-/*! function to unload a grammar to the asr interface */
-static switch_status_t lumenvox_asr_unload_grammar(switch_asr_handle_t *ah, const char *grammar)
-{
- lumenvox_t *lv = (lumenvox_t *) ah->private_info;
-
- if (lv->port.DeactivateGrammar(grammar)) {
- return SWITCH_STATUS_GENERR;
- }
-
- return SWITCH_STATUS_SUCCESS;
-}
-
-/*! function to close the asr interface */
-static switch_status_t lumenvox_asr_close(switch_asr_handle_t *ah, switch_asr_flag_t *flags)
-{
- lumenvox_t *lv = (lumenvox_t *) ah->private_info;
-
- switch_set_flag(ah, SWITCH_ASR_FLAG_CLOSED);
- lv->port.ClosePort();
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Port Closed.\n");
- return SWITCH_STATUS_SUCCESS;
-}
-
-/*! function to feed audio to the ASR*/
-static switch_status_t lumenvox_asr_feed(switch_asr_handle_t *ah, void *data, unsigned int len, switch_asr_flag_t *flags)
-{
-
- lumenvox_t *lv = (lumenvox_t *) ah->private_info;
-
- if (!switch_test_flag(lv, LVFLAG_HAS_TEXT) && switch_test_flag(lv, LVFLAG_READY)) {
- if (lv->port.StreamSendData(data, len)) {
- return SWITCH_STATUS_FALSE;
- }
- }
-
- return SWITCH_STATUS_SUCCESS;
-}
-
-/*! function to read results from the ASR*/
-static switch_status_t lumenvox_asr_check_results(switch_asr_handle_t *ah, switch_asr_flag_t *flags)
-{
- lumenvox_t *lv = (lumenvox_t *) ah->private_info;
-
- return (switch_test_flag(lv, LVFLAG_HAS_TEXT) || switch_test_flag(lv, LVFLAG_BARGE)) ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
-}
-
-/*! function to read results from the ASR*/
-static switch_status_t lumenvox_asr_get_results(switch_asr_handle_t *ah, char **xmlstr, switch_asr_flag_t *flags)
-{
- lumenvox_t *lv = (lumenvox_t *) ah->private_info;
- switch_status_t ret = SWITCH_STATUS_SUCCESS;
-
- if (switch_test_flag(lv, LVFLAG_BARGE)) {
- switch_clear_flag_locked(lv, LVFLAG_BARGE);
- ret = SWITCH_STATUS_BREAK;
- }
-
- if (switch_test_flag(lv, LVFLAG_HAS_TEXT)) {
- std::stringstream ss;
- int numInterp;
- int code;
-
-
- lv->port.StreamStop();
- code = lv->port.WaitForEngineToIdle(3000, lv->channel);
-
- if (code == LV_TIME_OUT) {
- return SWITCH_STATUS_FALSE;
- }
-
- numInterp = lv->port.GetNumberOfInterpretations(lv->channel);
-
- for (int t = 0; t < numInterp; ++t) {
- ss << lv->port.GetInterpretation(lv->channel, t);
- }
-
- *xmlstr = strdup((char *) ss.str().c_str());
- switch_clear_flag_locked(lv, LVFLAG_HAS_TEXT);
-
-
- if (switch_test_flag(lv, SWITCH_ASR_FLAG_AUTO_RESUME)) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Auto Resuming\n");
- switch_set_flag_locked(lv, LVFLAG_READY);
- if (lv->port.StreamStart()) {
- lv->port.ClosePort();
- return SWITCH_STATUS_GENERR;
- }
- }
-
- ret = SWITCH_STATUS_SUCCESS;
- }
-
- return ret;
-}
-
-static const switch_asr_interface_t lumenvox_asr_interface = {
- /*.interface_name */ "lumenvox",
- /*.asr_open */ lumenvox_asr_open,
- /*.asr_load_grammar */ lumenvox_asr_load_grammar,
- /*.asr_unload_grammar */ lumenvox_asr_unload_grammar,
- /*.asr_close */ lumenvox_asr_close,
- /*.asr_feed */ lumenvox_asr_feed,
- /*.asr_resume */ lumenvox_asr_resume,
- /*.asr_pause */ lumenvox_asr_pause,
- /*.asr_check_results */ lumenvox_asr_check_results,
- /*.asr_get_results */ lumenvox_asr_get_results
-};
-
-static const switch_loadable_module_interface_t lumenvox_module_interface = {
- /*.module_name */ modname,
- /*.endpoint_interface */ NULL,
- /*.timer_interface */ NULL,
- /*.dialplan_interface */ NULL,
- /*.codec_interface */ NULL,
- /*.application_interface */ NULL,
- /*.api_interface */ NULL,
- /*.file_interface */ NULL,
- /*.speech_interface */ NULL,
- /*.directory_interface */ NULL,
- /*.chat_interface */ NULL,
- /*.say_interface */ NULL,
- /*.asr_interface */ &lumenvox_asr_interface
-};
-
-SWITCH_MODULE_LOAD_FUNCTION(mod_lumenvox_load)
-{
- LVSpeechPort::RegisterAppLogMsg(log_callback, NULL, 5);
- //LVSpeechPort::SetClientPropertyEx(PROP_EX_SRE_SERVERS, PROP_EX_VALUE_TYPE_STRING, (void *)"127.0.0.1");
-
- /* connect my internal structure to the blank pointer passed to me */
- *module_interface = &lumenvox_module_interface;
-
- /* indicate that the module should continue to be loaded */
- return SWITCH_STATUS_SUCCESS;
-}
-
-SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_lumenvox_shutdown)
-{
- return SWITCH_STATUS_UNLOAD;
-}