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 _VXML_H
00030 #define _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/pipechan.h>
00042 #include <ptclib/delaychan.h>
00043 #include <ptclib/pwavfile.h>
00044 #include <ptclib/ptts.h>
00045 #include <ptclib/url.h>
00046
00047 #include <queue>
00048
00049
00050 class PVXMLSession;
00051 class PVXMLDialog;
00052 class PVXMLSession;
00053
00054
00055 #define VXML_PCM16 "PCM-16"
00056 #define VXML_G7231 "G.723.1"
00057 #define VXML_G729 "G.729"
00058
00059 #define PVXML_HAS_FACTORY 1
00060
00061 class PVXMLGrammar : public PObject
00062 {
00063 PCLASSINFO(PVXMLGrammar, PObject);
00064 public:
00065 PVXMLGrammar(PXMLElement * field);
00066 virtual PBoolean OnUserInput(const char ) { return PTrue; }
00067 virtual void Stop() { }
00068
00069 PString GetValue() const { return value; }
00070 PXMLElement * GetField() { return field; }
00071
00072 enum GrammarState {
00073 FILLED,
00074 NOINPUT,
00075 NOMATCH,
00076 HELP };
00077
00078 GrammarState GetState() const { return state; }
00079
00080 protected:
00081 PXMLElement * field;
00082 PString value;
00083 GrammarState state;
00084 };
00085
00086
00088
00089 class PVXMLMenuGrammar : public PVXMLGrammar
00090 {
00091 PCLASSINFO(PVXMLMenuGrammar, PVXMLGrammar);
00092 public:
00093 PVXMLMenuGrammar(PXMLElement * field);
00094 };
00095
00096
00098
00099 class PVXMLDigitsGrammar : public PVXMLGrammar
00100 {
00101 PCLASSINFO(PVXMLDigitsGrammar, PVXMLGrammar);
00102 public:
00103 PVXMLDigitsGrammar(PXMLElement * field, PINDEX minDigits, PINDEX maxDigits, PString terminators);
00104 PBoolean OnUserInput(const char ch);
00105 virtual void Stop();
00106
00107 protected:
00108 PINDEX minDigits;
00109 PINDEX maxDigits;
00110 PString terminators;
00111 };
00112
00113
00115
00116 class PVXMLCache : public PMutex
00117 {
00118 public:
00119 PVXMLCache(const PDirectory & _directory);
00120
00121 PFilePath CreateFilename(const PString & prefix, const PString & key, const PString & fileType);
00122
00123 void Put(const PString & prefix,
00124 const PString & key,
00125 const PString & fileType,
00126 const PString & contentType,
00127 const PFilePath & fn,
00128 PFilePath & dataFn);
00129
00130 PBoolean Get(const PString & prefix,
00131 const PString & key,
00132 const PString & fileType,
00133 PString & contentType,
00134 PFilePath & fn);
00135
00136 PFilePath GetCacheDir() const
00137 { return directory; }
00138
00139 PFilePath GetRandomFilename(const PString & prefix, const PString & fileType);
00140
00141 static PVXMLCache & GetResourceCache();
00142
00143 protected:
00144 PDirectory directory;
00145 };
00146
00148
00149 class PVXMLChannel;
00150
00151 class PVXMLChannelInterface {
00152 public:
00153 virtual ~PVXMLChannelInterface() { }
00154 virtual PWAVFile * CreateWAVFile(const PFilePath & fn, PFile::OpenMode mode, int opts, unsigned fmt) = 0;
00155 virtual void RecordEnd() = 0;
00156 virtual void OnEndRecording(const PString & channelName) = 0;
00157 virtual void Trigger() = 0;
00158 };
00159
00161
00162 class PVXMLSession : public PIndirectChannel, public PVXMLChannelInterface
00163 {
00164 PCLASSINFO(PVXMLSession, PIndirectChannel);
00165 public:
00166 PVXMLSession(PTextToSpeech * tts = NULL, PBoolean autoDelete = PFalse);
00167 virtual ~PVXMLSession();
00168
00169
00170 PTextToSpeech * SetTextToSpeech(PTextToSpeech * _tts, PBoolean autoDelete = PFalse);
00171 PTextToSpeech * SetTextToSpeech(const PString & ttsName);
00172 PTextToSpeech * GetTextToSpeech() { return textToSpeech; }
00173
00174 virtual PBoolean Load(const PString & source);
00175 virtual PBoolean LoadFile(const PFilePath & file);
00176 virtual PBoolean LoadURL(const PURL & url);
00177 virtual PBoolean LoadVXML(const PString & xml);
00178 virtual PBoolean IsLoaded() const { return loaded; }
00179
00180 virtual PBoolean Open(const PString & mediaFormat);
00181 virtual PBoolean Close();
00182
00183 PBoolean Execute();
00184
00185 PVXMLChannel * GetAndLockVXMLChannel()
00186 {
00187 sessionMutex.Wait();
00188 if (vxmlChannel != NULL)
00189 return vxmlChannel;
00190 sessionMutex.Signal();
00191 return NULL;
00192 }
00193 void UnLockVXMLChannel() { sessionMutex.Signal(); }
00194 PMutex & GetSessionMutex() { return sessionMutex; }
00195
00196 PBoolean LoadGrammar(PVXMLGrammar * grammar);
00197
00198 virtual PBoolean PlayText(const PString & text, PTextToSpeech::TextType type = PTextToSpeech::Default, PINDEX repeat = 1, PINDEX delay = 0);
00199 PBoolean ConvertTextToFilenameList(const PString & _text, PTextToSpeech::TextType type, PStringArray & list, PBoolean useCacheing);
00200
00201 virtual PBoolean PlayFile(const PString & fn, PINDEX repeat = 1, PINDEX delay = 0, PBoolean autoDelete = PFalse);
00202 virtual PBoolean PlayData(const PBYTEArray & data, PINDEX repeat = 1, PINDEX delay = 0);
00203 virtual PBoolean PlayCommand(const PString & data, PINDEX repeat = 1, PINDEX delay = 0);
00204 virtual PBoolean PlayResource(const PURL & url, PINDEX repeat = 1, PINDEX delay = 0);
00205 virtual PBoolean PlayTone(const PString & toneSpec, PINDEX repeat = 1, PINDEX delay = 0);
00206
00207
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 virtual PBoolean IsPlaying() const;
00219 virtual PBoolean IsRecording() const;
00220
00221 virtual PBoolean OnUserInput(const PString & str);
00222
00223 PString GetXMLError() const;
00224
00225 virtual void OnEndSession() { }
00226
00227 virtual PString GetVar(const PString & str) const;
00228 virtual void SetVar(const PString & ostr, const PString & val);
00229 virtual PString EvaluateExpr(const PString & oexpr);
00230
00231 virtual PBoolean RetreiveResource(const PURL & url, PString & contentType, PFilePath & fn, PBoolean useCache = PTrue);
00232
00233 PDECLARE_NOTIFIER(PThread, PVXMLSession, VXMLExecute);
00234
00235 void SetCallingToken( PString& token ) { callingCallToken = token; }
00236
00237 PXMLElement * FindHandler(const PString & event);
00238
00239
00240 PWAVFile * CreateWAVFile(const PFilePath & fn, PFile::OpenMode mode, int opts, unsigned fmt);
00241 void OnEndRecording(const PString & channelName);
00242 void RecordEnd();
00243 void Trigger();
00244
00245 PStringToString & GetSessionVars() { return sessionVars; }
00246
00247 protected:
00248 void Initialise();
00249
00250 void AllowClearCall();
00251 void ProcessUserInput();
00252 void ProcessNode();
00253 void ProcessGrammar();
00254
00255 PBoolean TraverseAudio();
00256 PBoolean TraverseGoto();
00257 PBoolean TraverseGrammar();
00258 PBoolean TraverseRecord();
00259
00260 PBoolean TraverseIf();
00261 PBoolean TraverseExit();
00262 PBoolean TraverseVar();
00263 PBoolean TraverseSubmit();
00264 PBoolean TraverseMenu();
00265 PBoolean TraverseChoice(const PString & grammarResult);
00266 PBoolean TraverseProperty();
00267
00268 void SayAs(const PString & className, const PString & text);
00269 void SayAs(const PString & className, const PString & text, const PString & voice);
00270
00271 static PTimeInterval StringToTime(const PString & str);
00272
00273 PURL NormaliseResourceName(const PString & src);
00274
00275 PXMLElement * FindForm(const PString & id);
00276
00277
00278
00279 PSyncPoint waitForEvent;
00280
00281 PMutex sessionMutex;
00282
00283 PXML xmlFile;
00284
00285 PVXMLGrammar * activeGrammar;
00286 PBoolean listening;
00287 int timeout;
00288
00289 PStringToString sessionVars;
00290 PStringToString documentVars;
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 PBoolean threadRunning;
00308 PBoolean forceEnd;
00309
00310 PString mediaFormat;
00311 PVXMLChannel * vxmlChannel;
00312
00313 PTextToSpeech * textToSpeech;
00314 PBoolean autoDeleteTextToSpeech;
00315
00316 PXMLElement * currentForm;
00317 PXMLElement * currentField;
00318 PXMLObject * currentNode;
00319
00320 private:
00321 void ExecuteDialog();
00322
00323 PString callingCallToken;
00324 PSyncPoint answerSync;
00325 PString grammarResult;
00326 PString eventName;
00327 PINDEX defaultDTMF;
00328 };
00329
00330
00332
00333 class PVXMLRecordable : public PObject
00334 {
00335 PCLASSINFO(PVXMLRecordable, PObject);
00336 public:
00337 PVXMLRecordable()
00338 { consecutiveSilence = 0; finalSilence = 3000; maxDuration = 30000; }
00339
00340 virtual PBoolean Open(const PString & _arg) = 0;
00341
00342 virtual void Record(PVXMLChannel & incomingChannel) = 0;
00343
00344 virtual void OnStart() { }
00345
00346 virtual PBoolean OnFrame(PBoolean ) { return PFalse; }
00347
00348 virtual void OnStop() { }
00349
00350 void SetFinalSilence(unsigned v)
00351 { finalSilence = v; }
00352
00353 unsigned GetFinalSilence()
00354 { return finalSilence; }
00355
00356 void SetMaxDuration(unsigned v)
00357 { maxDuration = v; }
00358
00359 unsigned GetMaxDuration()
00360 { return maxDuration; }
00361
00362 protected:
00363 PTime silenceStart;
00364 PTime recordStart;
00365 unsigned finalSilence;
00366 unsigned maxDuration;
00367 unsigned consecutiveSilence;
00368 };
00369
00371
00372 class PVXMLPlayable : public PObject
00373 {
00374 PCLASSINFO(PVXMLPlayable, PObject);
00375 public:
00376 PVXMLPlayable()
00377 { repeat = 1; delay = 0; sampleFrequency = 8000; autoDelete = PFalse; delayDone = PFalse; }
00378
00379 virtual PBoolean Open(PVXMLChannel & , PINDEX _delay, PINDEX _repeat, PBoolean _autoDelete);
00380
00381 virtual PBoolean Open(PVXMLChannel & chan, const PString & _arg, PINDEX _delay, PINDEX _repeat, PBoolean v);
00382
00383 virtual void Play(PVXMLChannel & outgoingChannel) = 0;
00384
00385 virtual void OnRepeat(PVXMLChannel & )
00386 { }
00387
00388 virtual void OnStart() { }
00389
00390 virtual void OnStop() { }
00391
00392 virtual void SetRepeat(PINDEX v)
00393 { repeat = v; }
00394
00395 virtual PINDEX GetRepeat() const
00396 { return repeat; }
00397
00398 virtual PINDEX GetDelay() const
00399 { return delay; }
00400
00401 void SetFormat(const PString & _fmt)
00402 { format = _fmt; }
00403
00404 void SetSampleFrequency(unsigned _rate)
00405 { sampleFrequency = _rate; }
00406
00407 virtual PBoolean ReadFrame(PVXMLChannel & channel, void * buf, PINDEX len);
00408
00409 virtual PBoolean Rewind(PChannel *)
00410 { return PFalse; }
00411
00412 friend class PVXMLChannel;
00413
00414 protected:
00415 PString arg;
00416 PINDEX repeat;
00417 PINDEX delay;
00418 PString format;
00419 unsigned sampleFrequency;
00420 PBoolean autoDelete;
00421 PBoolean delayDone;
00422 };
00423
00425
00426 class PVXMLPlayableStop : public PVXMLPlayable
00427 {
00428 PCLASSINFO(PVXMLPlayableStop, PVXMLPlayable);
00429 public:
00430 virtual void Play(PVXMLChannel & outgoingChannel);
00431 virtual PBoolean ReadFrame(PVXMLChannel & channel, void *, PINDEX);
00432 };
00433
00435
00436 class PVXMLPlayableURL : public PVXMLPlayable
00437 {
00438 PCLASSINFO(PVXMLPlayableURL, PVXMLPlayable);
00439 public:
00440 PBoolean Open(PVXMLChannel & chan, const PString & _url, PINDEX _delay, PINDEX _repeat, PBoolean v);
00441 void Play(PVXMLChannel & outgoingChannel);
00442 protected:
00443 PURL url;
00444 };
00445
00447
00448 class PVXMLPlayableData : public PVXMLPlayable
00449 {
00450 PCLASSINFO(PVXMLPlayableData, PVXMLPlayable);
00451 public:
00452 PBoolean Open(PVXMLChannel & chan, const PString & , PINDEX _delay, PINDEX _repeat, PBoolean v);
00453 void SetData(const PBYTEArray & _data);
00454 void Play(PVXMLChannel & outgoingChannel);
00455 PBoolean Rewind(PChannel * chan);
00456 protected:
00457 PBYTEArray data;
00458 };
00459
00461
00462 #include <ptclib/dtmf.h>
00463
00464 class PVXMLPlayableTone : public PVXMLPlayableData
00465 {
00466 PCLASSINFO(PVXMLPlayableTone, PVXMLPlayableData);
00467 public:
00468 PBoolean Open(PVXMLChannel & chan, const PString & toneSpec, PINDEX _delay, PINDEX _repeat, PBoolean v);
00469 protected:
00470 PTones tones;
00471 };
00472
00474
00475 class PVXMLPlayableCommand : public PVXMLPlayable
00476 {
00477 PCLASSINFO(PVXMLPlayableCommand, PVXMLPlayable);
00478 public:
00479 PVXMLPlayableCommand();
00480 void Play(PVXMLChannel & outgoingChannel);
00481 void OnStop();
00482
00483 protected:
00484 PPipeChannel * pipeCmd;
00485 };
00486
00488
00489 class PVXMLPlayableFilename : public PVXMLPlayable
00490 {
00491 PCLASSINFO(PVXMLPlayableFilename, PVXMLPlayable);
00492 public:
00493 PBoolean Open(PVXMLChannel & chan, const PString & _fn, PINDEX _delay, PINDEX _repeat, PBoolean _autoDelete);
00494 void Play(PVXMLChannel & outgoingChannel);
00495 void OnStop();
00496 virtual PBoolean Rewind(PChannel * chan);
00497 protected:
00498 PFilePath fn;
00499 };
00500
00502
00503 class PVXMLPlayableFilenameList : public PVXMLPlayable
00504 {
00505 PCLASSINFO(PVXMLPlayableFilenameList, PVXMLPlayable);
00506 public:
00507 PBoolean Open(PVXMLChannel & chan, const PStringArray & _filenames, PINDEX _delay, PINDEX _repeat, PBoolean _autoDelete);
00508 void Play(PVXMLChannel & outgoingChannel)
00509 { OnRepeat(outgoingChannel); }
00510 void OnRepeat(PVXMLChannel & outgoingChannel);
00511 void OnStop();
00512 protected:
00513 PINDEX currentIndex;
00514 PStringArray filenames;
00515 };
00516
00518
00519 class PVXMLRecordableFilename : public PVXMLRecordable
00520 {
00521 PCLASSINFO(PVXMLRecordableFilename, PVXMLRecordable);
00522 public:
00523 PBoolean Open(const PString & _arg);
00524 void Record(PVXMLChannel & incomingChannel);
00525 PBoolean OnFrame(PBoolean isSilence);
00526
00527 protected:
00528 PFilePath fn;
00529 };
00530
00532
00533 PQUEUE(PVXMLQueue, PVXMLPlayable);
00534
00536
00537 class PVXMLChannel : public PDelayChannel
00538 {
00539 PCLASSINFO(PVXMLChannel, PDelayChannel);
00540 public:
00541 PVXMLChannel(unsigned frameDelay, PINDEX frameSize);
00542 ~PVXMLChannel();
00543
00544 virtual PBoolean Open(PVXMLChannelInterface * _vxml);
00545
00546
00547 virtual PBoolean IsOpen() const;
00548 virtual PBoolean Close();
00549 virtual PBoolean Read(void * buffer, PINDEX amount);
00550 virtual PBoolean Write(const void * buf, PINDEX len);
00551
00552
00553 virtual PWAVFile * CreateWAVFile(const PFilePath & fn, PBoolean recording = PFalse);
00554
00555 const PString & GetMediaFormat() const { return mediaFormat; }
00556 PBoolean IsMediaPCM() const { return mediaFormat == "PCM-16"; }
00557 virtual PString AdjustWavFilename(const PString & fn);
00558
00559
00560 virtual PBoolean WriteFrame(const void * buf, PINDEX len) = 0;
00561 virtual PBoolean IsSilenceFrame(const void * buf, PINDEX len) const = 0;
00562
00563 virtual PBoolean QueueRecordable(PVXMLRecordable * newItem);
00564
00565 PBoolean StartRecording(const PFilePath & fn, unsigned finalSilence = 3000, unsigned maxDuration = 30000);
00566 PBoolean EndRecording();
00567 PBoolean IsRecording() const { return recording; }
00568
00569
00570 virtual PBoolean ReadFrame(void * buffer, PINDEX amount) = 0;
00571 virtual PINDEX CreateSilenceFrame(void * buffer, PINDEX amount) = 0;
00572 virtual void GetBeepData(PBYTEArray &, unsigned) { }
00573
00574 virtual PBoolean QueueResource(const PURL & url, PINDEX repeat= 1, PINDEX delay = 0);
00575
00576 virtual PBoolean QueuePlayable(const PString & type, const PString & str, PINDEX repeat = 1, PINDEX delay = 0, PBoolean autoDelete = PFalse);
00577 virtual PBoolean QueuePlayable(PVXMLPlayable * newItem);
00578 virtual PBoolean QueueData(const PBYTEArray & data, PINDEX repeat = 1, PINDEX delay = 0);
00579
00580 virtual PBoolean QueueFile(const PString & fn, PINDEX repeat = 1, PINDEX delay = 0, PBoolean autoDelete = PFalse)
00581 { return QueuePlayable("File", fn, repeat, delay, autoDelete); }
00582
00583 virtual PBoolean QueueCommand(const PString & cmd, PINDEX repeat = 1, PINDEX delay = 0)
00584 { return QueuePlayable("Command", cmd, repeat, delay, PTrue); }
00585
00586 virtual void FlushQueue();
00587 virtual PBoolean IsPlaying() const { return (playQueue.GetSize() > 0) || playing ; }
00588
00589 void SetPause(PBoolean _pause) { paused = _pause; }
00590
00591 void SetName(const PString & name) { channelName = name; }
00592
00593 unsigned GetSampleFrequency() const
00594 { return sampleFrequency; }
00595
00596 void SetSilentCount(int v) { silentCount = v; }
00597
00598 protected:
00599 PVXMLChannelInterface * vxmlInterface;
00600
00601 unsigned sampleFrequency;
00602 PString mediaFormat;
00603 PString wavFilePrefix;
00604
00605 PMutex channelWriteMutex;
00606 PMutex channelReadMutex;
00607 PBoolean closed;
00608
00609
00610 PBoolean recording;
00611 PVXMLRecordable * recordable;
00612 unsigned finalSilence;
00613 unsigned silenceRun;
00614
00615
00616 PBoolean playing;
00617 PMutex queueMutex;
00618 PVXMLQueue playQueue;
00619 PVXMLPlayable * currentPlayItem;
00620
00621 PBoolean paused;
00622 int silentCount;
00623 int totalData;
00624 PTimer delayTimer;
00625
00626
00627
00628 PString channelName;
00629 };
00630
00631
00633
00634
00635 #endif // P_VXML
00636
00637 #endif // _VXML_H
00638
00639
00640