📄 vxirec.cpp
字号:
/****************License************************************************
* Vocalocity OpenVXI
* Copyright (C) 2004-2005 by Vocalocity, Inc. All Rights Reserved.
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* Vocalocity, the Vocalocity logo, and VocalOS are trademarks or
* registered trademarks of Vocalocity, Inc.
* OpenVXI is a trademark of Scansoft, Inc. and used under license
* by Vocalocity.
***********************************************************************/
#define VXIREC_EXPORTS
#include "VXIrecAPI.h"
#include "VXIrec_utils.h"
#include "LogBlock.hpp"
#include <cstdio>
#include <cstring>
#include <sstream>
// ------*---------*---------*---------*---------*---------*---------*---------
static void ResultContentDestroy(VXIbyte **content, void *userData)
{
if (content && *content)
delete [] *content;
*content = NULL;
}
class VXIVectorHolder {
public:
VXIVectorHolder() : _vector(NULL) { _vector = VXIVectorCreate(); }
VXIVectorHolder(VXIVector * m) : _vector(m) { }
~VXIVectorHolder() { if (_vector != NULL) VXIVectorDestroy(&_vector);}
VXIVectorHolder & operator=(const VXIVectorHolder & x)
{ if (this != &x) {
if (_vector != NULL) VXIVectorDestroy(&_vector);
_vector = VXIVectorClone(x._vector); }
return *this; }
// GetValue returns the internal vector. The standard vector manipulation
// functions may then be used.
VXIVector * GetValue() const { return _vector; }
// These functions allow the holder to take ownership of an existing vector
// or to release the internal one.
VXIVector * Release()
{ VXIVector * m = _vector; _vector = NULL; return m; }
void Acquire(VXIVector * m)
{ if (_vector != NULL) VXIVectorDestroy(&_vector); else _vector = m; }
private:
VXIVectorHolder(const VXIVectorHolder &); // intentionally not defined.
VXIVector * _vector;
};
// ------*---------*---------*---------*---------*---------*---------*---------
// Global for the base diagnostic tag ID, see osbrec_utils.h for tags
//
static VXIunsigned gblDiagLogBase = 0;
// VXIrec implementation of the VXIrec interface
//
extern "C" {
struct VXIrecImpl {
// Base interface, must be first
VXIrecInterface intf;
// Class for managing grammars
VXIrecData *recData;
};
}
// A few conversion functions...
static inline VXIrecGrammar * ToVXIrecGrammar(VXIrecGrammar * i)
{ return reinterpret_cast<VXIrecGrammar *>(i); }
static inline VXIrecGrammar * FromVXIrecGrammar(VXIrecGrammar * i)
{ return reinterpret_cast<VXIrecGrammar *>(i); }
static inline VXIrecData * GetRecData(VXIrecInterface * i)
{
if (i == NULL) return NULL;
return reinterpret_cast<VXIrecImpl *>(i)->recData;
}
/*******************************************************
* Method routines for VXIrecInterface structure
*******************************************************/
// Get the VXIrec interface version supported
//
static VXIint32 VXIrecGetVersion(void)
{
return VXI_CURRENT_VERSION;
}
// Get the implementation name
//
static const VXIchar* VXIrecGetImplementationName(void)
{
static const VXIchar IMPLEMENTATION_NAME[] = COMPANY_DOMAIN L".VXIrec";
return IMPLEMENTATION_NAME;
}
static VXIrecResult VXIrecBeginSession(VXIrecInterface * pThis, VXIMap *)
{
const wchar_t* fnname = L"VXIrecBeginSession";
VXIrecData* tp = GetRecData(pThis);
if (tp == NULL) return VXIrec_RESULT_INVALID_ARGUMENT;
LogBlock logger(tp->GetLog(), gblDiagLogBase, fnname, VXIREC_MODULE);
return VXIrec_RESULT_SUCCESS;
}
static VXIrecResult VXIrecEndSession(VXIrecInterface *pThis, VXIMap *)
{
const wchar_t* fnname = L"VXIrecEndSession";
VXIrecData* tp = GetRecData(pThis);
if (tp == NULL) return VXIrec_RESULT_INVALID_ARGUMENT;
LogBlock logger(tp->GetLog(), gblDiagLogBase, fnname, VXIREC_MODULE);
tp->Clear();
return VXIrec_RESULT_SUCCESS;
}
static VXIrecResult VXIrecLoadGrammarFromString(VXIrecInterface *pThis,
const VXIMap *prop,
const VXIchar *type,
const VXIchar *str,
VXIrecGrammar **gram)
{
const wchar_t* fnname = L"VXIrecLoadGrammarFromString";
VXIrecData* tp = GetRecData(pThis);
if (tp == NULL) return VXIrec_RESULT_INVALID_ARGUMENT;
LogBlock logger(tp->GetLog(), gblDiagLogBase, fnname, VXIREC_MODULE);
// Check the arguments
if (str == NULL) {
logger = VXIrec_RESULT_INVALID_ARGUMENT;
return VXIrec_RESULT_INVALID_ARGUMENT;
}
if (type == NULL) {
logger = VXIrec_RESULT_UNSUPPORTED;
return VXIrec_RESULT_UNSUPPORTED;
}
VXIrecGrammar * gp = NULL;
vxistring srgsGram, mtype(type);
logger.logDiag(DIAG_TAG_GRAMMARS, L"%s%s", L"TYPE: ", mtype.c_str());
tp->ShowPropertyValue(prop);
if( mtype == L"application/x-jsgf" || mtype == REC_MIME_CHOICE || mtype == REC_MIME_CHOICE_DTMF)
{
// first crack the srgs grammar
JSGFInfo info;
tp->ConvertJSGFType(str, info);
// then try to convert to SRGS format
if( !tp->JSGFToSRGS(info.contentStr, srgsGram, prop) ) return VXIrec_RESULT_FAILURE;
mtype = VXI_MIME_SRGS; // reset mime type
logger.logDiag(DIAG_TAG_GRAMMARS, L"%s%s", L"Converted GRAMMAR: ", srgsGram.c_str());
}
else if( mtype == VXI_MIME_SRGS ) {
// processing below
srgsGram = str;
}
else {
// Handle your own type here, return unsupported for now
logger = VXIrec_RESULT_UNSUPPORTED;
return VXIrec_RESULT_UNSUPPORTED;
}
// Parsing SRGS grammar.
// NOTES: The parsing is very simple, therefore it may not work
// for complex grammar. As you know, this is a simulator!!!
VXIrecGrammar * gramPtr = tp->ParseSRGSGrammar(srgsGram, prop);
if( gramPtr == NULL ) return VXIrec_RESULT_FAILURE;
tp->AddGrammar(gramPtr);
*gram = ToVXIrecGrammar(gramPtr);
return VXIrec_RESULT_SUCCESS;
}
static VXIrecResult VXIrecLoadGrammarFromURI(struct VXIrecInterface *pThis,
const VXIMap *properties,
const VXIchar *type,
const VXIchar *uri,
const VXIMap *uriArgs,
VXIrecGrammar **gram)
{
VXIrecData* tp = GetRecData(pThis);
if (tp == NULL) return VXIrec_RESULT_INVALID_ARGUMENT;
const wchar_t* fnname = L"VXIrecLoadGrammarFromURI";
LogBlock logger(tp->GetLog(), gblDiagLogBase, fnname, VXIREC_MODULE);
tp->ShowPropertyValue(properties);
if (wcsncmp(uri, L"builtin", 7) == 0 ){
logger.logDiag(DIAG_TAG_GRAMMARS, L"%s", L"built-in not supported");
return VXIrec_RESULT_UNSUPPORTED;
}
VXIbyte *buffer = NULL;
VXIulong read = 0;
if (!tp->FetchContent(uri, uriArgs, &buffer, read))
return VXIrec_RESULT_FAILURE;
// NOTE: this code assumes the retieved buffer is
// composed of single byte chars. in the real world,
// that can't be assumed.
buffer[read] = 0;
VXIchar *charbuff = new VXIchar[read+1];
mbstowcs(charbuff, (char*)buffer, read+1);
VXIrecResult rc = VXIrecLoadGrammarFromString(pThis, properties,
type, charbuff, gram);
delete[] buffer;
delete[] charbuff;
return rc;
}
static VXIrecResult VXIrecLoadGrammarOption(VXIrecInterface * pThis,
const VXIMap * properties,
const VXIVector * gramChoice,
const VXIVector * gramValue,
const VXIVector * gramAcceptance,
const VXIbool isDTMF,
VXIrecGrammar ** gram)
{
const wchar_t* fnname = L"VXIrecLoadGrammarOption";
// Check the arguments
VXIrecData* tp = GetRecData(pThis);
if (tp == NULL) return VXIrec_RESULT_INVALID_ARGUMENT;
LogBlock logger(tp->GetLog(), gblDiagLogBase, fnname, VXIREC_MODULE);
if (gram == NULL) {
logger = VXIrec_RESULT_INVALID_ARGUMENT;
return VXIrec_RESULT_INVALID_ARGUMENT;
}
tp->ShowPropertyValue(properties);
VXIrecGrammar * gp = NULL;
vxistring srgsGram;
if( !tp->OptionToSRGS(properties, gramChoice, gramValue,
gramAcceptance, isDTMF, srgsGram) )
return VXIrec_RESULT_FAILURE;
// Parsing SRGS grammar.
// NOTES: The parsing is very simple, therefore it may not work
// for complex grammar. As you know, this is a simulator!!!
VXIrecGrammar * gramPtr = tp->ParseSRGSGrammar(srgsGram, properties, isDTMF);
if( gramPtr == NULL ) return VXIrec_RESULT_FAILURE;
tp->AddGrammar(gramPtr);
*gram = ToVXIrecGrammar(gramPtr);
return VXIrec_RESULT_SUCCESS;
}
static VXIrecResult VXIrecFreeGrammar(VXIrecInterface *pThis,
VXIrecGrammar **gram)
{
const wchar_t* fnname = L"VXIrecFreeGrammar";
// Check the arguments
VXIrecData* tp = GetRecData(pThis);
if (tp == NULL) return VXIrec_RESULT_INVALID_ARGUMENT;
LogBlock logger(tp->GetLog(), gblDiagLogBase, fnname, VXIREC_MODULE);
// If the grammar pointer is null, there is nothing to free.
if (gram == NULL || *gram == NULL) VXIrec_RESULT_SUCCESS;
tp->FreeGrammar(FromVXIrecGrammar(*gram));
*gram = NULL;
return VXIrec_RESULT_SUCCESS;
}
static VXIrecResult VXIrecActivateGrammar(VXIrecInterface *pThis,
const VXIMap *properties,
VXIrecGrammar *gram)
{
const wchar_t* fnname = L"VXIrecActivateGrammar";
VXIrecData* tp = GetRecData(pThis);
if (tp == NULL) return VXIrec_RESULT_INVALID_ARGUMENT;
LogBlock logger(tp->GetLog(), gblDiagLogBase, fnname, VXIREC_MODULE);
if (gram == NULL) {
logger = VXIrec_RESULT_INVALID_ARGUMENT;
return VXIrec_RESULT_INVALID_ARGUMENT;
}
tp->ActivateGrammar(FromVXIrecGrammar(gram));
return VXIrec_RESULT_SUCCESS;
}
static VXIrecResult VXIrecDeactivateGrammar(VXIrecInterface *pThis,
VXIrecGrammar *gram)
{
const wchar_t* fnname = L"VXIrecDeactivateGrammar";
VXIrecData* tp = GetRecData(pThis);
if (tp == NULL) return VXIrec_RESULT_INVALID_ARGUMENT;
LogBlock logger(tp->GetLog(), gblDiagLogBase, fnname, VXIREC_MODULE);
if (gram == NULL)
{
logger = VXIrec_RESULT_INVALID_ARGUMENT;
return VXIrec_RESULT_INVALID_ARGUMENT;
}
tp->DeactivateGrammar(FromVXIrecGrammar(gram));
return VXIrec_RESULT_SUCCESS;
}
/*******************************************************
* Recognize related
*******************************************************/
static void RecognitionResultDestroy(VXIrecRecognitionResult **Result)
{
if (Result == NULL || *Result == NULL) return;
VXIrecRecognitionResult * result = *Result;
if (result->utterance != NULL)
VXIContentDestroy(&result->utterance);
if (result->xmlresult != NULL)
VXIContentDestroy(&result->xmlresult);
if (result->markname != NULL)
VXIStringDestroy(&result->markname);
delete result;
*Result = NULL;
}
static void TransferResultDestroy(VXIrecTransferResult **Result)
{
if (Result == NULL || *Result == NULL) return;
VXIrecTransferResult * result = *Result;
if (result->utterance != NULL)
VXIContentDestroy(&result->utterance);
if (result->xmlresult != NULL)
VXIContentDestroy(&result->xmlresult);
if (result->markname != NULL)
VXIStringDestroy(&result->markname);
delete result;
*Result = NULL;
}
static const unsigned int NLSML_NOINPUT_SIZE = 109;
static const VXIchar NLSML_NOINPUT[NLSML_NOINPUT_SIZE] =
L"<?xml version='1.0'?>"
L"<result>"
L"<interpretation>"
L"<instance/>"
L"<input><noinput/></input>"
L"</interpretation>"
L"</result>\0";
static const unsigned int NLSML_NOMATCH_SIZE = 109;
static const VXIchar NLSML_NOMATCH[NLSML_NOMATCH_SIZE] =
L"<?xml version='1.0'?>"
L"<result>"
L"<interpretation>"
L"<instance/>"
L"<input><nomatch/></input>"
L"</interpretation>"
L"</result>\0";
void DestroyNLSMLBuffer(VXIbyte ** buffer, void * ok)
{
// Return immediate if we know the buffer is static memory,
// i.e: noinput, nomatch as defined above
if (ok == NULL || buffer == NULL) return;
// otherwise reclaim the memory
delete[] (*buffer);
*buffer = NULL;
}
static VXIrecResult VXIrecRecognize(VXIrecInterface *pThis,
const VXIMap *properties,
VXIrecRecognitionResult **recogResult)
{
const wchar_t* fnname = L"VXIrecRecognize";
VXIrecData* tp = GetRecData(pThis);
if (tp == NULL) return VXIrec_RESULT_INVALID_ARGUMENT;
LogBlock logger(tp->GetLog(), gblDiagLogBase, fnname, VXIREC_MODULE);
VXIchar* input = NULL;
VXIMap* res = NULL;
VXIchar* str = NULL;
VXIchar console[512];
bool recordUtterance = false;
bool haveUtterance = true;
if (properties != NULL) {
const VXIValue * ru = VXIMapGetProperty(properties, REC_RECORDUTTERANCE);
if (ru)
recordUtterance = wcscmp(VXIStringCStr((const VXIString*)ru), L"true") == 0;
const VXIValue * val = VXIMapGetProperty(properties, L"SpeechInput");
if( val ) {
logger.logDiag(DIAG_TAG_RECOGNITION, L"%s%s", L"SpeechInput: ",
VXIStringCStr((const VXIString*)val));
}
if (val == NULL || VXIValueGetType(val) != VALUE_STRING) {
val = VXIMapGetProperty(properties, L"DTMFInput");
if( val ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -