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
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201 #ifndef _VXML_H
00202 #define _VXML_H
00203
00204 #ifdef P_USE_PRAGMA
00205 #pragma interface
00206 #endif
00207
00208 #include <ptlib/pipechan.h>
00209
00210 #include <ptclib/pxml.h>
00211 #include <ptclib/delaychan.h>
00212 #include <ptclib/pwavfile.h>
00213 #include <ptclib/ptts.h>
00214 #include <ptclib/url.h>
00215
00216 #include <queue>
00217
00218
00219 class PVXMLSession;
00220 class PVXMLDialog;
00221 class PVXMLSession;
00222
00223 class PVXMLTransferOptions;
00224 class PVXMLTransferResult;
00225
00226
00227 #define VXML_PCM16 "PCM-16"
00228 #define VXML_G7231 "G.723.1"
00229 #define VXML_G729 "G.729"
00230
00231 #define PVXML_HAS_FACTORY 1
00232
00233 class PVXMLGrammar : public PObject
00234 {
00235 PCLASSINFO(PVXMLGrammar, PObject);
00236 public:
00237 PVXMLGrammar(PXMLElement * field);
00238 virtual BOOL OnUserInput(const char ) { return TRUE; }
00239 virtual void Stop() { }
00240
00241 PString GetValue() const { return value; }
00242 PXMLElement * GetField() { return field; }
00243
00244 enum GrammarState {
00245 FILLED,
00246 NOINPUT,
00247 NOMATCH,
00248 HELP };
00249
00250 GrammarState GetState() const { return state; }
00251
00252 protected:
00253 PXMLElement * field;
00254 PString value;
00255 GrammarState state;
00256 };
00257
00258
00260
00261 class PVXMLMenuGrammar : public PVXMLGrammar
00262 {
00263 PCLASSINFO(PVXMLMenuGrammar, PVXMLGrammar);
00264 public:
00265 PVXMLMenuGrammar(PXMLElement * field);
00266 };
00267
00268
00270
00271 class PVXMLDigitsGrammar : public PVXMLGrammar
00272 {
00273 PCLASSINFO(PVXMLDigitsGrammar, PVXMLGrammar);
00274 public:
00275 PVXMLDigitsGrammar(PXMLElement * field, PINDEX minDigits, PINDEX maxDigits, PString terminators);
00276 BOOL OnUserInput(const char ch);
00277 virtual void Stop();
00278
00279 protected:
00280 PINDEX minDigits;
00281 PINDEX maxDigits;
00282 PString terminators;
00283 };
00284
00285
00287
00288 class PVXMLCache : public PMutex
00289 {
00290 public:
00291 PVXMLCache(const PDirectory & _directory);
00292
00293 PFilePath CreateFilename(const PString & prefix, const PString & key, const PString & fileType);
00294
00295 void Put(const PString & prefix,
00296 const PString & key,
00297 const PString & fileType,
00298 const PString & contentType,
00299 const PFilePath & fn,
00300 PFilePath & dataFn);
00301
00302 BOOL Get(const PString & prefix,
00303 const PString & key,
00304 const PString & fileType,
00305 PString & contentType,
00306 PFilePath & fn);
00307
00308 PFilePath GetCacheDir() const
00309 { return directory; }
00310
00311 PFilePath GetRandomFilename(const PString & prefix, const PString & fileType);
00312
00313 static PVXMLCache & GetResourceCache();
00314
00315 protected:
00316 PDirectory directory;
00317 };
00318
00320
00321 class PVXMLChannel;
00322
00323 class PVXMLChannelInterface {
00324 public:
00325 virtual ~PVXMLChannelInterface() { }
00326 virtual PWAVFile * CreateWAVFile(const PFilePath & fn, PFile::OpenMode mode, int opts, unsigned fmt) = 0;
00327 virtual void RecordEnd() = 0;
00328 virtual void OnEndRecording(const PString & channelName) = 0;
00329 virtual void Trigger() = 0;
00330 };
00331
00333
00334 class PVXMLSession : public PIndirectChannel, public PVXMLChannelInterface
00335 {
00336 PCLASSINFO(PVXMLSession, PIndirectChannel);
00337 public:
00338 PVXMLSession(PTextToSpeech * tts = NULL, BOOL autoDelete = FALSE);
00339 virtual ~PVXMLSession();
00340
00341 void SetFinishWhenEmpty(BOOL v)
00342 { finishWhenEmpty = v; }
00343
00344
00345 PTextToSpeech * SetTextToSpeech(PTextToSpeech * _tts, BOOL autoDelete = FALSE);
00346 PTextToSpeech * SetTextToSpeech(const PString & ttsName);
00347 PTextToSpeech * GetTextToSpeech() { return textToSpeech; }
00348
00349 virtual BOOL Load(const PString & source);
00350 virtual BOOL LoadFile(const PFilePath & file);
00351 virtual BOOL LoadURL(const PURL & url);
00352 virtual BOOL LoadVXML(const PString & xml);
00353 virtual BOOL IsLoaded() const { return loaded; }
00354
00355 virtual BOOL Open(BOOL isPCM);
00356 virtual BOOL Open(const PString & mediaFormat);
00357 virtual BOOL Close();
00358
00359 BOOL Execute();
00360
00361 PVXMLChannel * GetAndLockVXMLChannel()
00362 {
00363 sessionMutex.Wait();
00364 if (vxmlChannel != NULL)
00365 return vxmlChannel;
00366 sessionMutex.Signal();
00367 return NULL;
00368 }
00369 void UnLockVXMLChannel() { sessionMutex.Signal(); }
00370 PMutex & GetSessionMutex() { return sessionMutex; }
00371
00372 BOOL LoadGrammar(PVXMLGrammar * grammar);
00373
00374 virtual BOOL PlayText(const PString & text, PTextToSpeech::TextType type = PTextToSpeech::Default, PINDEX repeat = 1, PINDEX delay = 0);
00375 BOOL ConvertTextToFilenameList(const PString & _text, PTextToSpeech::TextType type, PStringArray & list, BOOL useCacheing);
00376
00377 virtual BOOL PlayFile(const PString & fn, PINDEX repeat = 1, PINDEX delay = 0, BOOL autoDelete = FALSE);
00378 virtual BOOL PlayData(const PBYTEArray & data, PINDEX repeat = 1, PINDEX delay = 0);
00379 virtual BOOL PlayCommand(const PString & data, PINDEX repeat = 1, PINDEX delay = 0);
00380 virtual BOOL PlayResource(const PURL & url, PINDEX repeat = 1, PINDEX delay = 0);
00381
00382
00383 virtual BOOL PlaySilence(PINDEX msecs = 0);
00384 virtual BOOL PlaySilence(const PTimeInterval & timeout);
00385
00386 virtual void SetPause(BOOL pause);
00387 virtual void GetBeepData(PBYTEArray & data, unsigned ms);
00388
00389 virtual BOOL StartRecording(const PFilePath & fn, BOOL recordDTMFTerm, const PTimeInterval & recordMaxTime, const PTimeInterval & recordFinalSilence);
00390 virtual BOOL EndRecording();
00391 virtual BOOL IsPlaying() const;
00392 virtual BOOL IsRecording() const;
00393
00394 virtual BOOL OnUserInput(const PString & str);
00395
00396 PString GetXMLError() const;
00397
00398 virtual void OnEndSession() { }
00399
00400 virtual PString GetVar(const PString & str) const;
00401 virtual void SetVar(const PString & ostr, const PString & val);
00402 virtual PString EvaluateExpr(const PString & oexpr);
00403
00404 virtual BOOL RetreiveResource(const PURL & url, PString & contentType, PFilePath & fn, BOOL useCache = TRUE);
00405
00406 PDECLARE_NOTIFIER(PThread, PVXMLSession, VXMLExecute);
00407
00408 virtual BOOL DoTransfer(const PVXMLTransferOptions &) { return TRUE; }
00409 virtual void OnTransfer(const PVXMLTransferResult &);
00410
00411 void SetCallingToken( PString& token ) { callingCallToken = token; }
00412
00413 PXMLElement * FindHandler(const PString & event);
00414
00415
00416 PWAVFile * CreateWAVFile(const PFilePath & fn, PFile::OpenMode mode, int opts, unsigned fmt);
00417 void OnEndRecording(const PString & channelName);
00418 void RecordEnd();
00419 void Trigger();
00420
00421 protected:
00422 void Initialise();
00423
00424 void AllowClearCall();
00425 void ProcessUserInput();
00426 void ProcessNode();
00427 void ProcessGrammar();
00428
00429 BOOL TraverseAudio();
00430 BOOL TraverseGoto();
00431 BOOL TraverseGrammar();
00432 BOOL TraverseRecord();
00433
00434 BOOL TraverseIf();
00435 BOOL TraverseExit();
00436 BOOL TraverseVar();
00437 BOOL TraverseSubmit();
00438 BOOL TraverseMenu();
00439 BOOL TraverseChoice(const PString & grammarResult);
00440 BOOL TraverseProperty();
00441
00442 void SayAs(const PString & className, const PString & text);
00443 static PTimeInterval StringToTime(const PString & str);
00444
00445 PURL NormaliseResourceName(const PString & src);
00446
00447 PXMLElement * FindForm(const PString & id);
00448
00449 virtual BOOL TraverseTransfer();
00450
00451
00452
00453 PSyncPoint waitForEvent;
00454
00455 PMutex sessionMutex;
00456
00457 PXML xmlFile;
00458
00459 PVXMLGrammar * activeGrammar;
00460 BOOL listening;
00461 int timeout;
00462
00463 PStringToString sessionVars;
00464 PStringToString documentVars;
00465
00466 PMutex userInputMutex;
00467 std::queue<char> userInputQueue;
00468
00469 BOOL recording;
00470 PFilePath recordFn;
00471 BOOL recordDTMFTerm;
00472 PTimeInterval recordMaxTime;
00473 PTimeInterval recordFinalSilence;
00474 PSyncPoint recordSync;
00475
00476 BOOL loaded;
00477 BOOL finishWhenEmpty;
00478 BOOL allowFinish;
00479 PURL rootURL;
00480 BOOL emptyAction;
00481
00482 PThread * vxmlThread;
00483 BOOL threadRunning;
00484 BOOL forceEnd;
00485
00486 PString mediaFormat;
00487 PVXMLChannel * vxmlChannel;
00488
00489 PTextToSpeech * textToSpeech;
00490 BOOL autoDeleteTextToSpeech;
00491
00492 PXMLElement * currentForm;
00493 PXMLElement * currentField;
00494 PXMLObject * currentNode;
00495
00496 private:
00497 void ExecuteDialog();
00498
00499 PString callingCallToken;
00500 PSyncPoint transferSync;
00501 PSyncPoint answerSync;
00502 PString grammarResult;
00503 PString eventName;
00504 PINDEX defaultDTMF;
00505 };
00506
00507
00509
00510 class PVXMLRecordable : public PObject
00511 {
00512 PCLASSINFO(PVXMLRecordable, PObject);
00513 public:
00514 PVXMLRecordable()
00515 { consecutiveSilence = 0; finalSilence = 3000; maxDuration = 30000; }
00516
00517 virtual BOOL Open(const PString & _arg) = 0;
00518
00519 virtual void Record(PVXMLChannel & incomingChannel) = 0;
00520
00521 virtual void OnStart() { }
00522
00523 virtual BOOL OnFrame(BOOL ) { return FALSE; }
00524
00525 virtual void OnStop() { }
00526
00527 void SetFinalSilence(unsigned v)
00528 { finalSilence = v; }
00529
00530 unsigned GetFinalSilence()
00531 { return finalSilence; }
00532
00533 void SetMaxDuration(unsigned v)
00534 { maxDuration = v; }
00535
00536 unsigned GetMaxDuration()
00537 { return maxDuration; }
00538
00539 protected:
00540 PTime silenceStart;
00541 PTime recordStart;
00542 unsigned finalSilence;
00543 unsigned maxDuration;
00544 unsigned consecutiveSilence;
00545 };
00546
00548
00549 class PVXMLPlayable : public PObject
00550 {
00551 PCLASSINFO(PVXMLPlayable, PObject);
00552 public:
00553 PVXMLPlayable()
00554 { repeat = 1; delay = 0; sampleFrequency = 8000; autoDelete = FALSE; delayDone = FALSE; }
00555
00556 virtual BOOL Open(PVXMLChannel & , PINDEX _delay, PINDEX _repeat, BOOL _autoDelete)
00557 { delay = _delay; repeat = _repeat; autoDelete = _autoDelete; return TRUE; }
00558
00559 virtual BOOL Open(PVXMLChannel & chan, const PString & _arg, PINDEX _delay, PINDEX _repeat, BOOL v)
00560 { arg = _arg; return Open(chan, _delay, _repeat, v); }
00561
00562 virtual void Play(PVXMLChannel & outgoingChannel) = 0;
00563
00564 virtual void OnRepeat(PVXMLChannel & )
00565 { }
00566
00567 virtual void OnStart() { }
00568
00569 virtual void OnStop() { }
00570
00571 virtual void SetRepeat(PINDEX v)
00572 { repeat = v; }
00573
00574 virtual PINDEX GetRepeat() const
00575 { return repeat; }
00576
00577 virtual PINDEX GetDelay() const
00578 { return delay; }
00579
00580 void SetFormat(const PString & _fmt)
00581 { format = _fmt; }
00582
00583 void SetSampleFrequency(unsigned _rate)
00584 { sampleFrequency = _rate; }
00585
00586 virtual BOOL ReadFrame(PVXMLChannel & channel, void * buf, PINDEX len);
00587
00588 virtual BOOL Rewind(PChannel *)
00589 { return FALSE; }
00590
00591 friend class PVXMLChannel;
00592
00593 protected:
00594 PString arg;
00595 PINDEX repeat;
00596 PINDEX delay;
00597 PString format;
00598 unsigned sampleFrequency;
00599 BOOL autoDelete;
00600 BOOL delayDone;
00601 };
00602
00604
00605 class PVXMLPlayableURL : public PVXMLPlayable
00606 {
00607 PCLASSINFO(PVXMLPlayableURL, PVXMLPlayable);
00608 public:
00609 BOOL Open(PVXMLChannel & chan, const PString & _url, PINDEX _delay, PINDEX _repeat, BOOL v);
00610 void Play(PVXMLChannel & outgoingChannel);
00611 protected:
00612 PURL url;
00613 };
00614
00616
00617 class PVXMLPlayableData : public PVXMLPlayable
00618 {
00619 PCLASSINFO(PVXMLPlayableData, PVXMLPlayable);
00620 public:
00621 BOOL Open(PVXMLChannel & chan, const PString & , PINDEX _delay, PINDEX _repeat, BOOL v);
00622 void SetData(const PBYTEArray & _data);
00623 void Play(PVXMLChannel & outgoingChannel);
00624 BOOL Rewind(PChannel * chan);
00625 protected:
00626 PBYTEArray data;
00627 };
00628
00630
00631 class PVXMLPlayableCommand : public PVXMLPlayable
00632 {
00633 PCLASSINFO(PVXMLPlayableCommand, PVXMLPlayable);
00634 public:
00635 PVXMLPlayableCommand();
00636 void Play(PVXMLChannel & outgoingChannel);
00637 void OnStop();
00638
00639 protected:
00640 PPipeChannel * pipeCmd;
00641 };
00642
00644
00645 class PVXMLPlayableFilename : public PVXMLPlayable
00646 {
00647 PCLASSINFO(PVXMLPlayableFilename, PVXMLPlayable);
00648 public:
00649 BOOL Open(PVXMLChannel & chan, const PString & _fn, PINDEX _delay, PINDEX _repeat, BOOL _autoDelete);
00650 void Play(PVXMLChannel & outgoingChannel);
00651 void OnStop();
00652 virtual BOOL Rewind(PChannel * chan);
00653 protected:
00654 PFilePath fn;
00655 };
00656
00658
00659 class PVXMLPlayableFilenameList : public PVXMLPlayable
00660 {
00661 PCLASSINFO(PVXMLPlayableFilenameList, PVXMLPlayable);
00662 public:
00663 BOOL Open(PVXMLChannel & chan, const PStringArray & _filenames, PINDEX _delay, PINDEX _repeat, BOOL _autoDelete);
00664 void Play(PVXMLChannel & outgoingChannel)
00665 { OnRepeat(outgoingChannel); }
00666 void OnRepeat(PVXMLChannel & outgoingChannel);
00667 void OnStop();
00668 protected:
00669 PINDEX currentIndex;
00670 PStringArray filenames;
00671 };
00672
00674
00675 class PVXMLRecordableFilename : public PVXMLRecordable
00676 {
00677 PCLASSINFO(PVXMLRecordableFilename, PVXMLRecordable);
00678 public:
00679 BOOL Open(const PString & _arg);
00680 void Record(PVXMLChannel & incomingChannel);
00681 BOOL OnFrame(BOOL isSilence);
00682
00683 protected:
00684 PFilePath fn;
00685 };
00686
00688
00689 PQUEUE(PVXMLQueue, PVXMLPlayable);
00690
00692
00693 class PVXMLChannel : public PDelayChannel
00694 {
00695 PCLASSINFO(PVXMLChannel, PDelayChannel);
00696 public:
00697 PVXMLChannel(unsigned frameDelay, PINDEX frameSize);
00698 ~PVXMLChannel();
00699
00700 virtual BOOL Open(PVXMLChannelInterface * _vxml);
00701
00702
00703 virtual BOOL IsOpen() const;
00704 virtual BOOL Close();
00705 virtual BOOL Read(void * buffer, PINDEX amount);
00706 virtual BOOL Write(const void * buf, PINDEX len);
00707
00708
00709 virtual PWAVFile * CreateWAVFile(const PFilePath & fn, BOOL recording = FALSE);
00710
00711 const PString & GetMediaFormat() const { return mediaFormat; }
00712 BOOL IsMediaPCM() const { return mediaFormat == "PCM-16"; }
00713 virtual PString AdjustWavFilename(const PString & fn);
00714
00715
00716 virtual BOOL WriteFrame(const void * buf, PINDEX len) = 0;
00717 virtual BOOL IsSilenceFrame(const void * buf, PINDEX len) const = 0;
00718
00719 virtual BOOL QueueRecordable(PVXMLRecordable * newItem);
00720
00721 BOOL StartRecording(const PFilePath & fn, unsigned finalSilence = 3000, unsigned maxDuration = 30000);
00722 BOOL EndRecording();
00723 BOOL IsRecording() const { return recording; }
00724
00725
00726 virtual BOOL ReadFrame(void * buffer, PINDEX amount) = 0;
00727 virtual PINDEX CreateSilenceFrame(void * buffer, PINDEX amount) = 0;
00728 virtual void GetBeepData(PBYTEArray &, unsigned) { }
00729
00730 virtual BOOL QueueResource(const PURL & url, PINDEX repeat= 1, PINDEX delay = 0);
00731
00732 virtual BOOL QueuePlayable(const PString & type, const PString & str, PINDEX repeat = 1, PINDEX delay = 0, BOOL autoDelete = FALSE);
00733 virtual BOOL QueuePlayable(PVXMLPlayable * newItem);
00734 virtual BOOL QueueData(const PBYTEArray & data, PINDEX repeat = 1, PINDEX delay = 0);
00735
00736 virtual BOOL QueueFile(const PString & fn, PINDEX repeat = 1, PINDEX delay = 0, BOOL autoDelete = FALSE)
00737 { return QueuePlayable("File", fn, repeat, delay, autoDelete); }
00738
00739 virtual BOOL QueueCommand(const PString & cmd, PINDEX repeat = 1, PINDEX delay = 0)
00740 { return QueuePlayable("Command", cmd, repeat, delay, TRUE); }
00741
00742 virtual void FlushQueue();
00743 virtual BOOL IsPlaying() const { return (playQueue.GetSize() > 0) || playing ; }
00744
00745 void SetPause(BOOL _pause) { paused = _pause; }
00746
00747 void SetName(const PString & name) { channelName = name; }
00748
00749 unsigned GetSampleFrequency() const
00750 { return sampleFrequency; }
00751
00752 protected:
00753 PVXMLChannelInterface * vxmlInterface;
00754
00755 unsigned sampleFrequency;
00756 PString mediaFormat;
00757 PString wavFilePrefix;
00758
00759 PMutex channelWriteMutex;
00760 PMutex channelReadMutex;
00761 BOOL closed;
00762
00763
00764 BOOL recording;
00765 PVXMLRecordable * recordable;
00766 unsigned finalSilence;
00767 unsigned silenceRun;
00768
00769
00770 BOOL playing;
00771 PMutex queueMutex;
00772 PVXMLQueue playQueue;
00773 PVXMLPlayable * currentPlayItem;
00774
00775 BOOL paused;
00776 int silentCount;
00777 int totalData;
00778 PTimer delayTimer;
00779
00780
00781
00782 PString channelName;
00783 };
00784
00785
00787
00788 class PVXMLTransferOptions : public PObject
00789 {
00790 PCLASSINFO(PVXMLTransferOptions, PObject);
00791 public:
00792 PVXMLTransferOptions() { }
00793
00794 void SetCallingToken(const PString & calling) { callingToken = calling; }
00795 PString GetCallingToken() const { return callingToken; }
00796
00797 void SetCalledToken(const PString & called) { calledToken = called; }
00798 PString GetCalledToken( ) const { return calledToken; }
00799
00800 void SetSourceDNR(const PString & src) { source = src; }
00801 PString GetSourceDNR() const { return source; }
00802
00803 void SetDestinationDNR(const PString & dest ) { destination = dest; }
00804 PString GetDestinationDNR() const { return destination; }
00805
00806 void SetTimeout(unsigned int time) { timeout = time; }
00807 unsigned int GetTimeout() const { return timeout; }
00808
00809 void SetBridge(BOOL brdg) { bridge = brdg; }
00810 BOOL GetBridge() const { return bridge; }
00811
00812 private:
00813 PString callingToken;
00814 PString calledToken;
00815 PString destination;
00816 PString source;
00817 unsigned int timeout;
00818 BOOL bridge;
00819 };
00820
00821 class PVXMLTransferResult : public PString
00822 {
00823 PCLASSINFO(PVXMLTransferResult, PString);
00824 public:
00825 PVXMLTransferResult()
00826 { }
00827
00828 PVXMLTransferResult(char * cstr)
00829 : PString( cstr )
00830 { }
00831
00832 PVXMLTransferResult(const PString & str )
00833 : PString(str)
00834 {}
00835
00836 void SetName(const PString & n)
00837 { name = n; }
00838
00839 PString GetName() const
00840 { return name; }
00841
00842 private:
00843 PString name;
00844 };
00845
00846 #endif
00847
00848
00849