[Freeswitch-svn] [commit] r4052 - freeswitch/trunk/src/mod/asr_tts/mod_lumenvox

Freeswitch SVN anthm at freeswitch.org
Wed Jan 24 19:19:42 EST 2007


Author: anthm
Date: Wed Jan 24 19:19:41 2007
New Revision: 4052

Added:
   freeswitch/trunk/src/mod/asr_tts/mod_lumenvox/
   freeswitch/trunk/src/mod/asr_tts/mod_lumenvox/Makefile
   freeswitch/trunk/src/mod/asr_tts/mod_lumenvox/mod_lumenvox.cpp

Log:
Initial Check-In of mod_lumenvox

Added: freeswitch/trunk/src/mod/asr_tts/mod_lumenvox/Makefile
==============================================================================
--- (empty file)
+++ freeswitch/trunk/src/mod/asr_tts/mod_lumenvox/Makefile	Wed Jan 24 19:19:41 2007
@@ -0,0 +1,18 @@
+LDFLAGS += -L/opt/lumenvox/engine_7.0/lib -llv_lvspeechport
+CFLAGS += -fpermissive -Wno-deprecated -Wno-conversion -fpermissive -Wno-unused -Wno-comment -Wno-sign-compare -Wno-conversion -Wno-reorder -I/opt/lumenvox/engine_7.0/include
+LINKER=g++
+CC=g++
+
+all:	depends $(MODNAME).$(DYNAMIC_LIB_EXTEN)
+
+depends:
+
+$(MODNAME).$(DYNAMIC_LIB_EXTEN): $(MODNAME).cpp
+	$(CC) $(CFLAGS) -fPIC -c $(MODNAME).cpp -o $(MODNAME).o 
+	$(LINKER) $(SOLINK) -o $(MODNAME).$(DYNAMIC_LIB_EXTEN)  $(MODNAME).o $(LDFLAGS)
+
+clean:
+	rm -fr *.$(DYNAMIC_LIB_EXTEN) *.o *~
+
+install:
+	cp -f $(MODNAME).$(DYNAMIC_LIB_EXTEN) $(PREFIX)/mod

Added: freeswitch/trunk/src/mod/asr_tts/mod_lumenvox/mod_lumenvox.cpp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/src/mod/asr_tts/mod_lumenvox/mod_lumenvox.cpp	Wed Jan 24 19:19:41 2007
@@ -0,0 +1,459 @@
+/* 
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005/2006, Anthony Minessale II <anthmct at 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 at yahoo.com>
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * 
+ * Anthony Minessale II <anthmct at yahoo.com>
+ *
+ *
+ * mod_lumenvox.c -- Lumenvox Interface
+ * 
+ *
+ */
+#ifdef __ICC
+#pragma warning (disable:188)
+#endif
+
+#include <LVSpeechPort.h>
+#include <switch.h>
+#include <sstream>
+
+static const char modname[] = "mod_lumenvox";
+
+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, char *codec, int rate, 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, char *grammar, 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, 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_status_t switch_module_load(const switch_loadable_module_interface_t **module_interface, char *filename)
+{
+	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_MOD_DECLARE(switch_status_t) switch_module_shutdown(void)
+{
+	return SWITCH_STATUS_UNLOAD;
+}



More information about the Freeswitch-svn mailing list