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/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 = false);
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 PSyncPoint waitForEvent;
00278
00279 PMutex sessionMutex;
00280
00281 PXML xmlFile;
00282
00283 PVXMLGrammar * activeGrammar;
00284 PBoolean listening;
00285 int timeout;
00286
00287 PStringToString sessionVars;
00288 PStringToString documentVars;
00289
00290 PMutex userInputMutex;
00291 std::queue<char> userInputQueue;
00292
00293 PBoolean recording;
00294 PFilePath recordFn;
00295 PBoolean recordDTMFTerm;
00296 PTimeInterval recordMaxTime;
00297 PTimeInterval recordFinalSilence;
00298 PSyncPoint recordSync;
00299
00300 PBoolean loaded;
00301 PURL rootURL;
00302 PBoolean emptyAction;
00303
00304 PThread * vxmlThread;
00305 PBoolean threadRunning;
00306 PBoolean forceEnd;
00307
00308 PString mediaFormat;
00309 PVXMLChannel * & vxmlChannel;
00310
00311 PTextToSpeech * textToSpeech;
00312 PBoolean autoDeleteTextToSpeech;
00313
00314 PXMLElement * currentForm;
00315 PXMLElement * currentField;
00316 PXMLObject * currentNode;
00317
00318 private:
00319 void ExecuteDialog();
00320
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 ) { return PFalse; }
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 = PFalse; delayDone = PFalse; }
00376
00377 virtual PBoolean Open(PVXMLChannel & , 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 & )
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 PFalse; }
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;
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
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
00551 virtual PWAVFile * CreateWAVFile(const PFilePath & fn, PBoolean recording = PFalse);
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
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
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 = PFalse);
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 = PFalse)
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, PTrue); }
00583
00584 virtual void FlushQueue();
00585 virtual PBoolean IsPlaying() const { return (playQueue.GetSize() > 0) || playing ; }
00586
00587 void SetPause(PBoolean pause) { paused = pause; }
00588
00589 void SetName(const PString & name) { channelName = name; }
00590
00591 unsigned GetSampleFrequency() const
00592 { return sampleFrequency; }
00593
00594 void SetSilentCount(int v) { silentCount = v; }
00595
00596 protected:
00597 PVXMLChannelInterface * vxmlInterface;
00598
00599 unsigned sampleFrequency;
00600 PString mediaFormat;
00601 PString wavFilePrefix;
00602
00603 PMutex channelWriteMutex;
00604 PMutex channelReadMutex;
00605 PBoolean closed;
00606
00607
00608 PBoolean recording;
00609 PVXMLRecordable * recordable;
00610 unsigned finalSilence;
00611 unsigned silenceRun;
00612
00613
00614 PBoolean playing;
00615 PMutex queueMutex;
00616 PVXMLQueue playQueue;
00617 PVXMLPlayable * currentPlayItem;
00618
00619 PBoolean paused;
00620 int silentCount;
00621 int totalData;
00622 PTimer delayTimer;
00623
00624
00625
00626 PString channelName;
00627 };
00628
00629
00631
00632
00633 #endif // P_VXML
00634
00635 #endif // PTLIB_VXML_H
00636
00637
00638