[Freeswitch-svn] [commit] r14037 - freeswitch/trunk/src/mod/asr_tts/mod_unimrcp

FreeSWITCH SVN crienzo at freeswitch.org
Mon Jun 29 15:33:19 PDT 2009


Author: crienzo
Date: Mon Jun 29 17:33:18 2009
New Revision: 14037

Log:
MODUNIMRCP-4

Modified:
   freeswitch/trunk/src/mod/asr_tts/mod_unimrcp/mod_unimrcp.c

Modified: freeswitch/trunk/src/mod/asr_tts/mod_unimrcp/mod_unimrcp.c
==============================================================================
--- freeswitch/trunk/src/mod/asr_tts/mod_unimrcp/mod_unimrcp.c	(original)
+++ freeswitch/trunk/src/mod/asr_tts/mod_unimrcp/mod_unimrcp.c	Mon Jun 29 17:33:18 2009
@@ -53,6 +53,25 @@
 #include "mrcp_client_connection.h"
 #include "apt_net.h"
 
+
+/*********************************************************************************************************************************************
+ * PROFILE: profile management
+ */
+
+/**
+ * Profile-specific configuration.  This allows us to handle differing MRCP server behavior 
+ * on a per-profile basis 
+ */
+struct profile {
+	char *name;
+	const char *jsgf_mime_type;
+	const char *gsl_mime_type;
+	const char *srgs_xml_mime_type;
+	const char *srgs_mime_type;
+};
+typedef struct profile profile_t;
+static switch_status_t profile_create(profile_t **profile, const char *name, switch_memory_pool_t *pool);
+
 /*********************************************************************************************************************************************
  * mod_unimrcp : module interface to FreeSWITCH
  */
@@ -62,6 +81,7 @@
 /* module config file */
 #define CONFIG_FILE "unimrcp.conf"
 
+
 /**
  * A UniMRCP application.
  */
@@ -105,6 +125,8 @@
 	switch_mutex_t *mutex;
 	/** next available speech channel number */
 	int speech_channel_number;
+	/** the available profiles */
+	switch_hash_t *profiles;
 };
 typedef struct mod_unimrcp_globals mod_unimrcp_globals_t;
 
@@ -131,10 +153,11 @@
 SWITCH_MODULE_DEFINITION(mod_unimrcp, mod_unimrcp_load, mod_unimrcp_shutdown, NULL);
 
 static switch_status_t mod_unimrcp_do_config();
-static mrcp_client_t *mod_unimrcp_client_create();
+static mrcp_client_t *mod_unimrcp_client_create(switch_memory_pool_t *mod_pool);
 static int process_rtp_config(mrcp_client_t *client, mpf_rtp_config_t *rtp_config, const char *param, const char *val, apr_pool_t *pool);
 static int process_mrcpv1_config(rtsp_client_config_t *config, const char *param, const char *val, apr_pool_t *pool);
 static int process_mrcpv2_config(mrcp_sofia_client_config_t *config, const char *param, const char *val, apr_pool_t *pool);
+static int process_profile_config(profile_t *profile, const char *param, const char *val, apr_pool_t *pool);
 
 /* UniMRCP <--> FreeSWITCH logging bridge */
 static apt_bool_t unimrcp_log(const char *file, int line, const char *id, apt_log_priority_e priority, const char *format, va_list arg_ptr);
@@ -162,6 +185,7 @@
 typedef struct unimrcp_param_id unimrcp_param_id_t;
 static unimrcp_param_id_t *unimrcp_param_id_create(int id, switch_memory_pool_t *pool);
 
+
 /********************************************************************************************************************************************
  * AUDIO QUEUE : UniMRCP <--> FreeSWITCH audio buffering
  */
@@ -248,6 +272,8 @@
 struct speech_channel {
 	/** the name of this channel (for logging) */
 	char *name;
+	/** The profile used by this channel */
+	profile_t *profile;
 	/** type of channel */
 	speech_channel_type_t type;
 	/** application this channel is running */
@@ -286,7 +312,7 @@
 
 /* speech_channel funcs */
 static switch_status_t speech_channel_create(speech_channel_t **schannel, const char *name, speech_channel_type_t type, mod_unimrcp_application_t *app, const char *codec, uint16_t rate, switch_memory_pool_t *pool);
-static switch_status_t speech_channel_open(speech_channel_t *schannel, const char *profile_name);
+static switch_status_t speech_channel_open(speech_channel_t *schannel, profile_t *profile);
 static switch_status_t speech_channel_destroy(speech_channel_t *schannel);
 static switch_status_t speech_channel_stop(speech_channel_t *schannel);
 static switch_status_t speech_channel_set_param(speech_channel_t *schannel, const char *name, const char *val);
@@ -364,7 +390,7 @@
 typedef struct grammar grammar_t;
 
 static switch_status_t grammar_create(grammar_t **grammar, const char *name, grammar_type_t type, const char *data, switch_memory_pool_t *pool);
-static const char *grammar_type_to_mime(grammar_type_t type);
+static const char *grammar_type_to_mime(grammar_type_t type, profile_t *profile);
 
 /*********************************************************************************************************************************************
  * RECOGNIZER : UniMRCP <--> FreeSWITCH asr interface
@@ -421,6 +447,35 @@
 static switch_status_t recog_channel_set_header(speech_channel_t *schannel, int id, char *val, mrcp_message_t *msg, mrcp_recog_header_t *recog_hdr);
 static switch_status_t recog_channel_set_timers_started(speech_channel_t *schannel);
 
+
+/**
+ * Create a mod_unimrcp profile
+ * @param profile the created profile
+ * @param name the profile name
+ * @param pool the memory pool to use
+ * @return SWITCH_STATUS_SUCCESS
+ */
+static switch_status_t profile_create(profile_t **profile, const char *name, switch_memory_pool_t *pool)
+{
+	switch_status_t status = SWITCH_STATUS_SUCCESS;
+	profile_t *lprofile = NULL;
+	
+	lprofile = (profile_t *)switch_core_alloc(pool, sizeof(profile_t));
+	if (lprofile) {
+		lprofile->name = switch_core_strdup(pool, name);
+		lprofile->srgs_mime_type = "application/srgs";
+		lprofile->srgs_xml_mime_type = "application/srgs+xml";
+		lprofile->gsl_mime_type = "application/x-nuance-gsl";
+		lprofile->jsgf_mime_type = "application/x-jsgf";
+		*profile = lprofile;
+	} else {
+		*profile = NULL;
+		status = SWITCH_STATUS_FALSE;
+	}
+	
+	return status;
+}
+
 /**
  * Inspect text to determine if its first non-whitespace text matches "match"
  * @param text the text to inspect.
@@ -694,7 +749,7 @@
 		status = SWITCH_STATUS_FALSE;
 		goto done;
 	}
-	
+	schan->profile = NULL;
 	schan->type = type;
 	schan->application = app;
 	schan->state = SPEECH_CHANNEL_CLOSED;
@@ -702,7 +757,7 @@
 	schan->params = NULL;
 	schan->rate = rate;
 	schan->codec = switch_core_strdup(pool, codec);
-
+	
 	if (!strcmp("L16", schan->codec)) {
 		schan->silence = 0;
 	} else {
@@ -759,10 +814,10 @@
  * Open the speech channel
  *
  * @param schannel the channel to open
- * @param profile_name the profile to use
+ * @param profile the profile to use
  * @return SWITCH_STATUS_FALSE if failed, SWITCH_STATUS_RESTART if retry can be attempted with another profile, SWITCH_STATUS_SUCCESS if successful
  */
-static switch_status_t speech_channel_open(speech_channel_t *schannel, const char *profile_name)
+static switch_status_t speech_channel_open(speech_channel_t *schannel, profile_t *profile)
 {
 	switch_status_t status = SWITCH_STATUS_SUCCESS;
 	mpf_termination_t *termination = NULL;
@@ -770,17 +825,19 @@
 	mrcp_resource_type_e resource_type;
 
 	switch_mutex_lock(schannel->mutex);
-
+	
 	/* make sure we can open channel */
 	if (schannel->state != SPEECH_CHANNEL_CLOSED) {
 		status = SWITCH_STATUS_FALSE;
 		goto done;
 	}
 
+	schannel->profile = profile;
+
 	/* create MRCP session */
-	if ((schannel->unimrcp_session = mrcp_application_session_create(schannel->application->app, profile_name, schannel)) == NULL) {	
+	if ((schannel->unimrcp_session = mrcp_application_session_create(schannel->application->app, profile->name, schannel)) == NULL) {	
 		/* profile doesn't exist? */
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "(%s) Unable to create session with %s\n", schannel->name, profile_name);
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "(%s) Unable to create session with %s\n", schannel->name, profile->name);
 		status = SWITCH_STATUS_RESTART;
 		goto done;
 	}
@@ -810,7 +867,7 @@
 		termination = mrcp_application_source_termination_create(schannel->unimrcp_session, &schannel->application->audio_stream_vtable, codec, schannel);
 	}
 	if(termination == NULL) {
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "(%s) Unable to create termination with %s\n", schannel->name, profile_name);
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "(%s) Unable to create termination with %s\n", schannel->name, profile->name);
 		mrcp_application_session_destroy(schannel->unimrcp_session);
 		status = SWITCH_STATUS_FALSE;
 		goto done;
@@ -821,7 +878,7 @@
 		resource_type = MRCP_RECOGNIZER_RESOURCE;
 	}
 	if ((schannel->unimrcp_channel = mrcp_application_channel_create(schannel->unimrcp_session, resource_type, termination, NULL, schannel)) == NULL) {
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "(%s) Unable to create channel with %s\n", schannel->name, profile_name);
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "(%s) Unable to create channel with %s\n", schannel->name, profile->name);
 		mrcp_application_session_destroy(schannel->unimrcp_session);
 		status = SWITCH_STATUS_FALSE;
 		goto done;
@@ -829,7 +886,7 @@
 
 	/* add channel to session... this establishes the connection to the MRCP server */
 	if (mrcp_application_channel_add(schannel->unimrcp_session, schannel->unimrcp_channel) != TRUE) {
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "(%s) Unable to add channel to session with %s\n", schannel->name, profile_name);
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "(%s) Unable to add channel to session with %s\n", schannel->name, profile->name);
 		mrcp_application_session_destroy(schannel->unimrcp_session);
 		status = SWITCH_STATUS_FALSE;
 		goto done;
@@ -1322,10 +1379,11 @@
 {
 	switch_status_t status = SWITCH_STATUS_SUCCESS;
 	speech_channel_t *schannel = NULL;
-	const char *profile = sh->param;
+	const char *profile_name = sh->param;
+	profile_t *profile = NULL;
 	int speech_channel_number = get_next_speech_channel_number();
 	char name[200] = { 0 };
-
+	
 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "speech_handle: name = %s, rate = %d, speed = %d, samples = %d, voice = %s, engine = %s, param = %s\n",
 						sh->name, sh->rate, sh->speed, sh->samples, sh->voice, sh->engine, sh->param); 
 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "voice = %s, rate = %d\n", voice_name, rate);
@@ -1343,8 +1401,14 @@
 	sh->private_info = schannel;
 
 	/* try to open an MRCP channel */
-	if (switch_strlen_zero(profile)) {
-		profile = globals.unimrcp_default_synth_profile;
+	if (switch_strlen_zero(profile_name)) {
+		profile_name = globals.unimrcp_default_synth_profile;
+	}
+	profile = (profile_t *)switch_core_hash_find(globals.profiles, profile_name);
+	if (!profile) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "(%s) Can't find profile, %s\n", name, profile_name);
+		status = SWITCH_STATUS_FALSE;
+		goto done;
 	}
 	if (speech_channel_open(schannel, profile) != SWITCH_STATUS_SUCCESS) {
 		status = SWITCH_STATUS_FALSE;
@@ -1765,17 +1829,18 @@
 /**
  * Get the MIME type for this grammar type
  * @param type the grammar type
+ * @param profile the profile requesting the type
  * @return the MIME type
  */
-static const char *grammar_type_to_mime(grammar_type_t type)
+static const char *grammar_type_to_mime(grammar_type_t type, profile_t *profile)
 {
 	switch(type) {
 		case GRAMMAR_TYPE_UNKNOWN: return "";
 		case GRAMMAR_TYPE_URI: return "text/uri-list";
-		case GRAMMAR_TYPE_SRGS: return "application/srgs";
-		case GRAMMAR_TYPE_SRGS_XML: return "application/srgs+xml";
-		case GRAMMAR_TYPE_NUANCE_GSL: return "application/x-nuance-gsl";
-		case GRAMMAR_TYPE_JSGF: return "application/x-jsgf";
+		case GRAMMAR_TYPE_SRGS: return profile->srgs_mime_type;
+		case GRAMMAR_TYPE_SRGS_XML: return profile->srgs_xml_mime_type;
+		case GRAMMAR_TYPE_NUANCE_GSL: return profile->gsl_mime_type;
+		case GRAMMAR_TYPE_JSGF: return profile->jsgf_mime_type;
 	}
 	return "";
 }
@@ -1829,7 +1894,7 @@
 	}
 
 	/* set Content-Type */
-	mime_type = grammar_type_to_mime(r->grammar->type);
+	mime_type = grammar_type_to_mime(r->grammar->type, schannel->profile);
 	if (switch_strlen_zero(mime_type)) {
 		status = SWITCH_STATUS_FALSE;
 		goto done;
@@ -1923,7 +1988,7 @@
 			status = SWITCH_STATUS_FALSE;
 			goto done;
 		}
-		mime_type = grammar_type_to_mime(type);
+		mime_type = grammar_type_to_mime(type, schannel->profile);
 		if (switch_strlen_zero(mime_type)) {
 			status = SWITCH_STATUS_FALSE;
 			goto done;
@@ -2404,7 +2469,8 @@
 	speech_channel_t *schannel = NULL;
 	int speech_channel_number = get_next_speech_channel_number();
 	char name[200] = { 0 };
-	const char *profile;
+	const char *profile_name;
+	profile_t *profile = NULL;
 
 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "asr_handle: name = %s, codec = %s, rate = %d, grammar = %s, param = %s\n",
 		ah->name, ah->codec, ah->rate, ah->grammar, ah->param);
@@ -2424,7 +2490,13 @@
 	memset(schannel->data, 0, sizeof(recognizer_data_t));
 
 	/* try to open an MRCP channel */
-	profile = switch_strlen_zero(dest) ? globals.unimrcp_default_recog_profile : dest;
+	profile_name = switch_strlen_zero(dest) ? globals.unimrcp_default_recog_profile : dest;
+	profile = (profile_t *)switch_core_hash_find(globals.profiles, profile_name);
+	if (!profile) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "(%s) Can't find profile, %s\n", name, profile_name);
+		status = SWITCH_STATUS_FALSE;
+		goto done;
+	}
 	status = speech_channel_open(schannel, profile);
 
  done:
@@ -2524,7 +2596,7 @@
 			goto done;
 		}
 	}
-	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "(%s) grammar is %s\n", schannel->name, grammar_type_to_mime(type));
+	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "(%s) grammar is %s\n", schannel->name, grammar_type_to_mime(type, schannel->profile));
 
 	/* load the grammar and start recognition */
 	if (recog_channel_load_grammar(schannel, lname, type, grammar_data) != SWITCH_STATUS_SUCCESS) {
@@ -2996,6 +3068,32 @@
 }
 
 /**
+ * set mod_unimrcp-specific profile configuration
+ * 
+ * @param profile the MRCP profile to configure
+ * @param param the param name
+ * @param val the param value
+ * @param pool the memory pool to use
+ */
+static int process_profile_config(profile_t *profile, const char *param, const char *val, switch_memory_pool_t *pool)
+{
+	int mine = 1;
+	if (strcasecmp(param, "jsgf-mime-type") == 0) {
+		profile->jsgf_mime_type = switch_core_strdup(pool, val);
+	} else if (strcasecmp(param, "gsl-mime-type") == 0) {
+		profile->gsl_mime_type = switch_core_strdup(pool, val);
+	} else if (strcasecmp(param, "srgs-xml-mime-type") == 0) {
+		profile->srgs_xml_mime_type = switch_core_strdup(pool, val);
+	} else if (strcasecmp(param, "srgs-mime-type") == 0) {
+		profile->srgs_mime_type = switch_core_strdup(pool, val);
+	} else {
+		mine = 0;
+	}
+
+	return mine;
+}
+
+/**
  * set RTP config struct with param, val pair 
  * @param client the MRCP client
  * @param rtp_config the config struct to set
@@ -3112,7 +3210,7 @@
  *
  * @return the MRCP client
  */
-static mrcp_client_t *mod_unimrcp_client_create()
+static mrcp_client_t *mod_unimrcp_client_create(switch_memory_pool_t *mod_pool)
 {
 	switch_xml_t cfg = NULL, xml = NULL, profiles = NULL, profile = NULL;
 	mrcp_client_t *client = NULL;
@@ -3128,7 +3226,7 @@
 	client = mrcp_client_create(globals.unimrcp_dir_layout);
 	if (!client)
 		goto done;
-	
+
 	pool = mrcp_client_memory_pool_get(client);
 	if (!pool)
 		goto done;
@@ -3177,6 +3275,7 @@
 			mpf_termination_factory_t *termination_factory = NULL;
 			mrcp_profile_t * mprofile = NULL;
 			mpf_rtp_config_t *rtp_config = NULL;
+			profile_t *mod_profile = NULL;
 			
 			/* get profile attributes */
 			const char *name = apr_pstrdup(pool, switch_xml_attr(profile, "name"));
@@ -3187,6 +3286,10 @@
 				goto done;
 			}
 
+			/* prepare mod_unimrcp's profile for configuration */
+			profile_create(&mod_profile, name, mod_pool);
+			switch_core_hash_insert(globals.profiles, mod_profile->name, mod_profile);
+
 			/* create RTP config, common to MRCPv1 and MRCPv2 */
 			rtp_config = mpf_rtp_config_create(pool);
 			rtp_config->rtp_port_min = DEFAULT_RTP_PORT_MIN;
@@ -3211,7 +3314,8 @@
 					}
 					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Loading Param %s:%s\n", param_name, param_value);
 					if (!process_mrcpv1_config(config, param_name, param_value, pool) && 
-						!process_rtp_config(client, rtp_config, param_name, param_value, pool)) {
+						!process_rtp_config(client, rtp_config, param_name, param_value, pool) &&
+						!process_profile_config(mod_profile, param_name, param_value, mod_pool)) {
 						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unknown param %s\n", param_name);
 					}
 				}
@@ -3238,7 +3342,8 @@
 					}
 					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Loading Param %s:%s\n", param_name, param_value);
 					if (!process_mrcpv2_config(config, param_name, param_value, pool) &&
-						!process_rtp_config(client, rtp_config, param_name, param_value, pool)) {
+						!process_rtp_config(client, rtp_config, param_name, param_value, pool) &&
+						!process_profile_config(mod_profile, param_name, param_value, mod_pool)) {
 						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unknown param %s\n", param_name);
 					}
 				}
@@ -3283,9 +3388,9 @@
 	*module_interface = switch_loadable_module_create_module_interface(pool, modname);
 
 	memset(&globals, 0, sizeof(globals));
-
 	switch_mutex_init(&globals.mutex, SWITCH_MUTEX_UNNESTED, pool);
 	globals.speech_channel_number = 0;
+	switch_core_hash_init_case(&globals.profiles, pool, SWITCH_FALSE /* case_sensitive */);
 
 	/* get MRCP module configuration */
 	mod_unimrcp_do_config();
@@ -3310,7 +3415,7 @@
 	apt_log_ext_handler_set(unimrcp_log);
 
 	/* Create the MRCP client */
-	if ((globals.mrcp_client = mod_unimrcp_client_create()) == NULL) {
+	if ((globals.mrcp_client = mod_unimrcp_client_create(pool)) == NULL) {
 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to create mrcp client\n");
 		return SWITCH_STATUS_FALSE;
 	}
@@ -3347,6 +3452,7 @@
 	globals.mrcp_client = 0;
 
 	switch_mutex_destroy(globals.mutex);
+	switch_core_hash_destroy(&globals.profiles);
 
 	return SWITCH_STATUS_SUCCESS;
 }



More information about the Freeswitch-svn mailing list