vxml.h

Go to the documentation of this file.
00001 /*
00002  * vxml.h
00003  *
00004  * VXML engine for pwlib library
00005  *
00006  * Copyright (C) 2002 Equivalence Pty. Ltd.
00007  *
00008  * The contents of this file are subject to the Mozilla Public License
00009  * Version 1.0 (the "License"); you may not use this file except in
00010  * compliance with the License. You may obtain a copy of the License at
00011  * http://www.mozilla.org/MPL/
00012  *
00013  * Software distributed under the License is distributed on an "AS IS"
00014  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
00015  * the License for the specific language governing rights and limitations
00016  * under the License.
00017  *
00018  * The Original Code is Portable Windows Library.
00019  *
00020  * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
00021  *
00022  * Contributor(s): ______________________________________.
00023  *
00024  * $Revision: 23021 $
00025  * $Author: rjongbloed $
00026  * $Date: 2009-07-01 08:40:15 +0000 (Wed, 01 Jul 2009) $
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 // these are the same strings as the Opal equivalents, but as this is PWLib, we can't use Opal contants
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 /*ch*/) { 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     // new functions
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     //virtual PBoolean PlayMedia(const PURL & url, PINDEX repeat = 1, PINDEX delay = 0);
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 & /*destination*/, bool /*bridged*/) { }
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     // overrides from VXMLChannelInterface
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;                 // PTrue if waiting for recognition events
00287     int timeout;                    // timeout in msecs for the current recognition
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 /*isSilence*/) { 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 & /*chan*/, 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 & /*outgoingChannel*/)
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; // very tacky flag used to indicate when the post-play delay has been done
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     // overrides from PIndirectChannel
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     // new functions
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     // Incoming channel functions
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     // Outgoing channel functions
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     // Incoming audio variables
00611     PBoolean recording;
00612     PVXMLRecordable * recordable;
00613     unsigned finalSilence;
00614     unsigned silenceRun;
00615 
00616     // Outgoing audio variables
00617     PMutex queueMutex;
00618     PVXMLQueue playQueue;
00619     PVXMLPlayable * currentPlayItem;
00620 
00621     PBoolean paused;
00622     int silentCount;
00623     int totalData;
00624     PTimer delayTimer;
00625 
00626     // "channelname" (which is the name of the <record> tag) so
00627     // results can be saved in vxml session variable
00628     PString channelName;
00629 };
00630 
00631 
00633 
00634 
00635 #endif // P_VXML
00636 
00637 #endif // PTLIB_VXML_H
00638 
00639 
00640 // End of file ////////////////////////////////////////////////////////////////

Generated on Mon Aug 3 20:41:51 2009 for PTLib by  doxygen 1.5.1