📄 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.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){ arg.Replace("%s", PString(PString::Unsigned, sampleFrequency)); arg.Replace("%f", format); // execute a command and send the output through the stream pipeCmd = new PPipeChannel; if (!pipeCmd->Open(arg, PPipeChannel::ReadOnly)) { PTRACE(3, "PVXML\tCannot open command " << arg); delete pipeCmd; return; } if (pipeCmd == NULL) PTRACE(3, "PVXML\tCannot open command \"" << arg << "\""); else { pipeCmd->Execute(); PTRACE(3, "PVXML\tPlaying command \"" << arg << "\""); outgoingChannel.SetReadChannel(pipeCmd, TRUE); }}void PVXMLPlayableCommand::OnStop() { if (pipeCmd != NULL) { pipeCmd->WaitForTermination(); delete pipeCmd; }}PFactory<PVXMLPlayable>::Worker<PVXMLPlayableCommand> vxmlPlayableCommandFactory("Command");///////////////////////////////////////////////////////////////BOOL PVXMLPlayableData::Open(PVXMLChannel & chan, const PString & /*_fn*/, PINDEX _delay, PINDEX _repeat, BOOL v){ return PVXMLPlayable::Open(chan, _delay, _repeat, v); }void PVXMLPlayableData::SetData(const PBYTEArray & _data){ data = _data; }void PVXMLPlayableData::Play(PVXMLChannel & outgoingChannel){ PMemoryFile * chan = new PMemoryFile(data); PTRACE(3, "PVXML\tPlaying " << data.GetSize() << " bytes"); outgoingChannel.SetReadChannel(chan, TRUE);}BOOL PVXMLPlayableData::Rewind(PChannel * chan){ PMemoryFile * memfile = dynamic_cast<PMemoryFile *>(chan); if (memfile == NULL) return FALSE; return memfile->SetPosition(0); }PFactory<PVXMLPlayable>::Worker<PVXMLPlayableData> vxmlPlayableDataFactory("PCM Data");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -