[asterisk-commits] branch oej/siptransfer r19704 - in /team/oej/siptransfer: ./ apps/ channels/ ...

asterisk-commits at lists.digium.com asterisk-commits at lists.digium.com
Thu Apr 13 00:44:59 MST 2006


Author: oej
Date: Thu Apr 13 02:44:52 2006
New Revision: 19704

URL: http://svn.digium.com/view/asterisk?rev=19704&view=rev
Log:
Reset automerge

Modified:
    team/oej/siptransfer/   (props changed)
    team/oej/siptransfer/apps/app_speech_utils.c
    team/oej/siptransfer/channels/chan_sip.c
    team/oej/siptransfer/configs/modules.conf.sample
    team/oej/siptransfer/doc/speechrec.txt
    team/oej/siptransfer/formats/format_wav_gsm.c
    team/oej/siptransfer/include/asterisk/compat.h
    team/oej/siptransfer/include/asterisk/lock.h
    team/oej/siptransfer/include/asterisk/speech.h
    team/oej/siptransfer/res/res_speech.c

Propchange: team/oej/siptransfer/
------------------------------------------------------------------------------
    automerge = http://edvina.net/training/

Propchange: team/oej/siptransfer/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Thu Apr 13 02:44:52 2006
@@ -1,1 +1,1 @@
-/trunk:1-19576
+/trunk:1-19703

Modified: team/oej/siptransfer/apps/app_speech_utils.c
URL: http://svn.digium.com/view/asterisk/team/oej/siptransfer/apps/app_speech_utils.c?rev=19704&r1=19703&r2=19704&view=diff
==============================================================================
--- team/oej/siptransfer/apps/app_speech_utils.c (original)
+++ team/oej/siptransfer/apps/app_speech_utils.c Thu Apr 13 02:44:52 2006
@@ -86,6 +86,15 @@
 "If you call this application but end up wanting to recognize more speech, you must call SpeechCreate\n"
 	"again before calling any other application. It takes no arguments.\n";
 
+static char *speechload_descrip =
+"SpeechLoadGrammar(Grammar Name|Path)\n"
+"Load a grammar only on the channel, not globally.\n"
+"It takes the grammar name as first argument and path as second.\n";
+
+static char *speechunload_descrip =
+"SpeechUnloadGrammar(Grammar Name)\n"
+"Unload a grammar. It takes the grammar name as the only argument.\n";
+
 /*! \brief Helper function used by datastores to destroy the speech structure upon hangup */
 static void destroy_callback(void *data)
 {
@@ -121,6 +130,161 @@
 
 	return speech;
 }
+
+/* Helper function to find a specific speech recognition result by number */
+static struct ast_speech_result *find_result(struct ast_speech_result *results, int num)
+{
+	struct ast_speech_result *result = NULL;
+	int i = 0;
+
+	result = results;
+	while (result) {
+		if (i == num)
+			break;
+		i++;
+		result = result->next;
+	}
+
+	return result;
+}
+
+/*! \brief SPEECH_SCORE() Dialplan Function */
+static int speech_score(struct ast_channel *chan, char *cmd, char *data,
+		       char *buf, size_t len)
+{
+	struct ast_speech_result *result = NULL;
+	struct ast_speech *speech = find_speech(chan);
+	char tmp[128] = "";
+
+	if (data == NULL || speech == NULL || !(result = find_result(speech->results, atoi(data))))
+		return -1;
+	
+	snprintf(tmp, sizeof(tmp), "%d", result->score);
+	
+	ast_copy_string(buf, tmp, len);
+
+	return 0;
+}
+
+static struct ast_custom_function speech_score_function = {
+        .name = "SPEECH_SCORE",
+        .synopsis = "Gets the confidence score of a result.\n",
+        .syntax = "SPEECH_SCORE(result number)",
+        .desc =
+        "Gets the confidence score of a result.\n",
+        .read = speech_score,
+        .write = NULL,
+};
+
+/*! \brief SPEECH_TEXT() Dialplan Function */
+static int speech_text(struct ast_channel *chan, char *cmd, char *data,
+			char *buf, size_t len)
+{
+        struct ast_speech_result *result = NULL;
+        struct ast_speech *speech = find_speech(chan);
+
+	if (data == NULL || speech == NULL || !(result = find_result(speech->results, atoi(data))))
+                return -1;
+
+	if (result->text != NULL)
+		ast_copy_string(buf, result->text, len);
+
+        return 0;
+}
+
+static struct ast_custom_function speech_text_function = {
+        .name = "SPEECH_TEXT",
+        .synopsis = "Gets the recognized text of a result.\n",
+        .syntax = "SPEECH_TEXT(result number)",
+        .desc =
+        "Gets the recognized text of a result.\n",
+        .read = speech_text,
+        .write = NULL,
+};
+
+/*! \brief SPEECH_GRAMMAR() Dialplan Function */
+static int speech_grammar(struct ast_channel *chan, char *cmd, char *data,
+			char *buf, size_t len)
+{
+        struct ast_speech_result *result = NULL;
+        struct ast_speech *speech = find_speech(chan);
+
+	if (data == NULL || speech == NULL || !(result = find_result(speech->results, atoi(data))))
+                return -1;
+
+	if (result->grammar != NULL)
+		ast_copy_string(buf, result->grammar, len);
+
+        return 0;
+}
+
+static struct ast_custom_function speech_grammar_function = {
+        .name = "SPEECH_GRAMMAR",
+        .synopsis = "Gets the matched grammar of a result if available.",
+        .syntax = "SPEECH_GRAMMAR(result number)",
+        .desc =
+        "Gets the matched grammar of a result if available.\n",
+        .read = speech_grammar,
+        .write = NULL,
+};
+
+/*! \brief SPEECH() Dialplan Function */
+static int speech_read(struct ast_channel *chan, char *cmd, char *data,
+			char *buf, size_t len)
+{
+	int results = 0;
+	struct ast_speech_result *result = NULL;
+	struct ast_speech *speech = find_speech(chan);
+	char tmp[128] = "";
+
+	/* Now go for the various options */
+	if (!strcasecmp(data, "status")) {
+		if (speech != NULL)
+			ast_copy_string(buf, "1", len);
+		else
+			ast_copy_string(buf, "0", len);
+		return 0;
+	}
+
+	/* Make sure we have a speech structure for everything else */
+	if (speech == NULL) {
+		return -1;
+	}
+
+	/* Check to see if they are checking for silence */
+	if (!strcasecmp(data, "spoke")) {
+		if (ast_test_flag(speech, AST_SPEECH_SPOKE))
+			ast_copy_string(buf, "1", len);
+		else
+			ast_copy_string(buf, "0", len);
+	} else if (!strcasecmp(data, "results")) {
+		/* Count number of results */
+		result = speech->results;
+		while (result) {
+			results++;
+			result = result->next;
+		}
+		snprintf(tmp, sizeof(tmp), "%d", results);
+		ast_copy_string(buf, tmp, len);
+	}
+
+	return 0;
+}
+
+static struct ast_custom_function speech_function = {
+        .name = "SPEECH",
+        .synopsis = "Gets information about speech recognition results.",
+        .syntax = "SPEECH(argument)",
+        .desc =
+	"Gets information about speech recognition results.\n"
+	"status:   Returns 1 upon speech object existing, or 0 if not\n"
+	"spoke:  Returns 1 if spoker spoke, or 0 if not\n"
+	"results:  Returns number of results that were recognized\n",
+        .read = speech_read,
+        .write = NULL,
+};
+
+
 
 /*! \brief SpeechCreate() Dialplan Application */
 static int speech_create(struct ast_channel *chan, void *data)
@@ -153,6 +317,63 @@
 	LOCAL_USER_REMOVE(u);
 
 	return 0;
+}
+
+/*! \brief SpeechLoadGrammar(Grammar Name|Path) Dialplan Application */
+static int speech_load(struct ast_channel *chan, void *data)
+{
+	int res = 0, argc = 0;
+	struct localuser *u = NULL;
+	struct ast_speech *speech = find_speech(chan);
+	char *argv[2], *args = NULL, *name = NULL, *path = NULL;
+
+	if (!(args = ast_strdupa(data)))
+                return -1;
+
+	LOCAL_USER_ADD(u);
+
+	if (speech == NULL) {
+		LOCAL_USER_REMOVE(u);
+                return -1;
+        }
+
+	/* Parse out arguments */
+	argc = ast_app_separate_args(args, '|', argv, sizeof(argv) / sizeof(argv[0]));
+	if (argc != 2) {
+		LOCAL_USER_REMOVE(u);
+		return -1;
+	}
+	name = argv[0];
+	path = argv[1];
+
+        /* Load the grammar locally on the object */
+        res = ast_speech_grammar_load(speech, name, path);
+
+        LOCAL_USER_REMOVE(u);
+
+        return res;
+}
+
+/*! \brief SpeechUnloadGrammar(Grammar Name) Dialplan Application */
+static int speech_unload(struct ast_channel *chan, void *data)
+{
+        int res = 0;
+        struct localuser *u = NULL;
+        struct ast_speech *speech = find_speech(chan);
+
+        LOCAL_USER_ADD(u);
+
+        if (speech == NULL) {
+                LOCAL_USER_REMOVE(u);
+                return -1;
+        }
+
+        /* Unload the grammar */
+        res = ast_speech_grammar_unload(speech, data);
+
+        LOCAL_USER_REMOVE(u);
+
+        return res;
 }
 
 /*! \brief SpeechDeactivateGrammar(Grammar Name) Dialplan Application */
@@ -272,226 +493,207 @@
 /*! \brief SpeechBackground(Sound File|Timeout) Dialplan Application */
 static int speech_background(struct ast_channel *chan, void *data)
 {
-	unsigned int timeout = 0;
-	int res = 0, done = 0, concepts = 0, argc = 0, started = 0;
-	struct localuser *u = NULL;
-	struct ast_speech *speech = find_speech(chan);
-	struct ast_speech_result *results = NULL, *result = NULL;
-	struct ast_frame *f = NULL;
-	int oldreadformat = AST_FORMAT_SLINEAR;
-	char tmp[256] = "", tmp2[256] = "";
-	char dtmf[AST_MAX_EXTENSION] = "";
-	time_t start, current;
-	struct ast_datastore *datastore = NULL;
-	char *argv[2], *args = NULL, *filename = NULL;
-
-	if (!(args = ast_strdupa(data)))
-                return -1;
-
-	LOCAL_USER_ADD(u);
-
-	if (speech == NULL) {
-		LOCAL_USER_REMOVE(u);
-		return -1;
-	}
-
-	/* Record old read format */
-	oldreadformat = chan->readformat;
-
-	/* Change read format to be signed linear */
-	if (ast_set_read_format(chan, AST_FORMAT_SLINEAR)) {
-		LOCAL_USER_REMOVE(u);
-		return -1;
-	}
-
-	/* Parse out options */
-	argc = ast_app_separate_args(args, '|', argv, sizeof(argv) / sizeof(argv[0]));
-	if (argc > 0) {
-		/* Yay sound file */
-		filename = argv[0];
-		if (argv[1] != NULL)
-			timeout = atoi(argv[1]);
-	}
-
-	/* Start streaming the file if possible and specified */
-	if (filename != NULL && ast_streamfile(chan, filename, chan->language)) {
-		/* An error occured while streaming */
-		ast_set_read_format(chan, oldreadformat);
-		LOCAL_USER_REMOVE(u);
-		return -1;
-	}
-
-	/* Before we go into waiting for stuff... make sure the structure is ready, if not - start it again */
-	if (speech->state == AST_SPEECH_STATE_NOT_READY || speech->state == AST_SPEECH_STATE_DONE) {
-		speech->state = AST_SPEECH_STATE_NOT_READY;
-		ast_speech_start(speech);
-	}
-
-	/* Okay it's streaming so go into a loop grabbing frames! */
-	while (done == 0) {
-		/* Run scheduled stuff */
+        unsigned int timeout = 0;
+        int res = 0, done = 0, argc = 0, started = 0;
+        struct localuser *u = NULL;
+        struct ast_speech *speech = find_speech(chan);
+        struct ast_frame *f = NULL;
+        int oldreadformat = AST_FORMAT_SLINEAR;
+        char dtmf[AST_MAX_EXTENSION] = "";
+        time_t start, current;
+        struct ast_datastore *datastore = NULL;
+        char *argv[2], *args = NULL, *filename = NULL, tmp[2] = "";
+
+        if (!(args = ast_strdupa(data)))
+                return -1;
+
+        LOCAL_USER_ADD(u);
+
+        if (speech == NULL) {
+                LOCAL_USER_REMOVE(u);
+                return -1;
+        }
+
+        /* Record old read format */
+        oldreadformat = chan->readformat;
+
+        /* Change read format to be signed linear */
+        if (ast_set_read_format(chan, AST_FORMAT_SLINEAR)) {
+                LOCAL_USER_REMOVE(u);
+                return -1;
+        }
+
+        /* Parse out options */
+        argc = ast_app_separate_args(args, '|', argv, sizeof(argv) / sizeof(argv[0]));
+        if (argc > 0) {
+                /* Yay sound file */
+                filename = argv[0];
+                if (argv[1] != NULL)
+                        timeout = atoi(argv[1]);
+        }
+
+        /* Start streaming the file if possible and specified */
+        if (filename != NULL && ast_streamfile(chan, filename, chan->language)) {
+                /* An error occured while streaming */
+                ast_set_read_format(chan, oldreadformat);
+                LOCAL_USER_REMOVE(u);
+                return -1;
+        }
+
+        /* Before we go into waiting for stuff... make sure the structure is ready, if not - start it again */
+        if (speech->state == AST_SPEECH_STATE_NOT_READY || speech->state == AST_SPEECH_STATE_DONE) {
+		ast_speech_change_state(speech, AST_SPEECH_STATE_NOT_READY);
+                ast_speech_start(speech);
+        }
+
+        /* Okay it's streaming so go into a loop grabbing frames! */
+        while (done == 0) {
+                /* Run scheduled stuff */
                 ast_sched_runq(chan->sched);
 
-		/* Yay scheduling */
-		res = ast_sched_wait(chan->sched);
-		if (res < 0) {
-			res = 1000;
-		}
-
-		/* If there is a frame waiting, get it - if not - oh well */
-		if (ast_waitfor(chan, res) > 0) {
-			f = ast_read(chan);
-			if (f == NULL) {
-				/* The channel has hung up most likely */
-				done = 3;
+                /* Yay scheduling */
+                res = ast_sched_wait(chan->sched);
+                if (res < 0) {
+                        res = 1000;
+                }
+
+                /* If there is a frame waiting, get it - if not - oh well */
+                if (ast_waitfor(chan, res) > 0) {
+                        f = ast_read(chan);
+                        if (f == NULL) {
+                                /* The channel has hung up most likely */
+                                done = 3;
+                                break;
+                        }
+                }
+
+		/* Do timeout check (shared between audio/dtmf) */
+		if (started == 1) {
+			time(&current);
+			if ((current-start) >= timeout) {
+				done = 1;
 				break;
 			}
 		}
 
-		/* Do checks on speech structure to see if it's changed */
-		ast_mutex_lock(&speech->lock);
-		if (ast_test_flag(speech, AST_SPEECH_QUIET) && chan->stream != NULL) {
-			ast_stopstream(chan);
+                /* Do checks on speech structure to see if it's changed */
+                ast_mutex_lock(&speech->lock);
+                if (ast_test_flag(speech, AST_SPEECH_QUIET) && chan->stream != NULL) {
+                        ast_stopstream(chan);
 			ast_clear_flag(speech, AST_SPEECH_QUIET);
-		}
-		/* Check state so we can see what to do */
-		switch (speech->state) {
-		case AST_SPEECH_STATE_READY:
-			/* If audio playback has stopped do a check for timeout purposes */
-			if (chan->streamid == -1 && chan->timingfunc == NULL)
-				ast_stopstream(chan);
-			if (chan->stream == NULL && timeout > 0) {
-				/* If start time is not yet done... do it */
-				if (started == 0) {
-					time(&start);
-					started = 1;
-				} else {
-					time(&current);
-					if ((current-start) >= timeout) {
-						pbx_builtin_setvar_helper(chan, "SILENCE", "1");
-						done = 1;
-						break;
-					}
-				}
-			}
-			/* Deal with audio frames if present */
-			if (f != NULL && f->frametype == AST_FRAME_VOICE) {
-				ast_speech_write(speech, f->data, f->datalen);
-			}
-			break;
-		case AST_SPEECH_STATE_WAIT:
-			/* Cue up waiting sound if not already playing */
-			if (chan->stream == NULL) {
-				if (speech->processing_sound != NULL) {
+                }
+                /* Check state so we can see what to do */
+                switch (speech->state) {
+                case AST_SPEECH_STATE_READY:
+                        /* If audio playback has stopped do a check for timeout purposes */
+                        if (chan->streamid == -1 && chan->timingfunc == NULL)
+                                ast_stopstream(chan);
+                        if (chan->stream == NULL && timeout > 0 && started == 0) {
+				time(&start);
+				started = 1;
+                        }
+                        /* Deal with audio frames if present */
+                        if (f != NULL && f->frametype == AST_FRAME_VOICE) {
+                                ast_speech_write(speech, f->data, f->datalen);
+                        }
+                        break;
+                case AST_SPEECH_STATE_WAIT:
+                        /* Cue up waiting sound if not already playing */
+                        if (chan->stream == NULL) {
+                                if (speech->processing_sound != NULL) {
                                         if (strlen(speech->processing_sound) > 0 && strcasecmp(speech->processing_sound,"none")) {
                                                 speech_streamfile(chan, speech->processing_sound, chan->language);
                                         }
-				}
-			} else if (chan->streamid == -1 && chan->timingfunc == NULL) {
-				ast_stopstream(chan);
+                                }
+                        } else if (chan->streamid == -1 && chan->timingfunc == NULL) {
+                                ast_stopstream(chan);
                                 if (speech->processing_sound != NULL) {
-					if (strlen(speech->processing_sound) > 0 && strcasecmp(speech->processing_sound,"none")) {
-						speech_streamfile(chan, speech->processing_sound, chan->language);
-					}
+                                        if (strlen(speech->processing_sound) > 0 && strcasecmp(speech->processing_sound,"none")) {
+                                                speech_streamfile(chan, speech->processing_sound, chan->language);
+                                        }
                                 }
-			}
-			break;
-		case AST_SPEECH_STATE_DONE:
-			/* Assume there will be no results by default */
-			pbx_builtin_setvar_helper(chan, "RESULTS", "0");
-			pbx_builtin_setvar_helper(chan, "SILENCE", "0");
-			/* Decoding is done and over... see if we have results */
-			results = ast_speech_results_get(speech);
-			if (results != NULL) {
-				for (result=results; result!=NULL; result=result->next) {
-					/* Text */
-					snprintf(tmp, sizeof(tmp), "TEXT%d", concepts);
-					pbx_builtin_setvar_helper(chan, tmp, result->text);
-					/* Now... score! */
-					snprintf(tmp, sizeof(tmp), "SCORE%d", concepts);
-					snprintf(tmp2, sizeof(tmp2), "%d", result->score);
-					pbx_builtin_setvar_helper(chan, tmp, tmp2);
-					concepts++;
-				}
-				/* Expose number of results to dialplan */
-				snprintf(tmp, sizeof(tmp), "%d", concepts);
-				pbx_builtin_setvar_helper(chan, "RESULTS", tmp);
-				/* Destroy the results since they are now in the dialplan */
-				ast_speech_results_free(results);
-			}
-			/* Now that we are done... let's switch back to not ready state */
-			speech->state = AST_SPEECH_STATE_NOT_READY;
-			/* Break out of our background too */
-			done = 1;
-			/* Stop audio playback */
-			if (chan->stream != NULL) {
-				ast_stopstream(chan);
-			}
-			break;
-		default:
-			break;
-		}
-		ast_mutex_unlock(&speech->lock);
-
-		/* Deal with other frame types */
-		if (f != NULL) {
-			/* Free the frame we received */
-			switch (f->frametype) {
-			case AST_FRAME_DTMF:
+                        }
+                        break;
+                case AST_SPEECH_STATE_DONE:
+                        /* Copy to speech structure the results, if available */
+                        speech->results = ast_speech_results_get(speech);
+                        /* Now that we are done... let's switch back to not ready state */
+			ast_speech_change_state(speech, AST_SPEECH_STATE_NOT_READY);
+                        /* Break out of our background too */
+                        done = 1;
+                        /* Stop audio playback */
+                        if (chan->stream != NULL) {
+                                ast_stopstream(chan);
+                        }
+                        break;
+                default:
+                        break;
+                }
+                ast_mutex_unlock(&speech->lock);
+
+                /* Deal with other frame types */
+                if (f != NULL) {
+                        /* Free the frame we received */
+                        switch (f->frametype) {
+                        case AST_FRAME_DTMF:
 				if (f->subclass == '#') {
-					/* Input is done, throw it into the dialplan */
-					pbx_builtin_setvar_helper(chan, "RESULTS", "1");
-					pbx_builtin_setvar_helper(chan, "SCORE0", "1000");
-					pbx_builtin_setvar_helper(chan, "TEXT0", dtmf);
 					done = 1;
 				} else {
 					if (chan->stream != NULL) {
 						ast_stopstream(chan);
+						/* Change timeout to be 5 seconds for DTMF input */
+						timeout = 5;
+						time(&start);
+						started = 1;
 					}
-					/* Start timeout if not already started */
-					if (strlen(dtmf) == 0) {
-						time(&start);
-					}
-					/* Append to the current information */
 					snprintf(tmp, sizeof(tmp), "%c", f->subclass);
 					strncat(dtmf, tmp, sizeof(dtmf));
 				}
-				break;
-			case AST_FRAME_CONTROL:
-				ast_log(LOG_NOTICE, "Have a control frame of subclass %d\n", f->subclass);
-				switch (f->subclass) {
-				case AST_CONTROL_HANGUP:
-					/* Since they hung up we should destroy the speech structure */
-					done = 3;
-				default:
-					break;
-				}
-			default:
-				break;
-			}
-			ast_frfree(f);
-			f = NULL;
+                                break;
+                        case AST_FRAME_CONTROL:
+                                switch (f->subclass) {
+                                case AST_CONTROL_HANGUP:
+                                        /* Since they hung up we should destroy the speech structure */
+                                        done = 3;
+                                default:
+                                        break;
+                                }
+                        default:
+                                break;
+                        }
+                        ast_frfree(f);
+                        f = NULL;
+                }
+        }
+
+	if (strlen(dtmf) > 0 && speech->results == NULL) {
+		/* We sort of make a results entry */
+		speech->results = ast_calloc(1, sizeof(*speech->results));
+		if (speech->results != NULL) {
+			speech->results->score = 1000;
+			speech->results->text = strdup(dtmf);
+			speech->results->grammar = strdup("dtmf");
 		}
 	}
 
-	/* See if it was because they hung up */
-	if (done == 3) {
-		/* Destroy speech structure */
-		ast_speech_destroy(speech);
-
-		datastore = ast_channel_datastore_find(chan, &speech_datastore, NULL);
-		if (datastore != NULL) {
-			ast_channel_datastore_remove(chan, datastore);
-		}
-	} else {
-		/* Channel is okay so restore read format */
-		ast_set_read_format(chan, oldreadformat);
-	}
-
-	LOCAL_USER_REMOVE(u);
-
-	return 0;
-}
+        /* See if it was because they hung up */
+        if (done == 3) {
+                /* Destroy speech structure */
+                ast_speech_destroy(speech);
+                datastore = ast_channel_datastore_find(chan, &speech_datastore, NULL);
+                if (datastore != NULL) {
+                        ast_channel_datastore_remove(chan, datastore);
+                }
+        } else {
+                /* Channel is okay so restore read format */
+                ast_set_read_format(chan, oldreadformat);
+        }
+
+        LOCAL_USER_REMOVE(u);
+
+        return 0;
+}
+
 
 /*! \brief SpeechDestroy() Dialplan Application */
 static int speech_destroy(struct ast_channel *chan, void *data)
@@ -526,11 +728,18 @@
 	int res = 0;
 
 	res = ast_unregister_application("SpeechCreate");
+	res |= ast_unregister_application("SpeechLoadGrammar");
+	res |= ast_unregister_application("SpeechUnloadGrammar");
 	res |= ast_unregister_application("SpeechActivateGrammar");
         res |= ast_unregister_application("SpeechDeactivateGrammar");
 	res |= ast_unregister_application("SpeechStart");
 	res |= ast_unregister_application("SpeechBackground");
 	res |= ast_unregister_application("SpeechDestroy");
+	res |= ast_unregister_application("SpeechProcessingSound");
+	res |= ast_custom_function_unregister(&speech_function);
+	res |= ast_custom_function_unregister(&speech_score_function);
+	res |= ast_custom_function_unregister(&speech_text_function);
+	res |= ast_custom_function_unregister(&speech_grammar_function);
 
 	STANDARD_HANGUP_LOCALUSERS;
 
@@ -542,13 +751,19 @@
 	int res = 0;
 
 	res = ast_register_application("SpeechCreate", speech_create, "Create a Speech Structure", speechcreate_descrip);
+	res |= ast_register_application("SpeechLoadGrammar", speech_load, "Load a Grammar", speechload_descrip);
+	res |= ast_register_application("SpeechUnloadGrammar", speech_unload, "Unload a Grammar", speechunload_descrip);
 	res |= ast_register_application("SpeechActivateGrammar", speech_activate, "Activate a Grammar", speechactivategrammar_descrip);
         res |= ast_register_application("SpeechDeactivateGrammar", speech_deactivate, "Deactivate a Grammar", speechdeactivategrammar_descrip);
 	res |= ast_register_application("SpeechStart", speech_start, "Start recognizing", speechstart_descrip);
 	res |= ast_register_application("SpeechBackground", speech_background, "Play a sound file and wait for speech to be recognized", speechbackground_descrip);
 	res |= ast_register_application("SpeechDestroy", speech_destroy, "End speech recognition", speechdestroy_descrip);
 	res |= ast_register_application("SpeechProcessingSound", speech_processing_sound, "Change background processing sound", speechprocessingsound_descrip);
-	
+	res |= ast_custom_function_register(&speech_function);
+	res |= ast_custom_function_register(&speech_score_function);
+	res |= ast_custom_function_register(&speech_text_function);
+	res |= ast_custom_function_register(&speech_grammar_function);
+
 	return res;
 }
 

Modified: team/oej/siptransfer/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/team/oej/siptransfer/channels/chan_sip.c?rev=19704&r1=19703&r2=19704&view=diff
==============================================================================
--- team/oej/siptransfer/channels/chan_sip.c (original)
+++ team/oej/siptransfer/channels/chan_sip.c Thu Apr 13 02:44:52 2006
@@ -203,14 +203,6 @@
 #define RTP 	1
 #define NO_RTP	0
 
-<<<<<<< .working
-/*! \brief Authorization scheme for call transfers */
-enum transfermodes {
-	TRANSFER_OPENFORALL, 		/*!< Allow all SIP transfers */
-	TRANSFER_CLOSED,		/*!< Allow no SIP transfers */
-};
-
-=======
 /*! \brief Authorization scheme for call transfers 
 \note Not a bitfield flag, since there are plans for other modes,
 	like "only allow transfers for authenticated devices" */
@@ -220,7 +212,6 @@
 };
 
 
->>>>>>> .merge-right.r19549
 /* Do _NOT_ make any changes to this enum, or the array following it;
    if you think you are doing the right thing, you are probably
    not doing the right thing. If you think there are changes
@@ -359,13 +350,8 @@
 } sip_options[] = {	/* XXX used in 3 places */
 	/* Replaces: header for transfer */
 	{ SIP_OPT_REPLACES,	SUPPORTED,	"replaces" },	
-<<<<<<< .working
-	/* Polycom has the wrong notation. Tss tss. */
-	{ SIP_OPT_REPLACES,  SUPPORTED,  "replace" },
-=======
 	/* One version of Polycom firmware has the wrong label */
 	{ SIP_OPT_REPLACES,	SUPPORTED,	"replace" },	
->>>>>>> .merge-right.r19549
 	/* RFC3262: PRACK 100% reliability */
 	{ SIP_OPT_100REL,	NOT_SUPPORTED,	"100rel" },	
 	/* SIP Session Timers */
@@ -553,9 +539,10 @@
 
 /*! \brief structure used in transfers */
 struct sip_dual {
-	struct ast_channel *chan1;
-	struct ast_channel *chan2;
-	struct sip_request req;
+	struct ast_channel *chan1;	/*!< First channel involved */
+	struct ast_channel *chan2;	/*!< Second channel involved */
+	struct sip_request req;		/*!< Request that caused the transfer (REFER) */
+	int seqno;			/*!< Sequence number */
 	int seqno;				/*!< Sequence number */
 };
 
@@ -571,7 +558,7 @@
 	char *authheader;		/*!< Auth header */
 	enum sip_auth_type auth_type;	/*!< Authentication type */
 	const char *replaces;		/*!< Replaces header for call transfers */
-	int transfer;		/*!< Flag: Invite Part of a SIP transfer? */
+	int transfer;			/*!< Flag - is this Invite part of a SIP transfer? (invite/replaces) */
 };
 
 /*! \brief Structure to save routing information for a SIP session */
@@ -694,6 +681,8 @@
 #define sipdebug		ast_test_flag(&global_flags[1], SIP_PAGE2_DEBUG)
 #define sipdebug_config		ast_test_flag(&global_flags[1], SIP_PAGE2_DEBUG_CONFIG)
 #define sipdebug_console	ast_test_flag(&global_flags[1], SIP_PAGE2_DEBUG_CONSOLE)
+
+
 
 /*! \brief Parameters to know status of transfer */
 enum referstatus {
@@ -829,12 +818,8 @@
 	int rtptimeout;				/*!< RTP timeout time */
 	int rtpholdtimeout;			/*!< RTP timeout when on hold */
 	int rtpkeepalive;			/*!< Send RTP packets for keepalive */
-<<<<<<< .working
-	enum transfermodes allowtransfer;	/*!< Allow transfer modes */
+	enum transfermodes allowtransfer;	/*! SIP Refer restriction scheme */
 	struct sip_refer *refer;		/*!< Refer data */
-=======
-	enum transfermodes allowtransfer;	/*! SIP Refer restriction scheme */
->>>>>>> .merge-right.r19549
 	enum subscriptiontype subscribed;	/*!< Is this dialog a subscription?  */
 	int stateid;
 	int laststate;				/*!< Last known extension state */
@@ -896,11 +881,7 @@
 	int capability;			/*!< Codec capability */
 	int inUse;			/*!< Number of calls in use */
 	int call_limit;			/*!< Limit of concurrent calls */
-<<<<<<< .working
-	enum transfermodes allowtransfer;   /*!< Allow transfer modes */
-=======
 	enum transfermodes allowtransfer;	/*! SIP Refer restriction scheme */
->>>>>>> .merge-right.r19549
 	struct ast_ha *ha;		/*!< ACL setting */
 	struct ast_variable *chanvars;	/*!< Variables to set for channel created by user */
 	int maxcallbitrate;		/*!< Maximum Bitrate for a video call */
@@ -1279,6 +1260,19 @@
 	set_rtp_peer: sip_set_rtp_peer,
 	get_codec: sip_get_codec,
 };
+
+/*! \brief Convert transfer status to string */
+static char *referstatus2str(enum referstatus rstatus)
+{
+	int i = (sizeof(referstatusstrings) / sizeof(referstatusstrings[0]));
+	int x;
+
+	for (x = 0; x < i; x++) {
+		if (referstatusstrings[x].status ==  rstatus)
+			return (char *) referstatusstrings[x].text;
+	}
+	return "";
+}
 
 
 /*! \brief returns true if 'name' (with optional trailing whitespace)
@@ -5079,7 +5073,7 @@
 	add_header(&req, "Allow", ALLOWED_METHODS);
 	add_header(&req, "Supported", SUPPORTED_EXTENSIONS);
 	if (sipdebug)
-		add_header(&req, "X-Asterisk-Info", "SIP re-invite (RTP bridge)");
+		add_header(&req, "X-asterisk-Info", "SIP re-invite (External RTP bridge)");
 	if (recordhistory)
 		append_history(p, "ReInv", "Re-invite sent");
 	add_sdp(&req, p);
@@ -6991,6 +6985,10 @@
 		ast_copy_string(tmp, req->rlPart2, sizeof(tmp));
 	
 	ast_copy_string(tmpf, get_header(req, "From"), sizeof(tmpf));
+	if (pedanticsipchecking) {
+		ast_uri_decode(tmp);
+		ast_uri_decode(tmpf);
+	}
 
 	if (pedanticsipchecking) {
 		ast_uri_decode(tmp);
@@ -11977,37 +11975,10 @@
 	struct sip_dual current;	/* Chan1: Call between asterisk and transferer */
 					/* Chan2: Call between asterisk and transferee */
 
-<<<<<<< .working
 	int res = 0;
 
 	if (ast_test_flag(req, SIP_PKT_DEBUG))
 		ast_verbose("Call %s got a SIP call transfer from %s: (REFER)!\n", p->callid, ast_test_flag(&p->flags[0], SIP_OUTGOING) ? "callee" : "caller");
-
-	if (p->allowtransfer == TRANSFER_CLOSED ) {
-		/* Transfer not allowed, decline */
-		transmit_response(p, "603 Declined (policy)", req);
-		append_history(p, "Xfer", "Refer failed. Allowtransfer == closed.");
-		return 0;
-	}
-
-	if (!p->owner) {
-		/* This is a REFER outside of an existing SIP dialog */
-		/* We can't handle that, so decline it */
-		if (option_debug > 2)
-			ast_log(LOG_DEBUG, "Call %s: Declined REFER, outside of dialog...\n", p->callid);
-		transmit_response(p, "603 Declined (No dialog)", req);
-=======
-	if (option_debug > 2)
-		ast_log(LOG_DEBUG, "SIP call transfer received for call %s (REFER)!\n", p->callid);
-
-	/* Check if transfer is allowed from this device */
-	if (p->allowtransfer == TRANSFER_CLOSED ) {
-		/* Transfer not allowed, decline */
-		transmit_response(p, "603 Declined (policy)", req);
-		append_history(p, "Xfer", "Refer failed. Allowtransfer == closed.");
-		/* Do not destroy SIP session */
-		return 0;
-	}
 
 	if (!p->owner) {
 		/* This is a REFER outside of an existing SIP dialog */
@@ -12023,26 +11994,15 @@
 		return 0;
 	}	
 
-	if (ast_strlen_zero(p->context))
-		ast_string_field_set(p, context, default_context);
-	res = get_refer_info(p, req);
-	if (res > 0) {
-		if (ast_test_flag(&p->flags[1], SIP_PAGE2_ALLOWOVERLAP)) 
-			transmit_response_with_allow(p, "484 Address Incomplete", req, 1);
-		else
-			transmit_response_with_allow(p, "404 Not Found", req, 1);
-	} else if (res < 0)
-		transmit_response_with_allow(p, "404 Not Found", req, 1);
-	else {
-		int nobye = 0;
->>>>>>> .merge-right.r19549
-		if (!ast_test_flag(req, SIP_PKT_IGNORE)) {
-			append_history(p, "Xfer", "Refer failed. Outside of dialog.");
-			ast_set_flag(&p->flags[0], SIP_ALREADYGONE);	
-			ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);	
-		}
+
+	/* Check if transfer is allowed from this device */
+	if (p->allowtransfer == TRANSFER_CLOSED ) {
+		/* Transfer not allowed, decline */
+		transmit_response(p, "603 Declined (policy)", req);
+		append_history(p, "Xfer", "Refer failed. Allowtransfer == closed.");
+		/* Do not destroy SIP session */
 		return 0;
-	}	
+	}
 
 	if(!ignore && ast_test_flag(&p->flags[0], SIP_GOTREFER)) {
 		/* Already have a pending REFER */	
@@ -13706,14 +13666,8 @@
 		} else if (!strcasecmp(v->name, "permit") ||
 				   !strcasecmp(v->name, "deny")) {
 			user->ha = ast_append_ha(v->name, v->value, user->ha);
-<<<<<<< .working
-		} else if (!strcasecmp(v->name, "allowtransfer")) {
-			if (!ast_true(v->value))	/* no */
-				user->allowtransfer = TRANSFER_CLOSED;
-=======
 		} else if (!strcasecmp(v->name, "allowtransfer")) {
 			user->allowtransfer = ast_true(v->value) ? TRANSFER_OPENFORALL : TRANSFER_CLOSED;
->>>>>>> .merge-right.r19549
 		} else if (!strcasecmp(v->name, "secret")) {
 			ast_copy_string(user->secret, v->value, sizeof(user->secret)); 
 		} else if (!strcasecmp(v->name, "md5secret")) {
@@ -14139,12 +14093,7 @@
 	global_rtptimeout = 0;
 	global_rtpholdtimeout = 0;
 	global_rtpkeepalive = 0;
-<<<<<<< .working
-	global_allowtransfer = TRANSFER_OPENFORALL;           /* Default transfer mode: Open */
-
-=======
 	global_allowtransfer = TRANSFER_OPENFORALL;	/* Merrily accept all transfers by default */
->>>>>>> .merge-right.r19549
 	global_rtautoclear = 120;
 	ast_set_flag(&global_flags[1], SIP_PAGE2_ALLOWSUBSCRIBE);	/* Default for peers, users: TRUE */
 	ast_set_flag(&global_flags[1], SIP_PAGE2_ALLOWOVERLAP);		/* Default for peers, users: TRUE */

Modified: team/oej/siptransfer/configs/modules.conf.sample
URL: http://svn.digium.com/view/asterisk/team/oej/siptransfer/configs/modules.conf.sample?rev=19704&r1=19703&r2=19704&view=diff
==============================================================================
--- team/oej/siptransfer/configs/modules.conf.sample (original)
+++ team/oej/siptransfer/configs/modules.conf.sample Thu Apr 13 02:44:52 2006
@@ -17,6 +17,9 @@
 ; An example of loading ODBC support would be:
 ;preload => res_odbc.so
 ;preload => res_config_odbc.so
+;
+; Uncomment the following if you wish to use the Speech Recognition API
+;preload => res_speech.so
 ;
 ; If you want, load the GTK console right away.  
 ; Don't load the KDE console since

Modified: team/oej/siptransfer/doc/speechrec.txt
URL: http://svn.digium.com/view/asterisk/team/oej/siptransfer/doc/speechrec.txt?rev=19704&r1=19703&r2=19704&view=diff
==============================================================================
--- team/oej/siptransfer/doc/speechrec.txt (original)
+++ team/oej/siptransfer/doc/speechrec.txt Thu Apr 13 02:44:52 2006
@@ -1,40 +1,116 @@
-Generic Speech Recognition API
-
-Dialplan Applications:
-
-The dialplan API is based around a single speech utilities application file, which exports many applications to be used for speech recognition. These include an application to prepare for speech recognition, activate a grammar, and play back a sound file while waiting for the person to speak. Using a combination of these applications you can easily make a dialplan use speech recognition without worrying about what speech recognition engine is being used.
-
-SpeechCreate(Engine Name):
-
-This application creates information to be used by all the other applications. It must be called before doing any speech recognition activities such as activating a grammar. It takes the engine name to use as the argument, if not specified the default engine will be used.
-
-If an error occurs are you are not able to create an object, the variable ERROR will be set to 1. You can then exit your speech recognition specific context and play back an error message, or resort to a DTMF based IVR.
-
-SpeechActivateGrammar(Grammar Name):
-
-This activates the specified grammar to be recognized by the engine. A grammar tells the speech recognition engine what to recognize, and how to portray it back to you in the dialplan. The grammar name is the only argument to this application.
-
-SpeechStart():
-
-Tell the speech recognition engine that it should start trying to get results from audio being fed to it. This has no arguments.
-
-SpeechBackground(Sound File|Timeout):
-
-This application plays a sound file and waits for the person to speak. Once they start speaking playback of the file stops, and silence is heard. Once they stop talking the processing sound is played to indicate the speech recognition engine is working. Once results are available the application returns and results (score and text) are available as dialplan variables. The first text and score are ${TEXT0} AND ${SCORE0} while the second are ${TEXT1} and ${SCORE1}. This may change in the future, however, to use a dialplan function instead of dialplan variables. Note it is possible to have more then one result. The first argument is the sound file and the second is the timeout. Note the timeout will only start once the sound file has stopped playing. If the timeout is reached, then the variable SILENCE is set to 1 so that you will know that the person did not speak anything.
-
-SpeechDeactivateGrammar(Grammar Name):
-
-This deactivates the specified grammar so that it is no longer recognized. The only argument is the grammar name to deactivate.
-
-SpeechProcessingSound(Sound File):
-
-This changes the processing sound that SpeechBackground plays back when the speech recognition engine is processing and working to get results. It takes the sound file as the only argument.
-
-SpeechDestroy():
-
-This destroys the information used by all the other speech recognition applications. If you call this application but end up wanting to recognize more speech, you must call SpeechCreate again before calling any other application. It takes no arguments.
-
-Dialplan Flow:
+The Asterisk Speech Recognition API
+===================================
+
+The generic speech recognition engine is implemented in the res_speech.so module.
+This module connects through the API to speech recognition software, that is
+not included in the module.
+
+To use the API, you must load the res_speech.so module before any connectors.
+For your convenience, there is a preload line commented out in the modules.conf 
+sample file.
+
+* Dialplan Applications:
+------------------------
+
+The dialplan API is based around a single speech utilities application file,
+which exports many applications to be used for speech recognition. These include an 
+application to prepare for speech recognition, activate a grammar, and play back a 
+sound file while waiting for the person to speak. Using a combination of these applications 
+you can easily make a dialplan use speech recognition without worrying about what 
+speech recognition engine is being used.
+
+- SpeechCreate(Engine Name):
+
+This application creates information to be used by all the other applications. 
+It must be called before doing any speech recognition activities such as activating a 
+grammar. It takes the engine name to use as the argument, if not specified the default 
+engine will be used.
+
+If an error occurs are you are not able to create an object, the variable ERROR will be 

[... 822 lines stripped ...]


More information about the asterisk-commits mailing list