📄 vxml.cxx
字号:
/*
* 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 + -