📄 vxi.cpp
字号:
/****************License************************************************ * * Copyright 2000-2003. ScanSoft, Inc. * * Use of this software is subject to notices and obligations set forth * in the SpeechWorks Public License - Software Version 1.2 which is * included with this software. * * ScanSoft is a registered trademark of ScanSoft, Inc., and OpenSpeech, * SpeechWorks and the SpeechWorks logo are registered trademarks or * trademarks of SpeechWorks International, Inc. in the United States * and other countries. * ***********************************************************************/ #include "VXI.hpp" #include "DocumentParser.hpp" #include "SimpleLogger.hpp" #include "ValueLogging.hpp" // for VXIValue dumping #include "Scripter.hpp" // for use in ExecutionContext #include "GrammarManager.hpp" // for use in ExecutionContext #include "Counters.hpp" // for EventCounter #include "PropertyList.hpp" // for PropertyList #include "PromptManager.hpp" // for PromptManager #include "AnswerParser.hpp" // for AnswerParser #include "VXML.h" // for node & attribute names #include "VXItel.h" // for VXItelInterface #include "VXIrec.h" // for parameters from rec answer #include "VXIlog.h" // for event IDs #include "VXIobject.h" // for Object type #include "VXIinet.h" #include <deque> // for deque (used by Prompts) #include <sstream> // by ProcessNameList() #include <algorithm> // for sort, set_intersection, etc. #pragma message ("Cleanup comments - Did FIA level functions") static const wchar_t * const SCOPE_Session = L"session"; static const wchar_t * const SCOPE_Defaults = L"$_platDefaults_"; static const wchar_t * const SCOPE_Application = L"application"; static const wchar_t * const SCOPE_Document = L"document"; static const wchar_t * const SCOPE_Dialog = L"dialog"; static const wchar_t * const SCOPE_Local = L"local"; static const wchar_t * const SCOPE_Anonymous = L"$_execAnonymous_"; static const wchar_t * const GENERIC_DEFAULTS = L"*"; const int DEFAULT_MAX_EXE_STACK_DEPTH = 5; const int DEFAULT_MAX_EVENT_RETHROWS = 6; const int DEFAULT_MAX_EVENT_COUNT = 12; // ------*---------*---------*---------*---------*---------*---------*--------- static vxistring toString(const VXIString * s) { if (s == NULL) return L""; const VXIchar * temp = VXIStringCStr(s); if (temp == NULL) return L""; return temp; } static vxistring toString(const VXIchar * s) { if (s == NULL) return L""; return s; } // ------*---------*---------*---------*---------*---------*---------*--------- class VXIPromptTranslator : public PromptTranslator { public: virtual VXIValue * EvaluateExpression(const vxistring & expression) { if (expression.empty()) return NULL; return jsi.EvalScriptToValue(expression); } virtual void SetVariable(const vxistring & name, const vxistring & value) { if (name.empty()) return; jsi.MakeVar(name, NULL); jsi.SetString(name, value); } VXIPromptTranslator(Scripter & j) : jsi(j) { } virtual ~VXIPromptTranslator() { } private: Scripter & jsi; }; class VXIAnswerTranslator : public AnswerTranslator { public: virtual void EvaluateExpression(const vxistring & expression) { if (expression.empty()) return; jsi.EvalScript(expression); } virtual void SetString(const vxistring & var, const vxistring & val) { jsi.SetString(var, val); } VXIAnswerTranslator(Scripter & j) : jsi(j) { } virtual ~VXIAnswerTranslator() { } private: Scripter & jsi; }; // VXIContent wrapper that aid to // do automated memory managment, the class take ownership of the // passed-in content class VXIContentHolder { public: VXIContentHolder() : _content(NULL), _contentSize(0), _contentValue(NULL), _contentType(NULL) { } VXIContentHolder(VXIContent* c) : _content(NULL), _contentSize(0), _contentValue(NULL), _contentType(NULL) {SetContent(c);} virtual ~VXIContentHolder() { if (_content) VXIContentDestroy(&_content); } const VXIbyte* GetValue() { return _contentValue; } const VXIchar* GetType() { return _contentType; } VXIulong GetSize() { return _contentSize; } const VXIContent* GetContent() { return _content; } VXIContent* Release(void) { VXIContent* c = _content; _content = NULL; return c; } void SetContent(VXIContent* content) { _content = content; if( _content ) VXIContentValue(_content, &_contentType, &_contentValue, &_contentSize); } private: VXIContent* _content; const VXIchar* _contentType; const VXIbyte* _contentValue; VXIulong _contentSize; // do not allow these operations VXIContentHolder(const VXIContentHolder &); VXIContentHolder & operator=(const VXIContentHolder &); }; // Thrown after a successful recognition. // class AnswerInformation { public: VXMLElement element; VXMLElement dialog; AnswerInformation(VXMLElement & e, VXMLElement & d) : element(e), dialog(d) { } }; class JumpReturn { public: JumpReturn() { } }; class JumpItem { public: VXMLElement item; JumpItem(const VXMLElement & i) : item(i) { } }; class JumpDialog { public: VXMLElement dialog; JumpDialog(const VXMLElement d) : dialog(d) { } }; class JumpDoc { public: VXMLElement defaults; VXMLDocument application; vxistring applicationURI; VXMLDocument document; vxistring documentURI; VXMLElement documentDialog; bool isSubdialog; bool isSubmitElement; PropertyList properties; JumpDoc(const VXMLElement & def, const VXMLDocument & app, const vxistring & appURI, const VXMLDocument & doc, const vxistring & docURI, const VXMLElement & docdial, bool issub, bool issubmit, const PropertyList & p) : defaults(def), application(app), applicationURI(appURI), document(doc), documentURI(docURI), documentDialog(docdial), isSubdialog(issub), isSubmitElement(issubmit), properties(p) { } ~JumpDoc() { } }; //############################################################################# // ExecutionContext & Utilities //############################################################################# class ExecutionContext { public: // These are used by the main run loops, event handling, and subdialog. // Each of these gets initialized by InstallDocument. VXMLElement platDefaults; VXMLDocument application; vxistring applicationURI; VXMLDocument document; vxistring documentName; vxistring documentURI; VXMLElement currentDialog; VXMLElement currentFormItem; // Limited purpose members. VXMLElement eventSource; // For prompting (enumerate) during events VXMLElement lastItem; // Set by <subdialog> public: // These are used more generally. Scripter script; GrammarManager gm; PromptTracker promptcounts; EventCounter eventcounts; PropertyList properties; typedef std::deque<vxistring> STRINGDEQUE; STRINGDEQUE formitems; bool playingPrompts; ExecutionContext * next; ExecutionContext(VXIrecInterface * r, VXIjsiInterface * j, const SimpleLogger & l, ExecutionContext * n) : script(j), gm(r, l), next(n), playingPrompts(true), properties(l) { } // may throw VXIException::OutOfMemory() ~ExecutionContext() { } }; typedef std::deque<vxistring> STRINGDEQUE; static void ProcessNameList(const vxistring & namelist, STRINGDEQUE & names) { names.clear(); if (namelist.empty()) return; // The namelist is a series of whitespace delimited strings. Read each in // and insert it into the deque. std::basic_stringstream<VXIchar> namestream(namelist); #if (defined(__GNUC__) || defined(_decunix_)) // G++ 2.95 and 3.0.2 do not fully support istream_iterator. while (namestream.good()) { vxistring temp; namestream >> temp; if (!temp.empty()) names.push_back(temp); } #else std::copy(std::istream_iterator<vxistring, VXIchar>(namestream), std::istream_iterator<vxistring, VXIchar>(), std::back_inserter(names)); #endif // Now sort the deque and return the unique set of names. if (names.empty()) return; std::sort(names.begin(), names.end()); STRINGDEQUE::iterator i = std::unique(names.begin(), names.end()); if (i != names.end()) names.erase(i, names.end()); } //############################################################################# // Creation and Run //############################################################################# VXI::VXI() : parser(NULL), log(NULL), inet(NULL), rec(NULL), jsi(NULL), tel(NULL), exe(NULL), stackDepth(0), sdParams(NULL), sdResult(NULL), sdEvent(NULL), updateDefaultDoc(true), mutex(), uriPlatDefaults(), uriBeep(), lineHungUp(false), stopRequested(false), haveExternalEvents(false) { try { parser = new DocumentParser(); } catch (const VXIException::OutOfMemory &) { parser = NULL; throw; } try { pm = new PromptManager(); } catch (...) { delete parser; parser = NULL; pm = NULL; throw; } if (pm == NULL) { delete parser; parser = NULL; throw VXIException::OutOfMemory(); } } VXI::~VXI() { while (exe != NULL) { ExecutionContext * temp = exe->next; delete exe; exe = temp; } delete pm; delete parser; } // Determine if the user has already hung-up // if it is the case, throw the exit element to indicate // end of call void VXI::CheckLineStatus() { VXItelStatus status; int telResult = tel->GetStatus(tel, &status); bool needToThrow = false; if (telResult != VXItel_RESULT_SUCCESS) { needToThrow = true; log->LogError(201); } else if (status == VXItel_STATUS_INACTIVE) needToThrow = true; if (needToThrow) { mutex.Lock(); bool alreadyHungup = lineHungUp; lineHungUp = true; mutex.Unlock(); if (alreadyHungup) { log->LogDiagnostic(1, L"VXI::CheckLineStatus - Call has been hung-up, " L"exiting..."); throw VXIException::Exit(NULL); } else throw VXIException::InterpreterEvent(EV_TELEPHONE_HANGUP); } } bool VXI::SetRuntimeProperty(PropertyID id, const VXIchar * value) { mutex.Lock(); switch (id) { case VXI::BeepURI: if (value == NULL) uriBeep.erase(); else uriBeep = value; break; case VXI::PlatDefaultsURI: if (value == NULL) uriPlatDefaults.erase(); else uriPlatDefaults = value; updateDefaultDoc = true; break; default: mutex.Unlock(); return false; } mutex.Unlock(); return true; } void VXI::GetRuntimeProperty(PropertyID id, vxistring & value) const { mutex.Lock(); switch (id) { case VXI::BeepURI: value = uriBeep; break; case VXI::PlatDefaultsURI: value = uriPlatDefaults; break; default: value.erase(); } mutex.Unlock(); } void VXI::DeclareStopRequest(bool doStop) { mutex.Lock(); stopRequested = doStop; mutex.Unlock(); } int VXI::DeclareExternalEvent(const VXIchar * event, const VXIchar * message) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -