⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 promptmanager.cpp

📁 sloedgy open sip stack source code
💻 CPP
📖 第 1 页 / 共 2 页
字号:

 /****************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 <vxibuildopts.h>
#if P_VXI

 #include "PromptManager.hpp"
 #include "SimpleLogger.hpp"            // for SimpleLogger
 #include "vxi/VXIprompt.h"                 // for VXIpromptInterface
 #include "VXML.h"                      // for node names
 #include "DocumentModel.hpp"           // for VXMLNode, VXMLElement
 #include "CommonExceptions.hpp"        // for InterpreterEvent, OutOfMemory
 #include "PropertyList.hpp"            // for PropertyList
 #include <sstream>
 #include <iostream>
 
#ifdef _MSC_VER
#pragma warning(disable:4061)
#endif
 static VXIchar SPACE = ' ';
 
 //#############################################################################
 
 bool static ConvertValueToString(const VXIValue * value, vxistring & source)
 {
   if (value == NULL) return false;
 
   switch (VXIValueGetType(value)) {
   case VALUE_BOOLEAN:
   {
     std::basic_stringstream<VXIchar> attrStream;
     if(VXIBooleanValue(reinterpret_cast<const VXIBoolean *>(value)) == TRUE)
       attrStream << L"true";
     else
       attrStream << L"false";
     source = attrStream.str();
     return true;
   }
   case VALUE_INTEGER:
   {
     std::basic_stringstream<VXIchar> attrStream;
     attrStream << VXIIntegerValue(reinterpret_cast<const VXIInteger *>(value));
     source = attrStream.str();
     return true;
   }
   case VALUE_FLOAT:
   {
     std::basic_stringstream<VXIchar> attrStream;
     attrStream << VXIFloatValue(reinterpret_cast<const VXIFloat *>(value));
     source = attrStream.str();
     return true;
   }
   case VALUE_STRING:
     source = VXIStringCStr(reinterpret_cast<const VXIString *>(value));
     return true;
   default:
     return false;
   }
 }
 
 
 inline void AddSSMLAttribute(const VXMLElement & elem, VXMLAttributeType attr,
                              const VXIchar * const defaultVal,
                              const VXIchar * const name, vxistring & sofar)
 {
   // Get attribute or use the default value.
   vxistring attrString;
   if (!elem.GetAttribute(attr, attrString) || attrString.empty()) {
     if (defaultVal == NULL) return;
     attrString = defaultVal;
   }
 
   sofar += SPACE;
   sofar += name;
   sofar += L"=\"";
 
   // We need to escape three characters: (",<,&) -> (&quot;, &lt;, &amp;)
   vxistring::size_type pos = 0;
   while ((pos = attrString.find_first_of(L"\"<&", pos)) != vxistring::npos) {
     switch (attrString[pos]) {
     case '\"':   attrString.replace(pos, 1, L"&quot;");    ++pos;  break;
     case '<':    attrString.replace(pos, 1, L"&lt;");      ++pos;  break;
     case '&':    attrString.replace(pos, 1, L"&amp;");     ++pos;  break;
     }
   };
 
   sofar += attrString;
   sofar += L"\"";
 }
 
 
 inline void AppendTextSegment(vxistring & sofar, const vxistring & addition)
 {
   if (addition.empty()) return;
 
   vxistring::size_type pos = sofar.length();
 
   sofar += addition;
 
   // We need to escape two characters: (<,&) -> (&lt;, &amp;)
   // NOTE: It starts from the old length and operates only on the addition.
   while ((pos = sofar.find_first_of(L"<&", pos)) != vxistring::npos) {
     switch (sofar[pos]) {
     case '<':    sofar.replace(pos, 1, L"&lt;");      ++pos;  break;
     case '&':    sofar.replace(pos, 1, L"&amp;");     ++pos;  break;
     }
   }
 }
 
 //#############################################################################
 
 ////////
 // About prompts:
 //
 // Prompts may be defined in two places within VXML documents.
 // 1) form items - menu, field, initial, record, transfer, subdialog, object
 // 2) executable content - block, catch, filled
 //
 // The <enumerate> element only is valid with parent menu or fields having one
 // or more option elements.  Otherwise an error.semantic results.
 //
 // From the VXML working drafts, barge-in may be controlled on a prompt by
 // prompt basis.  There are several unresolved issues with this request.
 // Instead this implements a different tactic.
 
 void PromptManager::ThrowEventIfError(VXIpromptResult rc)
 {
   switch( rc )
   {
     case VXIprompt_RESULT_SUCCESS:
       break;
     case VXIprompt_RESULT_TTS_BAD_LANGUAGE:
       throw VXIException::InterpreterEvent(EV_UNSUPPORT_LANGUAGE);
     case VXIprompt_RESULT_FETCH_TIMEOUT:
     case VXIprompt_RESULT_FETCH_ERROR:
     case VXIprompt_RESULT_NON_FATAL_ERROR:
       throw VXIException::InterpreterEvent(EV_ERROR_BADFETCH);
     case VXIprompt_RESULT_HW_BAD_TYPE:
       throw VXIException::InterpreterEvent(EV_UNSUPPORT_FORMAT);
     case VXIprompt_RESULT_TTS_ACCESS_ERROR:
     case VXIprompt_RESULT_NO_RESOURCE:
       throw VXIException::InterpreterEvent(EV_ERROR_NORESOURCE);
     case VXIprompt_RESULT_NO_AUTHORIZATION:
       throw VXIException::InterpreterEvent(EV_ERROR_NOAUTHORIZ);
     case VXIprompt_RESULT_BAD_SAYAS_CLASS:
     case VXIprompt_RESULT_TTS_BAD_DOCUMENT:
     case VXIprompt_RESULT_TTS_SYNTAX_ERROR:
     case VXIprompt_RESULT_TTS_ERROR:
     default:
       throw VXIException::InterpreterEvent(EV_ERROR_SEMANTIC);
   }   
 }
 
 void PromptManager::WaitAndCheckError()
 {
   VXIpromptResult rc;
   prompt->Wait(prompt, &rc);
   ThrowEventIfError(rc);
 }
 
 bool PromptManager::ConnectResources(SimpleLogger * l, VXIpromptInterface * p)
 {
   if (l == NULL || p == NULL) return false;
   log = l;
   prompt = p;
   enabledSegmentInQueue = false;
   playedBargeinDisabledPrompt = false;
   timeout = -1;
   return true;
 }
 
 
 void PromptManager::PlayFiller(const vxistring & src, 
                                const VXIMapHolder & properties)
 {
   log->LogDiagnostic(2, L"PromptManager::PlayFiller()");
 
   if (src.empty()) return;
 
   const VXIMap * propMap = properties.GetValue();
   // Get fetchaudiominimum value
   VXIint minPlayMsec = 0;
   const VXIValue * val = (VXIMapGetProperty(propMap, L"fetchaudiominimum"));
   if( val &&  VXIValueGetType(val) == VALUE_STRING ) {
     const VXIchar* fmin = 
           VXIStringCStr(reinterpret_cast<const VXIString*>(val));
     if( fmin )
       PropertyList::ConvertTimeToMilliseconds(*log, fmin, minPlayMsec);
   }   
   prompt->PlayFiller(prompt, NULL, src.c_str(), NULL, propMap, minPlayMsec);
 }
 
 
 void PromptManager::Play(bool *playedBDPrompt)
 {
   log->LogDiagnostic(2, L"PromptManager::Play()");
 
   *playedBDPrompt = playedBargeinDisabledPrompt;
 
   //VXIpromptResult temp;
   //prompt->Wait(prompt, &temp);
   WaitAndCheckError();
   prompt->Play(prompt);
   enabledSegmentInQueue = false;
   playedBargeinDisabledPrompt = false;
   timeout = -1;
 }
 
 
 void PromptManager::PlayAll()
 {
   log->LogDiagnostic(2, L"PromptManager::PlayAll()");
 
   prompt->Play(prompt);
   //VXIpromptResult temp;
   //prompt->Wait(prompt, &temp);
   WaitAndCheckError();
   enabledSegmentInQueue = false;
   playedBargeinDisabledPrompt = false;
   timeout = -1;
 }
 
 
 int PromptManager::GetMillisecondTimeout() const
 {
   return timeout;
 }
 
 void PromptManager::Queue(const VXMLElement & elem, const VXMLElement & ref,
                           const PropertyList & propertyList,
                           PromptTranslator & translator)
 {
   log->LogDiagnostic(2, L"PromptManager::Queue()");
 
   // (1) Find <field> or <menu> associated with this prompt, if any.  This is
   // used by the <enumerate> element.
   VXMLElement item = ref;
   while (item != 0) {
     VXMLElementType type = item.GetName();
     if (type == NODE_FIELD || type == NODE_MENU) break;
     item = item.GetParent();
   }
 
   // (2) Get properties.
   VXIMapHolder properties;
   if (properties.GetValue() == NULL) throw VXIException::OutOfMemory();
 
   // (2.1) Flatten the property list.
   propertyList.GetProperties(properties);
 
   // (2.2) Add the URI information.
   propertyList.GetFetchobjBase(properties);
 
   // (3) Handle <prompt> elements
 
   // (3.1) Update timeout if specified.
   vxistring timeoutString;
   if (elem.GetAttribute(ATTRIBUTE_TIMEOUT, timeoutString) == true)
     PropertyList::ConvertTimeToMilliseconds(*log, timeoutString, timeout);
 
   // (3.2) Get bargein setting.
 
   PromptManager::BargeIn bargein = PromptManager::ENABLED;
   const VXIchar * j = propertyList.GetProperty(PROP_BARGEIN);
   if (j != NULL && vxistring(L"false") == j)
     bargein = PromptManager::DISABLED;
 
   vxistring bargeinAttr;
   if (elem.GetAttribute(ATTRIBUTE_BARGEIN, bargeinAttr) == true) {
     bargein = PromptManager::ENABLED;
     if (bargeinAttr == L"false") bargein = PromptManager::DISABLED;
     // override default bargein attribute
     VXIMapSetProperty(properties.GetValue(), PROP_BARGEIN, 
                      (VXIValue*)VXIStringCreate(bargeinAttr.c_str())); 
   }
   
   vxistring bargeinType;
   if (elem.GetAttribute(ATTRIBUTE_BARGEINTYPE, bargeinType) == true) {
     // override default bargeintype attribute
     VXIMapSetProperty(properties.GetValue(), PROP_BARGEINTYPE, 
                      (VXIValue*)VXIStringCreate(bargeinType.c_str())); 
   }
    
   // (4) Build prompt, recursively handling the contents.
   vxistring content;
   for (VXMLNodeIterator it(elem); it; ++it)
     ProcessSegments(*it, item, propertyList, translator,
                     bargein, properties, content);
   if (content.empty()) return;
 
   // (5) Add a new segment.
   AddSegment(SEGMENT_SSML, content, properties, bargein);
 }
 
 
 void PromptManager::Queue(const vxistring & uri)
 {
   if (uri.empty()) return;
 
   AddSegment(PromptManager::SEGMENT_AUDIO, uri, VXIMapHolder(),
              PromptManager::UNSPECIFIED);
 }
 
 
 bool PromptManager::AddSegment(PromptManager::SegmentType type,
                                const vxistring & data,
                                const VXIMapHolder & properties,
                                PromptManager::BargeIn bargein,
                                bool throwExceptions)
 {
   const VXIMap * propMap = properties.GetValue();
 
   VXIpromptResult result;
 
   // Handle the easy case.
   switch (type) {
   case PromptManager::SEGMENT_AUDIO:
     result = prompt->Queue(prompt, NULL, data.c_str(), NULL, propMap);
     break;
   case PromptManager::SEGMENT_SSML:
     result = prompt->Queue(prompt, VXI_MIME_SSML, NULL, data.c_str(), propMap);
     break;
   }
 
   if (throwExceptions) {
     ThrowEventIfError(result);
   }
 
   switch (bargein) {
   case PromptManager::DISABLED:
     if (!enabledSegmentInQueue) {
       prompt->Play(prompt);
       playedBargeinDisabledPrompt = true;
     }
     break;
   case PromptManager::ENABLED:
     enabledSegmentInQueue = true;
     break;
   case PromptManager::UNSPECIFIED:
     break;
   }
 
   return result == VXIprompt_RESULT_SUCCESS;
 }
 
 void PromptManager::ProcessSegments(const VXMLNode & node,
                                     const VXMLElement & item,
                                     const PropertyList & propertyList,
                                     PromptTranslator & translator,
                                     PromptManager::BargeIn bargein,
                                     VXIMapHolder & props,
                                     vxistring & sofar)
 {
   // (1) Handle bare content.
   switch (node.GetType()) {
   case VXMLNode::Type_VXMLContent:
   {
     const VXMLContent & content = reinterpret_cast<const VXMLContent &>(node);
     sofar += content.GetValue();
     return;
   }
   case VXMLNode::Type_VXMLElement:
     break;
   default: // This should never happen.
     log->LogError(999, SimpleLogger::MESSAGE,
                   L"unexpected type in PromptManager::ProcessSegments");
     throw VXIException::Fatal();
   }
 
   // (2) Retrieve fetch properties (if we haven't already)
   const VXMLElement & elem = reinterpret_cast<const VXMLElement &>(node);
   vxistring attr;
 
   switch (elem.GetName()) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -