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 virtual void OnTransfer(const PString & , bool ) { }
00227
00228 virtual PString GetVar(const PString & str) const;
00229 virtual void SetVar(const PString & ostr, const PString & val);
00230 virtual PString EvaluateExpr(const PString & oexpr);
00231
00232 virtual PBoolean RetreiveResource(const PURL & url, PString & contentType, PFilePath & fn, PBoolean useCache = PTrue);
00233
00234 PDECLARE_NOTIFIER(PThread, PVXMLSession, VXMLExecute);
00235
00236 void SetCallingToken( PString& token ) { callingCallToken = token; }
00237
00238 PXMLElement * FindHandler(const PString & event);
00239
00240
00241 PWAVFile * CreateWAVFile(const PFilePath & fn, PFile::OpenMode mode, int opts, unsigned fmt);
00242 void OnEndRecording(const PString & channelName);
00243 void RecordEnd();
00244 void Trigger();
00245
00246 PStringToString & GetSessionVars() { return sessionVars; }
00247
00248 protected:
00249 void Initialise();
00250
00251 void AllowClearCall();
00252 void ProcessUserInput();
00253 void ProcessNode();
00254 void ProcessGrammar();
00255
00256 PBoolean TraverseAudio();
00257 PBoolean TraverseGoto();
00258 PBoolean TraverseGrammar();
00259 PBoolean TraverseRecord();
00260
00261 PBoolean TraverseIf();
00262 PBoolean TraverseExit();
00263 PBoolean TraverseVar();
00264 PBoolean TraverseSubmit();
00265 PBoolean TraverseMenu();
00266 PBoolean TraverseChoice();
00267 PBoolean TraverseProperty();
00268 PBoolean TraverseTransfer();
00269
00270 void SayAs(const PString & className, const PString & text);
00271 void SayAs(const PString & className, const PString & text, const PString & voice);
00272
00273 static PTimeInterval StringToTime(const PString & str);
00274
00275 PURL NormaliseResourceName(const PString & src);
00276
00277 PXMLElement * FindForm(const PString & id);
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 bool m_speakNodeData;
00320
00321 private:
00322 void ExecuteDialog();
00323
00324 PString callingCallToken;
00325 PSyncPoint answerSync;
00326 PString grammarResult;
00327 PString eventName;
00328 PINDEX defaultDTMF;
00329 };
00330
00331
00333
00334 class PVXMLRecordable : public PObject
00335 {
00336 PCLASSINFO(PVXMLRecordable, PObject);
00337 public:
00338 PVXMLRecordable()
00339 { consecutiveSilence = 0; finalSilence = 3000; maxDuration = 30000; }
00340
00341 virtual PBoolean Open(const PString & arg) = 0;
00342
00343 virtual void Record(PVXMLChannel & incomingChannel) = 0;
00344
00345 virtual void OnStart() { }
00346
00347 virtual PBoolean OnFrame(PBoolean ) { return PFalse; }
00348
00349 virtual void OnStop() { }
00350
00351 void SetFinalSilence(unsigned v)
00352 { finalSilence = v; }
00353
00354 unsigned GetFinalSilence()
00355 { return finalSilence; }
00356
00357 void SetMaxDuration(unsigned v)
00358 { maxDuration = v; }
00359
00360 unsigned GetMaxDuration()
00361 { return maxDuration; }
00362
00363 protected:
00364 PTime silenceStart;
00365 PTime recordStart;
00366 unsigned finalSilence;
00367 unsigned maxDuration;
00368 unsigned consecutiveSilence;
00369 };
00370
00372
00373 class PVXMLPlayable : public PObject
00374 {
00375 PCLASSINFO(PVXMLPlayable, PObject);
00376 public:
00377 PVXMLPlayable()
00378 { repeat = 1; delay = 0; sampleFrequency = 8000; autoDelete = PFalse; delayDone = PFalse; }
00379
00380 virtual PBoolean Open(PVXMLChannel & , PINDEX delay, PINDEX repeat, PBoolean autoDelete);
00381
00382 virtual PBoolean Open(PVXMLChannel & chan, const PString & arg, PINDEX delay, PINDEX repeat, PBoolean v);
00383
00384 virtual void Play(PVXMLChannel & outgoingChannel) = 0;
00385
00386 virtual void OnRepeat(PVXMLChannel & )
00387 { }
00388
00389 virtual void OnStart() { }
00390
00391 virtual void OnStop() { }
00392
00393 virtual void SetRepeat(PINDEX v)
00394 { repeat = v; }
00395
00396 virtual PINDEX GetRepeat() const
00397 { return repeat; }
00398
00399 virtual PINDEX GetDelay() const
00400 { return delay; }
00401
00402 void SetFormat(const PString & fmt)
00403 { format = fmt; }
00404
00405 void SetSampleFrequency(unsigned rate)
00406 { sampleFrequency = rate; }
00407
00408 virtual PBoolean ReadFrame(PVXMLChannel & channel, void * buf, PINDEX len);
00409
00410 virtual PBoolean Rewind(PChannel *)
00411 { return PFalse; }
00412
00413 friend class PVXMLChannel;
00414
00415 protected:
00416 PString arg;
00417 PINDEX repeat;
00418 PINDEX delay;
00419 PString format;
00420 unsigned sampleFrequency;
00421 PBoolean autoDelete;
00422 PBoolean delayDone;
00423 };
00424
00426
00427 class PVXMLPlayableStop : public PVXMLPlayable
00428 {
00429 PCLASSINFO(PVXMLPlayableStop, PVXMLPlayable);
00430 public:
00431 virtual void Play(PVXMLChannel & outgoingChannel);
00432 virtual PBoolean ReadFrame(PVXMLChannel & channel, void *, PINDEX);
00433 };
00434
00436
00437 class PVXMLPlayableURL : public PVXMLPlayable
00438 {
00439 PCLASSINFO(PVXMLPlayableURL, PVXMLPlayable);
00440 public:
00441 PBoolean Open(PVXMLChannel & chan, const PString & url, PINDEX delay, PINDEX repeat, PBoolean v);
00442 void Play(PVXMLChannel & outgoingChannel);
00443 protected:
00444 PURL url;
00445 };
00446
00448
00449 class PVXMLPlayableData : public PVXMLPlayable
00450 {
00451 PCLASSINFO(PVXMLPlayableData, PVXMLPlayable);
00452 public:
00453 PBoolean Open(PVXMLChannel & chan, const PString & fn, PINDEX delay, PINDEX repeat, PBoolean v);
00454 void SetData(const PBYTEArray & data);
00455 void Play(PVXMLChannel & outgoingChannel);
00456 PBoolean Rewind(PChannel * chan);
00457 protected:
00458 PBYTEArray data;
00459 };
00460
00462
00463 #include <ptclib/dtmf.h>
00464
00465 class PVXMLPlayableTone : public PVXMLPlayableData
00466 {
00467 PCLASSINFO(PVXMLPlayableTone, PVXMLPlayableData);
00468 public:
00469 PBoolean Open(PVXMLChannel & chan, const PString & toneSpec, PINDEX delay, PINDEX repeat, PBoolean v);
00470 protected:
00471 PTones tones;
00472 };
00473
00475
00476 class PVXMLPlayableCommand : public PVXMLPlayable
00477 {
00478 PCLASSINFO(PVXMLPlayableCommand, PVXMLPlayable);
00479 public:
00480 PVXMLPlayableCommand();
00481 void Play(PVXMLChannel & outgoingChannel);
00482 void OnStop();
00483
00484 protected:
00485 PPipeChannel * pipeCmd;
00486 };
00487
00489
00490 class PVXMLPlayableFilename : public PVXMLPlayable
00491 {
00492 PCLASSINFO(PVXMLPlayableFilename, PVXMLPlayable);
00493 public:
00494 PBoolean Open(PVXMLChannel & chan, const PString & fn, PINDEX delay, PINDEX repeat, PBoolean autoDelete);
00495 void Play(PVXMLChannel & outgoingChannel);
00496 void OnStop();
00497 virtual PBoolean Rewind(PChannel * chan);
00498 protected:
00499 PFilePath fn;
00500 };
00501
00503
00504 class PVXMLPlayableFilenameList : public PVXMLPlayable
00505 {
00506 PCLASSINFO(PVXMLPlayableFilenameList, PVXMLPlayable);
00507 public:
00508 PBoolean Open(PVXMLChannel & chan, const PStringArray & filenames, PINDEX delay, PINDEX repeat, PBoolean autoDelete);
00509 void Play(PVXMLChannel & outgoingChannel)
00510 { OnRepeat(outgoingChannel); }
00511 void OnRepeat(PVXMLChannel & outgoingChannel);
00512 void OnStop();
00513 protected:
00514 PINDEX currentIndex;
00515 PStringArray filenames;
00516 };
00517
00519
00520 class PVXMLRecordableFilename : public PVXMLRecordable
00521 {
00522 PCLASSINFO(PVXMLRecordableFilename, PVXMLRecordable);
00523 public:
00524 PBoolean Open(const PString & arg);
00525 void Record(PVXMLChannel & incomingChannel);
00526 PBoolean OnFrame(PBoolean isSilence);
00527
00528 protected:
00529 PFilePath fn;
00530 };
00531
00533
00534 PQUEUE(PVXMLQueue, PVXMLPlayable);
00535
00537
00538 class PVXMLChannel : public PDelayChannel
00539 {
00540 PCLASSINFO(PVXMLChannel, PDelayChannel);
00541 public:
00542 PVXMLChannel(unsigned frameDelay, PINDEX frameSize);
00543 ~PVXMLChannel();
00544
00545 virtual PBoolean Open(PVXMLChannelInterface * vxml);
00546
00547
00548 virtual PBoolean IsOpen() const;
00549 virtual PBoolean Close();
00550 virtual PBoolean Read(void * buffer, PINDEX amount);
00551 virtual PBoolean Write(const void * buf, PINDEX len);
00552
00553
00554 virtual PWAVFile * CreateWAVFile(const PFilePath & fn, PBoolean recording = PFalse);
00555
00556 const PString & GetMediaFormat() const { return mediaFormat; }
00557 PBoolean IsMediaPCM() const { return mediaFormat == "PCM-16"; }
00558 virtual PString AdjustWavFilename(const PString & fn);
00559
00560
00561 virtual PBoolean WriteFrame(const void * buf, PINDEX len) = 0;
00562 virtual PBoolean IsSilenceFrame(const void * buf, PINDEX len) const = 0;
00563
00564 virtual PBoolean QueueRecordable(PVXMLRecordable * newItem);
00565
00566 PBoolean StartRecording(const PFilePath & fn, unsigned finalSilence = 3000, unsigned maxDuration = 30000);
00567 PBoolean EndRecording();
00568 PBoolean IsRecording() const { return recording; }
00569
00570
00571 virtual PBoolean ReadFrame(void * buffer, PINDEX amount) = 0;
00572 virtual PINDEX CreateSilenceFrame(void * buffer, PINDEX amount) = 0;
00573 virtual void GetBeepData(PBYTEArray &, unsigned) { }
00574
00575 virtual PBoolean QueueResource(const PURL & url, PINDEX repeat= 1, PINDEX delay = 0);
00576
00577 virtual PBoolean QueuePlayable(const PString & type, const PString & str, PINDEX repeat = 1, PINDEX delay = 0, PBoolean autoDelete = PFalse);
00578 virtual PBoolean QueuePlayable(PVXMLPlayable * newItem);
00579 virtual PBoolean QueueData(const PBYTEArray & data, PINDEX repeat = 1, PINDEX delay = 0);
00580
00581 virtual PBoolean QueueFile(const PString & fn, PINDEX repeat = 1, PINDEX delay = 0, PBoolean autoDelete = PFalse)
00582 { return QueuePlayable("File", fn, repeat, delay, autoDelete); }
00583
00584 virtual PBoolean QueueCommand(const PString & cmd, PINDEX repeat = 1, PINDEX delay = 0)
00585 { return QueuePlayable("Command", cmd, repeat, delay, PTrue); }
00586
00587 virtual void FlushQueue();
00588 virtual PBoolean IsPlaying() const { return currentPlayItem != NULL || playQueue.GetSize() > 0; }
00589
00590 void SetPause(PBoolean pause) { paused = pause; }
00591
00592 void SetName(const PString & name) { channelName = name; }
00593
00594 unsigned GetSampleFrequency() const
00595 { return sampleFrequency; }
00596
00597 void SetSilentCount(int v) { silentCount = v; }
00598
00599 protected:
00600 PVXMLChannelInterface * vxmlInterface;
00601
00602 unsigned sampleFrequency;
00603 PString mediaFormat;
00604 PString wavFilePrefix;
00605
00606 PMutex channelWriteMutex;
00607 PMutex channelReadMutex;
00608 PBoolean closed;
00609
00610
00611 PBoolean recording;
00612 PVXMLRecordable * recordable;
00613 unsigned finalSilence;
00614 unsigned silenceRun;
00615
00616
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 // PTLIB_VXML_H
00638
00639
00640