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 true; }
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 = false);
00167 virtual ~PVXMLSession();
00168
00169
00170 PTextToSpeech * SetTextToSpeech(PTextToSpeech * tts, PBoolean autoDelete = false);
00171 PTextToSpeech * SetTextToSpeech(const PString & ttsName);
00172 PTextToSpeech * GetTextToSpeech() const { 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 void UnLockVXMLChannel() { sessionMutex.Signal(); }
00187 PMutex & GetSessionMutex() { return sessionMutex; }
00188
00189 PBoolean LoadGrammar(PVXMLGrammar * grammar);
00190
00191 virtual PBoolean PlayText(const PString & text, PTextToSpeech::TextType type = PTextToSpeech::Default, PINDEX repeat = 1, PINDEX delay = 0);
00192 PBoolean ConvertTextToFilenameList(const PString & text, PTextToSpeech::TextType type, PStringArray & list, PBoolean useCacheing);
00193
00194 virtual PBoolean PlayFile(const PString & fn, PINDEX repeat = 1, PINDEX delay = 0, PBoolean autoDelete = false);
00195 virtual PBoolean PlayData(const PBYTEArray & data, PINDEX repeat = 1, PINDEX delay = 0);
00196 virtual PBoolean PlayCommand(const PString & data, PINDEX repeat = 1, PINDEX delay = 0);
00197 virtual PBoolean PlayResource(const PURL & url, PINDEX repeat = 1, PINDEX delay = 0);
00198 virtual PBoolean PlayTone(const PString & toneSpec, PINDEX repeat = 1, PINDEX delay = 0);
00199
00200
00201 virtual PBoolean PlaySilence(PINDEX msecs = 0);
00202 virtual PBoolean PlaySilence(const PTimeInterval & timeout);
00203
00204 virtual PBoolean PlayStop();
00205
00206 virtual void SetPause(PBoolean pause);
00207 virtual void GetBeepData(PBYTEArray & data, unsigned ms);
00208
00209 virtual PBoolean StartRecording(const PFilePath & fn, PBoolean recordDTMFTerm, const PTimeInterval & recordMaxTime, const PTimeInterval & recordFinalSilence);
00210 virtual PBoolean EndRecording();
00211 virtual PBoolean IsPlaying() const;
00212 virtual PBoolean IsRecording() const;
00213
00214 virtual PBoolean OnUserInput(const PString & str);
00215
00216 PString GetXMLError() const;
00217
00218 virtual void OnEndDialog();
00219 virtual void OnEndSession() { }
00220 virtual void OnTransfer(const PString & , bool ) { }
00221
00222 virtual PString GetVar(const PString & str) const;
00223 virtual void SetVar(const PString & ostr, const PString & val);
00224 virtual PString EvaluateExpr(const PString & oexpr);
00225
00226 virtual PBoolean RetreiveResource(const PURL & url, PString & contentType, PFilePath & fn, PBoolean useCache = true);
00227
00228 PDECLARE_NOTIFIER(PThread, PVXMLSession, VXMLExecute);
00229
00230 void SetCallingToken( PString& token ) { callingCallToken = token; }
00231
00232 PXMLElement * FindHandler(const PString & event);
00233
00234
00235 PWAVFile * CreateWAVFile(const PFilePath & fn, PFile::OpenMode mode, int opts, unsigned fmt);
00236 void OnEndRecording(const PString & channelName);
00237 void RecordEnd();
00238 void Trigger();
00239
00240 PStringToString & GetSessionVars() { return sessionVars; }
00241
00242 protected:
00243 void Initialise();
00244
00245 void AllowClearCall();
00246 void ProcessUserInput();
00247 void ProcessGrammar();
00248 void ProcessNode();
00249 bool NextNode();
00250
00251 PBoolean TraverseAudio();
00252 PBoolean TraverseGoto();
00253 PBoolean TraverseGrammar();
00254 PBoolean TraverseRecord();
00255
00256 PBoolean TraverseIf();
00257 PBoolean TraverseExit();
00258 PBoolean TraverseVar();
00259 PBoolean TraverseSubmit();
00260 PBoolean TraverseMenu();
00261 PBoolean TraverseChoice();
00262 PBoolean TraverseProperty();
00263 PBoolean TraverseTransfer();
00264
00265 void SayAs(const PString & className, const PString & text);
00266 void SayAs(const PString & className, const PString & text, const PString & voice);
00267
00268 static PTimeInterval StringToTime(const PString & str);
00269
00270 PURL NormaliseResourceName(const PString & src);
00271
00272 PXMLElement * FindForm(const PString & id);
00273
00274 PSyncPoint waitForEvent;
00275
00276 PMutex sessionMutex;
00277
00278 PXML xmlFile;
00279
00280 PVXMLGrammar * activeGrammar;
00281 PBoolean listening;
00282 int timeout;
00283
00284 PStringToString sessionVars;
00285 PStringToString documentVars;
00286
00287 PMutex userInputMutex;
00288 std::queue<char> userInputQueue;
00289
00290 PBoolean recording;
00291 PFilePath recordFn;
00292 PBoolean recordDTMFTerm;
00293 PTimeInterval recordMaxTime;
00294 PTimeInterval recordFinalSilence;
00295 PSyncPoint recordSync;
00296
00297 PBoolean loaded;
00298 PURL rootURL;
00299 PBoolean emptyAction;
00300
00301 PThread * vxmlThread;
00302 bool m_abortVXML;
00303
00304 PString mediaFormat;
00305 PVXMLChannel * & vxmlChannel;
00306
00307 PTextToSpeech * textToSpeech;
00308 PBoolean autoDeleteTextToSpeech;
00309
00310 PXMLElement * currentForm;
00311 PXMLElement * currentField;
00312 PXMLObject * currentNode;
00313 bool m_speakNodeData;
00314
00315 private:
00316 PString callingCallToken;
00317 PSyncPoint answerSync;
00318 PString grammarResult;
00319 PString eventName;
00320 PINDEX defaultDTMF;
00321 };
00322
00323
00325
00326 class PVXMLRecordable : public PObject
00327 {
00328 PCLASSINFO(PVXMLRecordable, PObject);
00329 public:
00330 PVXMLRecordable()
00331 { consecutiveSilence = 0; finalSilence = 3000; maxDuration = 30000; }
00332
00333 virtual PBoolean Open(const PString & arg) = 0;
00334
00335 virtual void Record(PVXMLChannel & incomingChannel) = 0;
00336
00337 virtual void OnStart() { }
00338
00339 virtual PBoolean OnFrame(PBoolean ) { return false; }
00340
00341 virtual void OnStop() { }
00342
00343 void SetFinalSilence(unsigned v)
00344 { finalSilence = v; }
00345
00346 unsigned GetFinalSilence()
00347 { return finalSilence; }
00348
00349 void SetMaxDuration(unsigned v)
00350 { maxDuration = v; }
00351
00352 unsigned GetMaxDuration()
00353 { return maxDuration; }
00354
00355 protected:
00356 PTime silenceStart;
00357 PTime recordStart;
00358 unsigned finalSilence;
00359 unsigned maxDuration;
00360 unsigned consecutiveSilence;
00361 };
00362
00364
00365 class PVXMLPlayable : public PObject
00366 {
00367 PCLASSINFO(PVXMLPlayable, PObject);
00368 public:
00369 PVXMLPlayable()
00370 { repeat = 1; delay = 0; sampleFrequency = 8000; autoDelete = false; delayDone = false; }
00371
00372 virtual PBoolean Open(PVXMLChannel & , PINDEX delay, PINDEX repeat, PBoolean autoDelete);
00373
00374 virtual PBoolean Open(PVXMLChannel & chan, const PString & arg, PINDEX delay, PINDEX repeat, PBoolean v);
00375
00376 virtual void Play(PVXMLChannel & outgoingChannel) = 0;
00377
00378 virtual void OnRepeat(PVXMLChannel & )
00379 { }
00380
00381 virtual void OnStart() { }
00382
00383 virtual void OnStop() { }
00384
00385 virtual void SetRepeat(PINDEX v)
00386 { repeat = v; }
00387
00388 virtual PINDEX GetRepeat() const
00389 { return repeat; }
00390
00391 virtual PINDEX GetDelay() const
00392 { return delay; }
00393
00394 void SetFormat(const PString & fmt)
00395 { format = fmt; }
00396
00397 void SetSampleFrequency(unsigned rate)
00398 { sampleFrequency = rate; }
00399
00400 virtual PBoolean ReadFrame(PVXMLChannel & channel, void * buf, PINDEX len);
00401
00402 virtual PBoolean Rewind(PChannel *)
00403 { return false; }
00404
00405 friend class PVXMLChannel;
00406
00407 protected:
00408 PString arg;
00409 PINDEX repeat;
00410 PINDEX delay;
00411 PString format;
00412 unsigned sampleFrequency;
00413 PBoolean autoDelete;
00414 PBoolean delayDone;
00415 };
00416
00418
00419 class PVXMLPlayableStop : public PVXMLPlayable
00420 {
00421 PCLASSINFO(PVXMLPlayableStop, PVXMLPlayable);
00422 public:
00423 virtual void Play(PVXMLChannel & outgoingChannel);
00424 virtual PBoolean ReadFrame(PVXMLChannel & channel, void *, PINDEX);
00425 };
00426
00428
00429 class PVXMLPlayableURL : public PVXMLPlayable
00430 {
00431 PCLASSINFO(PVXMLPlayableURL, PVXMLPlayable);
00432 public:
00433 PBoolean Open(PVXMLChannel & chan, const PString & url, PINDEX delay, PINDEX repeat, PBoolean v);
00434 void Play(PVXMLChannel & outgoingChannel);
00435 protected:
00436 PURL url;
00437 };
00438
00440
00441 class PVXMLPlayableData : public PVXMLPlayable
00442 {
00443 PCLASSINFO(PVXMLPlayableData, PVXMLPlayable);
00444 public:
00445 PBoolean Open(PVXMLChannel & chan, const PString & fn, PINDEX delay, PINDEX repeat, PBoolean v);
00446 void SetData(const PBYTEArray & data);
00447 void Play(PVXMLChannel & outgoingChannel);
00448 PBoolean Rewind(PChannel * chan);
00449 protected:
00450 PBYTEArray data;
00451 };
00452
00454
00455 #include <ptclib/dtmf.h>
00456
00457 class PVXMLPlayableTone : public PVXMLPlayableData
00458 {
00459 PCLASSINFO(PVXMLPlayableTone, PVXMLPlayableData);
00460 public:
00461 PBoolean Open(PVXMLChannel & chan, const PString & toneSpec, PINDEX delay, PINDEX repeat, PBoolean v);
00462 protected:
00463 PTones tones;
00464 };
00465
00467
00468 class PVXMLPlayableCommand : public PVXMLPlayable
00469 {
00470 PCLASSINFO(PVXMLPlayableCommand, PVXMLPlayable);
00471 public:
00472 PVXMLPlayableCommand();
00473 void Play(PVXMLChannel & outgoingChannel);
00474 void OnStop();
00475
00476 protected:
00477 PPipeChannel * pipeCmd;
00478 };
00479
00481
00482 class PVXMLPlayableFilename : public PVXMLPlayable
00483 {
00484 PCLASSINFO(PVXMLPlayableFilename, PVXMLPlayable);
00485 public:
00486 PBoolean Open(PVXMLChannel & chan, const PString & fn, PINDEX delay, PINDEX repeat, PBoolean autoDelete);
00487 void Play(PVXMLChannel & outgoingChannel);
00488 void OnStop();
00489 virtual PBoolean Rewind(PChannel * chan);
00490 protected:
00491 PFilePath fn;
00492 };
00493
00495
00496 class PVXMLPlayableFilenameList : public PVXMLPlayable
00497 {
00498 PCLASSINFO(PVXMLPlayableFilenameList, PVXMLPlayable);
00499 public:
00500 PBoolean Open(PVXMLChannel & chan, const PStringArray & filenames, PINDEX delay, PINDEX repeat, PBoolean autoDelete);
00501 void Play(PVXMLChannel & outgoingChannel)
00502 { OnRepeat(outgoingChannel); }
00503 void OnRepeat(PVXMLChannel & outgoingChannel);
00504 void OnStop();
00505 protected:
00506 PINDEX currentIndex;
00507 PStringArray filenames;
00508 };
00509
00511
00512 class PVXMLRecordableFilename : public PVXMLRecordable
00513 {
00514 PCLASSINFO(PVXMLRecordableFilename, PVXMLRecordable);
00515 public:
00516 PBoolean Open(const PString & arg);
00517 void Record(PVXMLChannel & incomingChannel);
00518 PBoolean OnFrame(PBoolean isSilence);
00519
00520 protected:
00521 PFilePath fn;
00522 };
00523
00525
00526 PQUEUE(PVXMLQueue, PVXMLPlayable);
00527
00529
00530 class PVXMLChannel : public PDelayChannel
00531 {
00532 PCLASSINFO(PVXMLChannel, PDelayChannel);
00533 public:
00534 PVXMLChannel(unsigned frameDelay, PINDEX frameSize);
00535 ~PVXMLChannel();
00536
00537 virtual PBoolean Open(PVXMLChannelInterface * vxml);
00538
00539
00540 virtual PBoolean IsOpen() const;
00541 virtual PBoolean Close();
00542 virtual PBoolean Read(void * buffer, PINDEX amount);
00543 virtual PBoolean Write(const void * buf, PINDEX len);
00544
00545
00546 virtual PWAVFile * CreateWAVFile(const PFilePath & fn, PBoolean recording = false);
00547
00548 const PString & GetMediaFormat() const { return mediaFormat; }
00549 PBoolean IsMediaPCM() const { return mediaFormat == "PCM-16"; }
00550 virtual PString AdjustWavFilename(const PString & fn);
00551
00552
00553 virtual PBoolean WriteFrame(const void * buf, PINDEX len) = 0;
00554 virtual PBoolean IsSilenceFrame(const void * buf, PINDEX len) const = 0;
00555
00556 virtual PBoolean QueueRecordable(PVXMLRecordable * newItem);
00557
00558 PBoolean StartRecording(const PFilePath & fn, unsigned finalSilence = 3000, unsigned maxDuration = 30000);
00559 PBoolean EndRecording();
00560 PBoolean IsRecording() const { return recording; }
00561
00562
00563 virtual PBoolean ReadFrame(void * buffer, PINDEX amount) = 0;
00564 virtual PINDEX CreateSilenceFrame(void * buffer, PINDEX amount) = 0;
00565 virtual void GetBeepData(PBYTEArray &, unsigned) { }
00566
00567 virtual PBoolean QueueResource(const PURL & url, PINDEX repeat= 1, PINDEX delay = 0);
00568
00569 virtual PBoolean QueuePlayable(const PString & type, const PString & str, PINDEX repeat = 1, PINDEX delay = 0, PBoolean autoDelete = false);
00570 virtual PBoolean QueuePlayable(PVXMLPlayable * newItem);
00571 virtual PBoolean QueueData(const PBYTEArray & data, PINDEX repeat = 1, PINDEX delay = 0);
00572
00573 virtual PBoolean QueueFile(const PString & fn, PINDEX repeat = 1, PINDEX delay = 0, PBoolean autoDelete = false)
00574 { return QueuePlayable("File", fn, repeat, delay, autoDelete); }
00575
00576 virtual PBoolean QueueCommand(const PString & cmd, PINDEX repeat = 1, PINDEX delay = 0)
00577 { return QueuePlayable("Command", cmd, repeat, delay, true); }
00578
00579 virtual void FlushQueue();
00580 virtual PBoolean IsPlaying() const { return currentPlayItem != NULL || playQueue.GetSize() > 0; }
00581
00582 void SetPause(PBoolean pause) { paused = pause; }
00583
00584 void SetName(const PString & name) { channelName = name; }
00585
00586 unsigned GetSampleFrequency() const { return sampleFrequency; }
00587
00588 void SetSilence(unsigned msecs);
00589
00590 protected:
00591 PVXMLChannelInterface * vxmlInterface;
00592
00593 unsigned sampleFrequency;
00594 PString mediaFormat;
00595 PString wavFilePrefix;
00596
00597 PMutex channelWriteMutex;
00598 PMutex channelReadMutex;
00599 PBoolean closed;
00600
00601
00602 PBoolean recording;
00603 PVXMLRecordable * recordable;
00604 unsigned finalSilence;
00605 unsigned silenceRun;
00606
00607
00608 PMutex queueMutex;
00609 PVXMLQueue playQueue;
00610 PVXMLPlayable * currentPlayItem;
00611
00612 PBoolean paused;
00613 PTimer m_silenceTimer;
00614 int totalData;
00615
00616
00617
00618 PString channelName;
00619 };
00620
00621
00623
00624
00625 #endif // P_VXML
00626
00627 #endif // PTLIB_VXML_H
00628
00629
00630