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

📄 vxml.cxx

📁 sloedgy open sip stack source code
💻 CXX
📖 第 1 页 / 共 5 页
字号:
      
      else {

        // Get the body of the response in a PBYTEArray (might be binary data)
        PBYTEArray incomingData;
        client.ReadContentBody(replyMIME, incomingData);
        contentType = replyMIME(PHTTPClient::ContentTypeTag);

        // write the data in the file
        PFile cacheFile(fn, PFile::WriteOnly);
        cacheFile.Write(incomingData.GetPointer(), incomingData.GetSize() );

        // if we have a cache and we are using it, then save the data
        if (useCache) 
          PVXMLCache::GetResourceCache().Put("url", url.AsString(), fileType, contentType, fn, dataFn);

        // data is loaded
        stat = TRUE;
      }
    }
  }

  // files on the local file system get loaded locally
  else if (url.GetScheme() *= "file") {
    dataFn = url.AsFilePath();
    stat = TRUE;
  }

  // unknown schemes give an error
  else 
    stat = FALSE;

  return stat;
}


PXMLElement * PVXMLSession::FindForm(const PString & id)
{
  // NOTE: should have some flag to know if it is loaded
  PXMLElement * root = xmlFile.GetRootElement();
  if (root == NULL)
    return NULL;
  
  // Only handle search of top level nodes for <form> element
  PINDEX i;
  for (i = 0; i < root->GetSize(); i++) {
    PXMLObject * xmlObject = root->GetElement(i); 
    if (xmlObject->IsElement()) {
      PXMLElement * xmlElement = (PXMLElement*)xmlObject;
      if (
          (xmlElement->GetName() *= "form") && 
          (id.IsEmpty() || (xmlElement->GetAttribute("id") *= id))
         )
        return xmlElement;
    }
  }
  return NULL;
}


BOOL PVXMLSession::Open(BOOL isPCM)
{
  if (isPCM)
    return Open(VXML_PCM16);
  else
    return Open(VXML_G7231);
}

BOOL PVXMLSession::Open(const PString & _mediaFormat)
{
  mediaFormat = _mediaFormat;

  PVXMLChannel * chan = PFactory<PVXMLChannel>::CreateInstance(mediaFormat);
  if (chan == NULL) {
    PTRACE(1, "VXML\tCannot create VXML channel with format " << mediaFormat);
    return FALSE;
  }

  chan->SetVXMLSession( this );

  // set the underlying channel
  if (!PIndirectChannel::Open(chan, chan))
    return FALSE;

  // start the VXML session in another thread
  {
    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();
  }
}

void PVXMLSession::OnEndPlay( const PString & identifier )
{
}

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("beep", beepData);

⌨️ 快捷键说明

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