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

📄 vxml.cxx

📁 sloedgy open sip stack source code
💻 CXX
📖 第 1 页 / 共 5 页
字号:
/*
 * vxml.cxx
 *
 * VXML engine for pwlib library
 *
 * Copyright (C) 2002 Equivalence Pty. Ltd.
 *
 * The contents of this file are subject to the Mozilla Public License
 * Version 1.0 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
 * the License for the specific language governing rights and limitations
 * under the License.
 *
 * The Original Code is Portable Windows Library.
 *
 * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
 *
 * Contributor(s): ______________________________________.
 *
 * $Log: vxml.cxx,v $
 * Revision 1.6  2007/06/12 09:23:15  joegenbaclor
 * Added IVR Call Transfer
 *
 * Revision 1.5  2007/06/08 15:10:53  joegenbaclor
 * Added IVR DTMF Grammar
 *
 * Revision 1.4  2007/06/08 02:34:10  joegenbaclor
 * Commiting more Media Server Related Changes
 *
 * Revision 1.3  2007/06/06 09:54:37  joegenbaclor
 * More B2BUAConnection IVR methods
 *
 * Revision 1.2  2007/03/08 10:23:41  joegenbaclor
 * Tidy up OpalManager Destruction
 * Enabled Recording in vxml
 *
 * Revision 1.1  2006/06/29 04:18:04  joegenbaclor
 * *** empty log message ***
 *
 * Revision 1.66  2005/12/01 01:05:59  csoutheren
 * Fixed uninitialised variable
 *
 * Revision 1.65  2005/11/30 12:47:41  csoutheren
 * Removed tabs, reformatted some code, and changed tags for Doxygen
 *
 * Revision 1.64  2005/10/30 23:25:52  csoutheren
 * Fixed formatting
 * Removed throw() declarations (PWLib does not do exceptions)
 * Removed duplicate destructor declarations and definitions
 *
 * Revision 1.63  2005/10/30 19:41:53  dominance
 * fixed most of the warnings occuring during compilation
 *
 * Revision 1.62  2005/10/21 08:18:21  csoutheren
 * Fixed Close operator
 *
 * Revision 1.61  2005/08/13 06:38:22  rjongbloed
 * Fixed illegal code line, assigning to const object!
 *
 * Revision 1.60  2005/08/12 16:41:51  shorne
 * A couple more small fixes thx. Nickolay V. Shmyrev
 *
 * Revision 1.59  2005/08/11 08:48:10  shorne
 * Removed Close from PVXMLSession::Open method. Thanks Nickolay V. Shmyrev
 *
 * Revision 1.58  2005/05/12 13:40:45  csoutheren
 * Fixed locking problems with currentPLayItem optimisation
 *
 * Revision 1.57  2005/05/12 05:28:36  csoutheren
 * Optimised read loop and fixed problems with playing repeated continuous tones
 *
 * Revision 1.56  2005/04/21 05:28:58  csoutheren
 * Fixed assert if recordable does not queue properly
 *
 * Revision 1.55  2005/03/19 02:52:54  csoutheren
 * Fix warnings from gcc 4.1-20050313 shapshot
 *
 * Revision 1.54  2004/12/03 02:06:05  csoutheren
 * Ensure FlushQueue called OnStop for queued elements
 *
 * Revision 1.53  2004/08/09 11:10:34  csoutheren
 * Changed SetTextToSpeech to return ptr to new engine
 *
 * Revision 1.52  2004/07/28 02:01:51  csoutheren
 * Removed deadlock in some call shutdown scenarios
 *
 * Revision 1.51  2004/07/27 05:26:46  csoutheren
 * Fixed recording
 *
 * Revision 1.50  2004/07/27 00:00:41  csoutheren
 * Allowed Close to set closed flag before attepting lock of channels
 *
 * Revision 1.49  2004/07/26 07:25:02  csoutheren
 * Fixed another problem with thread starvation due to delaying inside a mutex lock
 *
 * Revision 1.48  2004/07/26 00:40:41  csoutheren
 * Fixed thread starvation problem under Linux by splitting channelMutex
 * into seperate read and write mutexes
 *
 * Revision 1.47  2004/07/23 00:59:26  csoutheren
 * Check in latest changes
 *
 * Revision 1.46  2004/07/17 09:44:12  rjongbloed
 * Fixed missing set of last write count if not actually writing frames.
 *
 * Revision 1.45  2004/07/15 03:12:42  csoutheren
 * Migrated changes from crs_vxnml_devel branch into main trunk
 *
 * Revision 1.42.2.7  2004/07/13 08:13:05  csoutheren
 * Lots of implementation of factory-based PWAVFile
 *
 * Revision 1.42.2.6  2004/07/12 08:30:17  csoutheren
 * More fixes for abstract factory implementation of PWAVFile
 *
 * Revision 1.42.2.5  2004/07/08 04:58:11  csoutheren
 * Exposed VXML playable classes to allow descendants
 *
 * Revision 1.42.2.4  2004/07/07 07:07:43  csoutheren
 * Changed PWAVFile to use abstract factories (extensively)
 * Removed redundant blocking/unblocking when using G.723.1
 * More support for call transfer
 *
 * Revision 1.42.2.3  2004/07/06 01:38:57  csoutheren
 * Changed PVXMLChannel to use PDelayChannel
 * Fixed bug where played files were deleted after playing
 *
 * Revision 1.42.2.2  2004/07/02 07:22:40  csoutheren
 * Updated for latest factory changes
 *
 * Revision 1.42.2.1  2004/06/20 11:18:03  csoutheren
 * Rewrite of resource cacheing to cache text-to-speech output
 *
 * Revision 1.42  2004/06/19 07:21:08  csoutheren
 * Change TTS engine registration to use abstract factory code
 * Started disentanglement of PVXMLChannel from PVXMLSession
 * Fixed problem with VXML session closing if played data file is not exact frame size multiple
 * Allowed PVXMLSession to be used without a VXML script
 * Changed PVXMLChannel to handle "file:" URLs
 * Numerous other small improvements and optimisations
 *
 * Revision 1.41  2004/06/02 08:29:28  csoutheren
 * Added new code from Andreas Sikkema to implement various VXML features
 *
 * Revision 1.40  2004/06/02 06:16:48  csoutheren
 * Removed unnecessary buffer copying and removed potential busy loop
 *
 * Revision 1.39  2004/05/02 05:14:43  rjongbloed
 * Fixed possible deadlock in shutdown of VXML channel/session.
 *
 * Revision 1.38  2004/04/24 06:27:56  rjongbloed
 * Fixed GCC 3.4.0 warnings about PAssertNULL and improved recoverability on
 *   NULL pointer usage in various bits of code.
 *
 * Revision 1.37  2004/03/23 04:48:42  csoutheren
 * Improved ability to start VXML scripts as needed
 *
 * Revision 1.36  2003/11/12 20:38:16  csoutheren
 * Fixed problem with incorrect sense of ContentLength header detection thanks to Andreas Sikkema
 *
 * Revision 1.35  2003/05/14 01:12:53  rjongbloed
 * Fixed test for SID frames in record silence detection on G.723.1A
 *
 * Revision 1.34  2003/04/23 11:54:53  craigs
 * Added ability to record audio
 *
 * Revision 1.33  2003/04/10 04:19:43  robertj
 * Fixed incorrect timing on G.723.1 (framed codec)
 * Fixed not using correct codec file suffix for non PCM/G.723.1 codecs.
 *
 * Revision 1.32  2003/04/08 05:09:14  craigs
 * Added ability to use commands as an audio source
 *
 * Revision 1.31  2003/03/17 08:03:07  robertj
 * Combined to the separate incoming and outgoing substream classes into
 *   a single class to make it easier to produce codec aware descendents.
 * Added G.729 substream class.
 *
 * Revision 1.30  2002/12/03 22:39:14  robertj
 * Removed get document that just returns a content length as the chunked
 *   transfer encoding makes this very dangerous.
 *
 * Revision 1.29  2002/11/19 10:36:30  robertj
 * Added functions to set anf get "file:" URL. as PFilePath and do the right
 *   things with platform dependent directory components.
 *
 * Revision 1.28  2002/11/08 03:39:27  craigs
 * Fixed problem with G.723.1 files
 *
 * Revision 1.27  2002/09/24 13:47:41  robertj
 * Added support for more vxml commands, thanks Alexander Kovatch
 *
 * Revision 1.26  2002/09/18 06:37:40  robertj
 * Added functions to load vxml directly, via file or URL. Old function
 *   intelligently picks which one to use.
 *
 * Revision 1.25  2002/09/03 04:38:14  craigs
 * Added VXML 2.0 time attribute to <break>
 *
 * Revision 1.24  2002/09/03 04:11:37  craigs
 * More changes from Alexander Kovatch
 *
 * Revision 1.23  2002/08/30 07:33:16  craigs
 * Added extra initialisations
 *
 * Revision 1.22  2002/08/30 05:05:54  craigs
 * Added changes for PVXMLGrammar from Alexander Kovatch
 *
 * Revision 1.21  2002/08/29 00:16:12  craigs
 * Fixed typo, thanks to Peter Robinson
 *
 * Revision 1.20  2002/08/28 08:05:16  craigs
 * Reorganised VXMLSession class as per code from Alexander Kovatch
 *
 * Revision 1.19  2002/08/28 05:10:57  craigs
 * Added ability to load resources via URI
 * Added cache
 *
 * Revision 1.18  2002/08/27 02:46:56  craigs
 * Removed need for application to call AllowClearCall
 *
 * Revision 1.17  2002/08/27 02:20:09  craigs
 * Added <break> command in prompt blocks
 * Fixed potential deadlock
 * Added <prompt> command in top level fields, thanks to Alexander Kovatch
 *
 * Revision 1.16  2002/08/15 04:11:16  robertj
 * Fixed shutdown problems with closing vxml session, leaks a thread.
 * Fixed potential problems with indirect channel Close() function.
 *
 * Revision 1.15  2002/08/15 02:13:10  craigs
 * Fixed problem with handle leak (maybe) and change tts files back to autodelete
 *
 * Revision 1.14  2002/08/14 15:18:07  craigs
 * Improved random filename generation
 *
 * Revision 1.13  2002/08/08 01:03:06  craigs
 * Added function to re-enable automatic call clearing on script end
 *
 * Revision 1.12  2002/08/07 13:38:14  craigs
 * Fixed bug in calculating lengths of G.723.1 packets
 *
 * Revision 1.11  2002/08/06 07:45:28  craigs
 * Added lots of stuff from OpalVXML
 *
 * Revision 1.10  2002/07/29 15:08:50  craigs
 * Added autodelete option to PlayFile
 *
 * Revision 1.9  2002/07/29 15:03:36  craigs
 * Added access to queue functions
 * Added autodelete option to AddFile
 *
 * Revision 1.8  2002/07/29 14:16:05  craigs
 * Added asynchronous VXML execution
 *
 * Revision 1.7  2002/07/17 08:34:25  craigs
 * Fixed deadlock problems
 *
 * Revision 1.6  2002/07/17 06:08:23  craigs
 * Added additional "sayas" classes
 *
 * Revision 1.5  2002/07/10 13:15:20  craigs
 * Moved some VXML classes from Opal back into PTCLib
 * Fixed various race conditions
 *
 * Revision 1.4  2002/07/05 06:28:07  craigs
 * Added OnEmptyAction callback
 *
 * Revision 1.3  2002/07/02 06:24:53  craigs
 * Added recording functions
 *
 * Revision 1.2  2002/06/28 01:30:29  robertj
 * Fixed ability to compile if do not have expat library.
 *
 * Revision 1.1  2002/06/27 05:27:49  craigs
 * Initial version
 *
 *
 */

#ifdef __GNUC__
#pragma implementation "vxml.h"
#endif

#include <ptlib.h>

#define P_DISABLE_FACTORY_INSTANCES

//#if P_EXPAT

#include <ptlib/pfactory.h>
#include <ptclib/vxml.h>
#include <ptclib/memfile.h>
#include <ptclib/random.h>
#include <ptclib/http.h>

#define SMALL_BREAK_MSECS   1000
#define MEDIUM_BREAK_MSECS  2500
#define LARGE_BREAK_MSECS   5000

// LATER: Lookup what this value should be
#define DEFAULT_TIMEOUT     10000

//////////////////////////////////////////////////////////

static PString GetContentType(const PFilePath & fn)
{
  PString type = fn.GetType();

  if (type *= ".vxml")
    return "text/vxml";

  if (type *= ".wav")
    return "audio/x-wav";

  return PString::Empty();
}


///////////////////////////////////////////////////////////////

BOOL PVXMLPlayable::ReadFrame(PVXMLChannel & channel, void * _buf, PINDEX origLen)
{
  BYTE * buf = (BYTE *)_buf;
  PINDEX len = origLen;

  while (len > 0) {
    BOOL stat = channel.ReadFrame(buf, len);
    if (stat) 
      return TRUE;
    if ((repeat == 0) || !Rewind(channel.GetBaseReadChannel()))
      return FALSE;
    PINDEX readLen = channel.GetLastReadCount();
    len -= readLen;
    buf += readLen;
  }

  return TRUE;
}

///////////////////////////////////////////////////////////////

BOOL PVXMLPlayableFilename::Open(PVXMLChannel & chan, const PString & _fn, PINDEX _delay, PINDEX _repeat, BOOL _autoDelete)
{ 
  fn = _fn; 
  arg = _fn;
  if (!PFile::Exists(chan.AdjustWavFilename(fn)))
    return FALSE;

  return PVXMLPlayable::Open(chan, _delay, _repeat, _autoDelete); 
}

void PVXMLPlayableFilename::Play(PVXMLChannel & outgoingChannel)
{
  PChannel * chan = NULL;

  // check the file extension and open a .wav or a raw (.sw or .g723) file
  if ((fn.Right(4)).ToLower() == ".wav")
    chan = outgoingChannel.CreateWAVFile(fn);
  else {
    PFile * fileChan = new PFile(fn);
    if (fileChan->Open(PFile::ReadOnly))
      chan = fileChan;
    else {
      delete fileChan;
    }
  }

  if (chan == NULL)
    PTRACE(3, "PVXML\tCannot open file \"" << fn << "\"");
  else {
    PTRACE(3, "PVXML\tPlaying file \"" << fn << "\"");
    outgoingChannel.SetReadChannel(chan, TRUE);
  }
}

void PVXMLPlayableFilename::OnStop() 
{
  if (autoDelete) {
    PTRACE(3, "PVXML\tDeleting file \"" << fn << "\"");
    PFile::Remove(fn); 
  }
}

BOOL PVXMLPlayableFilename::Rewind(PChannel * chan) 
{ 
  PFile * file = dynamic_cast<PFile *>(chan); 
  if (file == NULL) 
    return FALSE;

  return file->SetPosition(0); 
}

PFactory<PVXMLPlayable>::Worker<PVXMLPlayableFilename> vxmlPlayableFilenameFactory("File");

///////////////////////////////////////////////////////////////

BOOL PVXMLPlayableFilenameList::Open(PVXMLChannel & chan, const PStringArray & _list, PINDEX _delay, PINDEX _repeat, BOOL _autoDelete)
{ 
  for (PINDEX i = 0; i < _list.GetSize(); ++i) {
    PString fn = chan.AdjustWavFilename(_list[i]);
    if (PFile::Exists(fn))
      filenames.AppendString(fn);
  }

  if (filenames.GetSize() == 0)
    return FALSE;

  currentIndex = 0;

  return PVXMLPlayable::Open(chan, _delay, ((_repeat >= 0) ? _repeat : 1) * filenames.GetSize(), _autoDelete); 
}

void PVXMLPlayableFilenameList::OnRepeat(PVXMLChannel & outgoingChannel)
{
  PFilePath fn = filenames[currentIndex++ % filenames.GetSize()];

  PChannel * chan = NULL;

  // check the file extension and open a .wav or a raw (.sw or .g723) file
  if ((fn.Right(4)).ToLower() == ".wav")
    chan = outgoingChannel.CreateWAVFile(fn);
  else {
    PFile * fileChan = new PFile(fn);
    if (fileChan->Open(PFile::ReadOnly))
      chan = fileChan;
    else {
      delete fileChan;
    }
  }

  if (chan == NULL)
    PTRACE(3, "PVXML\tCannot open file \"" << fn << "\"");
  else {
    PTRACE(3, "PVXML\tPlaying file \"" << fn << "\"");
    outgoingChannel.SetReadChannel(chan, TRUE);
  }
}

void PVXMLPlayableFilenameList::OnStop() 
{
  if (autoDelete)  {
    for (PINDEX i = 0; i < filenames.GetSize(); ++i) {
      PTRACE(3, "PVXML\tDeleting file \"" << filenames[i] << "\"");
      PFile::Remove(filenames[i]); 
    }
  }
}

PFactory<PVXMLPlayable>::Worker<PVXMLPlayableFilenameList> vxmlPlayableFilenameListFactory("FileList");

///////////////////////////////////////////////////////////////

PVXMLPlayableCommand::PVXMLPlayableCommand()
{ 
  pipeCmd = NULL; 
}

void PVXMLPlayableCommand::Play(PVXMLChannel & outgoingChannel)

⌨️ 快捷键说明

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