PTLib
Version 2.10.4
|
00001 /* 00002 * vxml.h 00003 * 00004 * VXML engine for pwlib library 00005 * 00006 * Copyright (C) 2002 Equivalence Pty. Ltd. 00007 * 00008 * The contents of this file are subject to the Mozilla Public License 00009 * Version 1.0 (the "License"); you may not use this file except in 00010 * compliance with the License. You may obtain a copy of the License at 00011 * http://www.mozilla.org/MPL/ 00012 * 00013 * Software distributed under the License is distributed on an "AS IS" 00014 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 00015 * the License for the specific language governing rights and limitations 00016 * under the License. 00017 * 00018 * The Original Code is Portable Windows Library. 00019 * 00020 * The Initial Developer of the Original Code is Equivalence Pty. Ltd. 00021 * 00022 * Contributor(s): ______________________________________. 00023 * 00024 * $Revision: 26933 $ 00025 * $Author: rjongbloed $ 00026 * $Date: 2012-02-02 21:17:20 -0600 (Thu, 02 Feb 2012) $ 00027 */ 00028 00029 #ifndef PTLIB_VXML_H 00030 #define PTLIB_VXML_H 00031 00032 #ifdef P_USE_PRAGMA 00033 #pragma interface 00034 #endif 00035 00036 00037 #include <ptclib/pxml.h> 00038 00039 #if P_VXML 00040 00041 #include <ptlib/pfactory.h> 00042 #include <ptlib/pipechan.h> 00043 #include <ptclib/delaychan.h> 00044 #include <ptclib/pwavfile.h> 00045 #include <ptclib/ptts.h> 00046 #include <ptclib/url.h> 00047 00048 #include <queue> 00049 00050 00051 class PVXMLSession; 00052 class PVXMLDialog; 00053 class PVXMLSession; 00054 00055 // these are the same strings as the Opal equivalents, but as this is PWLib, we can't use Opal contants 00056 #define VXML_PCM16 "PCM-16" 00057 #define VXML_G7231 "G.723.1" 00058 #define VXML_G729 "G.729" 00059 00060 00062 00063 class PVXMLGrammar : public PObject 00064 { 00065 PCLASSINFO(PVXMLGrammar, PObject); 00066 public: 00067 PVXMLGrammar(PVXMLSession & session, PXMLElement & field); 00068 00069 virtual void OnUserInput(const char ch) = 0; 00070 virtual void Start(); 00071 virtual bool Process(); 00072 00073 enum GrammarState { 00074 Idle, 00075 Started, 00076 Filled, 00077 NoInput, 00078 NoMatch, 00079 Help 00080 }; 00081 00082 GrammarState GetState() const { return m_state; } 00083 00084 protected: 00085 PDECLARE_NOTIFIER(PTimer, PVXMLGrammar, OnTimeout); 00086 00087 PVXMLSession & m_session; 00088 PXMLElement & m_field; 00089 PString m_value; 00090 GrammarState m_state; 00091 PTimer m_timer; 00092 PMutex m_mutex; 00093 }; 00094 00095 00097 00098 class PVXMLMenuGrammar : public PVXMLGrammar 00099 { 00100 PCLASSINFO(PVXMLMenuGrammar, PVXMLGrammar); 00101 public: 00102 PVXMLMenuGrammar(PVXMLSession & session, PXMLElement & field); 00103 virtual void OnUserInput(const char ch); 00104 virtual bool Process(); 00105 }; 00106 00107 00109 00110 class PVXMLDigitsGrammar : public PVXMLGrammar 00111 { 00112 PCLASSINFO(PVXMLDigitsGrammar, PVXMLGrammar); 00113 public: 00114 PVXMLDigitsGrammar( 00115 PVXMLSession & session, 00116 PXMLElement & field, 00117 PINDEX minDigits, 00118 PINDEX maxDigits, 00119 PString terminators 00120 ); 00121 00122 virtual void OnUserInput(const char ch); 00123 00124 protected: 00125 PINDEX m_minDigits; 00126 PINDEX m_maxDigits; 00127 PString m_terminators; 00128 }; 00129 00130 00132 00133 class PVXMLCache : public PMutex 00134 { 00135 public: 00136 PVXMLCache(const PDirectory & directory); 00137 00138 PFilePath CreateFilename(const PString & prefix, const PString & key, const PString & fileType); 00139 00140 void Put(const PString & prefix, 00141 const PString & key, 00142 const PString & fileType, 00143 const PString & contentType, 00144 const PFilePath & fn, 00145 PFilePath & dataFn); 00146 00147 PBoolean Get(const PString & prefix, 00148 const PString & key, 00149 const PString & fileType, 00150 PString & contentType, 00151 PFilePath & fn); 00152 00153 PFilePath GetCacheDir() const 00154 { return directory; } 00155 00156 PFilePath GetRandomFilename(const PString & prefix, const PString & fileType); 00157 00158 static PVXMLCache & GetResourceCache(); 00159 00160 protected: 00161 PDirectory directory; 00162 }; 00163 00165 00166 class PVXMLChannel; 00167 00168 class PVXMLSession : public PIndirectChannel 00169 { 00170 PCLASSINFO(PVXMLSession, PIndirectChannel); 00171 public: 00172 PVXMLSession(PTextToSpeech * tts = NULL, PBoolean autoDelete = false); 00173 virtual ~PVXMLSession(); 00174 00175 // new functions 00176 PTextToSpeech * SetTextToSpeech(PTextToSpeech * tts, PBoolean autoDelete = false); 00177 PTextToSpeech * SetTextToSpeech(const PString & ttsName); 00178 PTextToSpeech * GetTextToSpeech() const { return m_textToSpeech; } 00179 00180 virtual PBoolean Load(const PString & source); 00181 virtual PBoolean LoadFile(const PFilePath & file, const PString & firstForm = PString::Empty()); 00182 virtual PBoolean LoadURL(const PURL & url); 00183 virtual PBoolean LoadVXML(const PString & xml, const PString & firstForm = PString::Empty()); 00184 virtual PBoolean IsLoaded() const { return m_xml.IsLoaded(); } 00185 00186 virtual PBoolean Open(const PString & mediaFormat); 00187 virtual PBoolean Close(); 00188 00189 virtual PBoolean Execute(); 00190 00191 PVXMLChannel * GetAndLockVXMLChannel(); 00192 void UnLockVXMLChannel() { m_sessionMutex.Signal(); } 00193 PMutex & GetSessionMutex() { return m_sessionMutex; } 00194 00195 virtual PBoolean LoadGrammar(PVXMLGrammar * grammar); 00196 00197 virtual PBoolean PlayText(const PString & text, PTextToSpeech::TextType type = PTextToSpeech::Default, PINDEX repeat = 1, PINDEX delay = 0); 00198 PBoolean ConvertTextToFilenameList(const PString & text, PTextToSpeech::TextType type, PStringArray & list, PBoolean useCacheing); 00199 00200 virtual PBoolean PlayFile(const PString & fn, PINDEX repeat = 1, PINDEX delay = 0, PBoolean autoDelete = false); 00201 virtual PBoolean PlayData(const PBYTEArray & data, PINDEX repeat = 1, PINDEX delay = 0); 00202 virtual PBoolean PlayCommand(const PString & data, PINDEX repeat = 1, PINDEX delay = 0); 00203 virtual PBoolean PlayResource(const PURL & url, PINDEX repeat = 1, PINDEX delay = 0); 00204 virtual PBoolean PlayTone(const PString & toneSpec, PINDEX repeat = 1, PINDEX delay = 0); 00205 virtual PBoolean PlayElement(PXMLElement & element); 00206 00207 //virtual PBoolean PlayMedia(const PURL & url, PINDEX repeat = 1, PINDEX delay = 0); 00208 virtual PBoolean PlaySilence(PINDEX msecs = 0); 00209 virtual PBoolean PlaySilence(const PTimeInterval & timeout); 00210 00211 virtual PBoolean PlayStop(); 00212 00213 virtual void SetPause(PBoolean pause); 00214 virtual void GetBeepData(PBYTEArray & data, unsigned ms); 00215 00216 virtual PBoolean StartRecording(const PFilePath & fn, PBoolean recordDTMFTerm, const PTimeInterval & recordMaxTime, const PTimeInterval & recordFinalSilence); 00217 virtual PBoolean EndRecording(); 00218 00219 virtual void OnUserInput(const PString & str); 00220 00221 PString GetXMLError() const; 00222 00223 virtual void OnEndDialog(); 00224 virtual void OnEndSession(); 00225 00226 enum TransferType { 00227 BridgedTransfer, 00228 BlindTransfer, 00229 ConsultationTransfer 00230 }; 00231 virtual bool OnTransfer(const PString & /*destination*/, TransferType /*type*/) { return false; } 00232 void SetTransferComplete(bool state); 00233 00234 const PStringToString & GetVariables() { return m_variables; } 00235 virtual PCaselessString GetVar(const PString & str) const; 00236 virtual void SetVar(const PString & ostr, const PString & val); 00237 virtual PString EvaluateExpr(const PString & oexpr); 00238 00239 static PTimeInterval StringToTime(const PString & str); 00240 00241 virtual PBoolean RetreiveResource(const PURL & url, PString & contentType, PFilePath & fn, PBoolean useCache = true); 00242 00243 PDECLARE_NOTIFIER(PThread, PVXMLSession, VXMLExecute); 00244 00245 bool SetCurrentForm(const PString & id, bool fullURI); 00246 bool GoToEventHandler(PXMLElement & element, const PString & eventName); 00247 00248 // overrides from VXMLChannelInterface 00249 virtual void OnEndRecording(); 00250 virtual void Trigger(); 00251 00252 00253 virtual PBoolean TraverseAudio(PXMLElement & element); 00254 virtual PBoolean TraverseBreak(PXMLElement & element); 00255 virtual PBoolean TraverseValue(PXMLElement & element); 00256 virtual PBoolean TraverseSayAs(PXMLElement & element); 00257 virtual PBoolean TraverseGoto(PXMLElement & element); 00258 virtual PBoolean TraverseGrammar(PXMLElement & element); 00259 virtual PBoolean TraverseRecord(PXMLElement & element); 00260 virtual PBoolean TraversedRecord(PXMLElement & element); 00261 virtual PBoolean TraverseIf(PXMLElement & element); 00262 virtual PBoolean TraverseExit(PXMLElement & element); 00263 virtual PBoolean TraverseVar(PXMLElement & element); 00264 virtual PBoolean TraverseSubmit(PXMLElement & element); 00265 virtual PBoolean TraverseMenu(PXMLElement & element); 00266 virtual PBoolean TraversedMenu(PXMLElement & element); 00267 virtual PBoolean TraverseChoice(PXMLElement & element); 00268 virtual PBoolean TraverseProperty(PXMLElement & element); 00269 virtual PBoolean TraverseDisconnect(PXMLElement & element); 00270 virtual PBoolean TraverseForm(PXMLElement & element); 00271 virtual PBoolean TraversedForm(PXMLElement & element); 00272 virtual PBoolean TraversePrompt(PXMLElement & element); 00273 virtual PBoolean TraverseField(PXMLElement & element); 00274 virtual PBoolean TraversedField(PXMLElement & element); 00275 virtual PBoolean TraverseFilled(PXMLElement & element); 00276 virtual PBoolean TraverseNoInput(PXMLElement & element); 00277 virtual PBoolean TraverseNoMatch(PXMLElement & element); 00278 virtual PBoolean TraverseError(PXMLElement & element); 00279 virtual PBoolean TraverseCatch(PXMLElement & element); 00280 virtual PBoolean TraverseTransfer(PXMLElement & element); 00281 virtual PBoolean TraversedTransfer(PXMLElement & element); 00282 00283 __inline PVXMLChannel * GetVXMLChannel() const { return (PVXMLChannel *)readChannel; } 00284 00285 protected: 00286 virtual bool ProcessNode(); 00287 virtual bool ProcessEvents(); 00288 virtual bool ProcessGrammar(); 00289 virtual bool NextNode(bool skipChildren); 00290 00291 void SayAs(const PString & className, const PString & text); 00292 void SayAs(const PString & className, const PString & text, const PString & voice); 00293 00294 PURL NormaliseResourceName(const PString & src); 00295 00296 PMutex m_sessionMutex; 00297 00298 PURL m_rootURL; 00299 PXML m_xml; 00300 00301 PTextToSpeech * m_textToSpeech; 00302 bool m_autoDeleteTextToSpeech; 00303 00304 PThread * m_vxmlThread; 00305 bool m_abortVXML; 00306 PSyncPoint m_waitForEvent; 00307 PXMLObject * m_currentNode; 00308 bool m_xmlChanged; 00309 bool m_speakNodeData; 00310 00311 PVXMLGrammar * m_grammar; 00312 char m_defaultMenuDTMF; 00313 00314 PStringToString m_variables; 00315 PString m_variableScope; 00316 00317 std::queue<char> m_userInputQueue; 00318 PMutex m_userInputMutex; 00319 00320 enum { 00321 NotRecording, 00322 RecordingInProgress, 00323 RecordingComplete 00324 } m_recordingStatus; 00325 bool m_recordStopOnDTMF; 00326 00327 enum { 00328 NotTransfering, 00329 TransferInProgress, 00330 TransferFailed, 00331 TransferSuccessful 00332 } m_transferStatus; 00333 PTime m_transferStartTime; 00334 }; 00335 00336 00338 00339 class PVXMLRecordable : public PObject 00340 { 00341 PCLASSINFO(PVXMLRecordable, PObject); 00342 public: 00343 PVXMLRecordable(); 00344 00345 virtual PBoolean Open(const PString & arg) = 0; 00346 00347 virtual bool OnStart(PVXMLChannel & incomingChannel) = 0; 00348 virtual void OnStop() { } 00349 00350 virtual PBoolean OnFrame(PBoolean /*isSilence*/) { return false; } 00351 00352 void SetFinalSilence(unsigned v) 00353 { m_finalSilence = v > 0 ? v : 60000; } 00354 00355 unsigned GetFinalSilence() 00356 { return m_finalSilence; } 00357 00358 void SetMaxDuration(unsigned v) 00359 { m_maxDuration = v > 0 ? v : 86400000; } 00360 00361 unsigned GetMaxDuration() 00362 { return m_maxDuration; } 00363 00364 protected: 00365 PSimpleTimer m_silenceTimer; 00366 PSimpleTimer m_recordTimer; 00367 unsigned m_finalSilence; 00368 unsigned m_maxDuration; 00369 }; 00370 00372 00373 class PVXMLRecordableFilename : public PVXMLRecordable 00374 { 00375 PCLASSINFO(PVXMLRecordableFilename, PVXMLRecordable); 00376 public: 00377 PBoolean Open(const PString & arg); 00378 bool OnStart(PVXMLChannel & incomingChannel); 00379 PBoolean OnFrame(PBoolean isSilence); 00380 00381 protected: 00382 PFilePath m_fileName; 00383 }; 00384 00386 00387 class PVXMLPlayable : public PObject 00388 { 00389 PCLASSINFO(PVXMLPlayable, PObject); 00390 public: 00391 PVXMLPlayable(); 00392 00393 virtual PBoolean Open(PVXMLChannel & chan, const PString & arg, PINDEX delay, PINDEX repeat, PBoolean autoDelete); 00394 00395 virtual bool OnStart() = 0; 00396 virtual bool OnRepeat(); 00397 virtual bool OnDelay(); 00398 virtual void OnStop(); 00399 00400 virtual void SetRepeat(PINDEX v) 00401 { m_repeat = v; } 00402 00403 virtual PINDEX GetRepeat() const 00404 { return m_repeat; } 00405 00406 virtual PINDEX GetDelay() const 00407 { return m_delay; } 00408 00409 void SetFormat(const PString & fmt) 00410 { m_format = fmt; } 00411 00412 void SetSampleFrequency(unsigned rate) 00413 { m_sampleFrequency = rate; } 00414 00415 friend class PVXMLChannel; 00416 00417 protected: 00418 PVXMLChannel * m_vxmlChannel; 00419 PChannel * m_subChannel; 00420 PINDEX m_repeat; 00421 PINDEX m_delay; 00422 PString m_format; 00423 unsigned m_sampleFrequency; 00424 bool m_autoDelete; 00425 bool m_delayDone; // very tacky flag used to indicate when the post-play delay has been done 00426 }; 00427 00429 00430 class PVXMLPlayableStop : public PVXMLPlayable 00431 { 00432 PCLASSINFO(PVXMLPlayableStop, PVXMLPlayable); 00433 public: 00434 virtual bool OnStart(); 00435 }; 00436 00438 00439 class PVXMLPlayableURL : public PVXMLPlayable 00440 { 00441 PCLASSINFO(PVXMLPlayableURL, PVXMLPlayable); 00442 public: 00443 virtual PBoolean Open(PVXMLChannel & chan, const PString & arg, PINDEX delay, PINDEX repeat, PBoolean autoDelete); 00444 virtual bool OnStart(); 00445 protected: 00446 PURL m_url; 00447 }; 00448 00450 00451 class PVXMLPlayableData : public PVXMLPlayable 00452 { 00453 PCLASSINFO(PVXMLPlayableData, PVXMLPlayable); 00454 public: 00455 virtual PBoolean Open(PVXMLChannel & chan, const PString & arg, PINDEX delay, PINDEX repeat, PBoolean autoDelete); 00456 void SetData(const PBYTEArray & data); 00457 virtual bool OnStart(); 00458 virtual bool OnRepeat(); 00459 protected: 00460 PBYTEArray m_data; 00461 }; 00462 00464 00465 #include <ptclib/dtmf.h> 00466 00467 class PVXMLPlayableTone : public PVXMLPlayableData 00468 { 00469 PCLASSINFO(PVXMLPlayableTone, PVXMLPlayableData); 00470 public: 00471 virtual PBoolean Open(PVXMLChannel & chan, const PString & arg, PINDEX delay, PINDEX repeat, PBoolean autoDelete); 00472 protected: 00473 PTones m_tones; 00474 }; 00475 00477 00478 class PVXMLPlayableCommand : public PVXMLPlayable 00479 { 00480 PCLASSINFO(PVXMLPlayableCommand, PVXMLPlayable); 00481 public: 00482 virtual PBoolean Open(PVXMLChannel & chan, const PString & arg, PINDEX delay, PINDEX repeat, PBoolean autoDelete); 00483 virtual bool OnStart(); 00484 virtual void OnStop(); 00485 00486 protected: 00487 PString m_command; 00488 }; 00489 00491 00492 class PVXMLPlayableFile : public PVXMLPlayable 00493 { 00494 PCLASSINFO(PVXMLPlayableFile, PVXMLPlayable); 00495 public: 00496 virtual PBoolean Open(PVXMLChannel & chan, const PString & arg, PINDEX delay, PINDEX repeat, PBoolean autoDelete); 00497 virtual bool OnStart(); 00498 virtual bool OnRepeat(); 00499 virtual void OnStop(); 00500 protected: 00501 PFilePath m_filePath; 00502 }; 00503 00505 00506 class PVXMLPlayableFileList : public PVXMLPlayableFile 00507 { 00508 PCLASSINFO(PVXMLPlayableFileList, PVXMLPlayableFile); 00509 public: 00510 PVXMLPlayableFileList(); 00511 virtual PBoolean Open(PVXMLChannel & chan, const PString & arg, PINDEX delay, PINDEX repeat, PBoolean autoDelete); 00512 virtual PBoolean Open(PVXMLChannel & chan, const PStringArray & filenames, PINDEX delay, PINDEX repeat, PBoolean autoDelete); 00513 virtual bool OnStart(); 00514 virtual bool OnRepeat(); 00515 virtual void OnStop(); 00516 protected: 00517 PStringArray m_fileNames; 00518 PINDEX m_currentIndex; 00519 }; 00520 00522 00523 PQUEUE(PVXMLQueue, PVXMLPlayable); 00524 00526 00527 class PVXMLChannel : public PDelayChannel 00528 { 00529 PCLASSINFO(PVXMLChannel, PDelayChannel); 00530 public: 00531 PVXMLChannel(unsigned frameDelay, PINDEX frameSize); 00532 ~PVXMLChannel(); 00533 00534 virtual PBoolean Open(PVXMLSession * session); 00535 00536 // overrides from PIndirectChannel 00537 virtual PBoolean IsOpen() const; 00538 virtual PBoolean Close(); 00539 virtual PBoolean Read(void * buffer, PINDEX amount); 00540 virtual PBoolean Write(const void * buf, PINDEX len); 00541 00542 // new functions 00543 virtual PWAVFile * CreateWAVFile(const PFilePath & fn, PBoolean recording = false); 00544 00545 const PString & GetMediaFormat() const { return mediaFormat; } 00546 PBoolean IsMediaPCM() const { return mediaFormat == "PCM-16"; } 00547 virtual PString AdjustWavFilename(const PString & fn); 00548 00549 // Incoming channel functions 00550 virtual PBoolean WriteFrame(const void * buf, PINDEX len) = 0; 00551 virtual PBoolean IsSilenceFrame(const void * buf, PINDEX len) const = 0; 00552 00553 virtual PBoolean QueueRecordable(PVXMLRecordable * newItem); 00554 00555 PBoolean StartRecording(const PFilePath & fn, unsigned finalSilence = 3000, unsigned maxDuration = 30000); 00556 PBoolean EndRecording(); 00557 PBoolean IsRecording() const { return m_recordable != NULL; } 00558 00559 // Outgoing channel functions 00560 virtual PBoolean ReadFrame(void * buffer, PINDEX amount) = 0; 00561 virtual PINDEX CreateSilenceFrame(void * buffer, PINDEX amount) = 0; 00562 virtual void GetBeepData(PBYTEArray &, unsigned) { } 00563 00564 virtual PBoolean QueueResource(const PURL & url, PINDEX repeat= 1, PINDEX delay = 0); 00565 00566 virtual PBoolean QueuePlayable(const PString & type, const PString & str, PINDEX repeat = 1, PINDEX delay = 0, PBoolean autoDelete = false); 00567 virtual PBoolean QueuePlayable(PVXMLPlayable * newItem); 00568 virtual PBoolean QueueData(const PBYTEArray & data, PINDEX repeat = 1, PINDEX delay = 0); 00569 00570 virtual PBoolean QueueFile(const PString & fn, PINDEX repeat = 1, PINDEX delay = 0, PBoolean autoDelete = false) 00571 { return QueuePlayable("File", fn, repeat, delay, autoDelete); } 00572 00573 virtual PBoolean QueueCommand(const PString & cmd, PINDEX repeat = 1, PINDEX delay = 0) 00574 { return QueuePlayable("Command", cmd, repeat, delay, true); } 00575 00576 virtual void FlushQueue(); 00577 virtual PBoolean IsPlaying() const { return m_currentPlayItem != NULL || m_playQueue.GetSize() > 0; } 00578 00579 void SetPause(PBoolean pause) { m_paused = pause; } 00580 00581 unsigned GetSampleFrequency() const { return m_sampleFrequency; } 00582 00583 void SetSilence(unsigned msecs); 00584 00585 protected: 00586 PVXMLSession * m_vxmlSession; 00587 00588 unsigned m_sampleFrequency; 00589 PString mediaFormat; 00590 PString wavFilePrefix; 00591 00592 PMutex m_channelWriteMutex; 00593 PMutex m_channelReadMutex; 00594 bool m_closed; 00595 bool m_paused; 00596 PINDEX m_totalData; 00597 00598 // Incoming audio variables 00599 PVXMLRecordable * m_recordable; 00600 unsigned m_finalSilence; 00601 unsigned m_silenceRun; 00602 00603 // Outgoing audio variables 00604 PVXMLQueue m_playQueue; 00605 PVXMLPlayable * m_currentPlayItem; 00606 PSimpleTimer m_silenceTimer; 00607 }; 00608 00609 00611 00612 class PVXMLNodeHandler : public PObject 00613 { 00614 PCLASSINFO(PVXMLNodeHandler, PObject); 00615 public: 00616 // Return true for process node, false to skip and move to next sibling 00617 virtual bool Start(PVXMLSession & /*session*/, PXMLElement & /*node*/) const { return true; } 00618 00619 // Return true to move to next sibling, false to stay at this node. 00620 virtual bool Finish(PVXMLSession & /*session*/, PXMLElement & /*node*/) const { return true; } 00621 }; 00622 00623 00624 typedef PFactory<PVXMLNodeHandler, PCaselessString> PVXMLNodeFactory; 00625 00626 00627 #endif // P_VXML 00628 00629 #endif // PTLIB_VXML_H 00630 00631 00632 // End of file ////////////////////////////////////////////////////////////////