4 * Line Interface Device
6 * Open Phone Abstraction Library
8 * Copyright (c) 1999-2000 Equivalence Pty. Ltd.
10 * The contents of this file are subject to the Mozilla Public License
11 * Version 1.0 (the "License"); you may not use this file except in
12 * compliance with the License. You may obtain a copy of the License at
13 * http://www.mozilla.org/MPL/
15 * Software distributed under the License is distributed on an "AS IS"
16 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
17 * the License for the specific language governing rights and limitations
20 * The Original Code is Open H323 Library.
22 * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
24 * Contributor(s): ______________________________________.
27 * Revision 1.103 2004/07/19 14:16:10 csoutheren
28 * Fixed problem with pragma dispayed as warning in gcc 3.5-20040704
30 * Revision 1.102 2004/06/01 05:48:03 csoutheren
31 * Changed capability table to use abstract factory routines rather than internal linked list
33 * Revision 1.101 2004/05/19 07:38:24 csoutheren
34 * Changed OpalMediaFormat handling to use abstract factory method functions
36 * Revision 1.100 2004/05/04 03:33:33 csoutheren
37 * Added guards against comparing certain kinds of Capabilities
39 * Revision 1.99 2004/04/03 08:28:07 csoutheren
40 * Remove pseudo-RTTI and replaced with real RTTI
42 * Revision 1.98 2003/08/18 23:56:01 dereksmithies
43 * Fix typos in previous commit.
45 * Revision 1.97 2003/08/18 22:13:13 dereksmithies
46 * Add Singapore Ring Cadence. Thanks to Steve.
48 * Revision 1.96 2003/06/03 10:27:42 rjongbloed
49 * Added G.729 and G,729B detection from LID.
51 * Revision 1.95 2003/04/29 08:30:29 robertj
52 * Fixed return type of get wink function.
54 * Revision 1.94 2003/04/28 01:47:52 dereks
55 * Add ability to set/get wink duration for ixj device.
57 * Revision 1.93 2003/03/05 06:26:44 robertj
58 * Added function to play a WAV file to LID, thanks Pietro Ravasio
60 * Revision 1.92 2003/02/13 23:33:36 dereks
61 * Fix reporting of tonenames.
63 * Revision 1.91 2003/01/29 23:58:17 dereks
64 * Fix typo in United Kingdom tone definition.
66 * Revision 1.90 2002/12/02 03:06:26 robertj
67 * Fixed over zealous removal of code when NO_AUDIO_CODECS set.
69 * Revision 1.89 2002/11/05 04:27:12 robertj
70 * Imported RingLine() by array from OPAL.
72 * Revision 1.88 2002/10/30 05:54:17 craigs
73 * Fixed compatibilty problems with G.723.1 6k3 and 5k3
75 * Revision 1.87 2002/08/05 10:03:48 robertj
76 * Cosmetic changes to normalise the usage of pragma interface/implementation.
78 * Revision 1.86 2002/07/01 02:56:17 dereks
79 * Add PTRACE statements to "IsToneDetected"
81 * Revision 1.85 2002/06/27 08:52:57 robertj
82 * Fixed typo and naming convention for Cisco G.723.1 annex A capability.
84 * Revision 1.84 2002/06/26 05:45:45 robertj
85 * Added capability for Cisco IOS non-standard name for G.723.1 Annex A so
86 * can now utilise SID frames with Cisco gateways.
88 * Revision 1.83 2002/06/25 08:30:13 robertj
89 * Changes to differentiate between stright G.723.1 and G.723.1 Annex A using
90 * the OLC dataType silenceSuppression field so does not send SID frames
91 * to receiver codecs that do not understand them.
93 * Revision 1.82 2002/05/09 06:26:34 robertj
94 * Added fuction to get the current audio enable state for line in device.
95 * Changed IxJ EnableAudio() semantics so is exclusive, no direct switching
96 * from PSTN to POTS and vice versa without disabling the old one first.
98 * Revision 1.81 2002/01/23 06:13:56 robertj
99 * Added filter function hooks to codec raw data channel.
101 * Revision 1.80 2002/01/23 01:58:28 robertj
102 * Added function to determine if codecs raw data channel is native format.
104 * Revision 1.79 2002/01/13 23:57:04 robertj
105 * Added mutex so can change raw data channel while reading/writing from codec.
107 * Revision 1.78 2001/12/14 04:33:53 craigs
108 * Disabled 5.3k codec due to problems with Quicknet cards
110 * Revision 1.77 2001/12/11 04:27:28 craigs
111 * Added support for 5.3kbps G723.1
113 * Revision 1.76 2001/09/21 02:52:19 robertj
114 * Implemented static object for all "known" media formats.
116 * Revision 1.75 2001/09/11 01:24:36 robertj
117 * Added conditional compilation to remove video and/or audio codecs.
119 * Revision 1.74 2001/09/10 03:06:29 robertj
120 * Major change to fix problem with error codes being corrupted in a
121 * PChannel when have simultaneous reads and writes in threads.
123 * Revision 1.73 2001/08/06 03:08:57 robertj
124 * Fission of h323.h to h323ep.h & h323con.h, h323.h now just includes files.
126 * Revision 1.72 2001/07/24 02:28:22 robertj
127 * Added setting of tone filters for a handful of countries.
129 * Revision 1.71 2001/07/20 04:06:18 robertj
130 * Removed old Cisco hack code for G.728, they now do it rigth!
132 * Revision 1.70 2001/07/19 05:54:30 robertj
133 * Updated interface to xJACK drivers to utilise cadence and filter functions
134 * for dial tone, busy tone and ringback tone detection.
136 * Revision 1.69 2001/05/30 03:56:57 robertj
137 * Fixed initial value of read deblocking offset on stopping codec.
139 * Revision 1.68 2001/05/25 07:55:26 robertj
140 * Fixed problem with trace output of tone bits, thanks Vjacheslav Andrejev.
142 * Revision 1.67 2001/05/25 02:19:53 robertj
143 * Fixed problem with codec data reblocking code not being reset when
144 * code is stopped and restarted, thanks Artis Kugevics
146 * Revision 1.66 2001/05/22 00:31:43 robertj
147 * Changed to allow optional wink detection for line disconnect
149 * Revision 1.65 2001/05/14 05:56:28 robertj
150 * Added H323 capability registration system so can add capabilities by
151 * string name instead of having to instantiate explicit classes.
153 * Revision 1.64 2001/05/11 04:43:43 robertj
154 * Added variable names for standard PCM-16 media format name.
156 * Revision 1.63 2001/04/03 23:37:48 craigs
157 * Added extra logging of country change functions
159 * Revision 1.62 2001/03/29 23:43:02 robertj
160 * Added ability to get average signal level for both receive and transmit.
161 * Changed silence detection to use G.723.1 SID frames as indicator of
162 * silence instead of using the average energy and adaptive threshold.
164 * Revision 1.61 2001/03/23 05:38:30 robertj
165 * Added PTRACE_IF to output trace if a conditional is TRUE.
167 * Revision 1.60 2001/02/09 05:36:38 craigs
168 * Added pragma implementation
170 * Revision 1.59 2001/01/28 06:29:55 yurik
171 * WinCE-port - lid.h exists in SDK so we point to right one
173 * Revision 1.58 2001/01/25 07:27:16 robertj
174 * Major changes to add more flexible OpalMediaFormat class to normalise
175 * all information about media types, especially codecs.
177 * Revision 1.57 2001/01/11 06:24:55 robertj
178 * Fixed incorrect value for CNG frame
180 * Revision 1.56 2001/01/11 05:39:44 robertj
181 * Fixed usage of G.723.1 CNG 1 byte frames.
183 * Revision 1.55 2001/01/11 03:51:14 robertj
184 * Fixed bug in WriteBlock() flush, use actual frame size for last write.
186 * Revision 1.54 2001/01/04 06:39:51 robertj
187 * Fixed bug in G.711 mode with xJACK cards if data is not a multiple of 10ms
188 * and some silence is transmitted, closes the logical channel.
190 * Revision 1.53 2000/12/17 22:08:20 craigs
191 * Changed GetCountryCodeList to return PStringList
193 * Revision 1.52 2000/12/11 01:23:32 craigs
194 * Added extra routines to allow country string manipulation
196 * Revision 1.51 2000/12/04 00:04:21 robertj
197 * Changed G.711 "silence" to be 0xff to remove clicks from Quicknet cards,
199 * Revision 1.50 2000/11/30 08:48:36 robertj
200 * Added functions to enable/disable Voice Activity Detection in LID's
202 * Revision 1.49 2000/11/30 03:12:00 robertj
203 * Fixed bug in not resetting buffer offset on buffer flush.
205 * Revision 1.48 2000/11/29 22:08:31 craigs
206 * Fixed problem with using WaitForToneDetect with 0 timeout
208 * Revision 1.47 2000/11/27 05:19:27 robertj
211 * Revision 1.46 2000/11/27 00:19:39 robertj
212 * Fixed bug in SetRawCodec, conditional around the wrong way
214 * Revision 1.45 2000/11/26 23:12:18 craigs
215 * Added hook flash detection API
217 * Revision 1.44 2000/11/24 10:56:12 robertj
218 * Added a raw PCM dta mode for generating/detecting standard tones.
219 * Modified the ReadFrame/WriteFrame functions to allow for variable length codecs.
221 * Revision 1.43 2000/11/20 03:15:13 craigs
222 * Changed tone detection API slightly to allow detection of multiple
224 * Added fax CNG tone to tone list
226 * Revision 1.42 2000/11/03 06:25:37 robertj
227 * Added flag to IsLinePresent() to force slow test, guarenteeing correct value.
229 * Revision 1.41 2000/10/31 03:21:02 robertj
230 * Fixed bug that caused G.711 transmitter to continuously think there was silence.
232 * Revision 1.40 2000/10/16 09:45:10 robertj
233 * Fixed recently introduced bug, caused artifacts when should be silent G.723.1
235 * Revision 1.39 2000/10/13 02:24:06 robertj
236 * Moved frame reblocking code from LID channel to LID itself and added
237 * ReadBlock/WriteBlock functions to allow non integral frame sizes.
239 * Revision 1.38 2000/09/25 22:31:18 craigs
240 * Added G.723.1 frame erasure capability
242 * Revision 1.37 2000/09/23 07:20:45 robertj
243 * Fixed problem with being able to distinguish between sw and hw codecs in LID channel.
245 * Revision 1.36 2000/09/22 01:35:51 robertj
246 * Added support for handling LID's that only do symmetric codecs.
248 * Revision 1.35 2000/09/01 00:15:21 robertj
249 * Improved country code selection, can use 2 letter ISO codes or
250 * international dialling prefixes (with leading +) to select country.
252 * Revision 1.34 2000/08/31 13:14:40 craigs
253 * Added functions to LID
254 * More bulletproofing to Linux driver
256 * Revision 1.33 2000/08/30 23:24:36 robertj
257 * Renamed string version of SetCountrCode() to SetCountryCodeName() to avoid
258 * C++ masking ancestor overloaded function when overriding numeric version.
260 * Revision 1.32 2000/07/13 16:03:25 robertj
261 * Removed transmission of 1 byte repeat CNG frames in G.723.1 as it crashes other peoples stacks.
263 * Revision 1.31 2000/07/12 10:25:37 robertj
264 * Renamed all codecs so obvious whether software or hardware.
266 * Revision 1.30 2000/07/09 15:23:00 robertj
267 * Changed G.728 not to use Cisco hack. Cisco is just wrong!
268 * Fixed output of silence in G.711 so works with any sized frame.
270 * Revision 1.29 2000/07/02 14:09:49 craigs
271 * Fill uLaw and aLaw silence with 0x80 rather than 0x00
273 * Revision 1.28 2000/06/19 00:32:22 robertj
274 * Changed functionf or adding all lid capabilities to not assume it is to an endpoint.
276 * Revision 1.27 2000/06/01 07:52:30 robertj
277 * Changed some LID capability code back again so does not unneedfully break existing API.
279 * Revision 1.26 2000/05/30 10:19:28 robertj
280 * Added function to add capabilities given a LID.
281 * Improved LID capabilities so cannot create one that is not explicitly supported.
283 * Revision 1.25 2000/05/24 06:43:16 craigs
284 * Added routines to get xJack volume
285 * Fixed problem with receiving G>723.1 NULL frames
287 * Revision 1.24 2000/05/11 03:47:48 craigs
288 * Added extra debugging
290 * Revision 1.23 2000/05/10 04:05:34 robertj
291 * Changed capabilities so has a function to get name of codec, instead of relying on PrintOn.
293 * Revision 1.22 2000/05/04 12:56:43 robertj
296 * Revision 1.21 2000/05/04 11:52:35 robertj
297 * Added Packets Too Late statistics, requiring major rearrangement of jitter
298 * buffer code, not also changes semantics of codec Write() function slightly.
300 * Revision 1.20 2000/05/02 04:32:27 robertj
301 * Fixed copyright notice comment.
303 * Revision 1.19 2000/04/30 03:57:14 robertj
304 * Added PTRACE of read/write frame sizes required by LID.
306 * Revision 1.18 2000/04/19 02:04:30 robertj
309 * Revision 1.17 2000/04/14 17:18:07 robertj
310 * Fixed problem with error reporting from LID hardware.
312 * Revision 1.16 2000/04/10 17:45:11 robertj
313 * Added higher level "DialOut" function for PSTN lines.
314 * Added hook flash function.
316 * Revision 1.15 2000/04/05 18:04:12 robertj
317 * Changed caller ID code for better portability.
319 * Revision 1.14 2000/04/03 19:25:14 robertj
320 * Optimised G.711 codec to read/write larger chunks of data.
322 * Revision 1.13 2000/03/31 19:50:51 robertj
323 * Fixed receiver loop being able to deal with RTP packets smaller than expected.
325 * Revision 1.12 2000/03/30 19:32:35 robertj
326 * Added swab function which seems to be missing on Linux.
328 * Revision 1.11 2000/03/30 01:57:16 robertj
329 * Added hacks so G.728 works with (I think) broken cisco gateways.
331 * Revision 1.10 2000/03/29 21:01:52 robertj
332 * Changed codec to use number of frames rather than number of bytes.
333 * Added function on LID to get available codecs.
334 * Fixed codec table for G.729 codec
336 * Revision 1.9 2000/03/28 05:22:05 robertj
337 * Fixed translation of text country code to numeric code.
339 * Revision 1.8 2000/03/23 23:36:49 robertj
340 * Added more calling tone detection functionality.
342 * Revision 1.7 2000/03/21 03:06:50 robertj
343 * Changes to make RTP TX of exact numbers of frames in some codecs.
345 * Revision 1.6 2000/01/13 12:39:29 robertj
346 * Added string based country codes to LID.
348 * Revision 1.5 2000/01/13 04:03:46 robertj
349 * Added video transmission
351 * Revision 1.4 2000/01/07 10:01:26 robertj
352 * GCC/Linux compatibility
354 * Revision 1.3 2000/01/07 08:28:09 robertj
355 * Additions and changes to line interface device base class.
357 * Revision 1.2 1999/12/29 01:18:07 craigs
358 * Fixed problem with codecs other than G.711 not working after reorganisation
360 * Revision 1.1 1999/12/23 23:02:36 robertj
361 * File reorganision for separating RTP from H.323 and creation of LID for VPB support.
366 #pragma implementation "lid.h"
374 #include "..\include\lid.h"
382 ///////////////////////////////////////////////////////////////////////////////
385 static const char * const CallProgressTonesNames
[] = {
386 "DialTone", "RingTone", "BusyTone", "ClearTone", "CNGTone"
389 ostream
& operator<<(ostream
& o
, OpalLineInterfaceDevice::CallProgressTones t
)
392 while ((1 << i
) != t
)
395 if (i
< PARRAYSIZE(CallProgressTonesNames
))
396 return o
<< CallProgressTonesNames
[i
];
398 return o
<< "Unknown";
404 OpalLineInterfaceDevice::OpalLineInterfaceDevice()
408 countryCode
= UnknownCountry
;
409 readDeblockingOffset
= P_MAX_INDEX
;
410 writeDeblockingOffset
= 0;
414 BOOL
OpalLineInterfaceDevice::IsOpen() const
416 return os_handle
>= 0;
420 BOOL
OpalLineInterfaceDevice::Close()
430 BOOL
OpalLineInterfaceDevice::IsLineTerminal(unsigned)
436 BOOL
OpalLineInterfaceDevice::IsLinePresent(unsigned, BOOL
)
442 BOOL
OpalLineInterfaceDevice::HookFlash(unsigned line
, unsigned flashTime
)
444 if (!IsLineOffHook(line
))
447 if (!SetLineOnHook(line
))
450 PThread::Current()->Sleep(flashTime
);
452 return SetLineOffHook(line
);
456 BOOL
OpalLineInterfaceDevice::HasHookFlash(unsigned)
462 BOOL
OpalLineInterfaceDevice::IsLineRinging(unsigned, DWORD
*)
468 BOOL
OpalLineInterfaceDevice::RingLine(unsigned, DWORD
)
474 BOOL
OpalLineInterfaceDevice::RingLine(unsigned, PINDEX
, unsigned *)
480 BOOL
OpalLineInterfaceDevice::IsLineDisconnected(unsigned line
, BOOL
)
482 return IsToneDetected(line
) == BusyTone
;
486 BOOL
OpalLineInterfaceDevice::SetLineToLineDirect(unsigned, unsigned, BOOL
)
492 BOOL
OpalLineInterfaceDevice::IsLineToLineDirect(unsigned, unsigned)
498 OpalMediaFormat
FindMediaFormat(RTP_DataFrame::PayloadTypes pt
)
500 const OpalMediaFormat::List
& formats
= OpalMediaFormat::GetRegisteredMediaFormats();
501 for (PINDEX i
= 0; i
< formats
.GetSize(); i
++) {
502 if (formats
[i
].GetPayloadType() == pt
)
506 return "<<Unknown RTP payload type>>";
510 BOOL
OpalLineInterfaceDevice::SetReadCodec(unsigned line
,
511 RTP_DataFrame::PayloadTypes codec
)
513 return SetReadFormat(line
, FindMediaFormat(codec
));
517 BOOL
OpalLineInterfaceDevice::SetWriteCodec(unsigned line
,
518 RTP_DataFrame::PayloadTypes codec
)
520 return SetWriteFormat(line
, FindMediaFormat(codec
));
524 BOOL
OpalLineInterfaceDevice::SetRawCodec(unsigned line
)
526 if (!SetReadFormat(line
, OpalPCM16
))
529 if (SetWriteFormat(line
, OpalPCM16
))
537 BOOL
OpalLineInterfaceDevice::StopReadCodec(unsigned)
539 readDeblockingOffset
= P_MAX_INDEX
;
544 BOOL
OpalLineInterfaceDevice::StopWriteCodec(unsigned)
546 writeDeblockingOffset
= 0;
551 BOOL
OpalLineInterfaceDevice::StopRawCodec(unsigned line
)
553 BOOL ok
= StopReadCodec(line
);
554 return StopWriteCodec(line
) && ok
;
558 BOOL
OpalLineInterfaceDevice::SetReadFrameSize(unsigned, PINDEX
)
564 BOOL
OpalLineInterfaceDevice::SetWriteFrameSize(unsigned, PINDEX
)
570 BOOL
OpalLineInterfaceDevice::ReadBlock(unsigned line
, void * buffer
, PINDEX length
)
572 // Are reblocking the hardware frame sizes to those expected by the RTP packets.
573 PINDEX frameSize
= GetReadFrameSize(line
);
575 BYTE
* bufferPtr
= (BYTE
*)buffer
;
579 if (readDeblockingOffset
< frameSize
) {
580 PINDEX left
= frameSize
- readDeblockingOffset
;
583 memcpy(bufferPtr
, &readDeblockingBuffer
[readDeblockingOffset
], left
);
584 readDeblockingOffset
+= left
;
588 else if (length
< frameSize
) {
589 BYTE
* deblockPtr
= readDeblockingBuffer
.GetPointer(frameSize
);
590 if (!ReadFrame(line
, deblockPtr
, readBytes
))
592 readDeblockingOffset
= 0;
595 if (!ReadFrame(line
, bufferPtr
, readBytes
))
597 bufferPtr
+= readBytes
;
606 BOOL
OpalLineInterfaceDevice::WriteBlock(unsigned line
, const void * buffer
, PINDEX length
)
608 PINDEX frameSize
= GetWriteFrameSize(line
);
611 // If zero length then flush any remaining data
612 if (length
== 0 && writeDeblockingOffset
!= 0) {
613 SetWriteFrameSize(line
, writeDeblockingOffset
);
614 BOOL ok
= WriteFrame(line
,
615 writeDeblockingBuffer
.GetPointer(),
616 GetWriteFrameSize(line
),
618 SetWriteFrameSize(line
, frameSize
);
619 writeDeblockingOffset
= 0;
623 const BYTE
* bufferPtr
= (const BYTE
*)buffer
;
626 // If have enough data and nothing in the reblocking buffer, just send it
627 // straight on to the device.
628 if (writeDeblockingOffset
== 0 && length
>= frameSize
) {
629 if (!WriteFrame(line
, bufferPtr
, frameSize
, written
))
631 bufferPtr
+= written
;
635 BYTE
* savedFramePtr
= writeDeblockingBuffer
.GetPointer(frameSize
);
637 // See if new chunk gives us enough for one frames worth
638 if ((writeDeblockingOffset
+ length
) < frameSize
) {
639 // Nope, just copy bytes into buffer and return
640 memcpy(savedFramePtr
+ writeDeblockingOffset
, bufferPtr
, length
);
641 writeDeblockingOffset
+= length
;
645 /* Calculate bytes we want from the passed in buffer to fill a frame by
646 subtracting from full frame width the amount we have so far. This also
647 means the lastWriteCount is set to the correct amount of buffer we are
648 grabbing this time around.
650 PINDEX left
= frameSize
- writeDeblockingOffset
;
651 memcpy(savedFramePtr
+ writeDeblockingOffset
, bufferPtr
, left
);
652 writeDeblockingOffset
= 0;
654 // Write the saved frame out
655 if (!WriteFrame(line
, savedFramePtr
, frameSize
, written
))
667 unsigned OpalLineInterfaceDevice::GetAverageSignalLevel(unsigned, BOOL
)
673 BOOL
OpalLineInterfaceDevice::EnableAudio(unsigned line
, BOOL enabled
)
675 return line
< GetLineCount() && enabled
;
679 BOOL
OpalLineInterfaceDevice::IsAudioEnabled(unsigned line
)
681 return line
< GetLineCount();
685 BOOL
OpalLineInterfaceDevice::SetRecordVolume(unsigned, unsigned)
690 BOOL
OpalLineInterfaceDevice::GetRecordVolume(unsigned, unsigned &)
696 BOOL
OpalLineInterfaceDevice::SetPlayVolume(unsigned, unsigned)
701 BOOL
OpalLineInterfaceDevice::GetPlayVolume(unsigned, unsigned &)
707 OpalLineInterfaceDevice::AECLevels
OpalLineInterfaceDevice::GetAEC(unsigned)
713 BOOL
OpalLineInterfaceDevice::SetAEC(unsigned, AECLevels
)
718 unsigned OpalLineInterfaceDevice::GetWinkDuration(unsigned)
724 BOOL
OpalLineInterfaceDevice::SetWinkDuration(unsigned, unsigned)
730 BOOL
OpalLineInterfaceDevice::GetVAD(unsigned)
736 BOOL
OpalLineInterfaceDevice::SetVAD(unsigned, BOOL
)
742 BOOL
OpalLineInterfaceDevice::GetCallerID(unsigned, PString
& id
, BOOL
)
749 BOOL
OpalLineInterfaceDevice::SetCallerID(unsigned, const PString
&)
754 BOOL
OpalLineInterfaceDevice::SendCallerIDOnCallWaiting(unsigned, const PString
&)
760 BOOL
OpalLineInterfaceDevice::SendVisualMessageWaitingIndicator(unsigned, BOOL
)
765 BOOL
OpalLineInterfaceDevice::PlayDTMF(unsigned, const char *, DWORD
, DWORD
)
771 char OpalLineInterfaceDevice::ReadDTMF(unsigned)
777 BOOL
OpalLineInterfaceDevice::GetRemoveDTMF(unsigned)
783 BOOL
OpalLineInterfaceDevice::SetRemoveDTMF(unsigned, BOOL
)
789 unsigned OpalLineInterfaceDevice::IsToneDetected(unsigned)
795 unsigned OpalLineInterfaceDevice::WaitForToneDetect(unsigned line
, unsigned timeout
)
797 PTRACE(2, "LID\tWaitForToneDetect");
799 static const unsigned sampleRate
= 25;
801 timeout
= (timeout
+sampleRate
-1)/sampleRate
;
805 unsigned tones
= IsToneDetected(line
);
806 if (tones
!= NoTone
) {
807 PTRACE(2, "LID\tTone " << tones
<< " detected after " << (retry
*sampleRate
) << " ms");
811 PThread::Current()->Sleep(sampleRate
);
813 } while (retry
< timeout
);
815 PTRACE(3, "LID\tTone detection timeout " << (retry
*sampleRate
) << " ms");
820 BOOL
OpalLineInterfaceDevice::WaitForTone(unsigned line
,
821 CallProgressTones tone
,
824 PTRACE(3, "LID\tWaitFor the tone " << tone
);
825 BOOL res
= WaitForToneDetect(line
, timeout
) & tone
;
826 PTRACE(3, "LID\tWaitFor the tone " << tone
<<
827 " is successfull-" << (res
? "YES" : "No"));
832 BOOL
OpalLineInterfaceDevice::SetToneFilter(unsigned line
,
833 CallProgressTones tone
,
834 const PString
& description
)
836 PString freqDesc
, cadenceDesc
;
837 PINDEX colon
= description
.Find(':');
838 if (colon
== P_MAX_INDEX
)
839 freqDesc
= description
;
841 freqDesc
= description
.Left(colon
);
842 cadenceDesc
= description
.Mid(colon
+1);
845 unsigned low_freq
, high_freq
;
846 PINDEX dash
= freqDesc
.Find('-');
847 if (dash
== P_MAX_INDEX
)
848 low_freq
= high_freq
= freqDesc
.AsUnsigned();
850 low_freq
= freqDesc
.Left(dash
).AsUnsigned();
851 high_freq
= freqDesc
.Mid(dash
+1).AsUnsigned();
853 if (low_freq
< 100 || low_freq
> 3000 ||
854 high_freq
< 100 || high_freq
> 3000 ||
855 low_freq
> high_freq
) {
856 PTRACE(1, "LID\tIllegal frequency specified: " << description
);
860 PStringArray times
= cadenceDesc
.Tokenise("-");
861 PINDEX numCadences
= (times
.GetSize()+1)/2;
863 PUnsignedArray
onTimes(numCadences
), offTimes(numCadences
);
864 for (PINDEX i
= 0; i
< times
.GetSize(); i
++) {
865 double time
= atof(times
[i
]);
866 if (time
<= 0.01 || time
> 10) {
867 PTRACE(1, "LID\tIllegal cadence time specified: " << description
);
872 onTimes
[i
/2] = (unsigned)(time
*1000);
874 offTimes
[i
/2] = (unsigned)(time
*1000);
877 return SetToneFilterParameters(line
, tone
, low_freq
, high_freq
,
878 numCadences
, onTimes
, offTimes
);
882 BOOL
OpalLineInterfaceDevice::SetToneFilterParameters(unsigned /*line*/,
883 CallProgressTones
/*tone*/,
884 unsigned /*lowFrequency*/,
885 unsigned /*highFrequency*/,
886 PINDEX
/*numCadences*/,
887 const unsigned * /*onTimes*/,
888 const unsigned * /*offTimes*/)
894 BOOL
OpalLineInterfaceDevice::PlayTone(unsigned, CallProgressTones
)
900 BOOL
OpalLineInterfaceDevice::IsTonePlaying(unsigned)
906 BOOL
OpalLineInterfaceDevice::StopTone(unsigned)
912 BOOL
OpalLineInterfaceDevice::PlayAudio(unsigned /*line*/, const PString
& /*filename*/)
914 PTRACE(3, "LID\tBase Class PlayAudio method called, exiting with FALSE");
919 BOOL
OpalLineInterfaceDevice::StopAudio(unsigned /*line*/)
921 PTRACE(3, "LID\tBase Class StopAudio method called, exiting with FALSE");
926 OpalLineInterfaceDevice::CallProgressTones
927 OpalLineInterfaceDevice::DialOut(unsigned line
,
928 const PString
& number
,
931 PTRACE(3, "LID\tDialOut to " << number
);
933 if (IsLineTerminal(line
))
936 if (!SetLineOffHook(line
))
939 // Should get dial tone within 2 seconds of going off hook
940 if (!WaitForTone(line
, DialTone
, 2000)) {
948 while ((nextPos
= number
.FindOneOf("!@,")) != P_MAX_INDEX
) {
949 PlayDTMF(line
, number(lastPos
, nextPos
-1));
951 switch (number
[nextPos
]) {
953 if (!HookFlash(line
))
958 if (!WaitForTone(line
, DialTone
, 3000)) {
965 PThread::Current()->Sleep(2000);
970 PlayDTMF(line
, number
.Mid(lastPos
));
972 // Wait for busy or ring back
974 while ((tones
= WaitForToneDetect(line
, 5000)) != NoTone
) {
975 if (tones
& BusyTone
)
977 else if (tones
& RingTone
)
988 const char * isoName
;
990 OpalLineInterfaceDevice::T35CountryCodes t35Code
;
991 const char * fullName
;
992 const char * dialTone
;
993 const char * ringTone
;
994 const char * busyTone
;
996 { "AF", 93, OpalLineInterfaceDevice::Afghanistan
, "Afghanistan" },
997 { "AL", 355, OpalLineInterfaceDevice::Albania
, "Albania" },
998 { "DZ", 213, OpalLineInterfaceDevice::Algeria
, "Algeria" },
999 { "AS", 684, OpalLineInterfaceDevice::AmericanSamoa
, "American Samoa" },
1000 { "AO", 244, OpalLineInterfaceDevice::Angola
, "Angola" },
1001 { "AI", 1264, OpalLineInterfaceDevice::Anguilla
, "Anguilla" },
1002 { "AG", 1268, OpalLineInterfaceDevice::AntiguaAndBarbuda
, "Antigua and Barbuda" },
1003 { "AR", 54, OpalLineInterfaceDevice::Argentina
, "Argentina" },
1004 { "AC", 247, OpalLineInterfaceDevice::Ascension
, "Ascension Island" },
1005 { "AU", 61, OpalLineInterfaceDevice::Australia
, "Australia", "425:0.1", "425:0.4-0.2-0.4-2", "425:0.375-0.375" },
1006 { "AT", 43, OpalLineInterfaceDevice::Austria
, "Austria" },
1007 { "BS", 1242, OpalLineInterfaceDevice::Bahamas
, "Bahamas" },
1008 { "BH", 973, OpalLineInterfaceDevice::Bahrain
, "Bahrain" },
1009 { "BD", 880, OpalLineInterfaceDevice::Bangladesh
, "Bangladesh" },
1010 { "BB", 1246, OpalLineInterfaceDevice::Barbados
, "Barbados" },
1011 { "BE", 32, OpalLineInterfaceDevice::Belgium
, "Belgium" },
1012 { "BZ", 501, OpalLineInterfaceDevice::Belize
, "Belize" },
1013 { "BJ", 229, OpalLineInterfaceDevice::Benin
, "Benin" },
1014 { "BM", 1441, OpalLineInterfaceDevice::Bermudas
, "Bermudas" },
1015 { "BT", 975, OpalLineInterfaceDevice::Bhutan
, "Bhutan" },
1016 { "BO", 591, OpalLineInterfaceDevice::Bolivia
, "Bolivia" },
1017 { "BW", 267, OpalLineInterfaceDevice::Botswana
, "Botswana" },
1018 { "BR", 55, OpalLineInterfaceDevice::Brazil
, "Brazil" },
1019 { "xx", 0, OpalLineInterfaceDevice::BritishAntarcticTerritory
, "British Antarctic Territory" },
1020 { "IO", 246, OpalLineInterfaceDevice::BritishIndianOceanTerritory
, "British IndianOcean Territory" },
1021 { "VG", 1284, OpalLineInterfaceDevice::BritishVirginIslands
, "British Virgin Islands" },
1022 { "BN", 673, OpalLineInterfaceDevice::BruneiDarussalam
, "Brunei Darussalam" },
1023 { "BG", 359, OpalLineInterfaceDevice::Bulgaria
, "Bulgaria" },
1024 { "BF", 226, OpalLineInterfaceDevice::BurkinaFaso
, "Burkina Faso" },
1025 { "BI", 257, OpalLineInterfaceDevice::Burundi
, "Burundi" },
1026 { "xx", 0, OpalLineInterfaceDevice::Byelorussia
, "Byelorussia" },
1027 { "KH", 855, OpalLineInterfaceDevice::Cambodia
, "Cambodia" },
1028 { "CM", 237, OpalLineInterfaceDevice::Cameroon
, "Cameroon" },
1029 { "CA", 1, OpalLineInterfaceDevice::Canada
, "Canada" },
1030 { "CV", 238, OpalLineInterfaceDevice::CapeVerde
, "Cape Verde" },
1031 { "KY", 1345, OpalLineInterfaceDevice::CaymanIslands
, "Cayman Islands" },
1032 { "CF", 236, OpalLineInterfaceDevice::CentralAfricanRepublic
,"Central African Republic" },
1033 { "TD", 235, OpalLineInterfaceDevice::Chad
, "Chad" },
1034 { "CL", 56, OpalLineInterfaceDevice::Chile
, "Chile" },
1035 { "CN", 86, OpalLineInterfaceDevice::China
, "China" },
1036 { "CO", 57, OpalLineInterfaceDevice::Colombia
, "Colombia" },
1037 { "KM", 269, OpalLineInterfaceDevice::Comoros
, "Comoros" },
1038 { "CG", 242, OpalLineInterfaceDevice::Congo
, "Congo" },
1039 { "CK", 682, OpalLineInterfaceDevice::CookIslands
, "Cook Islands" },
1040 { "CR", 506, OpalLineInterfaceDevice::CostaRica
, "Costa Rica" },
1041 { "CI", 225, OpalLineInterfaceDevice::CotedIvoire
, "Cote dIvoire" },
1042 { "CU", 53, OpalLineInterfaceDevice::Cuba
, "Cuba" },
1043 { "CY", 357, OpalLineInterfaceDevice::Cyprus
, "Cyprus" },
1044 { "CZ", 420, OpalLineInterfaceDevice::Czechoslovakia
, "Czech Republic" },
1045 { "DK", 45, OpalLineInterfaceDevice::Denmark
, "Denmark" },
1046 { "DJ", 253, OpalLineInterfaceDevice::Djibouti
, "Djibouti" },
1047 { "DM", 1767, OpalLineInterfaceDevice::Dominica
, "Dominica" },
1048 { "DO", 1809, OpalLineInterfaceDevice::DominicanRepublic
, "Dominican Republic" },
1049 { "EC", 593, OpalLineInterfaceDevice::Ecuador
, "Ecuador" },
1050 { "EG", 20, OpalLineInterfaceDevice::Egypt
, "Egypt" },
1051 { "SV", 503, OpalLineInterfaceDevice::ElSalvador
, "El Salvador" },
1052 { "GQ", 240, OpalLineInterfaceDevice::EquatorialGuinea
, "Equatorial Guinea" },
1053 { "ET", 251, OpalLineInterfaceDevice::Ethiopia
, "Ethiopia" },
1054 { "FK", 500, OpalLineInterfaceDevice::FalklandIslands
, "Falkland Islands" },
1055 { "FJ", 679, OpalLineInterfaceDevice::Fiji
, "Fiji" },
1056 { "FI", 358, OpalLineInterfaceDevice::Finland
, "Finland" },
1057 { "FR", 33, OpalLineInterfaceDevice::France
, "France" },
1058 { "PF", 689, OpalLineInterfaceDevice::FrenchPolynesia
, "French Polynesia" },
1059 { "TF", 0, OpalLineInterfaceDevice::FrenchSouthernAndAntarcticLands
, "French Southern and Antarctic Lands" },
1060 { "GA", 241, OpalLineInterfaceDevice::Gabon
, "Gabon" },
1061 { "GM", 220, OpalLineInterfaceDevice::Gambia
, "Gambia" },
1062 { "DE", 49, OpalLineInterfaceDevice::Germany
, "Germany" },
1063 { "GH", 233, OpalLineInterfaceDevice::Ghana
, "Ghana" },
1064 { "GI", 350, OpalLineInterfaceDevice::Gibraltar
, "Gibraltar" },
1065 { "GR", 30, OpalLineInterfaceDevice::Greece
, "Greece" },
1066 { "GD", 1473, OpalLineInterfaceDevice::Grenada
, "Grenada" },
1067 { "GU", 1671, OpalLineInterfaceDevice::Guam
, "Guam" },
1068 { "GT", 502, OpalLineInterfaceDevice::Guatemala
, "Guatemala" },
1069 { "GY", 592, OpalLineInterfaceDevice::Guayana
, "Guayana" },
1070 { "GG", 441, OpalLineInterfaceDevice::Guernsey
, "Guernsey" },
1071 { "GN", 224, OpalLineInterfaceDevice::Guinea
, "Guinea" },
1072 { "GW", 245, OpalLineInterfaceDevice::GuineaBissau
, "Guinea Bissau" },
1073 { "HT", 509, OpalLineInterfaceDevice::Haiti
, "Haiti" },
1074 { "HN", 504, OpalLineInterfaceDevice::Honduras
, "Honduras" },
1075 { "HK", 852, OpalLineInterfaceDevice::Hongkong
, "Hong Kong" },
1076 { "HU", 36, OpalLineInterfaceDevice::Hungary
, "Hungary" },
1077 { "IS", 354, OpalLineInterfaceDevice::Iceland
, "Iceland" },
1078 { "IN", 91, OpalLineInterfaceDevice::India
, "India" },
1079 { "ID", 62, OpalLineInterfaceDevice::Indonesia
, "Indonesia" },
1080 { "IR", 98, OpalLineInterfaceDevice::Iran
, "Iran" },
1081 { "IQ", 964, OpalLineInterfaceDevice::Iraq
, "Iraq" },
1082 { "IE", 353, OpalLineInterfaceDevice::Ireland
, "Ireland" },
1083 { "IL", 972, OpalLineInterfaceDevice::Israel
, "Israel" },
1084 { "IT", 39, OpalLineInterfaceDevice::Italy
, "Italy" },
1085 { "JM", 1876, OpalLineInterfaceDevice::Jamaica
, "Jamaica" },
1086 { "JP", 81, OpalLineInterfaceDevice::Japan
, "Japan" },
1087 { "JE", 442, OpalLineInterfaceDevice::Jersey
, "Jersey" },
1088 { "JO", 962, OpalLineInterfaceDevice::Jordan
, "Jordan" },
1089 { "KE", 254, OpalLineInterfaceDevice::Kenya
, "Kenya" },
1090 { "KI", 686, OpalLineInterfaceDevice::Kiribati
, "Kiribati" },
1091 { "KR", 82, OpalLineInterfaceDevice::KoreaRepublic
, "Korea, Republic of" },
1092 { "KP", 850, OpalLineInterfaceDevice::DemocraticPeoplesRepublicOfKorea
, "Korea, Democratic Peoples Republic of" },
1093 { "KW", 965, OpalLineInterfaceDevice::Kuwait
, "Kuwait" },
1094 { "LA", 856, OpalLineInterfaceDevice::Lao
, "Lao" },
1095 { "LB", 961, OpalLineInterfaceDevice::Lebanon
, "Lebanon" },
1096 { "LS", 266, OpalLineInterfaceDevice::Lesotho
, "Lesotho" },
1097 { "LR", 231, OpalLineInterfaceDevice::Liberia
, "Liberia" },
1098 { "LY", 218, OpalLineInterfaceDevice::Libya
, "Libya" },
1099 { "LI", 423, OpalLineInterfaceDevice::Liechtenstein
, "Liechtenstein" },
1100 { "LU", 352, OpalLineInterfaceDevice::Luxemborg
, "Luxemborg" },
1101 { "MO", 853, OpalLineInterfaceDevice::Macao
, "Macao" },
1102 { "MG", 261, OpalLineInterfaceDevice::Madagascar
, "Madagascar" },
1103 { "MY", 60, OpalLineInterfaceDevice::Malaysia
, "Malaysia" },
1104 { "MW", 265, OpalLineInterfaceDevice::Malawi
, "Malawi" },
1105 { "MV", 960, OpalLineInterfaceDevice::Maldives
, "Maldives" },
1106 { "ML", 223, OpalLineInterfaceDevice::Mali
, "Mali" },
1107 { "MT", 356, OpalLineInterfaceDevice::Malta
, "Malta" },
1108 { "MR", 222, OpalLineInterfaceDevice::Mauritania
, "Mauritania" },
1109 { "MU", 230, OpalLineInterfaceDevice::Mauritius
, "Mauritius" },
1110 { "MX", 52, OpalLineInterfaceDevice::Mexico
, "Mexico" },
1111 { "MC", 377, OpalLineInterfaceDevice::Monaco
, "Monaco" },
1112 { "MN", 976, OpalLineInterfaceDevice::Mongolia
, "Mongolia" },
1113 { "MS", 1664, OpalLineInterfaceDevice::Montserrat
, "Montserrat" },
1114 { "MA", 212, OpalLineInterfaceDevice::Morocco
, "Morocco" },
1115 { "MZ", 258, OpalLineInterfaceDevice::Mozambique
, "Mozambique" },
1116 { "MM", 95, OpalLineInterfaceDevice::Myanmar
, "Myanmar" },
1117 { "NR", 674, OpalLineInterfaceDevice::Nauru
, "Nauru" },
1118 { "NP", 977, OpalLineInterfaceDevice::Nepal
, "Nepal" },
1119 { "NL", 31, OpalLineInterfaceDevice::Netherlands
, "Netherlands", "425:0.1", "425:1.0-4.0", "425:0.5-0.5" },
1120 { "AN", 599, OpalLineInterfaceDevice::NetherlandsAntilles
, "Netherlands Antilles" },
1121 { "NC", 687, OpalLineInterfaceDevice::NewCaledonia
, "New Caledonia" },
1122 { "NZ", 64, OpalLineInterfaceDevice::NewZealand
, "New Zealand" },
1123 { "NI", 505, OpalLineInterfaceDevice::Nicaragua
, "Nicaragua" },
1124 { "NE", 227, OpalLineInterfaceDevice::Niger
, "Niger" },
1125 { "NG", 234, OpalLineInterfaceDevice::Nigeria
, "Nigeria" },
1126 { "NO", 47, OpalLineInterfaceDevice::Norway
, "Norway" },
1127 { "OM", 968, OpalLineInterfaceDevice::Oman
, "Oman" },
1128 { "PK", 92, OpalLineInterfaceDevice::Pakistan
, "Pakistan" },
1129 { "PA", 507, OpalLineInterfaceDevice::Panama
, "Panama" },
1130 { "PG", 675, OpalLineInterfaceDevice::PapuaNewGuinea
, "Papua New Guinea" },
1131 { "PY", 595, OpalLineInterfaceDevice::Paraguay
, "Paraguay" },
1132 { "PE", 51, OpalLineInterfaceDevice::Peru
, "Peru" },
1133 { "PH", 63, OpalLineInterfaceDevice::Philippines
, "Philippines" },
1134 { "PL", 48, OpalLineInterfaceDevice::Poland
, "Poland" },
1135 { "PT", 351, OpalLineInterfaceDevice::Portugal
, "Portugal" },
1136 { "PR", 1787, OpalLineInterfaceDevice::PuertoRico
, "Puerto Rico" },
1137 { "QA", 974, OpalLineInterfaceDevice::Qatar
, "Qatar" },
1138 { "RO", 40, OpalLineInterfaceDevice::Romania
, "Romania" },
1139 { "RU", 7, OpalLineInterfaceDevice::USSR
, "Russia" },
1140 { "RW", 250, OpalLineInterfaceDevice::Rwanda
, "Rwanda" },
1141 { "xx", 0, OpalLineInterfaceDevice::SaintCroix
, "Saint Croix" },
1142 { "SH", 290, OpalLineInterfaceDevice::SaintHelenaAndAscension
, "Saint Helena and Ascension" },
1143 { "KN", 1869, OpalLineInterfaceDevice::SaintKittsAndNevis
, "Saint Kitts and Nevis" },
1144 { "LC", 1758, OpalLineInterfaceDevice::SaintLucia
, "Saint Lucia" },
1145 { "xx", 0, OpalLineInterfaceDevice::SaintThomas
, "Saint Thomas" },
1146 { "VC", 1784, OpalLineInterfaceDevice::SaintVicentAndTheGrenadines
, "Saint Vicent and the Grenadines" },
1147 { "SM", 378, OpalLineInterfaceDevice::SanMarino
, "San Marino" },
1148 { "ST", 239, OpalLineInterfaceDevice::SaoTomeAndPrincipe
, "Sao Tome and Principe" },
1149 { "SA", 966, OpalLineInterfaceDevice::SaudiArabia
, "Saudi Arabia" },
1150 { "SN", 221, OpalLineInterfaceDevice::Senegal
, "Senegal" },
1151 { "SC", 248, OpalLineInterfaceDevice::Seychelles
, "Seychelles" },
1152 { "SL", 232, OpalLineInterfaceDevice::SierraLeone
, "Sierra Leone" },
1153 { "SG", 65, OpalLineInterfaceDevice::Singapore
, "Singapore", "425:0.1", "425:0.4-0.2-0.4-2", "425:0.75-0.75"},
1154 { "SB", 677, OpalLineInterfaceDevice::SolomonIslands
, "Solomon Islands" },
1155 { "SO", 252, OpalLineInterfaceDevice::Somalia
, "Somalia" },
1156 { "ZA", 27, OpalLineInterfaceDevice::SouthAfrica
, "South Africa" },
1157 { "ES", 34, OpalLineInterfaceDevice::Spain
, "Spain" },
1158 { "LK", 94, OpalLineInterfaceDevice::SriLanka
, "Sri Lanka" },
1159 { "SD", 249, OpalLineInterfaceDevice::Sudan
, "Sudan" },
1160 { "SR", 597, OpalLineInterfaceDevice::Suriname
, "Suriname" },
1161 { "SZ", 268, OpalLineInterfaceDevice::Swaziland
, "Swaziland" },
1162 { "SE", 46, OpalLineInterfaceDevice::Sweden
, "Sweden" },
1163 { "CH", 41, OpalLineInterfaceDevice::Switzerland
, "Switzerland" },
1164 { "SY", 963, OpalLineInterfaceDevice::Syria
, "Syria" },
1165 { "TZ", 255, OpalLineInterfaceDevice::Tanzania
, "Tanzania" },
1166 { "TH", 66, OpalLineInterfaceDevice::Thailand
, "Thailand" },
1167 { "TG", 228, OpalLineInterfaceDevice::Togo
, "Togo" },
1168 { "TO", 676, OpalLineInterfaceDevice::Tonga
, "Tonga" },
1169 { "TT", 1868, OpalLineInterfaceDevice::TrinidadAndTobago
, "Trinidad and Tobago" },
1170 { "TN", 216, OpalLineInterfaceDevice::Tunisia
, "Tunisia" },
1171 { "TR", 90, OpalLineInterfaceDevice::Turkey
, "Turkey" },
1172 { "TC", 1649, OpalLineInterfaceDevice::TurksAndCaicosIslands
, "Turks and Caicos Islands" },
1173 { "TV", 688, OpalLineInterfaceDevice::Tuvalu
, "Tuvalu" },
1174 { "UG", 256, OpalLineInterfaceDevice::Uganda
, "Uganda" },
1175 { "UA", 380, OpalLineInterfaceDevice::Ukraine
, "Ukraine" },
1176 { "AE", 971, OpalLineInterfaceDevice::UnitedArabEmirates
, "United Arab Emirates" },
1177 { "GB", 44, OpalLineInterfaceDevice::UnitedKingdom
, "United Kingdom", "350-440:0.1", "400-450:0.4-0.2-0.4-2", "400:0.375-0.375" },
1178 { "US", 1, OpalLineInterfaceDevice::UnitedStates
, "United States", "350-440:0.1", "440-480:2.0-4.0", "480-620:0.5-0.5" },
1179 { "UY", 598, OpalLineInterfaceDevice::Uruguay
, "Uruguay" },
1180 { "VU", 678, OpalLineInterfaceDevice::Vanuatu
, "Vanuatu" },
1181 { "VA", 379, OpalLineInterfaceDevice::VaticanCityState
, "Vatican City State" },
1182 { "VE", 58, OpalLineInterfaceDevice::Venezuela
, "Venezuela" },
1183 { "VN", 84, OpalLineInterfaceDevice::VietNam
, "Viet Nam" },
1184 { "WF", 681, OpalLineInterfaceDevice::WallisAndFutuna
, "Wallis and Futuna" },
1185 { "WS", 685, OpalLineInterfaceDevice::WesternSamoa
, "Western Samoa" },
1186 { "YE", 967, OpalLineInterfaceDevice::Yemen
, "Yemen" },
1187 { "YU", 381, OpalLineInterfaceDevice::Yugoslavia
, "Yugoslavia" },
1188 { "xx", 0, OpalLineInterfaceDevice::Zaire
, "Zaire" },
1189 { "ZM", 260, OpalLineInterfaceDevice::Zambia
, "Zambia" },
1190 { "ZW", 263, OpalLineInterfaceDevice::Zimbabwe
, "Zimbabwe" }
1193 OpalLineInterfaceDevice::T35CountryCodes
OpalLineInterfaceDevice::GetCountryCode(const PString
& str
)
1195 for (PINDEX i
= 0; i
< PARRAYSIZE(CountryInfo
); i
++)
1196 if (str
*= CountryInfo
[i
].fullName
)
1197 return CountryInfo
[i
].t35Code
;
1199 return OpalLineInterfaceDevice::UnknownCountry
;
1203 PString
OpalLineInterfaceDevice::GetCountryCodeName(T35CountryCodes c
)
1205 for (PINDEX i
= 0; i
< PARRAYSIZE(CountryInfo
); i
++)
1206 if (CountryInfo
[i
].t35Code
== c
)
1207 return CountryInfo
[i
].fullName
;
1213 PString
OpalLineInterfaceDevice::GetCountryCodeName() const
1215 return GetCountryCodeName(countryCode
);
1219 BOOL
OpalLineInterfaceDevice::SetCountryCode(T35CountryCodes country
)
1221 countryCode
= country
;
1224 for (line
= 0; line
< GetLineCount(); line
++)
1225 SetToneFilter(line
, CNGTone
, "1100:0.25");
1227 for (PINDEX i
= 0; i
< PARRAYSIZE(CountryInfo
); i
++) {
1228 if (CountryInfo
[i
].t35Code
== country
) {
1229 PTRACE(2, "LID\tCountry set to " << CountryInfo
[i
].fullName
);
1230 for (line
= 0; line
< GetLineCount(); line
++) {
1231 if (CountryInfo
[i
].dialTone
!= NULL
)
1232 SetToneFilter(line
, DialTone
, CountryInfo
[i
].dialTone
);
1233 if (CountryInfo
[i
].ringTone
!= NULL
)
1234 SetToneFilter(line
, RingTone
, CountryInfo
[i
].ringTone
);
1235 if (CountryInfo
[i
].busyTone
!= NULL
)
1236 SetToneFilter(line
, BusyTone
, CountryInfo
[i
].busyTone
);
1242 PTRACE(2, "LID\tCountry set to " << GetCountryCodeName());
1247 PStringList
OpalLineInterfaceDevice::GetCountryCodeNameList() const
1250 list
.AppendString("United States");
1255 static PCaselessString
DeSpaced(const PString
& orig
)
1257 PString str
= orig
.Trim();
1260 while ((space
= str
.Find(' ')) != P_MAX_INDEX
)
1261 str
.Delete(space
, 1);
1267 BOOL
OpalLineInterfaceDevice::SetCountryCodeName(const PString
& countryName
)
1269 PTRACE(4, "IXJ\tSetting country code name to " << countryName
);
1270 PCaselessString spacelessAndCaseless
= DeSpaced(countryName
);
1271 if (spacelessAndCaseless
.IsEmpty())
1274 if (isdigit(spacelessAndCaseless
[0]))
1275 return SetCountryCode((T35CountryCodes
)spacelessAndCaseless
.AsUnsigned());
1278 if (spacelessAndCaseless
[0] == '+') {
1279 unsigned code
= spacelessAndCaseless
.AsUnsigned();
1280 for (i
= 0; i
< PARRAYSIZE(CountryInfo
); i
++)
1281 if (code
== CountryInfo
[i
].dialCode
)
1282 return SetCountryCode(CountryInfo
[i
].t35Code
);
1284 else if (spacelessAndCaseless
.GetLength() == 2) {
1285 for (i
= 0; i
< PARRAYSIZE(CountryInfo
); i
++)
1286 if (spacelessAndCaseless
== CountryInfo
[i
].isoName
)
1287 return SetCountryCode(CountryInfo
[i
].t35Code
);
1290 for (i
= 0; i
< PARRAYSIZE(CountryInfo
); i
++)
1291 if (spacelessAndCaseless
== DeSpaced(CountryInfo
[i
].fullName
))
1292 return SetCountryCode(CountryInfo
[i
].t35Code
);
1295 SetCountryCode(UnknownCountry
);
1300 PString
OpalLineInterfaceDevice::GetErrorText() const
1302 return PChannel::GetErrorText(PChannel::Miscellaneous
, osError
);
1306 void OpalLineInterfaceDevice::PrintOn(ostream
& strm
) const
1312 /////////////////////////////////////////////////////////////////////////////
1317 unsigned bytesPerFrame
;
1318 unsigned rxFramesInPacket
;
1319 unsigned txFramesInPacket
;
1322 H245_AudioCapability::Choices capabilitySubtype
;
1324 } CodecTypeInfo
[] = {
1325 // Do not alter the order of the next four entries without understanding what
1326 // H323_LIDCapability::OnReceivedPDU() does with them!
1327 #define G7231A_63_INDEX 1
1328 { OPAL_G7231A_5k3
, 24, 8, 3, TRUE
, H245_AudioCapability::e_g7231
},
1329 { OPAL_G7231A_6k3
, 24, 8, 3, TRUE
, H245_AudioCapability::e_g7231
},
1330 { OPAL_G7231_5k3
, 24, 8, 3, FALSE
, H245_AudioCapability::e_g7231
},
1331 { OPAL_G7231_6k3
, 24, 8, 3, FALSE
, H245_AudioCapability::e_g7231
},
1333 { OPAL_G729
, 10, 24, 6, FALSE
, H245_AudioCapability::e_g729
},
1334 { OPAL_G729A
, 10, 24, 6, FALSE
, H245_AudioCapability::e_g729AnnexA
},
1335 { OPAL_G729B
, 10, 24, 6, FALSE
, H245_AudioCapability::e_g729wAnnexB
},
1336 { OPAL_G729AB
, 10, 24, 6, FALSE
, H245_AudioCapability::e_g729AnnexAwAnnexB
},
1337 { OPAL_GSM0610
, 33, 7, 4, FALSE
, H245_AudioCapability::e_gsmFullRate
},
1338 { OPAL_G728
, 5, 96, 20, FALSE
, H245_AudioCapability::e_g728
},
1339 { OPAL_G711_ULAW_64K
, 8, 240, 30, FALSE
, H245_AudioCapability::e_g711Ulaw64k
},
1340 { OPAL_G711_ALAW_64K
, 8, 240, 30, FALSE
, H245_AudioCapability::e_g711Alaw64k
},
1343 #define DEFINE_LID_CAPABILITY(cls, capName, fmtName) \
1344 class cls : public H323_LIDCapability { \
1346 cls() : H323_LIDCapability(fmtName) { } \
1348 H323_REGISTER_CAPABILITY(cls, capName) \
1350 DEFINE_LID_CAPABILITY(H323_LID_G711_ALaw_Capability, OPAL_G711_ALAW_64K"{hw}", OpalG711ALaw)
1351 DEFINE_LID_CAPABILITY(H323_LID_G711_uLaw_Capability
, OPAL_G711_ULAW_64K
"{hw}", OpalG711uLaw
)
1352 DEFINE_LID_CAPABILITY(H323_LID_G728_Capability
, OPAL_G728
"{hw}", OpalG728
)
1353 DEFINE_LID_CAPABILITY(H323_LID_GSM0610_Capability
, OPAL_GSM0610
"{hw}", OpalGSM0610
)
1354 DEFINE_LID_CAPABILITY(H323_LID_G729_Capability
, OPAL_G729
"{hw}", OpalG729
)
1355 DEFINE_LID_CAPABILITY(H323_LID_G729A_Capability
, OPAL_G729A
"{hw}", OpalG729A
)
1356 DEFINE_LID_CAPABILITY(H323_LID_G729B_Capability
, OPAL_G729B
"{hw}", OpalG729B
)
1357 DEFINE_LID_CAPABILITY(H323_LID_G729AB_Capability
, OPAL_G729AB
"{hw}", OpalG729AB
)
1358 DEFINE_LID_CAPABILITY(H323_LID_G7231_6k3_Capability
, OPAL_G7231_6k3
"{hw}", OpalG7231_6k3
)
1359 DEFINE_LID_CAPABILITY(H323_LID_G7231_5k3_Capability
, OPAL_G7231_5k3
"{hw}", OpalG7231_5k3
)
1360 DEFINE_LID_CAPABILITY(H323_LID_G7231A_6k3_Capability
, OPAL_G7231A_6k3
"{hw}", OpalG7231A_6k3
)
1361 DEFINE_LID_CAPABILITY(H323_LID_G7231A_5k3_Capability
, OPAL_G7231A_5k3
"{hw}", OpalG7231A_5k3
)
1363 #define G7231_CISCO OPAL_G7231A_6k3"-Cisco{hw}"
1364 H323_REGISTER_CAPABILITY(H323_CiscoG7231aLIDCapability
, G7231_CISCO
)
1366 /////////////////////////////////////////////////////////////////////////////
1368 OpalLineChannel::OpalLineChannel(OpalLineInterfaceDevice
& dev
,
1370 const H323AudioCodec
& codec
)
1374 reading
= codec
.GetDirection() == H323Codec::Encoder
;
1375 OpalMediaFormat mediaFormat
= OpalPCM16
;
1377 if (PIsDescendant(&codec
, H323_LIDCodec
)) {
1378 OpalMediaFormat::List mediaFormats
= device
.GetMediaFormats();
1379 for (PINDEX i
= 0; i
< mediaFormats
.GetSize(); i
++) {
1380 if (mediaFormats
[i
] == codec
.GetMediaFormat())
1381 mediaFormat
= codec
.GetMediaFormat();
1386 if (!device
.SetReadFormat(lineNumber
, mediaFormat
))
1388 useDeblocking
= mediaFormat
.GetFrameSize() != device
.GetReadFrameSize(lineNumber
);
1391 if (!device
.SetWriteFormat(lineNumber
, mediaFormat
))
1393 useDeblocking
= mediaFormat
.GetFrameSize() != device
.GetWriteFrameSize(lineNumber
);
1396 PTRACE(3, "LID\tCodec set to " << mediaFormat
<< ", frame size: rd="
1397 << device
.GetReadFrameSize(lineNumber
) << " wr="
1398 << device
.GetWriteFrameSize(lineNumber
) << ", "
1399 << (useDeblocking
? "needs" : "no") << " reblocking.");
1404 OpalLineChannel::~OpalLineChannel()
1410 PString
OpalLineChannel::GetName() const
1412 return device
.GetName() + psprintf("-%u", lineNumber
);
1416 BOOL
OpalLineChannel::Close()
1424 return device
.StopReadCodec(lineNumber
);
1426 return device
.StopWriteCodec(lineNumber
);
1430 BOOL
OpalLineChannel::Read(void * buffer
, PINDEX length
)
1435 return SetErrorValues(Miscellaneous
, EINVAL
, LastReadError
);
1437 if (useDeblocking
) {
1438 device
.SetReadFrameSize(lineNumber
, length
);
1439 if (device
.ReadBlock(lineNumber
, buffer
, length
)) {
1440 lastReadCount
= length
;
1445 if (device
.ReadFrame(lineNumber
, buffer
, lastReadCount
))
1449 int osError
= device
.GetErrorNumber();
1450 PTRACE_IF(1, osError
!= 0, "LID\tDevice read frame error: " << device
.GetErrorText());
1452 return SetErrorValues(Miscellaneous
, osError
, LastReadError
);
1456 BOOL
OpalLineChannel::Write(const void * buffer
, PINDEX length
)
1461 return SetErrorValues(Miscellaneous
, EINVAL
, LastWriteError
);
1463 if (useDeblocking
) {
1464 device
.SetWriteFrameSize(lineNumber
, length
);
1465 if (device
.WriteBlock(lineNumber
, buffer
, length
)) {
1466 lastWriteCount
= length
;
1471 if (device
.WriteFrame(lineNumber
, buffer
, length
, lastWriteCount
))
1475 int osError
= device
.GetErrorNumber();
1476 PTRACE_IF(1, osError
!= 0, "LID\tDevice write frame error: " << device
.GetErrorText());
1478 return SetErrorValues(Miscellaneous
, osError
, LastWriteError
);
1482 ///////////////////////////////////////////////////////////////////////////////
1484 void H323_LIDCapability::AddAllCapabilities(const OpalLineInterfaceDevice
& device
,
1485 H323Capabilities
& capabilities
,
1486 PINDEX descriptorNum
,
1487 PINDEX simultaneous
)
1489 OpalMediaFormat::List codecsAvailable
= device
.GetMediaFormats();
1490 for (PINDEX c
= 0; c
< codecsAvailable
.GetSize(); c
++) {
1491 H323_LIDCapability
* cap
= new H323_LIDCapability(codecsAvailable
[c
]);
1492 if (cap
->IsValid() && !capabilities
.FindCapability(*cap
))
1493 capabilities
.SetCapability(descriptorNum
, simultaneous
, cap
);
1496 if (codecsAvailable
[c
] == OpalG7231A_6k3
)
1497 capabilities
.SetCapability(descriptorNum
, simultaneous
,
1498 new H323_CiscoG7231aLIDCapability
);
1503 H323_LIDCapability::H323_LIDCapability(const OpalMediaFormat
& fmt
)
1504 : H323AudioCapability(0, 0),
1507 codecTableIndex
= 0;
1510 if (mediaFormat
== CodecTypeInfo
[codecTableIndex
].name
) {
1511 rxFramesInPacket
= CodecTypeInfo
[codecTableIndex
].rxFramesInPacket
;
1512 txFramesInPacket
= CodecTypeInfo
[codecTableIndex
].txFramesInPacket
;
1521 BOOL
H323_LIDCapability::IsValid() const
1523 return codecTableIndex
< PARRAYSIZE(CodecTypeInfo
);
1527 PObject::Comparison
H323_LIDCapability::Compare(const PObject
& obj
) const
1529 if (!PIsDescendant(&obj
, H323_LIDCapability
))
1532 Comparison result
= H323AudioCapability::Compare(obj
);
1533 if (result
!= EqualTo
)
1536 PINDEX otherIndex
= ((const H323_LIDCapability
&)obj
).codecTableIndex
;
1537 if (CodecTypeInfo
[codecTableIndex
].g7231annexA
< CodecTypeInfo
[otherIndex
].g7231annexA
)
1539 if (CodecTypeInfo
[codecTableIndex
].g7231annexA
> CodecTypeInfo
[otherIndex
].g7231annexA
)
1545 PObject
* H323_LIDCapability::Clone() const
1547 return new H323_LIDCapability(*this);
1551 PString
H323_LIDCapability::GetFormatName() const
1553 return mediaFormat
+ "{hw}";
1557 unsigned H323_LIDCapability::GetSubType() const
1559 return CodecTypeInfo
[codecTableIndex
].capabilitySubtype
;
1563 H323Codec
* H323_LIDCapability::CreateCodec(H323Codec::Direction direction
) const
1565 return new H323_LIDCodec(mediaFormat
,
1567 direction
== H323Codec::Encoder
? txFramesInPacket
: rxFramesInPacket
,
1572 BOOL
H323_LIDCapability::OnSendingPDU(H245_AudioCapability
& pdu
,
1573 unsigned packetSize
) const
1575 pdu
.SetTag(GetSubType());
1577 switch (pdu
.GetTag()) {
1578 case H245_AudioCapability::e_gsmFullRate
:
1580 H245_GSMAudioCapability
& gsm
= pdu
;
1581 gsm
.m_audioUnitSize
= packetSize
*33;
1584 case H245_AudioCapability::e_g7231
:
1586 H245_AudioCapability_g7231
& g7231
= pdu
;
1587 g7231
.m_maxAl_sduAudioFrames
= packetSize
;
1588 g7231
.m_silenceSuppression
= CodecTypeInfo
[codecTableIndex
].g7231annexA
;
1593 PASN_Integer
& value
= pdu
;
1602 BOOL
H323_LIDCapability::OnReceivedPDU(const H245_AudioCapability
& pdu
,
1603 unsigned & packetSize
)
1605 if (pdu
.GetTag() != GetSubType())
1608 switch (pdu
.GetTag()) {
1609 case H245_AudioCapability::e_gsmFullRate
:
1611 const H245_GSMAudioCapability
& gsm
= pdu
;
1612 packetSize
= gsm
.m_audioUnitSize
/33;
1615 case H245_AudioCapability::e_g7231
:
1617 const H245_AudioCapability_g7231
& g7231
= pdu
;
1618 packetSize
= g7231
.m_maxAl_sduAudioFrames
;
1620 BOOL g7231annexA
= g7231
.m_silenceSuppression
;
1621 if (g7231annexA
!= CodecTypeInfo
[codecTableIndex
].g7231annexA
) {
1622 // Move to the other G.723.1 version
1623 codecTableIndex
+= (g7231annexA
? -2 : 2);
1624 mediaFormat
= CodecTypeInfo
[codecTableIndex
].name
;
1630 const PASN_Integer
& value
= pdu
;
1639 /////////////////////////////////////////////////////////////////////////////
1641 H323_CiscoG7231aLIDCapability::H323_CiscoG7231aLIDCapability()
1642 : H323NonStandardAudioCapability(1, 1, 181, 0, 18, (const BYTE
*)"G7231ar", 7)
1647 PObject
* H323_CiscoG7231aLIDCapability::Clone() const
1649 return new H323_CiscoG7231aLIDCapability(*this);
1653 PString
H323_CiscoG7231aLIDCapability::GetFormatName() const
1659 H323Codec
* H323_CiscoG7231aLIDCapability::CreateCodec(H323Codec::Direction direction
) const
1661 return new H323_LIDCodec(OpalG7231A_6k3
, direction
, 1, G7231A_63_INDEX
);
1665 /////////////////////////////////////////////////////////////////////////////
1667 H323_LIDCodec::H323_LIDCodec(const char * fmt
,
1668 Direction direction
,
1671 : H323AudioCodec(fmt
, direction
)
1673 codecTableIndex
= index
;
1674 packetSize
= CodecTypeInfo
[index
].bytesPerFrame
;
1676 /* Special case for G.711 encoder, note this helps with optimisation of
1677 sound data but will break if remote does not send the maximum number of
1678 bytes that it said it could. It is legal for the remote end to do so
1679 though no endpoints seem to actually do that.
1681 if (packetSize
== 8) {
1682 packetSize
*= numFrames
;
1683 samplesPerFrame
*= numFrames
;
1688 lastFrameWasSignal
= TRUE
;
1690 PTRACE(3, "LID\tCreated codec: pt=" << mediaFormat
.GetPayloadType()
1691 << ", bytes=" << packetSize
<< ", samples=" << mediaFormat
.GetFrameTime());
1695 BOOL
H323_LIDCodec::Read(BYTE
* buffer
, unsigned & length
, RTP_DataFrame
&)
1697 PWaitAndSignal
mutex(rawChannelMutex
);
1699 // This reads to an H323_IxJChannel class
1701 if (!ReadRaw(buffer
, packetSize
, count
))
1704 // In the case of G.723.1 remember the last SID frame we sent and send
1705 // it again if the hardware sends us a CNG frame.
1706 if (mediaFormat
.GetPayloadType() == RTP_DataFrame::G7231
) {
1708 case 1 : // CNG frame
1709 memcpy(buffer
, lastSID
, 4);
1711 lastFrameWasSignal
= FALSE
;
1714 if ((*buffer
&3) == 2)
1715 memcpy(lastSID
, buffer
, 4);
1716 lastFrameWasSignal
= FALSE
;
1719 lastFrameWasSignal
= TRUE
;
1723 length
= DetectSilence() ? 0 : count
;
1728 BOOL
H323_LIDCodec::Write(const BYTE
* buffer
,
1730 const RTP_DataFrame
& /*frame*/,
1733 // This writes to an H323_IxJChannel class
1734 if (length
> packetSize
)
1735 length
= packetSize
;
1737 // Check for writing silence
1738 PBYTEArray silenceBuffer
;
1742 switch (mediaFormat
.GetPayloadType()) {
1743 case RTP_DataFrame::G7231
:
1744 if (missedCount
++ < 4) {
1745 static const BYTE g723_erasure_frame
[24] = { 0xff, 0xff, 0xff, 0xff };
1746 buffer
= g723_erasure_frame
;
1750 static const BYTE g723_cng_frame
[4] = { 3 };
1751 buffer
= g723_cng_frame
;
1756 case RTP_DataFrame::PCMU
:
1757 case RTP_DataFrame::PCMA
:
1758 buffer
= silenceBuffer
.GetPointer(packetSize
);
1759 memset((void *)buffer
, 0xff, packetSize
);
1760 length
= packetSize
;
1763 case RTP_DataFrame::G729
:
1764 if (mediaFormat
.Find('B') != P_MAX_INDEX
) {
1765 static const BYTE g729_sid_frame
[2] = { 1 };
1766 buffer
= g729_sid_frame
;
1770 // Else fall into default case
1773 buffer
= silenceBuffer
.GetPointer(packetSize
); // Fills with zeros
1774 length
= packetSize
;
1779 PWaitAndSignal
mutex(rawChannelMutex
);
1781 if (!rawDataChannel
->Write(buffer
, length
))
1784 written
= rawDataChannel
->GetLastWriteCount();
1789 BOOL
H323_LIDCodec::IsRawDataChannelNative() const
1795 BOOL
H323_LIDCodec::DetectSilence()
1797 // Can never have silence if NoSilenceDetection
1798 if (silenceDetectMode
== NoSilenceDetection
)
1801 if (!CodecTypeInfo
[codecTableIndex
].g7231annexA
)
1802 return H323AudioCodec::DetectSilence();
1804 // Utilise the codecs own silence detection algorithm
1806 // If no change ie still talking or still silent, resent frame counter
1807 if (inTalkBurst
== lastFrameWasSignal
)
1811 // If have had enough consecutive frames talking/silent, swap modes.
1812 if (framesReceived
>= (inTalkBurst
? silenceDeadbandFrames
: signalDeadbandFrames
)) {
1813 inTalkBurst
= !inTalkBurst
;
1814 PTRACE(4, "Codec\tSilence detection transition: "
1815 << (inTalkBurst
? "Talk" : "Silent"));
1819 return !inTalkBurst
;
1823 unsigned H323_LIDCodec::GetAverageSignalLevel()
1825 PWaitAndSignal
mutex(rawChannelMutex
);
1827 return ((OpalLineChannel
*)rawDataChannel
)->GetDevice().GetAverageSignalLevel(0, direction
== Decoder
);
1831 /////////////////////////////////////////////////////////////////////////////