PTLib  Version 2.10.10
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
vxml.h
Go to the documentation of this file.
1 /*
2  * vxml.h
3  *
4  * VXML engine for pwlib library
5  *
6  * Copyright (C) 2002 Equivalence Pty. Ltd.
7  *
8  * The contents of this file are subject to the Mozilla Public License
9  * Version 1.0 (the "License"); you may not use this file except in
10  * compliance with the License. You may obtain a copy of the License at
11  * http://www.mozilla.org/MPL/
12  *
13  * Software distributed under the License is distributed on an "AS IS"
14  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
15  * the License for the specific language governing rights and limitations
16  * under the License.
17  *
18  * The Original Code is Portable Windows Library.
19  *
20  * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
21  *
22  * Contributor(s): ______________________________________.
23  *
24  * $Revision: 29067 $
25  * $Author: rjongbloed $
26  * $Date: 2013-02-11 22:34:39 -0600 (Mon, 11 Feb 2013) $
27  */
28 
29 #ifndef PTLIB_VXML_H
30 #define PTLIB_VXML_H
31 
32 #ifdef P_USE_PRAGMA
33 #pragma interface
34 #endif
35 
36 
37 #include <ptclib/pxml.h>
38 
39 #if P_VXML
40 
41 #include <ptlib/pfactory.h>
42 #include <ptlib/pipechan.h>
43 #include <ptclib/delaychan.h>
44 #include <ptclib/pwavfile.h>
45 #include <ptclib/ptts.h>
46 #include <ptclib/url.h>
47 
48 #include <queue>
49 
50 
51 class PVXMLSession;
52 class PVXMLDialog;
53 class PVXMLSession;
54 
55 // these are the same strings as the Opal equivalents, but as this is PWLib, we can't use Opal contants
56 #define VXML_PCM16 "PCM-16"
57 #define VXML_G7231 "G.723.1"
58 #define VXML_G729 "G.729"
59 
60 
62 
63 class PVXMLGrammar : public PObject
64 {
65  PCLASSINFO(PVXMLGrammar, PObject);
66  public:
67  PVXMLGrammar(PVXMLSession & session, PXMLElement & field);
68 
69  virtual void OnUserInput(const char ch) = 0;
70  virtual void Start();
71  virtual bool Process();
72 
73  enum GrammarState {
74  Idle,
80  };
81 
82  GrammarState GetState() const { return m_state; }
83 
84  void SetTimeout(const PTimeInterval & timeout);
85 
86  protected:
88 
96 };
97 
98 
100 
102 {
103  PCLASSINFO(PVXMLMenuGrammar, PVXMLGrammar);
104  public:
105  PVXMLMenuGrammar(PVXMLSession & session, PXMLElement & field);
106  virtual void OnUserInput(const char ch);
107  virtual bool Process();
108 };
109 
110 
112 
114 {
115  PCLASSINFO(PVXMLDigitsGrammar, PVXMLGrammar);
116  public:
118  PVXMLSession & session,
119  PXMLElement & field,
120  PINDEX minDigits,
121  PINDEX maxDigits,
122  PString terminators
123  );
124 
125  virtual void OnUserInput(const char ch);
126 
127  protected:
128  PINDEX m_minDigits;
129  PINDEX m_maxDigits;
131 };
132 
133 
135 
136 class PVXMLCache : public PMutex
137 {
138  public:
140 
141  PFilePath CreateFilename(const PString & prefix, const PString & key, const PString & fileType);
142 
143  void Put(const PString & prefix,
144  const PString & key,
145  const PString & fileType,
146  const PString & contentType,
147  const PFilePath & fn,
148  PFilePath & dataFn);
149 
150  PBoolean Get(const PString & prefix,
151  const PString & key,
152  const PString & fileType,
153  PString & contentType,
154  PFilePath & fn);
155 
157  { return directory; }
158 
159  PFilePath GetRandomFilename(const PString & prefix, const PString & fileType);
160 
161  static PVXMLCache & GetResourceCache();
162 
163  protected:
165 };
166 
168 
169 class PVXMLChannel;
170 
172 {
173  PCLASSINFO(PVXMLSession, PIndirectChannel);
174  public:
175  PVXMLSession(PTextToSpeech * tts = NULL, PBoolean autoDelete = false);
176  virtual ~PVXMLSession();
177 
178  // new functions
179  PTextToSpeech * SetTextToSpeech(PTextToSpeech * tts, PBoolean autoDelete = false);
180  PTextToSpeech * SetTextToSpeech(const PString & ttsName);
181  PTextToSpeech * GetTextToSpeech() const { return m_textToSpeech; }
182 
183  virtual PBoolean Load(const PString & source);
184  virtual PBoolean LoadFile(const PFilePath & file, const PString & firstForm = PString::Empty());
185  virtual PBoolean LoadURL(const PURL & url);
186  virtual PBoolean LoadVXML(const PString & xml, const PString & firstForm = PString::Empty());
187  virtual PBoolean IsLoaded() const { return m_xml.IsLoaded(); }
188 
189  virtual PBoolean Open(const PString & mediaFormat);
190  virtual PBoolean Close();
191 
192  virtual PBoolean Execute();
193 
195  void UnLockVXMLChannel() { m_sessionMutex.Signal(); }
197 
198  virtual PBoolean LoadGrammar(PVXMLGrammar * grammar);
199 
200  virtual PBoolean PlayText(const PString & text, PTextToSpeech::TextType type = PTextToSpeech::Default, PINDEX repeat = 1, PINDEX delay = 0);
201  PBoolean ConvertTextToFilenameList(const PString & text, PTextToSpeech::TextType type, PStringArray & list, PBoolean useCacheing);
202 
203  virtual PBoolean PlayFile(const PString & fn, PINDEX repeat = 1, PINDEX delay = 0, PBoolean autoDelete = false);
204  virtual PBoolean PlayData(const PBYTEArray & data, PINDEX repeat = 1, PINDEX delay = 0);
205  virtual PBoolean PlayCommand(const PString & data, PINDEX repeat = 1, PINDEX delay = 0);
206  virtual PBoolean PlayResource(const PURL & url, PINDEX repeat = 1, PINDEX delay = 0);
207  virtual PBoolean PlayTone(const PString & toneSpec, PINDEX repeat = 1, PINDEX delay = 0);
208  virtual PBoolean PlayElement(PXMLElement & element);
209 
210  //virtual PBoolean PlayMedia(const PURL & url, PINDEX repeat = 1, PINDEX delay = 0);
211  virtual PBoolean PlaySilence(PINDEX msecs = 0);
212  virtual PBoolean PlaySilence(const PTimeInterval & timeout);
213 
214  virtual PBoolean PlayStop();
215 
216  virtual void SetPause(PBoolean pause);
217  virtual void GetBeepData(PBYTEArray & data, unsigned ms);
218 
219  virtual PBoolean StartRecording(const PFilePath & fn, PBoolean recordDTMFTerm, const PTimeInterval & recordMaxTime, const PTimeInterval & recordFinalSilence);
220  virtual PBoolean EndRecording();
221 
222  virtual void OnUserInput(const PString & str);
223 
224  PString GetXMLError() const;
225 
226  virtual void OnEndDialog();
227  virtual void OnEndSession();
228 
233  };
234  virtual bool OnTransfer(const PString & /*destination*/, TransferType /*type*/) { return false; }
235  void SetTransferComplete(bool state);
236 
238  virtual PCaselessString GetVar(const PString & str) const;
239  virtual void SetVar(const PString & ostr, const PString & val);
240  virtual PString EvaluateExpr(const PString & oexpr);
241 
242  static PTimeInterval StringToTime(const PString & str, int dflt = 0);
243 
244  virtual PBoolean RetreiveResource(const PURL & url, PString & contentType, PFilePath & fn, PBoolean useCache = true);
245 
246  PDECLARE_NOTIFIER(PThread, PVXMLSession, VXMLExecute);
247 
248  bool SetCurrentForm(const PString & id, bool fullURI);
249  bool GoToEventHandler(PXMLElement & element, const PString & eventName);
250 
251  // overrides from VXMLChannelInterface
252  virtual void OnEndRecording();
253  virtual void Trigger();
254 
255 
256  virtual PBoolean TraverseAudio(PXMLElement & element);
257  virtual PBoolean TraverseBreak(PXMLElement & element);
258  virtual PBoolean TraverseValue(PXMLElement & element);
259  virtual PBoolean TraverseSayAs(PXMLElement & element);
260  virtual PBoolean TraverseGoto(PXMLElement & element);
261  virtual PBoolean TraverseGrammar(PXMLElement & element);
262  virtual PBoolean TraverseRecord(PXMLElement & element);
263  virtual PBoolean TraversedRecord(PXMLElement & element);
264  virtual PBoolean TraverseIf(PXMLElement & element);
265  virtual PBoolean TraverseExit(PXMLElement & element);
266  virtual PBoolean TraverseVar(PXMLElement & element);
267  virtual PBoolean TraverseSubmit(PXMLElement & element);
268  virtual PBoolean TraverseMenu(PXMLElement & element);
269  virtual PBoolean TraversedMenu(PXMLElement & element);
270  virtual PBoolean TraverseChoice(PXMLElement & element);
271  virtual PBoolean TraverseProperty(PXMLElement & element);
272  virtual PBoolean TraverseDisconnect(PXMLElement & element);
273  virtual PBoolean TraverseForm(PXMLElement & element);
274  virtual PBoolean TraversedForm(PXMLElement & element);
275  virtual PBoolean TraversePrompt(PXMLElement & element);
276  virtual PBoolean TraversedPrompt(PXMLElement & element);
277  virtual PBoolean TraverseField(PXMLElement & element);
278  virtual PBoolean TraversedField(PXMLElement & element);
279  virtual PBoolean TraverseTransfer(PXMLElement & element);
280  virtual PBoolean TraversedTransfer(PXMLElement & element);
281 
282  __inline PVXMLChannel * GetVXMLChannel() const { return (PVXMLChannel *)readChannel; }
283 
284  protected:
285  virtual bool InternalLoadVXML(const PString & xml, const PString & firstForm);
286 
287  virtual bool ProcessNode();
288  virtual bool ProcessEvents();
289  virtual bool ProcessGrammar();
290  virtual bool NextNode(bool processChildren);
291 
292  void SayAs(const PString & className, const PString & text);
293  void SayAs(const PString & className, const PString & text, const PString & voice);
294 
295  PURL NormaliseResourceName(const PString & src);
296 
298 
301 
302  PTextToSpeech * m_textToSpeech;
304 
311  bool m_bargeIn;
313 
316 
319 
320  std::queue<char> m_userInputQueue;
322 
323  enum {
329 
330  enum {
337 };
338 
339 
341 
342 class PVXMLRecordable : public PObject
343 {
344  PCLASSINFO(PVXMLRecordable, PObject);
345  public:
346  PVXMLRecordable();
347 
348  virtual PBoolean Open(const PString & arg) = 0;
349 
350  virtual bool OnStart(PVXMLChannel & incomingChannel) = 0;
351  virtual void OnStop() { }
352 
353  virtual PBoolean OnFrame(PBoolean /*isSilence*/) { return false; }
354 
355  void SetFinalSilence(unsigned v)
356  { m_finalSilence = v > 0 ? v : 60000; }
357 
358  unsigned GetFinalSilence()
359  { return m_finalSilence; }
360 
361  void SetMaxDuration(unsigned v)
362  { m_maxDuration = v > 0 ? v : 86400000; }
363 
364  unsigned GetMaxDuration()
365  { return m_maxDuration; }
366 
367  protected:
370  unsigned m_finalSilence;
371  unsigned m_maxDuration;
372 };
373 
375 
377 {
379  public:
380  PBoolean Open(const PString & arg);
381  bool OnStart(PVXMLChannel & incomingChannel);
382  PBoolean OnFrame(PBoolean isSilence);
383 
384  protected:
386 };
387 
389 
390 class PVXMLPlayable : public PObject
391 {
392  PCLASSINFO(PVXMLPlayable, PObject);
393  public:
394  PVXMLPlayable();
395 
396  virtual PBoolean Open(PVXMLChannel & chan, const PString & arg, PINDEX delay, PINDEX repeat, PBoolean autoDelete);
397 
398  virtual bool OnStart() = 0;
399  virtual bool OnRepeat();
400  virtual bool OnDelay();
401  virtual void OnStop();
402 
403  virtual void SetRepeat(PINDEX v)
404  { m_repeat = v; }
405 
406  virtual PINDEX GetRepeat() const
407  { return m_repeat; }
408 
409  virtual PINDEX GetDelay() const
410  { return m_delay; }
411 
412  void SetFormat(const PString & fmt)
413  { m_format = fmt; }
414 
415  void SetSampleFrequency(unsigned rate)
416  { m_sampleFrequency = rate; }
417 
418  friend class PVXMLChannel;
419 
420  protected:
423  PINDEX m_repeat;
424  PINDEX m_delay;
428  bool m_delayDone; // very tacky flag used to indicate when the post-play delay has been done
429 };
430 
432 
434 {
435  PCLASSINFO(PVXMLPlayableStop, PVXMLPlayable);
436  public:
437  virtual bool OnStart();
438 };
439 
441 
443 {
444  PCLASSINFO(PVXMLPlayableURL, PVXMLPlayable);
445  public:
446  virtual PBoolean Open(PVXMLChannel & chan, const PString & arg, PINDEX delay, PINDEX repeat, PBoolean autoDelete);
447  virtual bool OnStart();
448  protected:
450 };
451 
453 
455 {
456  PCLASSINFO(PVXMLPlayableData, PVXMLPlayable);
457  public:
458  virtual PBoolean Open(PVXMLChannel & chan, const PString & arg, PINDEX delay, PINDEX repeat, PBoolean autoDelete);
459  void SetData(const PBYTEArray & data);
460  virtual bool OnStart();
461  virtual bool OnRepeat();
462  protected:
464 };
465 
467 
468 #include <ptclib/dtmf.h>
469 
471 {
473  public:
474  virtual PBoolean Open(PVXMLChannel & chan, const PString & arg, PINDEX delay, PINDEX repeat, PBoolean autoDelete);
475  protected:
477 };
478 
480 
482 {
483  PCLASSINFO(PVXMLPlayableCommand, PVXMLPlayable);
484  public:
485  virtual PBoolean Open(PVXMLChannel & chan, const PString & arg, PINDEX delay, PINDEX repeat, PBoolean autoDelete);
486  virtual bool OnStart();
487  virtual void OnStop();
488 
489  protected:
491 };
492 
494 
496 {
497  PCLASSINFO(PVXMLPlayableFile, PVXMLPlayable);
498  public:
499  virtual PBoolean Open(PVXMLChannel & chan, const PString & arg, PINDEX delay, PINDEX repeat, PBoolean autoDelete);
500  virtual bool OnStart();
501  virtual bool OnRepeat();
502  virtual void OnStop();
503  protected:
505 };
506 
508 
510 {
512  public:
514  virtual PBoolean Open(PVXMLChannel & chan, const PString & arg, PINDEX delay, PINDEX repeat, PBoolean autoDelete);
515  virtual PBoolean Open(PVXMLChannel & chan, const PStringArray & filenames, PINDEX delay, PINDEX repeat, PBoolean autoDelete);
516  virtual bool OnStart();
517  virtual bool OnRepeat();
518  virtual void OnStop();
519  protected:
522 };
523 
525 
526 PQUEUE(PVXMLQueue, PVXMLPlayable);
527 
529 
531 {
532  PCLASSINFO(PVXMLChannel, PDelayChannel);
533  public:
534  PVXMLChannel(unsigned frameDelay, PINDEX frameSize);
535  ~PVXMLChannel();
536 
537  virtual PBoolean Open(PVXMLSession * session);
538 
539  // overrides from PIndirectChannel
540  virtual PBoolean IsOpen() const;
541  virtual PBoolean Close();
542  virtual PBoolean Read(void * buffer, PINDEX amount);
543  virtual PBoolean Write(const void * buf, PINDEX len);
544 
545  // new functions
546  virtual PWAVFile * CreateWAVFile(const PFilePath & fn, PBoolean recording = false);
547 
548  const PString & GetMediaFormat() const { return mediaFormat; }
549  PBoolean IsMediaPCM() const { return mediaFormat == "PCM-16"; }
550  virtual PString AdjustWavFilename(const PString & fn);
551 
552  // Incoming channel functions
553  virtual PBoolean WriteFrame(const void * buf, PINDEX len) = 0;
554  virtual PBoolean IsSilenceFrame(const void * buf, PINDEX len) const = 0;
555 
556  virtual PBoolean QueueRecordable(PVXMLRecordable * newItem);
557 
558  PBoolean StartRecording(const PFilePath & fn, unsigned finalSilence = 3000, unsigned maxDuration = 30000);
560  PBoolean IsRecording() const { return m_recordable != NULL; }
561 
562  // Outgoing channel functions
563  virtual PBoolean ReadFrame(void * buffer, PINDEX amount) = 0;
564  virtual PINDEX CreateSilenceFrame(void * buffer, PINDEX amount) = 0;
565  virtual void GetBeepData(PBYTEArray &, unsigned) { }
566 
567  virtual PBoolean QueueResource(const PURL & url, PINDEX repeat= 1, PINDEX delay = 0);
568 
569  virtual PBoolean QueuePlayable(const PString & type, const PString & str, PINDEX repeat = 1, PINDEX delay = 0, PBoolean autoDelete = false);
570  virtual PBoolean QueuePlayable(PVXMLPlayable * newItem);
571  virtual PBoolean QueueData(const PBYTEArray & data, PINDEX repeat = 1, PINDEX delay = 0);
572 
573  virtual PBoolean QueueFile(const PString & fn, PINDEX repeat = 1, PINDEX delay = 0, PBoolean autoDelete = false)
574  { return QueuePlayable("File", fn, repeat, delay, autoDelete); }
575 
576  virtual PBoolean QueueCommand(const PString & cmd, PINDEX repeat = 1, PINDEX delay = 0)
577  { return QueuePlayable("Command", cmd, repeat, delay, true); }
578 
579  virtual void FlushQueue();
580  virtual PBoolean IsPlaying() const { return m_currentPlayItem != NULL || m_playQueue.GetSize() > 0; }
581 
582  void SetPause(PBoolean pause) { m_paused = pause; }
583 
584  unsigned GetSampleFrequency() const { return m_sampleFrequency; }
585 
586  void SetSilence(unsigned msecs);
587 
588  protected:
590 
594 
597  bool m_closed;
598  bool m_paused;
599  PINDEX m_totalData;
600 
601  // Incoming audio variables
603  unsigned m_finalSilence;
604  unsigned m_silenceRun;
605 
606  // Outgoing audio variables
607  PVXMLQueue m_playQueue;
610 };
611 
612 
614 
615 class PVXMLNodeHandler : public PObject
616 {
617  PCLASSINFO(PVXMLNodeHandler, PObject);
618  public:
619  // Return true for process node, false to skip and move to next sibling
620  virtual bool Start(PVXMLSession & /*session*/, PXMLElement & /*node*/) const { return true; }
621 
622  // Return true to move to next sibling, false to stay at this node.
623  virtual bool Finish(PVXMLSession & /*session*/, PXMLElement & /*node*/) const { return true; }
624 };
625 
626 
628 
629 
630 #endif // P_VXML
631 
632 #endif // PTLIB_VXML_H
633 
634 
635 // End of file ////////////////////////////////////////////////////////////////