1 /*
2  * lidpluginmgr.h
3  *
4  * Line Interface Device plugins manager
5  *
6  * Open Phone Abstraction Library (OPAL)
7  * Formally known as the Open H323 project.
8  *
9  * Copyright (C) 2005 Post Increment
10  *
11  * The contents of this file are subject to the Mozilla Public License
12  * Version 1.0 (the "License"); you may not use this file except in
13  * compliance with the License. You may obtain a copy of the License at
14  * http://www.mozilla.org/MPL/
15  *
16  * Software distributed under the License is distributed on an "AS IS"
17  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
18  * the License for the specific language governing rights and limitations
19  * under the License.
20  *
21  * The Original Code is Open Phone Abstraction Library.
22  *
23  * The Initial Developer of the Original Code is Post Increment
24  *
25  * Contributor(s): ______________________________________.
26  *
27  * $Revision: 24178 $
28  * $Author: rjongbloed $
29  * $Date: 2010-04-05 19:10:56 -0500 (Mon, 05 Apr 2010) $
30  */
31 
32 #ifndef OPAL_LIDS_LIDPLUGINMGR_H
33 #define OPAL_LIDS_LIDPLUGINMGR_H
34 
35 #ifdef P_USE_PRAGMA
36 #pragma interface
37 #endif
38 
39 #include <opal/buildopts.h>
40 
41 #include <ptlib/pluginmgr.h>
42 #include <ptlib/sound.h>
43 #include <lids/lidplugin.h>
44 #include <lids/lid.h>
45 
46 
47 
48 class OpalPluginLIDRegistration : public OpalLIDRegistration
49 {
50   public:
51     OpalPluginLIDRegistration(const PluginLID_Definition & definition);
52 
53     OpalLineInterfaceDevice * Create(void * param) const;
54 
55   private:
56     PluginLID_Definition m_definition;
57 };
58 
59 
60 class OpalPluginLIDManager : public PPluginModuleManager
61 {
62   PCLASSINFO(OpalPluginLIDManager, PPluginModuleManager);
63   public:
64     OpalPluginLIDManager(PPluginManager * pluginMgr = NULL);
65     ~OpalPluginLIDManager();
66 
67     virtual void OnLoadPlugin(PDynaLink & dll, INT code);
68     virtual void OnShutdown();
69 
70   protected:
71     PList<OpalPluginLIDRegistration> m_registrations;
72 };
73 
74 
75 
76 class OpalPluginLID : public OpalLineInterfaceDevice
77 {
78   PCLASSINFO(OpalPluginLID, OpalLineInterfaceDevice);
79   public:
80     OpalPluginLID(const PluginLID_Definition & definition);
81     ~OpalPluginLID();
82 
83     /**Open the line interface device.
84       */
85     virtual PBoolean Open(
86       const PString & device      ///<  Device identifier name.
87     );
88 
89     /**Close the line interface device.
90       */
91     virtual PBoolean Close();
92 
93     /**Get the device type identifier.
94        This is as is used in the factory registration.
95       */
96     virtual PString GetDeviceType() const;
97 
98     /**Get the device name, as used to open the device.
99        Note the format of this name should be as is returned from GetAllName()
100        and must be able to be used in a subsequent Open() call.
101       */
102     virtual PString GetDeviceName() const;
103 
104     /**Get all the possible devices that can be opened.
105       */
106     virtual PStringArray GetAllNames() const;
107 
108     /**Get the description of the line interface device.
109        This is a string indication of the card type for user interface
110        display purposes or device specific control. The device should be
111        as detailed as possible eg "Quicknet LineJACK".
112       */
113     virtual PString GetDescription() const;
114 
115     /**Get the total number of lines supported by this device.
116       */
117     virtual unsigned GetLineCount() const;
118 
119     /**Get the type of the line.
120        A "terminal" line is one where a call may terminate. For example a POTS
121        line with a standard telephone handset on it would be a terminal line.
122        The alternative is a "network" line, that is one connected to switched
123        network eg the standard PSTN.
124       */
125     virtual PBoolean IsLineTerminal(
126       unsigned line   ///<  Number of line
127     );
128 
129 
130     /**Determine if a physical line is present on the logical line.
131       */
132     virtual PBoolean IsLinePresent(
133       unsigned line,      ///<  Number of line
134       PBoolean force = false  ///<  Force test, do not optimise
135     );
136 
137 
138     /**Determine if line is currently off hook.
139        This function implies that the state is debounced and that a return
140        value of true indicates that the phone is really off hook. That is
141        hook flashes and winks are masked out.
142       */
143     virtual PBoolean IsLineOffHook(
144       unsigned line   ///<  Number of line
145     );
146 
147     /**Set the hook state of the line.
148        Note that not be possible on a given line, for example a POTS line with
149        a standard telephone handset. The hook state is determined by external
150        hardware and cannot be changed by the software.
151       */
152     virtual PBoolean SetLineOffHook(
153       unsigned line,        ///<  Number of line
154       PBoolean newState = true  ///<  New state to set
155     );
156 
157     /**Set the hook state off then straight back on again.
158        This will only operate if the line is currently off hook.
159       */
160     virtual PBoolean HookFlash(
161       unsigned line,              ///<  Number of line
162       unsigned flashTime = 200    ///<  Time for hook flash in milliseconds
163     );
164 
165     /**Return true if a hook flash has been detected
166       */
167     virtual PBoolean HasHookFlash(unsigned line);
168 
169 
170     /**Determine if line is ringing.
171        This function implies that the state is "debounced" and that a return
172        value of true indicates that the phone is still ringing and it is not
173        simply a pause in the ring cadence.
174 
175        If cadence is not NULL then it is set with the bit pattern for the
176        incoming ringing. Note that in this case the funtion may take a full
177        sequence to return. If it is NULL it can be assumed that the function
178        will return quickly.
179       */
180     virtual PBoolean IsLineRinging(
181       unsigned line,          ///<  Number of line
182       DWORD * cadence = NULL  ///<  Cadence of incoming ring
183     );
184 
185     /**Begin ringing local phone set with specified cadence.
186        If nCadence is zero then stops ringing.
187 
188        Note that not be possible on a given line, for example on a PSTN line
189        the ring state is determined by external hardware and cannot be
190        changed by the software.
191 
192        Also note that the cadence may be ignored by particular hardware driver
193        so that only the zero or non-zero values are significant.
194 
195        The ring pattern is an array of millisecond times for on and off parts
196        of the cadence. Thus the Australian ring cadence would be represented
197        by the array   unsigned AusRing[] = { 400, 200, 400, 2000 }
198       */
199     virtual PBoolean RingLine(
200       unsigned line,                   ///< Number of line
201       PINDEX nCadence,                 ///< Number of entries in cadence array
202       const unsigned * pattern = NULL, ///< Ring pattern times
203       unsigned frequency = 400         ///< Frequency of ring (if relevant)
204     );
205 
206 
207     /**Indicate to the POTS handset that the call is connected.
208        This uses the hardware (and country) dependent means to indicate to
209        the remote end of a POTS connection that we have answerd. Typically
210        this is a "polarity reversal" but other techniques may be used.
211 
212        The "connected" state remains in force till the remote disconnects
213        the call, though hanging up.
214 
215        Returns true if successful, always returns false for PSTN lines.
216       */
217     virtual PBoolean SetLineConnected(
218       unsigned line   ///<  Number of line
219     );
220 
221     /**Determine if remote has answered call on line.
222        This uses the hardware (and country) dependent means for determining
223        if the remote end of a PSTN connection has answered. Typically this
224        is a "polarity reversal" but other techniques may be used.
225 
226        For a POTS port this is equivalent to IsLineOffHook().
227       */
228     virtual PBoolean IsLineConnected(
229       unsigned line   ///<  Number of line
230     );
231 
232 
233     /**Determine if line has been disconnected from a call.
234        This uses the hardware (and country) dependent means for determining
235        if the remote end of a PSTN connection has hung up.
236 
237        For a POTS port this is equivalent to !IsLineOffHook().
238       */
239     virtual PBoolean IsLineDisconnected(
240       unsigned line,   ///<  Number of line
241       PBoolean checkForWink = true   ///< Check for remote hang up signal
242     );
243 
244 
245     /**Directly connect the two lines.
246       */
247     virtual PBoolean SetLineToLineDirect(
248       unsigned line1,   ///<  Number of first line
249       unsigned line2,   ///<  Number of second line
250       PBoolean connect      ///<  Flag for connect/disconnect
251     );
252 
253     /**Determine if the two lines are directly connected.
254       */
255     virtual PBoolean IsLineToLineDirect(
256       unsigned line1,   ///<  Number of first line
257       unsigned line2    ///<  Number of second line
258     );
259 
260 
261     /**Get the media formats this device is capable of using.
262       */
263     virtual OpalMediaFormatList GetMediaFormats() const;
264 
265     /**Set the media format (codec) for reading on the specified line.
266       */
267     virtual PBoolean SetReadFormat(
268       unsigned line,    ///<  Number of line
269       const OpalMediaFormat & mediaFormat   ///<  Codec type
270     );
271 
272     /**Set the media format (codec) for writing on the specified line.
273       */
274     virtual PBoolean SetWriteFormat(
275       unsigned line,    ///<  Number of line
276       const OpalMediaFormat & mediaFormat   ///<  Codec type
277     );
278 
279     /**Get the media format (codec) for reading on the specified line.
280       */
281     virtual OpalMediaFormat GetReadFormat(
282       unsigned line    ///<  Number of line
283     );
284 
285     /**Get the media format (codec) for writing on the specified line.
286       */
287     virtual OpalMediaFormat GetWriteFormat(
288       unsigned line    ///<  Number of line
289     );
290 
291     /**Stop the read codec.
292       */
293     virtual PBoolean StopReading(
294       unsigned line   ///<  Number of line
295     );
296 
297     /**Stop the write codec.
298       */
299     virtual PBoolean StopWriting(
300       unsigned line   ///<  Number of line
301     );
302 
303     /**Set the read frame size in bytes.
304        Note that a LID may ignore this value so always use GetReadFrameSize()
305        for I/O.
306       */
307     virtual PBoolean SetReadFrameSize(
308       unsigned line,    ///<  Number of line
309       PINDEX frameSize  ///<  New frame size
310     );
311 
312     /**Set the write frame size in bytes.
313        Note that a LID may ignore this value so always use GetReadFrameSize()
314        for I/O.
315       */
316     virtual PBoolean SetWriteFrameSize(
317       unsigned line,    ///<  Number of line
318       PINDEX frameSize  ///<  New frame size
319     );
320 
321     /**Get the read frame size in bytes.
322        All calls to ReadFrame() will return this number of bytes.
323       */
324     virtual PINDEX GetReadFrameSize(
325       unsigned line   ///<  Number of line
326     );
327 
328     /**Get the write frame size in bytes.
329        All calls to WriteFrame() must be this number of bytes.
330       */
331     virtual PINDEX GetWriteFrameSize(
332       unsigned line   ///<  Number of line
333     );
334 
335     /**Low level read of a frame from the device.
336      */
337     virtual PBoolean ReadFrame(
338       unsigned line,    ///<  Number of line
339       void * buf,       ///<  Pointer to a block of memory to receive data.
340       PINDEX & count    ///<  Number of bytes read, <= GetReadFrameSize()
341     );
342 
343     /**Low level write frame to the device.
344      */
345     virtual PBoolean WriteFrame(
346       unsigned line,    ///<  Number of line
347       const void * buf, ///<  Pointer to a block of memory to write.
348       PINDEX count,     ///<  Number of bytes to write, <= GetWriteFrameSize()
349       PINDEX & written  ///<  Number of bytes written, <= GetWriteFrameSize()
350     );
351 
352 
353     /**Get average signal level in last frame.
354       */
355     virtual unsigned GetAverageSignalLevel(
356       unsigned line,  ///<  Number of line
357       PBoolean playback   ///<  Get average playback or record level.
358     );
359 
360 
361     /**Enable audio for the line.
362       */
363     virtual PBoolean EnableAudio(
364       unsigned line,      ///<  Number of line
365       PBoolean enable = true   ///< Flag for enable/disable audio on line
366     );
367 
368     /**Determine if audio for the line is enabled.
369       */
370     virtual PBoolean IsAudioEnabled(
371       unsigned line      ///<  Number of line
372     ) const;
373 
374 
375     /**Set volume level for recording.
376        A value of 100 is the maximum volume possible for the hardware.
377        A value of 0 is the minimum volume possible for the hardware.
378       */
379     virtual PBoolean SetRecordVolume(
380       unsigned line,    ///<  Number of line
381       unsigned volume   ///<  Volume level from 0 to 100%
382     );
383 
384     /**Set volume level for playing.
385        A value of 100 is the maximum volume possible for the hardware.
386        A value of 0 is the minimum volume possible for the hardware.
387       */
388     virtual PBoolean SetPlayVolume(
389       unsigned line,    ///<  Number of line
390       unsigned volume   ///<  Volume level from 0 to 100%
391     );
392 
393     /**Get volume level for recording.
394        A value of 100 is the maximum volume possible for the hardware.
395        A value of 0 is the minimum volume possible for the hardware.
396       */
397     virtual PBoolean GetRecordVolume(
398       unsigned line,      ///<  Number of line
399       unsigned & volume   ///<  Volume level from 0 to 100%
400     );
401 
402     /**Set volume level for playing.
403        A value of 100 is the maximum volume possible for the hardware.
404        A value of 0 is the minimum volume possible for the hardware.
405       */
406     virtual PBoolean GetPlayVolume(
407       unsigned line,      ///<  Number of line
408       unsigned & volume   ///<  Volume level from 0 to 100%
409     );
410 
411 
412     /**Get acoustic echo cancellation.
413        Note, not all devices may support this function.
414       */
415     virtual AECLevels GetAEC(
416       unsigned line    ///<  Number of line
417     ) const;
418 
419     /**Set acoustic echo cancellation.
420        Note, not all devices may support this function.
421       */
422     virtual PBoolean SetAEC(
423       unsigned line,    ///<  Number of line
424       AECLevels level   ///<  AEC level
425     );
426 
427     /**Get voice activity detection.
428        Note, not all devices, or selected codecs, may support this function.
429       */
430     virtual PBoolean GetVAD(
431       unsigned line    ///<  Number of line
432     ) const;
433 
434     /**Set voice activity detection.
435        Note, not all devices, or selected codecs, may support this function.
436       */
437     virtual PBoolean SetVAD(
438       unsigned line,    ///<  Number of line
439       PBoolean enable       ///<  Flag for enabling VAD
440     );
441 
442 
443     /**Get Caller ID from the last incoming ring.
444        The idString parameter is either simply the "number" field of the caller
445        ID data, or if full is true, all of the fields in the caller ID data.
446 
447        The full data of the caller ID string consists fields separated by tab
448        characters ('\\t'), the first three are always the Calling Line Identity
449        (CLI or calling number), the date and the Calling Line Name field. Other
450        fields may follow and are the of the form name=value. The values are
451        LID dependent.
452 
453        A false is returned if there is no Caller ID information available, e.g.
454        if no ring has occurred.
455       */
456     virtual PBoolean GetCallerID(
457       unsigned line,      ///<  Number of line
458       PString & idString, ///<  ID string returned
459       PBoolean full = false   ///<  Get full information in idString
460     );
461 
462     /**Set Caller ID information.
463        The idString must be as a minimum a number fields for the Calling Line
464        Identity.
465 
466        The full data of the caller ID string consists fields separated by tab
467        characters ('\\t'), the first three are always the Calling Line Identity
468        (CLI or calling number), the date and the Calling Line Name field. Other
469        fields may follow and are the of the form name=value. The values are
470        LID dependent.
471 
472        If the date field is missing (e.g. two consecutive tabs) then the current
473        time and date is used. Using an empty string will clear the caller ID
474        so that no caller ID is sent on the next RingLine() call.
475 
476        if the line is on hook then this information is sent when the next
477        RingLine() function is called to start a ring cycle. Note that if the
478        Ring cycle had already been started then this function may return false.
479 
480        If the line is off hook, then a Caller ID on Message Waiting is sent, if
481        supported by the LID, otherwise false is returned.
482       */
483     virtual PBoolean SetCallerID(
484       unsigned line,            ///<  Number of line
485       const PString & idString  ///<  ID string to use
486     );
487 
488     /**Send a Visual Message Waiting Indicator
489       */
490     virtual PBoolean SendVisualMessageWaitingIndicator(
491       unsigned line,            ///<  Number of line
492       PBoolean on               ///< Flag for VMWI on/off
493     );
494 
495 
496     /**Play a DTMF digit.
497        Any characters that are not in the set 0-9, A-D, * or # will be ignored.
498       */
499     virtual PBoolean PlayDTMF(
500       unsigned line,            ///<  Number of line
501       const char * digits,      ///<  DTMF digits to be played
502       DWORD onTime = DefaultDTMFOnTime,  ///<  Number of milliseconds to play each DTMF digit
503       DWORD offTime = DefaultDTMFOffTime ///<  Number of milliseconds between digits
504     );
505 
506     /**Read a DTMF digit detected.
507        This may be characters from the set 0-9, A-D, * or #. A null ('\\0')
508        character indicates that there are no tones in the queue.
509        Characters E through P indicate the following tones:
510 
511          E = 800   F = 1000  G = 1250  H = 950   I = 1100  J = 1400
512          K = 1500  L = 1600  M = 1800  N = 2100  O = 1300  P = 2450
513 
514       */
515     virtual char ReadDTMF(
516       unsigned line   ///<  Number of line
517     );
518 
519     /**Get DTMF removal mode.
520        When set in this mode the DTMF tones detected are removed from the
521        encoded data stream as returned by ReadFrame().
522       */
523     virtual PBoolean GetRemoveDTMF(
524       unsigned line   ///<  Number of line
525     );
526 
527     /**Set DTMF removal mode.
528        When set in this mode the DTMF tones detected are removed from the
529        encoded data stream as returned by ReadFrame().
530       */
531     virtual PBoolean SetRemoveDTMF(
532       unsigned line,     ///<  Number of line
533       PBoolean removeTones   ///<  Flag for removing DTMF tones.
534     );
535 
536 
537     /**See if any tone is detected.
538       */
539     virtual CallProgressTones IsToneDetected(
540       unsigned line   ///< Number of line
541     );
542 
543     /**See if any tone is detected.
544       */
545     virtual CallProgressTones WaitForToneDetect(
546       unsigned line,          ///< Number of line
547       unsigned timeout = 3000 ///< Milliseconds to wait for
548     );
549 
550     /**See if a specific tone is detected.
551       */
552     virtual PBoolean WaitForTone(
553       unsigned line,          ///<  Number of line
554       CallProgressTones tone, ///<  Tone to wait for
555       unsigned timeout = 3000 ///<  Milliseconds to wait for
556     );
557 
558     /**Set a tones filter information.
559       */
560     virtual bool SetToneParameters(
561       unsigned line,            ///<  Number of line
562       CallProgressTones tone,   ///<  Tone filter to change
563       unsigned frequency1,      ///<  Usually low frequency
564       unsigned frequency2,      ///<  Usually high frequency
565       ToneMixingModes mode,     ///<  Mode for how freqencies are mixed, -1 is
566       PINDEX numCadences,       ///<  Number of cadence times
567       const unsigned * onTimes, ///<  Cadence ON times
568       const unsigned * offTimes ///<  Cadence OFF times
569     );
570 
571     /**Play a tone.
572       */
573     virtual PBoolean PlayTone(
574       unsigned line,          ///<  Number of line
575       CallProgressTones tone  ///<  Tone to be played
576     );
577 
578     /**Determine if a tone is still playing
579       */
580     virtual PBoolean IsTonePlaying(
581       unsigned line   ///<  Number of line
582     );
583 
584     /**Stop playing a tone.
585       */
586     virtual PBoolean StopTone(
587       unsigned line   ///<  Number of line
588     );
589 
590 
591     /**Dial a number on network line.
592        The takes the line off hook, waits for dial tone, and transmits the
593        specified number as DTMF tones.
594 
595        If the requireTones flag is true the call is aborted of the call
596        progress tones are not detected. Otherwise the call proceeds with short
597        delays while it tries to detect the call progress tones.
598 
599        The return code indicates the following:
600           DialTone  No dial tone detected
601           RingTone  Dial was successful
602           BusyTone  The remote phone was busy
603           ClearTone Dial failed (usually means rang out)
604           NoTone    There was an internal error making the call
605       */
606     virtual CallProgressTones DialOut(
607       unsigned line,                ///< Number of line
608       const PString & number,       ///< Number to dial
609       const DialParams & params = DialParams() ///< Optional parameters for dial out.
610     );
611 
612 
613     /**Get wink detect minimum duration.
614        This is the signal used by telcos to end PSTN call.
615       */
616     virtual unsigned GetWinkDuration(
617       unsigned line    ///<  Number of line
618     );
619 
620     /**Set wink detect minimum duration.
621        This is the signal used by telcos to end PSTN call.
622       */
623     virtual PBoolean SetWinkDuration(
624       unsigned line,        ///<  Number of line
625       unsigned winkDuration ///<  New minimum duration
626     );
627 
628     /**Set the country code set for the device.
629        This may change the line analogue coefficients, ring detect, call
630        disconnect detect and call progress tones to fit the countries
631        telephone network.
632       */
633     virtual PBoolean SetCountryCode(
634       T35CountryCodes country   ///<  COuntry code for device
635     );
636 
637     /**Get the list of countries actually supported by the device
638      */
639     virtual PStringList GetCountryCodeNameList() const;
640 
641 
642 
643   protected:
644     PDECLARE_NOTIFIER(PThread, OpalPluginLID, TonePlayer);
645     bool StartTonePlayerThread(int tone);
646     void StopTonePlayerThread();
647 
648 #if PTRACING
649     bool BadContext() const;
650     bool BadFunction(void * fnPtr, const char * fnName) const;
651     PluginLID_Errors CheckError(PluginLID_Errors error, const char * fnName) const;
652 #endif
653 
654     const PluginLID_Definition & m_definition;
655     void                       * m_context;
656     PString                      m_deviceName;
657 
658     PSoundChannel                m_recorder;
659     PSoundChannel                m_player;
660     PThread                    * m_tonePlayer;
661     PSyncPoint                   m_stopTone;
662     bool                         m_lockOutTones;
663 };
664 
665 
666 PFACTORY_LOAD(OpalPluginLIDManager);
667 
668 
669 #endif // OPAL_LIDS_LIDPLUGINMGR_H
670