|
PTLib Version 2.10.2
|
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: 25892 $ 00025 * $Author: rjongbloed $ 00026 * $Date: 2011-05-25 20:27:19 -0500 (Wed, 25 May 2011) $ 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(PXMLElement * field); 00068 virtual PBoolean OnUserInput(const char /*ch*/) { return true; } 00069 virtual void Stop() { } 00070 00071 PString GetValue() const { return value; } 00072 PXMLElement * GetField() { return field; } 00073 00074 enum GrammarState { 00075 FILLED, 00076 NOINPUT, 00077 NOMATCH, 00078 HELP }; 00079 00080 GrammarState GetState() const { return state; } 00081 00082 protected: 00083 PXMLElement * field; 00084 PString value; 00085 GrammarState state; 00086 }; 00087 00088 00090 00091 class PVXMLMenuGrammar : public PVXMLGrammar 00092 { 00093 PCLASSINFO(PVXMLMenuGrammar, PVXMLGrammar); 00094 public: 00095 PVXMLMenuGrammar(PXMLElement * field); 00096 }; 00097 00098 00100 00101 class PVXMLDigitsGrammar : public PVXMLGrammar 00102 { 00103 PCLASSINFO(PVXMLDigitsGrammar, PVXMLGrammar); 00104 public: 00105 PVXMLDigitsGrammar(PXMLElement * field, PINDEX minDigits, PINDEX maxDigits, PString terminators); 00106 PBoolean OnUserInput(const char ch); 00107 virtual void Stop(); 00108 00109 protected: 00110 PINDEX minDigits; 00111 PINDEX maxDigits; 00112 PString terminators; 00113 }; 00114 00115 00117 00118 class PVXMLCache : public PMutex 00119 { 00120 public: 00121 PVXMLCache(const PDirectory & directory); 00122 00123 PFilePath CreateFilename(const PString & prefix, const PString & key, const PString & fileType); 00124 00125 void Put(const PString & prefix, 00126 const PString & key, 00127 const PString & fileType, 00128 const PString & contentType, 00129 const PFilePath & fn, 00130 PFilePath & dataFn); 00131 00132 PBoolean Get(const PString & prefix, 00133 const PString & key, 00134 const PString & fileType, 00135 PString & contentType, 00136 PFilePath & fn); 00137 00138 PFilePath GetCacheDir() const 00139 { return directory; } 00140 00141 PFilePath GetRandomFilename(const PString & prefix, const PString & fileType); 00142 00143 static PVXMLCache & GetResourceCache(); 00144 00145 protected: 00146 PDirectory directory; 00147 }; 00148 00150 00151 class PVXMLChannel; 00152 00153 class PVXMLChannelInterface { 00154 public: 00155 virtual ~PVXMLChannelInterface() { } 00156 virtual void RecordEnd() = 0; 00157 virtual void OnEndRecording(const PString & channelName) = 0; 00158 virtual void Trigger() = 0; 00159 }; 00160 00162 00163 class PVXMLSession : public PIndirectChannel, public PVXMLChannelInterface 00164 { 00165 PCLASSINFO(PVXMLSession, PIndirectChannel); 00166 public: 00167 PVXMLSession(PTextToSpeech * tts = NULL, PBoolean autoDelete = false); 00168 virtual ~PVXMLSession(); 00169 00170 // new functions 00171 PTextToSpeech * SetTextToSpeech(PTextToSpeech * tts, PBoolean autoDelete = false); 00172 PTextToSpeech * SetTextToSpeech(const PString & ttsName); 00173 PTextToSpeech * GetTextToSpeech() const { return textToSpeech; } 00174 00175 virtual PBoolean Load(const PString & source); 00176 virtual PBoolean LoadFile(const PFilePath & file); 00177 virtual PBoolean LoadURL(const PURL & url); 00178 virtual PBoolean LoadVXML(const PString & xml); 00179 virtual PBoolean IsLoaded() const { return loaded; } 00180 00181 virtual PBoolean Open(const PString & mediaFormat); 00182 virtual PBoolean Close(); 00183 00184 virtual PBoolean Execute(); 00185 00186 PVXMLChannel * GetAndLockVXMLChannel(); 00187 void UnLockVXMLChannel() { sessionMutex.Signal(); } 00188 PMutex & GetSessionMutex() { return sessionMutex; } 00189 00190 virtual PBoolean LoadGrammar(PVXMLGrammar * grammar); 00191 00192 virtual PBoolean PlayText(const PString & text, PTextToSpeech::TextType type = PTextToSpeech::Default, PINDEX repeat = 1, PINDEX delay = 0); 00193 PBoolean ConvertTextToFilenameList(const PString & text, PTextToSpeech::TextType type, PStringArray & list, PBoolean useCacheing); 00194 00195 virtual PBoolean PlayFile(const PString & fn, PINDEX repeat = 1, PINDEX delay = 0, PBoolean autoDelete = false); 00196 virtual PBoolean PlayData(const PBYTEArray & data, PINDEX repeat = 1, PINDEX delay = 0); 00197 virtual PBoolean PlayCommand(const PString & data, PINDEX repeat = 1, PINDEX delay = 0); 00198 virtual PBoolean PlayResource(const PURL & url, PINDEX repeat = 1, PINDEX delay = 0); 00199 virtual PBoolean PlayTone(const PString & toneSpec, PINDEX repeat = 1, PINDEX delay = 0); 00200 00201 //virtual PBoolean PlayMedia(const PURL & url, PINDEX repeat = 1, PINDEX delay = 0); 00202 virtual PBoolean PlaySilence(PINDEX msecs = 0); 00203 virtual PBoolean PlaySilence(const PTimeInterval & timeout); 00204 00205 virtual PBoolean PlayStop(); 00206 00207 virtual void SetPause(PBoolean pause); 00208 virtual void GetBeepData(PBYTEArray & data, unsigned ms); 00209 00210 virtual PBoolean StartRecording(const PFilePath & fn, PBoolean recordDTMFTerm, const PTimeInterval & recordMaxTime, const PTimeInterval & recordFinalSilence); 00211 virtual PBoolean EndRecording(); 00212 virtual PBoolean IsPlaying() const; 00213 virtual PBoolean IsRecording() const; 00214 00215 virtual PBoolean OnUserInput(const PString & str); 00216 00217 PString GetXMLError() const; 00218 00219 virtual void OnEndDialog(); 00220 virtual void OnEndSession() { } 00221 virtual void OnTransfer(const PString & /*destination*/, bool /*bridged*/) { } 00222 00223 const PStringToString & GetVariables() { return m_variables; } 00224 virtual PCaselessString GetVar(const PString & str) const; 00225 virtual void SetVar(const PString & ostr, const PString & val); 00226 virtual PString EvaluateExpr(const PString & oexpr); 00227 00228 virtual PBoolean RetreiveResource(const PURL & url, PString & contentType, PFilePath & fn, PBoolean useCache = true); 00229 00230 PDECLARE_NOTIFIER(PThread, PVXMLSession, VXMLExecute); 00231 00232 void SetCallingToken( PString& token ) { callingCallToken = token; } 00233 00234 PXMLElement * FindHandler(const PString & event); 00235 00236 // overrides from VXMLChannelInterface 00237 virtual void OnEndRecording(const PString & channelName); 00238 virtual void RecordEnd(); 00239 virtual void Trigger(); 00240 00241 00242 virtual PBoolean TraverseAudio(); 00243 virtual PBoolean TraverseBreak(); 00244 virtual PBoolean TraverseValue(); 00245 virtual PBoolean TraverseSayAs(); 00246 virtual PBoolean TraverseGoto(); 00247 virtual PBoolean TraverseGrammar(); 00248 virtual PBoolean TraverseRecord(); 00249 virtual PBoolean TraverseIf(); 00250 virtual PBoolean TraverseExit(); 00251 virtual PBoolean TraverseVar(); 00252 virtual PBoolean TraverseSubmit(); 00253 virtual PBoolean TraverseMenu(); 00254 virtual PBoolean TraverseChoice(); 00255 virtual PBoolean TraverseProperty(); 00256 virtual PBoolean TraverseDisconnect(); 00257 virtual PBoolean TraverseForm(); 00258 virtual PBoolean TraversePrompt(); 00259 virtual PBoolean TraverseField(); 00260 virtual PBoolean TraversedField(); 00261 virtual PBoolean TraversedTransfer(); 00262 00263 protected: 00264 void Initialise(); 00265 00266 virtual void ProcessUserInput(); 00267 virtual void ProcessGrammar(); 00268 virtual void ProcessNode(); 00269 virtual bool NextNode(); 00270 00271 void SayAs(const PString & className, const PString & text); 00272 void SayAs(const PString & className, const PString & text, const PString & voice); 00273 00274 static PTimeInterval StringToTime(const PString & str); 00275 00276 PURL NormaliseResourceName(const PString & src); 00277 00278 PXMLElement * FindForm(const PString & id); 00279 00280 PSyncPoint waitForEvent; 00281 00282 PMutex sessionMutex; 00283 00284 PXML xmlFile; 00285 00286 PVXMLGrammar * activeGrammar; 00287 PBoolean listening; // true if waiting for recognition events 00288 int timeout; // timeout in msecs for the current recognition 00289 00290 PStringToString m_variables; 00291 00292 PMutex userInputMutex; 00293 std::queue<char> userInputQueue; 00294 00295 PBoolean recording; 00296 PFilePath recordFn; 00297 PBoolean recordDTMFTerm; 00298 PTimeInterval recordMaxTime; 00299 PTimeInterval recordFinalSilence; 00300 PSyncPoint recordSync; 00301 00302 PBoolean loaded; 00303 PURL rootURL; 00304 PBoolean emptyAction; 00305 00306 PThread * vxmlThread; 00307 bool m_abortVXML; 00308 00309 PString mediaFormat; 00310 PVXMLChannel * & vxmlChannel; 00311 00312 PTextToSpeech * textToSpeech; 00313 PBoolean autoDeleteTextToSpeech; 00314 00315 PXMLElement * currentForm; 00316 PXMLElement * currentField; 00317 PXMLObject * currentNode; 00318 bool m_speakNodeData; 00319 00320 private: 00321 PString callingCallToken; 00322 PSyncPoint answerSync; 00323 PString grammarResult; 00324 PString eventName; 00325 PINDEX defaultDTMF; 00326 }; 00327 00328 00330 00331 class PVXMLRecordable : public PObject 00332 { 00333 PCLASSINFO(PVXMLRecordable, PObject); 00334 public: 00335 PVXMLRecordable() 00336 { consecutiveSilence = 0; finalSilence = 3000; maxDuration = 30000; } 00337 00338 virtual PBoolean Open(const PString & arg) = 0; 00339 00340 virtual void Record(PVXMLChannel & incomingChannel) = 0; 00341 00342 virtual void OnStart() { } 00343 00344 virtual PBoolean OnFrame(PBoolean /*isSilence*/) { return false; } 00345 00346 virtual void OnStop() { } 00347 00348 void SetFinalSilence(unsigned v) 00349 { finalSilence = v; } 00350 00351 unsigned GetFinalSilence() 00352 { return finalSilence; } 00353 00354 void SetMaxDuration(unsigned v) 00355 { maxDuration = v; } 00356 00357 unsigned GetMaxDuration() 00358 { return maxDuration; } 00359 00360 protected: 00361 PTime silenceStart; 00362 PTime recordStart; 00363 unsigned finalSilence; 00364 unsigned maxDuration; 00365 unsigned consecutiveSilence; 00366 }; 00367 00369 00370 class PVXMLPlayable : public PObject 00371 { 00372 PCLASSINFO(PVXMLPlayable, PObject); 00373 public: 00374 PVXMLPlayable() 00375 { repeat = 1; delay = 0; sampleFrequency = 8000; autoDelete = false; delayDone = false; } 00376 00377 virtual PBoolean Open(PVXMLChannel & /*chan*/, PINDEX delay, PINDEX repeat, PBoolean autoDelete); 00378 00379 virtual PBoolean Open(PVXMLChannel & chan, const PString & arg, PINDEX delay, PINDEX repeat, PBoolean v); 00380 00381 virtual void Play(PVXMLChannel & outgoingChannel) = 0; 00382 00383 virtual void OnRepeat(PVXMLChannel & /*outgoingChannel*/) 00384 { } 00385 00386 virtual void OnStart() { } 00387 00388 virtual void OnStop() { } 00389 00390 virtual void SetRepeat(PINDEX v) 00391 { repeat = v; } 00392 00393 virtual PINDEX GetRepeat() const 00394 { return repeat; } 00395 00396 virtual PINDEX GetDelay() const 00397 { return delay; } 00398 00399 void SetFormat(const PString & fmt) 00400 { format = fmt; } 00401 00402 void SetSampleFrequency(unsigned rate) 00403 { sampleFrequency = rate; } 00404 00405 virtual PBoolean ReadFrame(PVXMLChannel & channel, void * buf, PINDEX len); 00406 00407 virtual PBoolean Rewind(PChannel *) 00408 { return false; } 00409 00410 friend class PVXMLChannel; 00411 00412 protected: 00413 PString arg; 00414 PINDEX repeat; 00415 PINDEX delay; 00416 PString format; 00417 unsigned sampleFrequency; 00418 PBoolean autoDelete; 00419 PBoolean delayDone; // very tacky flag used to indicate when the post-play delay has been done 00420 }; 00421 00423 00424 class PVXMLPlayableStop : public PVXMLPlayable 00425 { 00426 PCLASSINFO(PVXMLPlayableStop, PVXMLPlayable); 00427 public: 00428 virtual void Play(PVXMLChannel & outgoingChannel); 00429 virtual PBoolean ReadFrame(PVXMLChannel & channel, void *, PINDEX); 00430 }; 00431 00433 00434 class PVXMLPlayableURL : public PVXMLPlayable 00435 { 00436 PCLASSINFO(PVXMLPlayableURL, PVXMLPlayable); 00437 public: 00438 PBoolean Open(PVXMLChannel & chan, const PString & url, PINDEX delay, PINDEX repeat, PBoolean v); 00439 void Play(PVXMLChannel & outgoingChannel); 00440 protected: 00441 PURL url; 00442 }; 00443 00445 00446 class PVXMLPlayableData : public PVXMLPlayable 00447 { 00448 PCLASSINFO(PVXMLPlayableData, PVXMLPlayable); 00449 public: 00450 PBoolean Open(PVXMLChannel & chan, const PString & fn, PINDEX delay, PINDEX repeat, PBoolean v); 00451 void SetData(const PBYTEArray & data); 00452 void Play(PVXMLChannel & outgoingChannel); 00453 PBoolean Rewind(PChannel * chan); 00454 protected: 00455 PBYTEArray data; 00456 }; 00457 00459 00460 #include <ptclib/dtmf.h> 00461 00462 class PVXMLPlayableTone : public PVXMLPlayableData 00463 { 00464 PCLASSINFO(PVXMLPlayableTone, PVXMLPlayableData); 00465 public: 00466 PBoolean Open(PVXMLChannel & chan, const PString & toneSpec, PINDEX delay, PINDEX repeat, PBoolean v); 00467 protected: 00468 PTones tones; 00469 }; 00470 00472 00473 class PVXMLPlayableCommand : public PVXMLPlayable 00474 { 00475 PCLASSINFO(PVXMLPlayableCommand, PVXMLPlayable); 00476 public: 00477 PVXMLPlayableCommand(); 00478 void Play(PVXMLChannel & outgoingChannel); 00479 void OnStop(); 00480 00481 protected: 00482 PPipeChannel * pipeCmd; 00483 }; 00484 00486 00487 class PVXMLPlayableFilename : public PVXMLPlayable 00488 { 00489 PCLASSINFO(PVXMLPlayableFilename, PVXMLPlayable); 00490 public: 00491 PBoolean Open(PVXMLChannel & chan, const PString & fn, PINDEX delay, PINDEX repeat, PBoolean autoDelete); 00492 void Play(PVXMLChannel & outgoingChannel); 00493 void OnStop(); 00494 virtual PBoolean Rewind(PChannel * chan); 00495 protected: 00496 PFilePath fn; 00497 }; 00498 00500 00501 class PVXMLPlayableFilenameList : public PVXMLPlayable 00502 { 00503 PCLASSINFO(PVXMLPlayableFilenameList, PVXMLPlayable); 00504 public: 00505 PBoolean Open(PVXMLChannel & chan, const PStringArray & filenames, PINDEX delay, PINDEX repeat, PBoolean autoDelete); 00506 void Play(PVXMLChannel & outgoingChannel) 00507 { OnRepeat(outgoingChannel); } 00508 void OnRepeat(PVXMLChannel & outgoingChannel); 00509 void OnStop(); 00510 protected: 00511 PINDEX currentIndex; 00512 PStringArray filenames; 00513 }; 00514 00516 00517 class PVXMLRecordableFilename : public PVXMLRecordable 00518 { 00519 PCLASSINFO(PVXMLRecordableFilename, PVXMLRecordable); 00520 public: 00521 PBoolean Open(const PString & arg); 00522 void Record(PVXMLChannel & incomingChannel); 00523 PBoolean OnFrame(PBoolean isSilence); 00524 00525 protected: 00526 PFilePath fn; 00527 }; 00528 00530 00531 PQUEUE(PVXMLQueue, PVXMLPlayable); 00532 00534 00535 class PVXMLChannel : public PDelayChannel 00536 { 00537 PCLASSINFO(PVXMLChannel, PDelayChannel); 00538 public: 00539 PVXMLChannel(unsigned frameDelay, PINDEX frameSize); 00540 ~PVXMLChannel(); 00541 00542 virtual PBoolean Open(PVXMLChannelInterface * vxml); 00543 00544 // overrides from PIndirectChannel 00545 virtual PBoolean IsOpen() const; 00546 virtual PBoolean Close(); 00547 virtual PBoolean Read(void * buffer, PINDEX amount); 00548 virtual PBoolean Write(const void * buf, PINDEX len); 00549 00550 // new functions 00551 virtual PWAVFile * CreateWAVFile(const PFilePath & fn, PBoolean recording = false); 00552 00553 const PString & GetMediaFormat() const { return mediaFormat; } 00554 PBoolean IsMediaPCM() const { return mediaFormat == "PCM-16"; } 00555 virtual PString AdjustWavFilename(const PString & fn); 00556 00557 // Incoming channel functions 00558 virtual PBoolean WriteFrame(const void * buf, PINDEX len) = 0; 00559 virtual PBoolean IsSilenceFrame(const void * buf, PINDEX len) const = 0; 00560 00561 virtual PBoolean QueueRecordable(PVXMLRecordable * newItem); 00562 00563 PBoolean StartRecording(const PFilePath & fn, unsigned finalSilence = 3000, unsigned maxDuration = 30000); 00564 PBoolean EndRecording(); 00565 PBoolean IsRecording() const { return recording; } 00566 00567 // Outgoing channel functions 00568 virtual PBoolean ReadFrame(void * buffer, PINDEX amount) = 0; 00569 virtual PINDEX CreateSilenceFrame(void * buffer, PINDEX amount) = 0; 00570 virtual void GetBeepData(PBYTEArray &, unsigned) { } 00571 00572 virtual PBoolean QueueResource(const PURL & url, PINDEX repeat= 1, PINDEX delay = 0); 00573 00574 virtual PBoolean QueuePlayable(const PString & type, const PString & str, PINDEX repeat = 1, PINDEX delay = 0, PBoolean autoDelete = false); 00575 virtual PBoolean QueuePlayable(PVXMLPlayable * newItem); 00576 virtual PBoolean QueueData(const PBYTEArray & data, PINDEX repeat = 1, PINDEX delay = 0); 00577 00578 virtual PBoolean QueueFile(const PString & fn, PINDEX repeat = 1, PINDEX delay = 0, PBoolean autoDelete = false) 00579 { return QueuePlayable("File", fn, repeat, delay, autoDelete); } 00580 00581 virtual PBoolean QueueCommand(const PString & cmd, PINDEX repeat = 1, PINDEX delay = 0) 00582 { return QueuePlayable("Command", cmd, repeat, delay, true); } 00583 00584 virtual void FlushQueue(); 00585 virtual PBoolean IsPlaying() const { return currentPlayItem != NULL || playQueue.GetSize() > 0; } 00586 00587 void SetPause(PBoolean pause) { paused = pause; } 00588 00589 void SetName(const PString & name) { channelName = name; } 00590 00591 unsigned GetSampleFrequency() const { return sampleFrequency; } 00592 00593 void SetSilence(unsigned msecs); 00594 00595 protected: 00596 PVXMLChannelInterface * vxmlInterface; 00597 00598 unsigned sampleFrequency; 00599 PString mediaFormat; 00600 PString wavFilePrefix; 00601 00602 PMutex channelWriteMutex; 00603 PMutex channelReadMutex; 00604 PBoolean closed; 00605 00606 // Incoming audio variables 00607 PBoolean recording; 00608 PVXMLRecordable * recordable; 00609 unsigned finalSilence; 00610 unsigned silenceRun; 00611 00612 // Outgoing audio variables 00613 PMutex queueMutex; 00614 PVXMLQueue playQueue; 00615 PVXMLPlayable * currentPlayItem; 00616 00617 PBoolean paused; 00618 PTimer m_silenceTimer; 00619 int totalData; 00620 00621 // "channelname" (which is the name of the <record> tag) so 00622 // results can be saved in vxml session variable 00623 PString channelName; 00624 }; 00625 00626 00628 00629 class PVXMLNodeHandler : public PObject 00630 { 00631 PCLASSINFO(PVXMLNodeHandler, PObject); 00632 public: 00633 virtual bool Start(PVXMLSession & /*session*/, const PXMLElement & /*node*/) const { return false; } 00634 virtual bool Finish(PVXMLSession & /*session*/, const PXMLElement & /*node*/) const { return false; } 00635 }; 00636 00637 00638 typedef PFactory<PVXMLNodeHandler, PCaselessString> PVXMLNodeFactory; 00639 00640 00641 #endif // P_VXML 00642 00643 #endif // PTLIB_VXML_H 00644 00645 00646 // End of file ////////////////////////////////////////////////////////////////