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: 20385 $
00025  * $Author: rjongbloed $
00026  * $Date: 2008-06-04 10:40:38 +0000 (Wed, 04 Jun 2008) $
00027  */
00028 
00029 #ifndef _VXML_H
00030 #define _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 = PFalse);
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 
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     // overrides from VXMLChannelInterface
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     //friend class PVXMLChannel;
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 
00320   private:
00321     void      ExecuteDialog();
00322 
00323     PString       callingCallToken;
00324     PSyncPoint    answerSync;
00325     PString       grammarResult;
00326     PString       eventName;
00327     PINDEX        defaultDTMF;
00328 };
00329 
00330 
00332 
00333 class PVXMLRecordable : public PObject
00334 {
00335   PCLASSINFO(PVXMLRecordable, PObject);
00336   public:
00337     PVXMLRecordable()
00338     { consecutiveSilence = 0; finalSilence = 3000; maxDuration = 30000; }
00339 
00340     virtual PBoolean Open(const PString & _arg) = 0;
00341 
00342     virtual void Record(PVXMLChannel & incomingChannel) = 0;
00343 
00344     virtual void OnStart() { }
00345 
00346     virtual PBoolean OnFrame(PBoolean /*isSilence*/) { return PFalse; }
00347 
00348     virtual void OnStop() { }
00349 
00350     void SetFinalSilence(unsigned v)
00351     { finalSilence = v; }
00352 
00353     unsigned GetFinalSilence()
00354     { return finalSilence; }
00355 
00356     void SetMaxDuration(unsigned v)
00357     { maxDuration = v; }
00358 
00359     unsigned GetMaxDuration()
00360     { return maxDuration; }
00361 
00362   protected:
00363     PTime silenceStart;
00364     PTime recordStart;
00365     unsigned finalSilence;
00366     unsigned maxDuration;
00367     unsigned consecutiveSilence;
00368 };
00369 
00371 
00372 class PVXMLPlayable : public PObject
00373 {
00374   PCLASSINFO(PVXMLPlayable, PObject);
00375   public:
00376     PVXMLPlayable()
00377     { repeat = 1; delay = 0; sampleFrequency = 8000; autoDelete = PFalse; delayDone = PFalse; }
00378 
00379     virtual PBoolean Open(PVXMLChannel & /*chan*/, PINDEX _delay, PINDEX _repeat, PBoolean _autoDelete);
00380 
00381     virtual PBoolean Open(PVXMLChannel & chan, const PString & _arg, PINDEX _delay, PINDEX _repeat, PBoolean v);
00382 
00383     virtual void Play(PVXMLChannel & outgoingChannel) = 0;
00384 
00385     virtual void OnRepeat(PVXMLChannel & /*outgoingChannel*/)
00386     { }
00387 
00388     virtual void OnStart() { }
00389 
00390     virtual void OnStop() { }
00391 
00392     virtual void SetRepeat(PINDEX v) 
00393     { repeat = v; }
00394 
00395     virtual PINDEX GetRepeat() const
00396     { return repeat; }
00397 
00398     virtual PINDEX GetDelay() const
00399     { return delay; }
00400 
00401     void SetFormat(const PString & _fmt)
00402     { format = _fmt; }
00403 
00404     void SetSampleFrequency(unsigned _rate)
00405     { sampleFrequency = _rate; }
00406 
00407     virtual PBoolean ReadFrame(PVXMLChannel & channel, void * buf, PINDEX len);
00408 
00409     virtual PBoolean Rewind(PChannel *) 
00410     { return PFalse; }
00411 
00412     friend class PVXMLChannel;
00413 
00414   protected:
00415     PString arg;
00416     PINDEX repeat;
00417     PINDEX delay;
00418     PString format;
00419     unsigned sampleFrequency;
00420     PBoolean autoDelete;
00421     PBoolean delayDone; // very tacky flag used to indicate when the post-play delay has been done
00422 };
00423 
00425 
00426 class PVXMLPlayableStop : public PVXMLPlayable
00427 {
00428   PCLASSINFO(PVXMLPlayableStop, PVXMLPlayable);
00429   public:
00430     virtual void Play(PVXMLChannel & outgoingChannel);
00431     virtual PBoolean ReadFrame(PVXMLChannel & channel, void *, PINDEX);
00432 };
00433 
00435 
00436 class PVXMLPlayableURL : public PVXMLPlayable
00437 {
00438   PCLASSINFO(PVXMLPlayableURL, PVXMLPlayable);
00439   public:
00440     PBoolean Open(PVXMLChannel & chan, const PString & _url, PINDEX _delay, PINDEX _repeat, PBoolean v);
00441     void Play(PVXMLChannel & outgoingChannel);
00442   protected:
00443     PURL url;
00444 };
00445 
00447 
00448 class PVXMLPlayableData : public PVXMLPlayable
00449 {
00450   PCLASSINFO(PVXMLPlayableData, PVXMLPlayable);
00451   public:
00452     PBoolean Open(PVXMLChannel & chan, const PString & /*_fn*/, PINDEX _delay, PINDEX _repeat, PBoolean v);
00453     void SetData(const PBYTEArray & _data);
00454     void Play(PVXMLChannel & outgoingChannel);
00455     PBoolean Rewind(PChannel * chan);
00456   protected:
00457     PBYTEArray data;
00458 };
00459 
00461 
00462 #include <ptclib/dtmf.h>
00463 
00464 class PVXMLPlayableTone : public PVXMLPlayableData
00465 {
00466   PCLASSINFO(PVXMLPlayableTone, PVXMLPlayableData);
00467   public:
00468     PBoolean Open(PVXMLChannel & chan, const PString & toneSpec, PINDEX _delay, PINDEX _repeat, PBoolean v);
00469   protected:
00470     PTones tones;
00471 };
00472 
00474 
00475 class PVXMLPlayableCommand : public PVXMLPlayable
00476 {
00477   PCLASSINFO(PVXMLPlayableCommand, PVXMLPlayable);
00478   public:
00479     PVXMLPlayableCommand();
00480     void Play(PVXMLChannel & outgoingChannel);
00481     void OnStop();
00482 
00483   protected:
00484     PPipeChannel * pipeCmd;
00485 };
00486 
00488 
00489 class PVXMLPlayableFilename : public PVXMLPlayable
00490 {
00491   PCLASSINFO(PVXMLPlayableFilename, PVXMLPlayable);
00492   public:
00493     PBoolean Open(PVXMLChannel & chan, const PString & _fn, PINDEX _delay, PINDEX _repeat, PBoolean _autoDelete);
00494     void Play(PVXMLChannel & outgoingChannel);
00495     void OnStop();
00496     virtual PBoolean Rewind(PChannel * chan);
00497   protected:
00498     PFilePath fn;
00499 };
00500 
00502 
00503 class PVXMLPlayableFilenameList : public PVXMLPlayable
00504 {
00505   PCLASSINFO(PVXMLPlayableFilenameList, PVXMLPlayable);
00506   public:
00507     PBoolean Open(PVXMLChannel & chan, const PStringArray & _filenames, PINDEX _delay, PINDEX _repeat, PBoolean _autoDelete);
00508     void Play(PVXMLChannel & outgoingChannel)
00509     { OnRepeat(outgoingChannel); }
00510     void OnRepeat(PVXMLChannel & outgoingChannel);
00511     void OnStop();
00512   protected:
00513     PINDEX currentIndex;
00514     PStringArray filenames;
00515 };
00516 
00518 
00519 class PVXMLRecordableFilename : public PVXMLRecordable
00520 {
00521   PCLASSINFO(PVXMLRecordableFilename, PVXMLRecordable);
00522   public:
00523     PBoolean Open(const PString & _arg);
00524     void Record(PVXMLChannel & incomingChannel);
00525     PBoolean OnFrame(PBoolean isSilence);
00526 
00527   protected:
00528     PFilePath fn;
00529 };
00530 
00532 
00533 PQUEUE(PVXMLQueue, PVXMLPlayable);
00534 
00536 
00537 class PVXMLChannel : public PDelayChannel
00538 {
00539   PCLASSINFO(PVXMLChannel, PDelayChannel);
00540   public:
00541     PVXMLChannel(unsigned frameDelay, PINDEX frameSize);
00542     ~PVXMLChannel();
00543 
00544     virtual PBoolean Open(PVXMLChannelInterface * _vxml);
00545 
00546     // overrides from PIndirectChannel
00547     virtual PBoolean IsOpen() const;
00548     virtual PBoolean Close();
00549     virtual PBoolean Read(void * buffer, PINDEX amount);
00550     virtual PBoolean Write(const void * buf, PINDEX len);
00551 
00552     // new functions
00553     virtual PWAVFile * CreateWAVFile(const PFilePath & fn, PBoolean recording = PFalse);
00554 
00555     const PString & GetMediaFormat() const { return mediaFormat; }
00556     PBoolean IsMediaPCM() const { return mediaFormat == "PCM-16"; }
00557     virtual PString AdjustWavFilename(const PString & fn);
00558 
00559     // Incoming channel functions
00560     virtual PBoolean WriteFrame(const void * buf, PINDEX len) = 0;
00561     virtual PBoolean IsSilenceFrame(const void * buf, PINDEX len) const = 0;
00562 
00563     virtual PBoolean QueueRecordable(PVXMLRecordable * newItem);
00564 
00565     PBoolean StartRecording(const PFilePath & fn, unsigned finalSilence = 3000, unsigned maxDuration = 30000);
00566     PBoolean EndRecording();
00567     PBoolean IsRecording() const { return recording; }
00568 
00569     // Outgoing channel functions
00570     virtual PBoolean ReadFrame(void * buffer, PINDEX amount) = 0;
00571     virtual PINDEX CreateSilenceFrame(void * buffer, PINDEX amount) = 0;
00572     virtual void GetBeepData(PBYTEArray &, unsigned) { }
00573 
00574     virtual PBoolean QueueResource(const PURL & url, PINDEX repeat= 1, PINDEX delay = 0);
00575 
00576     virtual PBoolean QueuePlayable(const PString & type, const PString & str, PINDEX repeat = 1, PINDEX delay = 0, PBoolean autoDelete = PFalse);
00577     virtual PBoolean QueuePlayable(PVXMLPlayable * newItem);
00578     virtual PBoolean QueueData(const PBYTEArray & data, PINDEX repeat = 1, PINDEX delay = 0);
00579 
00580     virtual PBoolean QueueFile(const PString & fn, PINDEX repeat = 1, PINDEX delay = 0, PBoolean autoDelete = PFalse)
00581     { return QueuePlayable("File", fn, repeat, delay, autoDelete); }
00582 
00583     virtual PBoolean QueueCommand(const PString & cmd, PINDEX repeat = 1, PINDEX delay = 0)
00584     { return QueuePlayable("Command", cmd, repeat, delay, PTrue); }
00585 
00586     virtual void FlushQueue();
00587     virtual PBoolean IsPlaying() const   { return (playQueue.GetSize() > 0) || playing ; }
00588 
00589     void SetPause(PBoolean _pause) { paused = _pause; }
00590 
00591     void SetName(const PString & name) { channelName = name; }
00592 
00593     unsigned GetSampleFrequency() const
00594     { return sampleFrequency; }
00595 
00596           void SetSilentCount(int v) { silentCount = v; }
00597 
00598   protected:
00599     PVXMLChannelInterface * vxmlInterface;
00600 
00601     unsigned sampleFrequency;
00602     PString mediaFormat;
00603     PString wavFilePrefix;
00604 
00605     PMutex channelWriteMutex;
00606     PMutex channelReadMutex;
00607     PBoolean closed;
00608 
00609     // Incoming audio variables
00610     PBoolean recording;
00611     PVXMLRecordable * recordable;
00612     unsigned finalSilence;
00613     unsigned silenceRun;
00614 
00615     // Outgoing audio variables
00616     PBoolean playing;
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 // _VXML_H
00638 
00639 
00640 // End of file ////////////////////////////////////////////////////////////////

Generated on Mon Sep 15 01:21:35 2008 for PTLib by  doxygen 1.5.1