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

📄 vxml.cxx

📁 pwlib源码库
💻 CXX
📖 第 1 页 / 共 5 页
字号:
  {    PWaitAndSignal m(sessionMutex);    if (!chan->Open(this))      return FALSE;    vxmlChannel = chan;  }  return Execute();}BOOL PVXMLSession::Execute(){  PWaitAndSignal m(sessionMutex);  // cannot open if no data is loaded  if (loaded && vxmlThread == NULL) {    threadRunning = TRUE;    vxmlThread = PThread::Create(PCREATE_NOTIFIER(VXMLExecute), 0, PThread::NoAutoDeleteThread);  }  return TRUE;}BOOL PVXMLSession::Close(){  {    PWaitAndSignal m(sessionMutex);    if (vxmlThread != NULL) {      // Stop condition for thread      threadRunning = FALSE;      forceEnd      = TRUE;      waitForEvent.Signal();      // Signal all syncpoints that could be waiting for things      transferSync.Signal();      answerSync.Signal();      vxmlChannel->Close();      vxmlThread->WaitForTermination();      delete vxmlThread;      vxmlThread = NULL;    }    vxmlChannel = NULL;  }  return PIndirectChannel::Close();}void PVXMLSession::VXMLExecute(PThread &, INT){  while (!forceEnd && threadRunning) {    // process current node in the VXML script    ExecuteDialog();    // wait for something to happen    if (currentNode == NULL || IsPlaying())      waitForEvent.Wait();  }  // Make sure the script has been run to the end so  // submit actions etc. can be performed  // record and audio and other user interaction commands should be skipped  if (forceEnd) {    PTRACE(1, "Fast forwarding through script because of forceEnd" );    while (currentNode != NULL)      ExecuteDialog();  }  OnEndSession();  //PWaitAndSignal m(sessionMutex);  if (vxmlChannel != NULL)    vxmlChannel->Close();  return;}void PVXMLSession::ProcessUserInput(){  // without this initialisation, gcc 4.1 gives a warning  char ch = 0;  {    PWaitAndSignal m(userInputMutex);    if (userInputQueue.size() == 0)      return;    ch = userInputQueue.front();    userInputQueue.pop();  }  PTRACE(3, "VXML\tHandling user input " << ch);  // recording  if (recording) {    if (recordDTMFTerm)      RecordEnd();  }   // playback  else {    if (activeGrammar != NULL)      activeGrammar->OnUserInput(ch);  }}void PVXMLSession::ExecuteDialog(){  // check for user input  ProcessUserInput();  // process any active grammars  ProcessGrammar();  // process current node in the VXML script  ProcessNode();  // Wait for the buffer to complete before continuing to the next node  if (currentNode == NULL) {    if (IsPlaying())      return;  }  // if the current node has children, then process the first child  else if (currentNode->IsElement() && (((PXMLElement *)currentNode)->GetElement(0) != NULL))    currentNode = ((PXMLElement *)currentNode)->GetElement(0);  // else process the next sibling  else {    // Keep moving up the parents until we find a next sibling    while ((currentNode != NULL) && currentNode->GetNextObject() == NULL) {      currentNode = currentNode->GetParent();      // if we are on the backwards traversal through a <field> then wait      // for a grammar recognition and throw events if necessary      if (currentNode != NULL && (currentNode->IsElement() == TRUE) && (((PXMLElement*)currentNode)->GetName() *= "field")) {        listening = TRUE;        PlaySilence(timeout);      }    }    if (currentNode != NULL)      currentNode = currentNode->GetNextObject();  }  // Determine if we should quit  if ((currentNode == NULL) && (activeGrammar == NULL) && !IsPlaying() && !IsRecording() && allowFinish && finishWhenEmpty) {    threadRunning = FALSE;    waitForEvent.Signal();  }}void PVXMLSession::ProcessGrammar(){  if (activeGrammar == NULL)    return;  BOOL processGrammar(FALSE);  // Stop if we've matched a grammar or have a failed recognition  if (activeGrammar->GetState() == PVXMLGrammar::FILLED || activeGrammar->GetState() == PVXMLGrammar::NOMATCH)    processGrammar = TRUE;  // Stop the grammar if we've timed out  else if (listening && !IsPlaying())   {    activeGrammar->Stop();    processGrammar = TRUE;  }  // Let the loop run again if we're still waiting to time out and haven't resolved the grammar one way or the other  if (!processGrammar && listening)    return;  if (processGrammar)  {    PVXMLGrammar::GrammarState state = activeGrammar->GetState();    grammarResult = activeGrammar->GetValue();    LoadGrammar(NULL);    listening = FALSE;    // Stop any playback    if (vxmlChannel != NULL) {      vxmlChannel->FlushQueue();      vxmlChannel->EndRecording();    }    // Check we're not in a menu    if (eventName.IsEmpty()) {      // Figure out what happened      switch (state)      {      case PVXMLGrammar::FILLED:        eventName = "filled";        break;      case PVXMLGrammar::NOINPUT:        eventName = "noinput";        break;      case PVXMLGrammar::NOMATCH:        eventName = "nomatch";        break;      default:        ; //ERROR - unexpected grammar state      }      // Find the handler and move there      PXMLElement * handler = FindHandler(eventName);      if (handler != NULL)        currentNode = handler;    }  }}void PVXMLSession::ProcessNode(){  if (currentNode == NULL)    return;  if (!currentNode->IsElement()) {    if (!forceEnd)      TraverseAudio();    else      currentNode = NULL;  }  else {    PXMLElement * element = (PXMLElement*)currentNode;    PCaselessString nodeType = element->GetName();    PTRACE(3, "PVXML\t**** Processing VoiceXML element: <" << nodeType << "> ***");    if (nodeType *= "audio") {      if (!forceEnd)        TraverseAudio();    }    else if (nodeType *= "block") {      // check 'cond' attribute to see if this element's children are to be skipped      // go on and process the children    }    else if (nodeType *= "break")      TraverseAudio();    else if (nodeType *= "disconnect")      currentNode = NULL;    else if (nodeType *= "field") {      currentField = (PXMLElement*)currentNode;      timeout = DEFAULT_TIMEOUT;      TraverseGrammar();  // this will set activeGrammar    }    else if (nodeType *= "form") {      // this is now the current element - go on      currentForm = element;      currentField = NULL;  // no active field in a new form    }    else if (nodeType *= "goto")      TraverseGoto();    else if (nodeType *= "grammar")      TraverseGrammar();  // this will set activeGrammar    else if (nodeType *= "record") {      if (!forceEnd)  		  TraverseRecord();		    }    else if (nodeType *= "prompt") {      if (!forceEnd) {        // LATER:        // check 'cond' attribute to see if the children of this node should be processed        // check 'count' attribute to see if this node should be processed        // flush all prompts if 'bargein' attribute is set to false        // Update timeout of current recognition (if 'timeout' attribute is set)        if (element->HasAttribute("timeout")) {          PTimeInterval timeout = StringToTime(element->GetAttribute("timeout"));        }      }    }    else if (nodeType *= "say-as") {      if (!forceEnd) {      }    }    else if (nodeType *= "value") {      if (!forceEnd)        TraverseAudio();    }    else if (nodeType *= "var")      TraverseVar();    else if (nodeType *= "if")       TraverseIf();    else if (nodeType *= "exit")       TraverseExit();    else if (nodeType *= "menu")  {      if (!forceEnd) {        TraverseMenu();        eventName = "menu";      }    }    else if (nodeType *= "choice") {      if (!TraverseChoice(grammarResult))        defaultDTMF++;      else {        // If the correct choice has been found,         /// make sure everything is reset correctly        eventName.MakeEmpty();        grammarResult.MakeEmpty();        defaultDTMF = 1;      }    }    else if (nodeType *= "transfer") {      if (!forceEnd)         TraverseTransfer();    }    else if (nodeType *= "submit")      TraverseSubmit();    else if (nodeType *= "property")      TraverseProperty();  }}BOOL PVXMLSession::OnUserInput(const PString & str){  {    PWaitAndSignal m(userInputMutex);    for (PINDEX i = 0; i < str.GetLength(); i++)      userInputQueue.push(str[i]);  }  waitForEvent.Signal();  return TRUE;}BOOL PVXMLSession::TraverseRecord(){  if (currentNode->IsElement()) {        PString strName;    PXMLElement * element = (PXMLElement *)currentNode;        // Get the name (name)    if (element->HasAttribute("name"))      strName = element->GetAttribute("name");    else if (element->HasAttribute("id"))      strName = element->GetAttribute("id");        // Get the destination filename (dest)    PString strDest;    if (element->HasAttribute("dest"))       strDest = element->GetAttribute("dest");        // see if we need a beep    if (element->GetAttribute("beep").ToLower() *= "true") {      PBYTEArray beepData;      GetBeepData(beepData, 1000);      if (beepData.GetSize() != 0)        PlayData(beepData);    }    if (strDest.IsEmpty()) {      PTime now;      strDest = GetVar("session.telephone.dnis" ) + "_" + GetVar( "session.telephone.ani" ) + "_" + now.AsString( "yyyyMMdd_hhmmss") + ".wav";    }        // For some reason, if the file is there the create     // seems to fail.     PFile::Remove(strDest);    PFilePath file(strDest);        // Get max record time (maxtime)    PTimeInterval maxTime = PMaxTimeInterval;    if (element->HasAttribute("maxtime"))       maxTime = StringToTime(element->GetAttribute("maxtime"));        // Get terminating silence duration (finalsilence)    PTimeInterval termTime(3000);    if (element->HasAttribute("finalsilence"))       termTime = StringToTime(element->GetAttribute("finalsilence"));        // Get dtmf term (dtmfterm)    BOOL dtmfTerm = TRUE;    if (element->HasAttribute("dtmfterm"))      dtmfTerm = !(element->GetAttribute("dtmfterm").ToLower() *= "false");        // create a semaphore, and then wait for the recording to terminate    StartRecording(file, dtmfTerm, maxTime, termTime);    recordSync.Wait(maxTime);        if (!recordSync.Wait(maxTime)) {      // The Wait() has timed out, to signal that the record timed out.      // This is VXML version 2 property, but nice.      // So it's possible to detect if the record timed out from within the       // VXML script      SetVar(strName + "$.maxtime", "true");    }    else {      // Normal hangup before timeout      SetVar( strName + "$.maxtime", "false");    }    // when this returns, we are done    EndRecording();  }    return TRUE;}PString PVXMLSession::GetXMLError() const{  return psprintf("(%i:%i) ", xmlFile.GetErrorLine(), xmlFile.GetErrorColumn()) + xmlFile.GetErrorString();}PString PVXMLSession::EvaluateExpr(const PString & oexpr){  PString expr = oexpr.Trim();  // see if all digits  PINDEX i;  BOOL allDigits = TRUE;  for (i = 0; i < expr.GetLength(); i++) {    allDigits = allDigits && isdigit(expr[i]);  }  if (allDigits)    return expr;  return GetVar(expr);}PString PVXMLSession::GetVar(const PString & ostr) const{  PString str = ostr;  PString scope;  // get scope  PINDEX pos = str.Find('.');  if (pos != P_MAX_INDEX) {    scope = str.Left(pos);    str   = str.Mid(pos+1);  }  // process session scope  if (scope.IsEmpty() || (scope *= "session")) {    if (sessionVars.Contains(str))      return sessionVars(str);  }  // assume any other scope is actually document or application  return documentVars(str);}void PVXMLSession::SetVar(const PString & ostr, const PString & val){  PString str = ostr;  PString scope;  // get scope  PINDEX pos = str.Find('.');  if (pos != P_MAX_INDEX) {    scope = str.Left(pos);    str   = str.Mid(pos+1);  }  // do session scope  if (scope.IsEmpty() || (scope *= "session")) {    sessionVars.SetAt(str, val);    return;  }

⌨️ 快捷键说明

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