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