lumenvox wanted us to pay them to make this module for them, we did it anyway, now they want us to pay for dev licenses, we no longer support that sort of company who does not support open source.....
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@9647 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
parent
0abf149dba
commit
59b53aaca3
|
@ -1,11 +0,0 @@
|
|||
# define these targets in your makefile if you wish
|
||||
# local_all local_depend local_clean depend_install local_install local_distclean local_extraclean:
|
||||
|
||||
# and define these variables to impact your build
|
||||
|
||||
LVENGINE_DIR=/opt/lumenvox/engine_7.0
|
||||
LOCAL_CFLAGS= -fpermissive -Wno-deprecated -Wno-conversion -fpermissive -Wno-unused
|
||||
LOCAL_CFLAGS+= -Wno-comment -Wno-sign-compare -Wno-conversion -Wno-reorder -I$(LVINCLUDE)
|
||||
LOCAL_LDFLAGS= -L$(LVLIB) -llv_lvspeechport
|
||||
include ../../../../build/modmake.rules
|
||||
|
|
@ -1,453 +0,0 @@
|
|||
/*
|
||||
* 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;
|
||||
}
|
Loading…
Reference in New Issue