00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
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
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 void SetTimeout(const PTimeInterval & timeout);
00085
00086 protected:
00087 PDECLARE_NOTIFIER(PTimer, PVXMLGrammar, OnTimeout);
00088
00089 PVXMLSession & m_session;
00090 PXMLElement & m_field;
00091 PString m_value;
00092 GrammarState m_state;
00093 PTimeInterval m_timeout;
00094 PTimer m_timer;
00095 PMutex m_mutex;
00096 };
00097
00098
00100
00101 class PVXMLMenuGrammar : public PVXMLGrammar
00102 {
00103 PCLASSINFO(PVXMLMenuGrammar, PVXMLGrammar);
00104 public:
00105 PVXMLMenuGrammar(PVXMLSession & session, PXMLElement & field);
00106 virtual void OnUserInput(const char ch);
00107 virtual bool Process();
00108 };
00109
00110
00112
00113 class PVXMLDigitsGrammar : public PVXMLGrammar
00114 {
00115 PCLASSINFO(PVXMLDigitsGrammar, PVXMLGrammar);
00116 public:
00117 PVXMLDigitsGrammar(
00118 PVXMLSession & session,
00119 PXMLElement & field,
00120 PINDEX minDigits,
00121 PINDEX maxDigits,
00122 PString terminators
00123 );
00124
00125 virtual void OnUserInput(const char ch);
00126
00127 protected:
00128 PINDEX m_minDigits;
00129 PINDEX m_maxDigits;
00130 PString m_terminators;
00131 };
00132
00133
00135
00136 class PVXMLCache : public PMutex
00137 {
00138 public:
00139 PVXMLCache(const PDirectory & directory);
00140
00141 PFilePath CreateFilename(const PString & prefix, const PString & key, const PString & fileType);
00142
00143 void Put(const PString & prefix,
00144 const PString & key,
00145 const PString & fileType,
00146 const PString & contentType,
00147 const PFilePath & fn,
00148 PFilePath & dataFn);
00149
00150 PBoolean Get(const PString & prefix,
00151 const PString & key,
00152 const PString & fileType,
00153 PString & contentType,
00154 PFilePath & fn);
00155
00156 PFilePath GetCacheDir() const
00157 { return directory; }
00158
00159 PFilePath GetRandomFilename(const PString & prefix, const PString & fileType);
00160
00161 static PVXMLCache & GetResourceCache();
00162
00163 protected:
00164 PDirectory directory;
00165 };
00166
00168
00169 class PVXMLChannel;
00170
00171 class PVXMLSession : public PIndirectChannel
00172 {
00173 PCLASSINFO(PVXMLSession, PIndirectChannel);
00174 public:
00175 PVXMLSession(PTextToSpeech * tts = NULL, PBoolean autoDelete = false);
00176 virtual ~PVXMLSession();
00177
00178
00179 PTextToSpeech * SetTextToSpeech(PTextToSpeech * tts, PBoolean autoDelete = false);
00180 PTextToSpeech * SetTextToSpeech(const PString & ttsName);
00181 PTextToSpeech * GetTextToSpeech() const { return m_textToSpeech; }
00182
00183 virtual PBoolean Load(const PString & source);
00184 virtual PBoolean LoadFile(const PFilePath & file, const PString & firstForm = PString::Empty());
00185 virtual PBoolean LoadURL(const PURL & url);
00186 virtual PBoolean LoadVXML(const PString & xml, const PString & firstForm = PString::Empty());
00187 virtual PBoolean IsLoaded() const { return m_xml.IsLoaded(); }
00188
00189 virtual PBoolean Open(const PString & mediaFormat);
00190 virtual PBoolean Close();
00191
00192 virtual PBoolean Execute();
00193
00194 PVXMLChannel * GetAndLockVXMLChannel();
00195 void UnLockVXMLChannel() { m_sessionMutex.Signal(); }
00196 PMutex & GetSessionMutex() { return m_sessionMutex; }
00197
00198 virtual PBoolean LoadGrammar(PVXMLGrammar * grammar);
00199
00200 virtual PBoolean PlayText(const PString & text, PTextToSpeech::TextType type = PTextToSpeech::Default, PINDEX repeat = 1, PINDEX delay = 0);
00201 PBoolean ConvertTextToFilenameList(const PString & text, PTextToSpeech::TextType type, PStringArray & list, PBoolean useCacheing);
00202
00203 virtual PBoolean PlayFile(const PString & fn, PINDEX repeat = 1, PINDEX delay = 0, PBoolean autoDelete = false);
00204 virtual PBoolean PlayData(const PBYTEArray & data, PINDEX repeat = 1, PINDEX delay = 0);
00205 virtual PBoolean PlayCommand(const PString & data, PINDEX repeat = 1, PINDEX delay = 0);
00206 virtual PBoolean PlayResource(const PURL & url, PINDEX repeat = 1, PINDEX delay = 0);
00207 virtual PBoolean PlayTone(const PString & toneSpec, PINDEX repeat = 1, PINDEX delay = 0);
00208 virtual PBoolean PlayElement(PXMLElement & element);
00209
00210
00211 virtual PBoolean PlaySilence(PINDEX msecs = 0);
00212 virtual PBoolean PlaySilence(const PTimeInterval & timeout);
00213
00214 virtual PBoolean PlayStop();
00215
00216 virtual void SetPause(PBoolean pause);
00217 virtual void GetBeepData(PBYTEArray & data, unsigned ms);
00218
00219 virtual PBoolean StartRecording(const PFilePath & fn, PBoolean recordDTMFTerm, const PTimeInterval & recordMaxTime, const PTimeInterval & recordFinalSilence);
00220 virtual PBoolean EndRecording();
00221
00222 virtual void OnUserInput(const PString & str);
00223
00224 PString GetXMLError() const;
00225
00226 virtual void OnEndDialog();
00227 virtual void OnEndSession();
00228
00229 enum TransferType {
00230 BridgedTransfer,
00231 BlindTransfer,
00232 ConsultationTransfer
00233 };
00234 virtual bool OnTransfer(const PString & , TransferType ) { return false; }
00235 void SetTransferComplete(bool state);
00236
00237 const PStringToString & GetVariables() { return m_variables; }
00238 virtual PCaselessString GetVar(const PString & str) const;
00239 virtual void SetVar(const PString & ostr, const PString & val);
00240 virtual PString EvaluateExpr(const PString & oexpr);
00241
00242 static PTimeInterval StringToTime(const PString & str, int dflt = 0);
00243
00244 virtual PBoolean RetreiveResource(const PURL & url, PString & contentType, PFilePath & fn, PBoolean useCache = true);
00245
00246 PDECLARE_NOTIFIER(PThread, PVXMLSession, VXMLExecute);
00247
00248 bool SetCurrentForm(const PString & id, bool fullURI);
00249 bool GoToEventHandler(PXMLElement & element, const PString & eventName);
00250
00251
00252 virtual void OnEndRecording();
00253 virtual void Trigger();
00254
00255
00256 virtual PBoolean TraverseAudio(PXMLElement & element);
00257 virtual PBoolean TraverseBreak(PXMLElement & element);
00258 virtual PBoolean TraverseValue(PXMLElement & element);
00259 virtual PBoolean TraverseSayAs(PXMLElement & element);
00260 virtual PBoolean TraverseGoto(PXMLElement & element);
00261 virtual PBoolean TraverseGrammar(PXMLElement & element);
00262 virtual PBoolean TraverseRecord(PXMLElement & element);
00263 virtual PBoolean TraversedRecord(PXMLElement & element);
00264 virtual PBoolean TraverseIf(PXMLElement & element);
00265 virtual PBoolean TraverseExit(PXMLElement & element);
00266 virtual PBoolean TraverseVar(PXMLElement & element);
00267 virtual PBoolean TraverseSubmit(PXMLElement & element);
00268 virtual PBoolean TraverseMenu(PXMLElement & element);
00269 virtual PBoolean TraversedMenu(PXMLElement & element);
00270 virtual PBoolean TraverseChoice(PXMLElement & element);
00271 virtual PBoolean TraverseProperty(PXMLElement & element);
00272 virtual PBoolean TraverseDisconnect(PXMLElement & element);
00273 virtual PBoolean TraverseForm(PXMLElement & element);
00274 virtual PBoolean TraversedForm(PXMLElement & element);
00275 virtual PBoolean TraversePrompt(PXMLElement & element);
00276 virtual PBoolean TraversedPrompt(PXMLElement & element);
00277 virtual PBoolean TraverseField(PXMLElement & element);
00278 virtual PBoolean TraversedField(PXMLElement & element);
00279 virtual PBoolean TraverseTransfer(PXMLElement & element);
00280 virtual PBoolean TraversedTransfer(PXMLElement & element);
00281
00282 __inline PVXMLChannel * GetVXMLChannel() const { return (PVXMLChannel *)readChannel; }
00283
00284 protected:
00285 virtual bool InternalLoadVXML(const PString & xml, const PString & firstForm);
00286
00287 virtual bool ProcessNode();
00288 virtual bool ProcessEvents();
00289 virtual bool ProcessGrammar();
00290 virtual bool NextNode(bool processChildren);
00291
00292 void SayAs(const PString & className, const PString & text);
00293 void SayAs(const PString & className, const PString & text, const PString & voice);
00294
00295 PURL NormaliseResourceName(const PString & src);
00296
00297 PMutex m_sessionMutex;
00298
00299 PURL m_rootURL;
00300 PXML m_xml;
00301
00302 PTextToSpeech * m_textToSpeech;
00303 bool m_autoDeleteTextToSpeech;
00304
00305 PThread * m_vxmlThread;
00306 bool m_abortVXML;
00307 PSyncPoint m_waitForEvent;
00308 PXMLObject * m_currentNode;
00309 bool m_xmlChanged;
00310 bool m_speakNodeData;
00311 bool m_bargeIn;
00312 bool m_bargingIn;
00313
00314 PVXMLGrammar * m_grammar;
00315 char m_defaultMenuDTMF;
00316
00317 PStringToString m_variables;
00318 PString m_variableScope;
00319
00320 std::queue<char> m_userInputQueue;
00321 PMutex m_userInputMutex;
00322
00323 enum {
00324 NotRecording,
00325 RecordingInProgress,
00326 RecordingComplete
00327 } m_recordingStatus;
00328 bool m_recordStopOnDTMF;
00329
00330 enum {
00331 NotTransfering,
00332 TransferInProgress,
00333 TransferFailed,
00334 TransferSuccessful
00335 } m_transferStatus;
00336 PTime m_transferStartTime;
00337 };
00338
00339
00341
00342 class PVXMLRecordable : public PObject
00343 {
00344 PCLASSINFO(PVXMLRecordable, PObject);
00345 public:
00346 PVXMLRecordable();
00347
00348 virtual PBoolean Open(const PString & arg) = 0;
00349
00350 virtual bool OnStart(PVXMLChannel & incomingChannel) = 0;
00351 virtual void OnStop() { }
00352
00353 virtual PBoolean OnFrame(PBoolean ) { return false; }
00354
00355 void SetFinalSilence(unsigned v)
00356 { m_finalSilence = v > 0 ? v : 60000; }
00357
00358 unsigned GetFinalSilence()
00359 { return m_finalSilence; }
00360
00361 void SetMaxDuration(unsigned v)
00362 { m_maxDuration = v > 0 ? v : 86400000; }
00363
00364 unsigned GetMaxDuration()
00365 { return m_maxDuration; }
00366
00367 protected:
00368 PSimpleTimer m_silenceTimer;
00369 PSimpleTimer m_recordTimer;
00370 unsigned m_finalSilence;
00371 unsigned m_maxDuration;
00372 };
00373
00375
00376 class PVXMLRecordableFilename : public PVXMLRecordable
00377 {
00378 PCLASSINFO(PVXMLRecordableFilename, PVXMLRecordable);
00379 public:
00380 PBoolean Open(const PString & arg);
00381 bool OnStart(PVXMLChannel & incomingChannel);
00382 PBoolean OnFrame(PBoolean isSilence);
00383
00384 protected:
00385 PFilePath m_fileName;
00386 };
00387
00389
00390 class PVXMLPlayable : public PObject
00391 {
00392 PCLASSINFO(PVXMLPlayable, PObject);
00393 public:
00394 PVXMLPlayable();
00395
00396 virtual PBoolean Open(PVXMLChannel & chan, const PString & arg, PINDEX delay, PINDEX repeat, PBoolean autoDelete);
00397
00398 virtual bool OnStart() = 0;
00399 virtual bool OnRepeat();
00400 virtual bool OnDelay();
00401 virtual void OnStop();
00402
00403 virtual void SetRepeat(PINDEX v)
00404 { m_repeat = v; }
00405
00406 virtual PINDEX GetRepeat() const
00407 { return m_repeat; }
00408
00409 virtual PINDEX GetDelay() const
00410 { return m_delay; }
00411
00412 void SetFormat(const PString & fmt)
00413 { m_format = fmt; }
00414
00415 void SetSampleFrequency(unsigned rate)
00416 { m_sampleFrequency = rate; }
00417
00418 friend class PVXMLChannel;
00419
00420 protected:
00421 PVXMLChannel * m_vxmlChannel;
00422 PChannel * m_subChannel;
00423 PINDEX m_repeat;
00424 PINDEX m_delay;
00425 PString m_format;
00426 unsigned m_sampleFrequency;
00427 bool m_autoDelete;
00428 bool m_delayDone;
00429 };
00430
00432
00433 class PVXMLPlayableStop : public PVXMLPlayable
00434 {
00435 PCLASSINFO(PVXMLPlayableStop, PVXMLPlayable);
00436 public:
00437 virtual bool OnStart();
00438 };
00439
00441
00442 class PVXMLPlayableURL : public PVXMLPlayable
00443 {
00444 PCLASSINFO(PVXMLPlayableURL, PVXMLPlayable);
00445 public:
00446 virtual PBoolean Open(PVXMLChannel & chan, const PString & arg, PINDEX delay, PINDEX repeat, PBoolean autoDelete);
00447 virtual bool OnStart();
00448 protected:
00449 PURL m_url;
00450 };
00451
00453
00454 class PVXMLPlayableData : public PVXMLPlayable
00455 {
00456 PCLASSINFO(PVXMLPlayableData, PVXMLPlayable);
00457 public:
00458 virtual PBoolean Open(PVXMLChannel & chan, const PString & arg, PINDEX delay, PINDEX repeat, PBoolean autoDelete);
00459 void SetData(const PBYTEArray & data);
00460 virtual bool OnStart();
00461 virtual bool OnRepeat();
00462 protected:
00463 PBYTEArray m_data;
00464 };
00465
00467
00468 #include <ptclib/dtmf.h>
00469
00470 class PVXMLPlayableTone : public PVXMLPlayableData
00471 {
00472 PCLASSINFO(PVXMLPlayableTone, PVXMLPlayableData);
00473 public:
00474 virtual PBoolean Open(PVXMLChannel & chan, const PString & arg, PINDEX delay, PINDEX repeat, PBoolean autoDelete);
00475 protected:
00476 PTones m_tones;
00477 };
00478
00480
00481 class PVXMLPlayableCommand : public PVXMLPlayable
00482 {
00483 PCLASSINFO(PVXMLPlayableCommand, PVXMLPlayable);
00484 public:
00485 virtual PBoolean Open(PVXMLChannel & chan, const PString & arg, PINDEX delay, PINDEX repeat, PBoolean autoDelete);
00486 virtual bool OnStart();
00487 virtual void OnStop();
00488
00489 protected:
00490 PString m_command;
00491 };
00492
00494
00495 class PVXMLPlayableFile : public PVXMLPlayable
00496 {
00497 PCLASSINFO(PVXMLPlayableFile, PVXMLPlayable);
00498 public:
00499 virtual PBoolean Open(PVXMLChannel & chan, const PString & arg, PINDEX delay, PINDEX repeat, PBoolean autoDelete);
00500 virtual bool OnStart();
00501 virtual bool OnRepeat();
00502 virtual void OnStop();
00503 protected:
00504 PFilePath m_filePath;
00505 };
00506
00508
00509 class PVXMLPlayableFileList : public PVXMLPlayableFile
00510 {
00511 PCLASSINFO(PVXMLPlayableFileList, PVXMLPlayableFile);
00512 public:
00513 PVXMLPlayableFileList();
00514 virtual PBoolean Open(PVXMLChannel & chan, const PString & arg, PINDEX delay, PINDEX repeat, PBoolean autoDelete);
00515 virtual PBoolean Open(PVXMLChannel & chan, const PStringArray & filenames, PINDEX delay, PINDEX repeat, PBoolean autoDelete);
00516 virtual bool OnStart();
00517 virtual bool OnRepeat();
00518 virtual void OnStop();
00519 protected:
00520 PStringArray m_fileNames;
00521 PINDEX m_currentIndex;
00522 };
00523
00525
00526 PQUEUE(PVXMLQueue, PVXMLPlayable);
00527
00529
00530 class PVXMLChannel : public PDelayChannel
00531 {
00532 PCLASSINFO(PVXMLChannel, PDelayChannel);
00533 public:
00534 PVXMLChannel(unsigned frameDelay, PINDEX frameSize);
00535 ~PVXMLChannel();
00536
00537 virtual PBoolean Open(PVXMLSession * session);
00538
00539
00540 virtual PBoolean IsOpen() const;
00541 virtual PBoolean Close();
00542 virtual PBoolean Read(void * buffer, PINDEX amount);
00543 virtual PBoolean Write(const void * buf, PINDEX len);
00544
00545
00546 virtual PWAVFile * CreateWAVFile(const PFilePath & fn, PBoolean recording = false);
00547
00548 const PString & GetMediaFormat() const { return mediaFormat; }
00549 PBoolean IsMediaPCM() const { return mediaFormat == "PCM-16"; }
00550 virtual PString AdjustWavFilename(const PString & fn);
00551
00552
00553 virtual PBoolean WriteFrame(const void * buf, PINDEX len) = 0;
00554 virtual PBoolean IsSilenceFrame(const void * buf, PINDEX len) const = 0;
00555
00556 virtual PBoolean QueueRecordable(PVXMLRecordable * newItem);
00557
00558 PBoolean StartRecording(const PFilePath & fn, unsigned finalSilence = 3000, unsigned maxDuration = 30000);
00559 PBoolean EndRecording();
00560 PBoolean IsRecording() const { return m_recordable != NULL; }
00561
00562
00563 virtual PBoolean ReadFrame(void * buffer, PINDEX amount) = 0;
00564 virtual PINDEX CreateSilenceFrame(void * buffer, PINDEX amount) = 0;
00565 virtual void GetBeepData(PBYTEArray &, unsigned) { }
00566
00567 virtual PBoolean QueueResource(const PURL & url, PINDEX repeat= 1, PINDEX delay = 0);
00568
00569 virtual PBoolean QueuePlayable(const PString & type, const PString & str, PINDEX repeat = 1, PINDEX delay = 0, PBoolean autoDelete = false);
00570 virtual PBoolean QueuePlayable(PVXMLPlayable * newItem);
00571 virtual PBoolean QueueData(const PBYTEArray & data, PINDEX repeat = 1, PINDEX delay = 0);
00572
00573 virtual PBoolean QueueFile(const PString & fn, PINDEX repeat = 1, PINDEX delay = 0, PBoolean autoDelete = false)
00574 { return QueuePlayable("File", fn, repeat, delay, autoDelete); }
00575
00576 virtual PBoolean QueueCommand(const PString & cmd, PINDEX repeat = 1, PINDEX delay = 0)
00577 { return QueuePlayable("Command", cmd, repeat, delay, true); }
00578
00579 virtual void FlushQueue();
00580 virtual PBoolean IsPlaying() const { return m_currentPlayItem != NULL || m_playQueue.GetSize() > 0; }
00581
00582 void SetPause(PBoolean pause) { m_paused = pause; }
00583
00584 unsigned GetSampleFrequency() const { return m_sampleFrequency; }
00585
00586 void SetSilence(unsigned msecs);
00587
00588 protected:
00589 PVXMLSession * m_vxmlSession;
00590
00591 unsigned m_sampleFrequency;
00592 PString mediaFormat;
00593 PString wavFilePrefix;
00594
00595 PMutex m_channelWriteMutex;
00596 PMutex m_channelReadMutex;
00597 bool m_closed;
00598 bool m_paused;
00599 PINDEX m_totalData;
00600
00601
00602 PVXMLRecordable * m_recordable;
00603 unsigned m_finalSilence;
00604 unsigned m_silenceRun;
00605
00606
00607 PVXMLQueue m_playQueue;
00608 PVXMLPlayable * m_currentPlayItem;
00609 PSimpleTimer m_silenceTimer;
00610 };
00611
00612
00614
00615 class PVXMLNodeHandler : public PObject
00616 {
00617 PCLASSINFO(PVXMLNodeHandler, PObject);
00618 public:
00619
00620 virtual bool Start(PVXMLSession & , PXMLElement & ) const { return true; }
00621
00622
00623 virtual bool Finish(PVXMLSession & , PXMLElement & ) const { return true; }
00624 };
00625
00626
00627 typedef PFactory<PVXMLNodeHandler, PCaselessString> PVXMLNodeFactory;
00628
00629
00630 #endif // P_VXML
00631
00632 #endif // PTLIB_VXML_H
00633
00634
00635