PTLib  Version 2.10.4
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: 26933 $
00025  * $Author: rjongbloed $
00026  * $Date: 2012-02-02 21:17:20 -0600 (Thu, 02 Feb 2012) $
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/pfactory.h>
00042 #include <ptlib/pipechan.h>
00043 #include <ptclib/delaychan.h>
00044 #include <ptclib/pwavfile.h>
00045 #include <ptclib/ptts.h>
00046 #include <ptclib/url.h>
00047 
00048 #include <queue>
00049 
00050 
00051 class PVXMLSession;
00052 class PVXMLDialog;
00053 class PVXMLSession;
00054 
00055 // these are the same strings as the Opal equivalents, but as this is PWLib, we can't use Opal contants
00056 #define VXML_PCM16         "PCM-16"
00057 #define VXML_G7231         "G.723.1"
00058 #define VXML_G729          "G.729"
00059 
00060 
00062 
00063 class PVXMLGrammar : public PObject
00064 {
00065   PCLASSINFO(PVXMLGrammar, PObject);
00066   public:
00067     PVXMLGrammar(PVXMLSession & session, PXMLElement & field);
00068 
00069     virtual void OnUserInput(const char ch) = 0;
00070     virtual void Start();
00071     virtual bool Process();
00072 
00073     enum GrammarState {
00074       Idle,         
00075       Started,      
00076       Filled,       
00077       NoInput,      
00078       NoMatch,      
00079       Help          
00080     };
00081 
00082     GrammarState GetState() const { return m_state; }
00083 
00084   protected:
00085     PDECLARE_NOTIFIER(PTimer, PVXMLGrammar, OnTimeout);
00086 
00087     PVXMLSession & m_session;
00088     PXMLElement  & m_field;
00089     PString        m_value;
00090     GrammarState   m_state;
00091     PTimer         m_timer;
00092     PMutex         m_mutex;
00093 };
00094 
00095 
00097 
00098 class PVXMLMenuGrammar : public PVXMLGrammar
00099 {
00100   PCLASSINFO(PVXMLMenuGrammar, PVXMLGrammar);
00101   public:
00102     PVXMLMenuGrammar(PVXMLSession & session, PXMLElement & field);
00103     virtual void OnUserInput(const char ch);
00104     virtual bool Process();
00105 };
00106 
00107 
00109 
00110 class PVXMLDigitsGrammar : public PVXMLGrammar
00111 {
00112   PCLASSINFO(PVXMLDigitsGrammar, PVXMLGrammar);
00113   public:
00114     PVXMLDigitsGrammar(
00115       PVXMLSession & session,
00116       PXMLElement & field,
00117       PINDEX minDigits,
00118       PINDEX maxDigits,
00119       PString terminators
00120     );
00121 
00122     virtual void OnUserInput(const char ch);
00123 
00124   protected:
00125     PINDEX  m_minDigits;
00126     PINDEX  m_maxDigits;
00127     PString m_terminators;
00128 };
00129 
00130 
00132 
00133 class PVXMLCache : public PMutex
00134 {
00135   public:
00136     PVXMLCache(const PDirectory & directory);
00137 
00138     PFilePath CreateFilename(const PString & prefix, const PString & key, const PString & fileType);
00139 
00140     void Put(const PString & prefix,
00141              const PString & key, 
00142              const PString & fileType, 
00143              const PString & contentType,       
00144            const PFilePath & fn, 
00145                  PFilePath & dataFn);
00146 
00147     PBoolean Get(const PString & prefix,
00148              const PString & key, 
00149              const PString & fileType, 
00150                    PString & contentType,       
00151                  PFilePath & fn);
00152 
00153     PFilePath GetCacheDir() const
00154     { return directory; }
00155 
00156     PFilePath GetRandomFilename(const PString & prefix, const PString & fileType);
00157 
00158     static PVXMLCache & GetResourceCache();
00159 
00160   protected:
00161     PDirectory directory;
00162 };
00163 
00165 
00166 class PVXMLChannel;
00167 
00168 class PVXMLSession : public PIndirectChannel
00169 {
00170   PCLASSINFO(PVXMLSession, PIndirectChannel);
00171   public:
00172     PVXMLSession(PTextToSpeech * tts = NULL, PBoolean autoDelete = false);
00173     virtual ~PVXMLSession();
00174 
00175     // new functions
00176     PTextToSpeech * SetTextToSpeech(PTextToSpeech * tts, PBoolean autoDelete = false);
00177     PTextToSpeech * SetTextToSpeech(const PString & ttsName);
00178     PTextToSpeech * GetTextToSpeech() const { return m_textToSpeech; }
00179 
00180     virtual PBoolean Load(const PString & source);
00181     virtual PBoolean LoadFile(const PFilePath & file, const PString & firstForm = PString::Empty());
00182     virtual PBoolean LoadURL(const PURL & url);
00183     virtual PBoolean LoadVXML(const PString & xml, const PString & firstForm = PString::Empty());
00184     virtual PBoolean IsLoaded() const { return m_xml.IsLoaded(); }
00185 
00186     virtual PBoolean Open(const PString & mediaFormat);
00187     virtual PBoolean Close();
00188 
00189     virtual PBoolean Execute();
00190 
00191     PVXMLChannel * GetAndLockVXMLChannel();
00192     void UnLockVXMLChannel() { m_sessionMutex.Signal(); }
00193     PMutex & GetSessionMutex() { return m_sessionMutex; }
00194 
00195     virtual PBoolean LoadGrammar(PVXMLGrammar * grammar);
00196 
00197     virtual PBoolean PlayText(const PString & text, PTextToSpeech::TextType type = PTextToSpeech::Default, PINDEX repeat = 1, PINDEX delay = 0);
00198     PBoolean ConvertTextToFilenameList(const PString & text, PTextToSpeech::TextType type, PStringArray & list, PBoolean useCacheing);
00199 
00200     virtual PBoolean PlayFile(const PString & fn, PINDEX repeat = 1, PINDEX delay = 0, PBoolean autoDelete = false);
00201     virtual PBoolean PlayData(const PBYTEArray & data, PINDEX repeat = 1, PINDEX delay = 0);
00202     virtual PBoolean PlayCommand(const PString & data, PINDEX repeat = 1, PINDEX delay = 0);
00203     virtual PBoolean PlayResource(const PURL & url, PINDEX repeat = 1, PINDEX delay = 0);
00204     virtual PBoolean PlayTone(const PString & toneSpec, PINDEX repeat = 1, PINDEX delay = 0);
00205     virtual PBoolean PlayElement(PXMLElement & element);
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 
00219     virtual void OnUserInput(const PString & str);
00220 
00221     PString GetXMLError() const;
00222 
00223     virtual void OnEndDialog();
00224     virtual void OnEndSession();
00225 
00226     enum TransferType {
00227       BridgedTransfer,
00228       BlindTransfer,
00229       ConsultationTransfer
00230     };
00231     virtual bool OnTransfer(const PString & /*destination*/, TransferType /*type*/) { return false; }
00232     void SetTransferComplete(bool state);
00233 
00234     const PStringToString & GetVariables() { return m_variables; }
00235     virtual PCaselessString GetVar(const PString & str) const;
00236     virtual void SetVar(const PString & ostr, const PString & val);
00237     virtual PString EvaluateExpr(const PString & oexpr);
00238 
00239     static PTimeInterval StringToTime(const PString & str);
00240 
00241     virtual PBoolean RetreiveResource(const PURL & url, PString & contentType, PFilePath & fn, PBoolean useCache = true);
00242 
00243     PDECLARE_NOTIFIER(PThread, PVXMLSession, VXMLExecute);
00244 
00245     bool SetCurrentForm(const PString & id, bool fullURI);
00246     bool GoToEventHandler(PXMLElement & element, const PString & eventName);
00247 
00248     // overrides from VXMLChannelInterface
00249     virtual void OnEndRecording();
00250     virtual void Trigger();
00251 
00252 
00253     virtual PBoolean TraverseAudio(PXMLElement & element);
00254     virtual PBoolean TraverseBreak(PXMLElement & element);
00255     virtual PBoolean TraverseValue(PXMLElement & element);
00256     virtual PBoolean TraverseSayAs(PXMLElement & element);
00257     virtual PBoolean TraverseGoto(PXMLElement & element);
00258     virtual PBoolean TraverseGrammar(PXMLElement & element);
00259     virtual PBoolean TraverseRecord(PXMLElement & element);
00260     virtual PBoolean TraversedRecord(PXMLElement & element);
00261     virtual PBoolean TraverseIf(PXMLElement & element);
00262     virtual PBoolean TraverseExit(PXMLElement & element);
00263     virtual PBoolean TraverseVar(PXMLElement & element);
00264     virtual PBoolean TraverseSubmit(PXMLElement & element);
00265     virtual PBoolean TraverseMenu(PXMLElement & element);
00266     virtual PBoolean TraversedMenu(PXMLElement & element);
00267     virtual PBoolean TraverseChoice(PXMLElement & element);
00268     virtual PBoolean TraverseProperty(PXMLElement & element);
00269     virtual PBoolean TraverseDisconnect(PXMLElement & element);
00270     virtual PBoolean TraverseForm(PXMLElement & element);
00271     virtual PBoolean TraversedForm(PXMLElement & element);
00272     virtual PBoolean TraversePrompt(PXMLElement & element);
00273     virtual PBoolean TraverseField(PXMLElement & element);
00274     virtual PBoolean TraversedField(PXMLElement & element);
00275     virtual PBoolean TraverseFilled(PXMLElement & element);
00276     virtual PBoolean TraverseNoInput(PXMLElement & element);
00277     virtual PBoolean TraverseNoMatch(PXMLElement & element);
00278     virtual PBoolean TraverseError(PXMLElement & element);
00279     virtual PBoolean TraverseCatch(PXMLElement & element);
00280     virtual PBoolean TraverseTransfer(PXMLElement & element);
00281     virtual PBoolean TraversedTransfer(PXMLElement & element);
00282 
00283     __inline PVXMLChannel * GetVXMLChannel() const { return (PVXMLChannel *)readChannel; }
00284 
00285   protected:
00286     virtual bool ProcessNode();
00287     virtual bool ProcessEvents();
00288     virtual bool ProcessGrammar();
00289     virtual bool NextNode(bool skipChildren);
00290 
00291     void SayAs(const PString & className, const PString & text);
00292     void SayAs(const PString & className, const PString & text, const PString & voice);
00293 
00294     PURL NormaliseResourceName(const PString & src);
00295 
00296     PMutex           m_sessionMutex;
00297 
00298     PURL             m_rootURL;
00299     PXML             m_xml;
00300 
00301     PTextToSpeech *  m_textToSpeech;
00302     bool             m_autoDeleteTextToSpeech;
00303 
00304     PThread     *    m_vxmlThread;
00305     bool             m_abortVXML;
00306     PSyncPoint       m_waitForEvent;
00307     PXMLObject  *    m_currentNode;
00308     bool             m_xmlChanged;
00309     bool             m_speakNodeData;
00310 
00311     PVXMLGrammar *   m_grammar;
00312     char             m_defaultMenuDTMF;
00313 
00314     PStringToString  m_variables;
00315     PString          m_variableScope;
00316 
00317     std::queue<char> m_userInputQueue;
00318     PMutex           m_userInputMutex;
00319 
00320     enum {
00321       NotRecording,
00322       RecordingInProgress,
00323       RecordingComplete
00324     }    m_recordingStatus;
00325     bool m_recordStopOnDTMF;
00326 
00327     enum {
00328       NotTransfering,
00329       TransferInProgress,
00330       TransferFailed,
00331       TransferSuccessful
00332     }     m_transferStatus;
00333     PTime m_transferStartTime;
00334 };
00335 
00336 
00338 
00339 class PVXMLRecordable : public PObject
00340 {
00341   PCLASSINFO(PVXMLRecordable, PObject);
00342   public:
00343     PVXMLRecordable();
00344 
00345     virtual PBoolean Open(const PString & arg) = 0;
00346 
00347     virtual bool OnStart(PVXMLChannel & incomingChannel) = 0;
00348     virtual void OnStop() { }
00349 
00350     virtual PBoolean OnFrame(PBoolean /*isSilence*/) { return false; }
00351 
00352     void SetFinalSilence(unsigned v)
00353     { m_finalSilence = v > 0 ? v : 60000; }
00354 
00355     unsigned GetFinalSilence()
00356     { return m_finalSilence; }
00357 
00358     void SetMaxDuration(unsigned v)
00359     { m_maxDuration = v > 0 ? v : 86400000; }
00360 
00361     unsigned GetMaxDuration()
00362     { return m_maxDuration; }
00363 
00364   protected:
00365     PSimpleTimer m_silenceTimer;
00366     PSimpleTimer m_recordTimer;
00367     unsigned     m_finalSilence;
00368     unsigned     m_maxDuration;
00369 };
00370 
00372 
00373 class PVXMLRecordableFilename : public PVXMLRecordable
00374 {
00375   PCLASSINFO(PVXMLRecordableFilename, PVXMLRecordable);
00376   public:
00377     PBoolean Open(const PString & arg);
00378     bool OnStart(PVXMLChannel & incomingChannel);
00379     PBoolean OnFrame(PBoolean isSilence);
00380 
00381   protected:
00382     PFilePath m_fileName;
00383 };
00384 
00386 
00387 class PVXMLPlayable : public PObject
00388 {
00389   PCLASSINFO(PVXMLPlayable, PObject);
00390   public:
00391     PVXMLPlayable();
00392 
00393     virtual PBoolean Open(PVXMLChannel & chan, const PString & arg, PINDEX delay, PINDEX repeat, PBoolean autoDelete);
00394 
00395     virtual bool OnStart() = 0;
00396     virtual bool OnRepeat();
00397     virtual bool OnDelay();
00398     virtual void OnStop();
00399 
00400     virtual void SetRepeat(PINDEX v) 
00401     { m_repeat = v; }
00402 
00403     virtual PINDEX GetRepeat() const
00404     { return m_repeat; }
00405 
00406     virtual PINDEX GetDelay() const
00407     { return m_delay; }
00408 
00409     void SetFormat(const PString & fmt)
00410     { m_format = fmt; }
00411 
00412     void SetSampleFrequency(unsigned rate)
00413     { m_sampleFrequency = rate; }
00414 
00415     friend class PVXMLChannel;
00416 
00417   protected:
00418     PVXMLChannel * m_vxmlChannel;
00419     PChannel * m_subChannel;
00420     PINDEX   m_repeat;
00421     PINDEX   m_delay;
00422     PString  m_format;
00423     unsigned m_sampleFrequency;
00424     bool     m_autoDelete;
00425     bool     m_delayDone; // very tacky flag used to indicate when the post-play delay has been done
00426 };
00427 
00429 
00430 class PVXMLPlayableStop : public PVXMLPlayable
00431 {
00432   PCLASSINFO(PVXMLPlayableStop, PVXMLPlayable);
00433   public:
00434     virtual bool OnStart();
00435 };
00436 
00438 
00439 class PVXMLPlayableURL : public PVXMLPlayable
00440 {
00441   PCLASSINFO(PVXMLPlayableURL, PVXMLPlayable);
00442   public:
00443     virtual PBoolean Open(PVXMLChannel & chan, const PString & arg, PINDEX delay, PINDEX repeat, PBoolean autoDelete);
00444     virtual bool OnStart();
00445   protected:
00446     PURL m_url;
00447 };
00448 
00450 
00451 class PVXMLPlayableData : public PVXMLPlayable
00452 {
00453   PCLASSINFO(PVXMLPlayableData, PVXMLPlayable);
00454   public:
00455     virtual PBoolean Open(PVXMLChannel & chan, const PString & arg, PINDEX delay, PINDEX repeat, PBoolean autoDelete);
00456     void SetData(const PBYTEArray & data);
00457     virtual bool OnStart();
00458     virtual bool OnRepeat();
00459   protected:
00460     PBYTEArray m_data;
00461 };
00462 
00464 
00465 #include <ptclib/dtmf.h>
00466 
00467 class PVXMLPlayableTone : public PVXMLPlayableData
00468 {
00469   PCLASSINFO(PVXMLPlayableTone, PVXMLPlayableData);
00470   public:
00471     virtual PBoolean Open(PVXMLChannel & chan, const PString & arg, PINDEX delay, PINDEX repeat, PBoolean autoDelete);
00472   protected:
00473     PTones m_tones;
00474 };
00475 
00477 
00478 class PVXMLPlayableCommand : public PVXMLPlayable
00479 {
00480   PCLASSINFO(PVXMLPlayableCommand, PVXMLPlayable);
00481   public:
00482     virtual PBoolean Open(PVXMLChannel & chan, const PString & arg, PINDEX delay, PINDEX repeat, PBoolean autoDelete);
00483     virtual bool OnStart();
00484     virtual void OnStop();
00485 
00486   protected:
00487     PString m_command;
00488 };
00489 
00491 
00492 class PVXMLPlayableFile : public PVXMLPlayable
00493 {
00494   PCLASSINFO(PVXMLPlayableFile, PVXMLPlayable);
00495   public:
00496     virtual PBoolean Open(PVXMLChannel & chan, const PString & arg, PINDEX delay, PINDEX repeat, PBoolean autoDelete);
00497     virtual bool OnStart();
00498     virtual bool OnRepeat();
00499     virtual void OnStop();
00500   protected:
00501     PFilePath m_filePath;
00502 };
00503 
00505 
00506 class PVXMLPlayableFileList : public PVXMLPlayableFile
00507 {
00508   PCLASSINFO(PVXMLPlayableFileList, PVXMLPlayableFile);
00509   public:
00510     PVXMLPlayableFileList();
00511     virtual PBoolean Open(PVXMLChannel & chan, const PString & arg, PINDEX delay, PINDEX repeat, PBoolean autoDelete);
00512     virtual PBoolean Open(PVXMLChannel & chan, const PStringArray & filenames, PINDEX delay, PINDEX repeat, PBoolean autoDelete);
00513     virtual bool OnStart();
00514     virtual bool OnRepeat();
00515     virtual void OnStop();
00516   protected:
00517     PStringArray m_fileNames;
00518     PINDEX       m_currentIndex;
00519 };
00520 
00522 
00523 PQUEUE(PVXMLQueue, PVXMLPlayable);
00524 
00526 
00527 class PVXMLChannel : public PDelayChannel
00528 {
00529   PCLASSINFO(PVXMLChannel, PDelayChannel);
00530   public:
00531     PVXMLChannel(unsigned frameDelay, PINDEX frameSize);
00532     ~PVXMLChannel();
00533 
00534     virtual PBoolean Open(PVXMLSession * session);
00535 
00536     // overrides from PIndirectChannel
00537     virtual PBoolean IsOpen() const;
00538     virtual PBoolean Close();
00539     virtual PBoolean Read(void * buffer, PINDEX amount);
00540     virtual PBoolean Write(const void * buf, PINDEX len);
00541 
00542     // new functions
00543     virtual PWAVFile * CreateWAVFile(const PFilePath & fn, PBoolean recording = false);
00544 
00545     const PString & GetMediaFormat() const { return mediaFormat; }
00546     PBoolean IsMediaPCM() const { return mediaFormat == "PCM-16"; }
00547     virtual PString AdjustWavFilename(const PString & fn);
00548 
00549     // Incoming channel functions
00550     virtual PBoolean WriteFrame(const void * buf, PINDEX len) = 0;
00551     virtual PBoolean IsSilenceFrame(const void * buf, PINDEX len) const = 0;
00552 
00553     virtual PBoolean QueueRecordable(PVXMLRecordable * newItem);
00554 
00555     PBoolean StartRecording(const PFilePath & fn, unsigned finalSilence = 3000, unsigned maxDuration = 30000);
00556     PBoolean EndRecording();
00557     PBoolean IsRecording() const { return m_recordable != NULL; }
00558 
00559     // Outgoing channel functions
00560     virtual PBoolean ReadFrame(void * buffer, PINDEX amount) = 0;
00561     virtual PINDEX CreateSilenceFrame(void * buffer, PINDEX amount) = 0;
00562     virtual void GetBeepData(PBYTEArray &, unsigned) { }
00563 
00564     virtual PBoolean QueueResource(const PURL & url, PINDEX repeat= 1, PINDEX delay = 0);
00565 
00566     virtual PBoolean QueuePlayable(const PString & type, const PString & str, PINDEX repeat = 1, PINDEX delay = 0, PBoolean autoDelete = false);
00567     virtual PBoolean QueuePlayable(PVXMLPlayable * newItem);
00568     virtual PBoolean QueueData(const PBYTEArray & data, PINDEX repeat = 1, PINDEX delay = 0);
00569 
00570     virtual PBoolean QueueFile(const PString & fn, PINDEX repeat = 1, PINDEX delay = 0, PBoolean autoDelete = false)
00571     { return QueuePlayable("File", fn, repeat, delay, autoDelete); }
00572 
00573     virtual PBoolean QueueCommand(const PString & cmd, PINDEX repeat = 1, PINDEX delay = 0)
00574     { return QueuePlayable("Command", cmd, repeat, delay, true); }
00575 
00576     virtual void FlushQueue();
00577     virtual PBoolean IsPlaying() const { return m_currentPlayItem != NULL || m_playQueue.GetSize() > 0; }
00578 
00579     void SetPause(PBoolean pause) { m_paused = pause; }
00580 
00581     unsigned GetSampleFrequency() const { return m_sampleFrequency; }
00582 
00583     void SetSilence(unsigned msecs);
00584 
00585   protected:
00586     PVXMLSession * m_vxmlSession;
00587 
00588     unsigned m_sampleFrequency;
00589     PString mediaFormat;
00590     PString wavFilePrefix;
00591 
00592     PMutex   m_channelWriteMutex;
00593     PMutex   m_channelReadMutex;
00594     bool     m_closed;
00595     bool     m_paused;
00596     PINDEX   m_totalData;
00597 
00598     // Incoming audio variables
00599     PVXMLRecordable * m_recordable;
00600     unsigned          m_finalSilence;
00601     unsigned          m_silenceRun;
00602 
00603     // Outgoing audio variables
00604     PVXMLQueue      m_playQueue;
00605     PVXMLPlayable * m_currentPlayItem;
00606     PSimpleTimer    m_silenceTimer;
00607 };
00608 
00609 
00611 
00612 class PVXMLNodeHandler : public PObject
00613 {
00614     PCLASSINFO(PVXMLNodeHandler, PObject);
00615   public:
00616     // Return true for process node, false to skip and move to next sibling
00617     virtual bool Start(PVXMLSession & /*session*/, PXMLElement & /*node*/) const { return true; }
00618 
00619     // Return true to move to next sibling, false to stay at this node.
00620     virtual bool Finish(PVXMLSession & /*session*/, PXMLElement & /*node*/) const { return true; }
00621 };
00622 
00623 
00624 typedef PFactory<PVXMLNodeHandler, PCaselessString> PVXMLNodeFactory;
00625 
00626 
00627 #endif // P_VXML
00628 
00629 #endif // PTLIB_VXML_H
00630 
00631 
00632 // End of file ////////////////////////////////////////////////////////////////
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines