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: 24254 $
00025  * $Author: rjongbloed $
00026  * $Date: 2010-04-21 03:08:03 -0500 (Wed, 21 Apr 2010) $
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 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     // new functions
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     //virtual PBoolean PlayMedia(const PURL & url, PINDEX repeat = 1, PINDEX delay = 0);
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 & /*destination*/, bool /*bridged*/) { }
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     // overrides from VXMLChannelInterface
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;                 // true if waiting for recognition events
00282     int timeout;                    // timeout in msecs for the current recognition
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 /*isSilence*/) { 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 & /*chan*/, 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 & /*outgoingChannel*/)
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; // very tacky flag used to indicate when the post-play delay has been done
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     // overrides from PIndirectChannel
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     // new functions
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     // Incoming channel functions
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     // Outgoing channel functions
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     // Incoming audio variables
00602     PBoolean recording;
00603     PVXMLRecordable * recordable;
00604     unsigned finalSilence;
00605     unsigned silenceRun;
00606 
00607     // Outgoing audio variables
00608     PMutex queueMutex;
00609     PVXMLQueue playQueue;
00610     PVXMLPlayable * currentPlayItem;
00611 
00612     PBoolean paused;
00613     PTimer   m_silenceTimer;
00614     int totalData;
00615 
00616     // "channelname" (which is the name of the <record> tag) so
00617     // results can be saved in vxml session variable
00618     PString channelName;
00619 };
00620 
00621 
00623 
00624 
00625 #endif // P_VXML
00626 
00627 #endif // PTLIB_VXML_H
00628 
00629 
00630 // End of file ////////////////////////////////////////////////////////////////

Generated on Fri Oct 14 01:44:10 2011 for PTLib by  doxygen 1.4.7