home *** CD-ROM | disk | FTP | other *** search
/ ftp.muug.mb.ca / 2014.06.ftp.muug.mb.ca.tar / ftp.muug.mb.ca / pub / openh323.tar.gz / openh323.tar / openh323 / src / lid.cxx < prev    next >
Text File  |  2003-08-18  |  62KB  |  1,857 lines

  1. /*
  2.  * lid.cxx
  3.  *
  4.  * Line Interface Device
  5.  *
  6.  * Open Phone Abstraction Library
  7.  *
  8.  * Copyright (c) 1999-2000 Equivalence Pty. Ltd.
  9.  *
  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/
  14.  *
  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
  18.  * under the License.
  19.  *
  20.  * The Original Code is Open H323 Library.
  21.  *
  22.  * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
  23.  *
  24.  * Contributor(s): ______________________________________.
  25.  *
  26.  * $Log: lid.cxx,v $
  27.  * Revision 1.98  2003/08/18 23:56:01  dereksmithies
  28.  * Fix typos in previous commit.
  29.  *
  30.  * Revision 1.97  2003/08/18 22:13:13  dereksmithies
  31.  * Add Singapore Ring Cadence. Thanks to Steve.
  32.  *
  33.  * Revision 1.96  2003/06/03 10:27:42  rjongbloed
  34.  * Added G.729 and G,729B detection from LID.
  35.  *
  36.  * Revision 1.95  2003/04/29 08:30:29  robertj
  37.  * Fixed return type of get wink function.
  38.  *
  39.  * Revision 1.94  2003/04/28 01:47:52  dereks
  40.  * Add ability to set/get wink duration for ixj device.
  41.  *
  42.  * Revision 1.93  2003/03/05 06:26:44  robertj
  43.  * Added function to play a WAV file to LID, thanks Pietro Ravasio
  44.  *
  45.  * Revision 1.92  2003/02/13 23:33:36  dereks
  46.  * Fix reporting of tonenames.
  47.  *
  48.  * Revision 1.91  2003/01/29 23:58:17  dereks
  49.  * Fix typo in United Kingdom tone definition.
  50.  *
  51.  * Revision 1.90  2002/12/02 03:06:26  robertj
  52.  * Fixed over zealous removal of code when NO_AUDIO_CODECS set.
  53.  *
  54.  * Revision 1.89  2002/11/05 04:27:12  robertj
  55.  * Imported RingLine() by array from OPAL.
  56.  *
  57.  * Revision 1.88  2002/10/30 05:54:17  craigs
  58.  * Fixed compatibilty problems with G.723.1 6k3 and 5k3
  59.  *
  60.  * Revision 1.87  2002/08/05 10:03:48  robertj
  61.  * Cosmetic changes to normalise the usage of pragma interface/implementation.
  62.  *
  63.  * Revision 1.86  2002/07/01 02:56:17  dereks
  64.  * Add PTRACE statements to  "IsToneDetected"
  65.  *
  66.  * Revision 1.85  2002/06/27 08:52:57  robertj
  67.  * Fixed typo and naming convention for Cisco G.723.1 annex A capability.
  68.  *
  69.  * Revision 1.84  2002/06/26 05:45:45  robertj
  70.  * Added capability for Cisco IOS non-standard name for G.723.1 Annex A so
  71.  *   can now utilise SID frames with Cisco gateways.
  72.  *
  73.  * Revision 1.83  2002/06/25 08:30:13  robertj
  74.  * Changes to differentiate between stright G.723.1 and G.723.1 Annex A using
  75.  *   the OLC dataType silenceSuppression field so does not send SID frames
  76.  *   to receiver codecs that do not understand them.
  77.  *
  78.  * Revision 1.82  2002/05/09 06:26:34  robertj
  79.  * Added fuction to get the current audio enable state for line in device.
  80.  * Changed IxJ EnableAudio() semantics so is exclusive, no direct switching
  81.  *   from PSTN to POTS and vice versa without disabling the old one first.
  82.  *
  83.  * Revision 1.81  2002/01/23 06:13:56  robertj
  84.  * Added filter function hooks to codec raw data channel.
  85.  *
  86.  * Revision 1.80  2002/01/23 01:58:28  robertj
  87.  * Added function to determine if codecs raw data channel is native format.
  88.  *
  89.  * Revision 1.79  2002/01/13 23:57:04  robertj
  90.  * Added mutex so can change raw data channel while reading/writing from codec.
  91.  *
  92.  * Revision 1.78  2001/12/14 04:33:53  craigs
  93.  * Disabled 5.3k codec due to problems with Quicknet cards
  94.  *
  95.  * Revision 1.77  2001/12/11 04:27:28  craigs
  96.  * Added support for 5.3kbps G723.1
  97.  *
  98.  * Revision 1.76  2001/09/21 02:52:19  robertj
  99.  * Implemented static object for all "known" media formats.
  100.  *
  101.  * Revision 1.75  2001/09/11 01:24:36  robertj
  102.  * Added conditional compilation to remove video and/or audio codecs.
  103.  *
  104.  * Revision 1.74  2001/09/10 03:06:29  robertj
  105.  * Major change to fix problem with error codes being corrupted in a
  106.  *   PChannel when have simultaneous reads and writes in threads.
  107.  *
  108.  * Revision 1.73  2001/08/06 03:08:57  robertj
  109.  * Fission of h323.h to h323ep.h & h323con.h, h323.h now just includes files.
  110.  *
  111.  * Revision 1.72  2001/07/24 02:28:22  robertj
  112.  * Added setting of tone filters for a handful of countries.
  113.  *
  114.  * Revision 1.71  2001/07/20 04:06:18  robertj
  115.  * Removed old Cisco hack code for G.728, they now do it rigth!
  116.  *
  117.  * Revision 1.70  2001/07/19 05:54:30  robertj
  118.  * Updated interface to xJACK drivers to utilise cadence and filter functions
  119.  *   for dial tone, busy tone and ringback tone detection.
  120.  *
  121.  * Revision 1.69  2001/05/30 03:56:57  robertj
  122.  * Fixed initial value of read deblocking offset on stopping codec.
  123.  *
  124.  * Revision 1.68  2001/05/25 07:55:26  robertj
  125.  * Fixed problem with trace output of tone bits, thanks Vjacheslav Andrejev.
  126.  *
  127.  * Revision 1.67  2001/05/25 02:19:53  robertj
  128.  * Fixed problem with codec data reblocking code not being reset when
  129.  *   code is stopped and restarted, thanks Artis Kugevics
  130.  *
  131.  * Revision 1.66  2001/05/22 00:31:43  robertj
  132.  * Changed to allow optional wink detection for line disconnect
  133.  *
  134.  * Revision 1.65  2001/05/14 05:56:28  robertj
  135.  * Added H323 capability registration system so can add capabilities by
  136.  *   string name instead of having to instantiate explicit classes.
  137.  *
  138.  * Revision 1.64  2001/05/11 04:43:43  robertj
  139.  * Added variable names for standard PCM-16 media format name.
  140.  *
  141.  * Revision 1.63  2001/04/03 23:37:48  craigs
  142.  * Added extra logging of country change functions
  143.  *
  144.  * Revision 1.62  2001/03/29 23:43:02  robertj
  145.  * Added ability to get average signal level for both receive and transmit.
  146.  * Changed silence detection to use G.723.1 SID frames as indicator of
  147.  *   silence instead of using the average energy and adaptive threshold.
  148.  *
  149.  * Revision 1.61  2001/03/23 05:38:30  robertj
  150.  * Added PTRACE_IF to output trace if a conditional is TRUE.
  151.  *
  152.  * Revision 1.60  2001/02/09 05:36:38  craigs
  153.  * Added pragma implementation
  154.  *
  155.  * Revision 1.59  2001/01/28 06:29:55  yurik
  156.  * WinCE-port - lid.h exists in SDK so we point to right one
  157.  *
  158.  * Revision 1.58  2001/01/25 07:27:16  robertj
  159.  * Major changes to add more flexible OpalMediaFormat class to normalise
  160.  *   all information about media types, especially codecs.
  161.  *
  162.  * Revision 1.57  2001/01/11 06:24:55  robertj
  163.  * Fixed incorrect value for CNG frame
  164.  *
  165.  * Revision 1.56  2001/01/11 05:39:44  robertj
  166.  * Fixed usage of G.723.1 CNG 1 byte frames.
  167.  *
  168.  * Revision 1.55  2001/01/11 03:51:14  robertj
  169.  * Fixed bug in WriteBlock() flush, use actual frame size for last write.
  170.  *
  171.  * Revision 1.54  2001/01/04 06:39:51  robertj
  172.  * Fixed bug in G.711 mode with xJACK cards if data is not a multiple of 10ms
  173.  *    and some silence is transmitted, closes the logical channel.
  174.  *
  175.  * Revision 1.53  2000/12/17 22:08:20  craigs
  176.  * Changed GetCountryCodeList to return PStringList
  177.  *
  178.  * Revision 1.52  2000/12/11 01:23:32  craigs
  179.  * Added extra routines to allow country string manipulation
  180.  *
  181.  * Revision 1.51  2000/12/04 00:04:21  robertj
  182.  * Changed G.711 "silence" to be 0xff to remove clicks from Quicknet cards,
  183.  *
  184.  * Revision 1.50  2000/11/30 08:48:36  robertj
  185.  * Added functions to enable/disable Voice Activity Detection in LID's
  186.  *
  187.  * Revision 1.49  2000/11/30 03:12:00  robertj
  188.  * Fixed bug in not resetting buffer offset on buffer flush.
  189.  *
  190.  * Revision 1.48  2000/11/29 22:08:31  craigs
  191.  * Fixed problem with using WaitForToneDetect with 0 timeout
  192.  *
  193.  * Revision 1.47  2000/11/27 05:19:27  robertj
  194.  * Fixed MSVC warning
  195.  *
  196.  * Revision 1.46  2000/11/27 00:19:39  robertj
  197.  * Fixed bug in SetRawCodec, conditional around the wrong way
  198.  *
  199.  * Revision 1.45  2000/11/26 23:12:18  craigs
  200.  * Added hook flash detection API
  201.  *
  202.  * Revision 1.44  2000/11/24 10:56:12  robertj
  203.  * Added a raw PCM dta mode for generating/detecting standard tones.
  204.  * Modified the ReadFrame/WriteFrame functions to allow for variable length codecs.
  205.  *
  206.  * Revision 1.43  2000/11/20 03:15:13  craigs
  207.  * Changed tone detection API slightly to allow detection of multiple
  208.  * simultaneous tones
  209.  * Added fax CNG tone to tone list
  210.  *
  211.  * Revision 1.42  2000/11/03 06:25:37  robertj
  212.  * Added flag to IsLinePresent() to force slow test, guarenteeing correct value.
  213.  *
  214.  * Revision 1.41  2000/10/31 03:21:02  robertj
  215.  * Fixed bug that caused G.711 transmitter to continuously think there was silence.
  216.  *
  217.  * Revision 1.40  2000/10/16 09:45:10  robertj
  218.  * Fixed recently introduced bug, caused artifacts when should be silent G.723.1
  219.  *
  220.  * Revision 1.39  2000/10/13 02:24:06  robertj
  221.  * Moved frame reblocking code from LID channel to LID itself and added
  222.  *    ReadBlock/WriteBlock functions to allow non integral frame sizes.
  223.  *
  224.  * Revision 1.38  2000/09/25 22:31:18  craigs
  225.  * Added G.723.1 frame erasure capability
  226.  *
  227.  * Revision 1.37  2000/09/23 07:20:45  robertj
  228.  * Fixed problem with being able to distinguish between sw and hw codecs in LID channel.
  229.  *
  230.  * Revision 1.36  2000/09/22 01:35:51  robertj
  231.  * Added support for handling LID's that only do symmetric codecs.
  232.  *
  233.  * Revision 1.35  2000/09/01 00:15:21  robertj
  234.  * Improved country code selection, can use 2 letter ISO codes or
  235.  *    international dialling prefixes (with leading +) to select country.
  236.  *
  237.  * Revision 1.34  2000/08/31 13:14:40  craigs
  238.  * Added functions to LID
  239.  * More bulletproofing to Linux driver
  240.  *
  241.  * Revision 1.33  2000/08/30 23:24:36  robertj
  242.  * Renamed string version of SetCountrCode() to SetCountryCodeName() to avoid
  243.  *    C++ masking ancestor overloaded function when overriding numeric version.
  244.  *
  245.  * Revision 1.32  2000/07/13 16:03:25  robertj
  246.  * Removed transmission of 1 byte repeat CNG frames in G.723.1 as it crashes other peoples stacks.
  247.  *
  248.  * Revision 1.31  2000/07/12 10:25:37  robertj
  249.  * Renamed all codecs so obvious whether software or hardware.
  250.  *
  251.  * Revision 1.30  2000/07/09 15:23:00  robertj
  252.  * Changed G.728 not to use Cisco hack. Cisco is just wrong!
  253.  * Fixed output of silence in G.711 so works with any sized frame.
  254.  *
  255.  * Revision 1.29  2000/07/02 14:09:49  craigs
  256.  * Fill uLaw and aLaw silence with 0x80 rather than 0x00
  257.  *
  258.  * Revision 1.28  2000/06/19 00:32:22  robertj
  259.  * Changed functionf or adding all lid capabilities to not assume it is to an endpoint.
  260.  *
  261.  * Revision 1.27  2000/06/01 07:52:30  robertj
  262.  * Changed some LID capability code back again so does not unneedfully break existing API.
  263.  *
  264.  * Revision 1.26  2000/05/30 10:19:28  robertj
  265.  * Added function to add capabilities given a LID.
  266.  * Improved LID capabilities so cannot create one that is not explicitly supported.
  267.  *
  268.  * Revision 1.25  2000/05/24 06:43:16  craigs
  269.  * Added routines to get xJack volume
  270.  * Fixed problem with receiving G>723.1 NULL frames
  271.  *
  272.  * Revision 1.24  2000/05/11 03:47:48  craigs
  273.  * Added extra debugging
  274.  *
  275.  * Revision 1.23  2000/05/10 04:05:34  robertj
  276.  * Changed capabilities so has a function to get name of codec, instead of relying on PrintOn.
  277.  *
  278.  * Revision 1.22  2000/05/04 12:56:43  robertj
  279.  * Fixed GNU warning.
  280.  *
  281.  * Revision 1.21  2000/05/04 11:52:35  robertj
  282.  * Added Packets Too Late statistics, requiring major rearrangement of jitter
  283.  *    buffer code, not also changes semantics of codec Write() function slightly.
  284.  *
  285.  * Revision 1.20  2000/05/02 04:32:27  robertj
  286.  * Fixed copyright notice comment.
  287.  *
  288.  * Revision 1.19  2000/04/30 03:57:14  robertj
  289.  * Added PTRACE of read/write frame sizes required by LID.
  290.  *
  291.  * Revision 1.18  2000/04/19 02:04:30  robertj
  292.  * BeOS port changes.
  293.  *
  294.  * Revision 1.17  2000/04/14 17:18:07  robertj
  295.  * Fixed problem with error reporting from LID hardware.
  296.  *
  297.  * Revision 1.16  2000/04/10 17:45:11  robertj
  298.  * Added higher level "DialOut" function for PSTN lines.
  299.  * Added hook flash function.
  300.  *
  301.  * Revision 1.15  2000/04/05 18:04:12  robertj
  302.  * Changed caller ID code for better portability.
  303.  *
  304.  * Revision 1.14  2000/04/03 19:25:14  robertj
  305.  * Optimised G.711 codec to read/write larger chunks of data.
  306.  *
  307.  * Revision 1.13  2000/03/31 19:50:51  robertj
  308.  * Fixed receiver loop being able to deal with RTP packets smaller than expected.
  309.  *
  310.  * Revision 1.12  2000/03/30 19:32:35  robertj
  311.  * Added swab function which seems to be missing on Linux.
  312.  *
  313.  * Revision 1.11  2000/03/30 01:57:16  robertj
  314.  * Added hacks so G.728 works with (I think) broken cisco gateways.
  315.  *
  316.  * Revision 1.10  2000/03/29 21:01:52  robertj
  317.  * Changed codec to use number of frames rather than number of bytes.
  318.  * Added function on LID to get available codecs.
  319.  * Fixed codec table for G.729 codec
  320.  *
  321.  * Revision 1.9  2000/03/28 05:22:05  robertj
  322.  * Fixed translation of text country code to numeric code.
  323.  *
  324.  * Revision 1.8  2000/03/23 23:36:49  robertj
  325.  * Added more calling tone detection functionality.
  326.  *
  327.  * Revision 1.7  2000/03/21 03:06:50  robertj
  328.  * Changes to make RTP TX of exact numbers of frames in some codecs.
  329.  *
  330.  * Revision 1.6  2000/01/13 12:39:29  robertj
  331.  * Added string based country codes to LID.
  332.  *
  333.  * Revision 1.5  2000/01/13 04:03:46  robertj
  334.  * Added video transmission
  335.  *
  336.  * Revision 1.4  2000/01/07 10:01:26  robertj
  337.  * GCC/Linux compatibility
  338.  *
  339.  * Revision 1.3  2000/01/07 08:28:09  robertj
  340.  * Additions and changes to line interface device base class.
  341.  *
  342.  * Revision 1.2  1999/12/29 01:18:07  craigs
  343.  * Fixed problem with codecs other than G.711 not working after reorganisation
  344.  *
  345.  * Revision 1.1  1999/12/23 23:02:36  robertj
  346.  * File reorganision for separating RTP from H.323 and creation of LID for VPB support.
  347.  *
  348.  */
  349.  
  350. #include <ptlib.h>
  351.  
  352.  
  353. #ifdef __GNUC__
  354. #pragma implementation "lid.cxx"
  355. #endif
  356.  
  357. #ifndef _WIN32_WCE
  358. #include "lid.h"
  359. #else
  360. #include "..\include\lid.h"
  361. #endif
  362. #include "h245.h"
  363.  
  364.  
  365. #define new PNEW
  366.  
  367.  
  368. ///////////////////////////////////////////////////////////////////////////////
  369.  
  370. #if PTRACING
  371. static const char * const CallProgressTonesNames[] = {
  372.   "DialTone", "RingTone", "BusyTone", "ClearTone", "CNGTone"
  373. };
  374.  
  375. ostream & operator<<(ostream & o, OpalLineInterfaceDevice::CallProgressTones t)
  376. {
  377.   PINDEX i = 0;    
  378.   while ((1 << i) != t)
  379.     i++;
  380.  
  381.   if (i < PARRAYSIZE(CallProgressTonesNames))
  382.     return o << CallProgressTonesNames[i];
  383.   else
  384.     return o << "Unknown";
  385. }
  386.  
  387. #endif
  388.  
  389.  
  390. OpalLineInterfaceDevice::OpalLineInterfaceDevice()
  391. {
  392.   os_handle = -1;
  393.   osError = 0;
  394.   countryCode = UnknownCountry;
  395.   readDeblockingOffset = P_MAX_INDEX;
  396.   writeDeblockingOffset = 0;
  397. }
  398.  
  399.  
  400. BOOL OpalLineInterfaceDevice::IsOpen() const
  401. {
  402.   return os_handle >= 0;
  403. }
  404.  
  405.  
  406. BOOL OpalLineInterfaceDevice::Close()
  407. {
  408.   if (os_handle < 0)
  409.     return FALSE;
  410.  
  411.   os_handle = -1;
  412.   return TRUE;
  413. }
  414.  
  415.  
  416. BOOL OpalLineInterfaceDevice::IsLineTerminal(unsigned)
  417. {
  418.   return FALSE;
  419. }
  420.  
  421.  
  422. BOOL OpalLineInterfaceDevice::IsLinePresent(unsigned, BOOL)
  423. {
  424.   return TRUE;
  425. }
  426.  
  427.  
  428. BOOL OpalLineInterfaceDevice::HookFlash(unsigned line, unsigned flashTime)
  429. {
  430.   if (!IsLineOffHook(line))
  431.     return FALSE;
  432.  
  433.   if (!SetLineOnHook(line))
  434.     return FALSE;
  435.  
  436.   PThread::Current()->Sleep(flashTime);
  437.  
  438.   return SetLineOffHook(line);
  439. }
  440.  
  441.  
  442. BOOL OpalLineInterfaceDevice::HasHookFlash(unsigned)
  443. {
  444.   return FALSE;
  445. }
  446.  
  447.  
  448. BOOL OpalLineInterfaceDevice::IsLineRinging(unsigned, DWORD *)
  449. {
  450.   return FALSE;
  451. }
  452.  
  453.  
  454. BOOL OpalLineInterfaceDevice::RingLine(unsigned, DWORD)
  455. {
  456.   return FALSE;
  457. }
  458.  
  459.  
  460. BOOL OpalLineInterfaceDevice::RingLine(unsigned, PINDEX, unsigned *)
  461. {
  462.   return FALSE;
  463. }
  464.  
  465.  
  466. BOOL OpalLineInterfaceDevice::IsLineDisconnected(unsigned line, BOOL)
  467. {
  468.   return IsToneDetected(line) == BusyTone;
  469. }
  470.  
  471.  
  472. BOOL OpalLineInterfaceDevice::SetLineToLineDirect(unsigned, unsigned, BOOL)
  473. {
  474.   return FALSE;
  475. }
  476.  
  477.  
  478. BOOL OpalLineInterfaceDevice::IsLineToLineDirect(unsigned, unsigned)
  479. {
  480.   return FALSE;
  481. }
  482.  
  483.  
  484. OpalMediaFormat FindMediaFormat(RTP_DataFrame::PayloadTypes pt)
  485. {
  486.   const OpalMediaFormat::List & formats = OpalMediaFormat::GetRegisteredMediaFormats();
  487.   for (PINDEX i = 0; i < formats.GetSize(); i++) {
  488.     if (formats[i].GetPayloadType() == pt)
  489.       return formats[i];
  490.   }
  491.  
  492.   return "<<Unknown RTP payload type>>";
  493. }
  494.  
  495.  
  496. BOOL OpalLineInterfaceDevice::SetReadCodec(unsigned line,
  497.                                            RTP_DataFrame::PayloadTypes codec)
  498. {
  499.   return SetReadFormat(line, FindMediaFormat(codec));
  500. }
  501.  
  502.  
  503. BOOL OpalLineInterfaceDevice::SetWriteCodec(unsigned line,
  504.                                             RTP_DataFrame::PayloadTypes codec)
  505. {
  506.   return SetWriteFormat(line, FindMediaFormat(codec));
  507. }
  508.  
  509.  
  510. BOOL OpalLineInterfaceDevice::SetRawCodec(unsigned line)
  511. {
  512.   if (!SetReadFormat(line, OpalPCM16))
  513.     return FALSE;
  514.  
  515.   if (SetWriteFormat(line, OpalPCM16))
  516.     return TRUE;
  517.  
  518.   StopReadCodec(line);
  519.   return FALSE;
  520. }
  521.  
  522.  
  523. BOOL OpalLineInterfaceDevice::StopReadCodec(unsigned)
  524. {
  525.   readDeblockingOffset = P_MAX_INDEX;
  526.   return TRUE;
  527. }
  528.  
  529.  
  530. BOOL OpalLineInterfaceDevice::StopWriteCodec(unsigned)
  531. {
  532.   writeDeblockingOffset = 0;
  533.   return TRUE;
  534. }
  535.  
  536.  
  537. BOOL OpalLineInterfaceDevice::StopRawCodec(unsigned line)
  538. {
  539.   BOOL ok = StopReadCodec(line);
  540.   return StopWriteCodec(line) && ok;
  541. }
  542.  
  543.  
  544. BOOL OpalLineInterfaceDevice::SetReadFrameSize(unsigned, PINDEX)
  545. {
  546.   return FALSE;
  547. }
  548.  
  549.  
  550. BOOL OpalLineInterfaceDevice::SetWriteFrameSize(unsigned, PINDEX)
  551. {
  552.   return FALSE;
  553. }
  554.  
  555.  
  556. BOOL OpalLineInterfaceDevice::ReadBlock(unsigned line, void * buffer, PINDEX length)
  557. {
  558.   // Are reblocking the hardware frame sizes to those expected by the RTP packets.
  559.   PINDEX frameSize = GetReadFrameSize(line);
  560.  
  561.   BYTE * bufferPtr = (BYTE *)buffer;
  562.  
  563.   PINDEX readBytes;
  564.   while (length > 0) {
  565.     if (readDeblockingOffset < frameSize) {
  566.       PINDEX left = frameSize - readDeblockingOffset;
  567.       if (left > length)
  568.         left = length;
  569.       memcpy(bufferPtr, &readDeblockingBuffer[readDeblockingOffset], left);
  570.       readDeblockingOffset += left;
  571.       bufferPtr += left;
  572.       length -= left;
  573.     }
  574.     else if (length < frameSize) {
  575.       BYTE * deblockPtr = readDeblockingBuffer.GetPointer(frameSize);
  576.       if (!ReadFrame(line, deblockPtr, readBytes))
  577.         return FALSE;
  578.       readDeblockingOffset = 0;
  579.     }
  580.     else {
  581.       if (!ReadFrame(line, bufferPtr, readBytes))
  582.         return FALSE;
  583.       bufferPtr += readBytes;
  584.       length -= readBytes;
  585.     }
  586.   }
  587.  
  588.   return TRUE;
  589. }
  590.  
  591.  
  592. BOOL OpalLineInterfaceDevice::WriteBlock(unsigned line, const void * buffer, PINDEX length)
  593. {
  594.   PINDEX frameSize = GetWriteFrameSize(line);
  595.   PINDEX written;
  596.  
  597.   // If zero length then flush any remaining data
  598.   if (length == 0 && writeDeblockingOffset != 0) {
  599.     SetWriteFrameSize(line, writeDeblockingOffset);
  600.     BOOL ok = WriteFrame(line,
  601.                          writeDeblockingBuffer.GetPointer(),
  602.                          GetWriteFrameSize(line),
  603.                          written);
  604.     SetWriteFrameSize(line, frameSize);
  605.     writeDeblockingOffset = 0;
  606.     return ok;
  607.   }
  608.  
  609.   const BYTE * bufferPtr = (const BYTE *)buffer;
  610.  
  611.   while (length > 0) {
  612.     // If have enough data and nothing in the reblocking buffer, just send it
  613.     // straight on to the device.
  614.     if (writeDeblockingOffset == 0 && length >= frameSize) {
  615.       if (!WriteFrame(line, bufferPtr, frameSize, written))
  616.         return FALSE;
  617.       bufferPtr += written;
  618.       length -= written;
  619.     }
  620.     else {
  621.       BYTE * savedFramePtr = writeDeblockingBuffer.GetPointer(frameSize);
  622.  
  623.       // See if new chunk gives us enough for one frames worth
  624.       if ((writeDeblockingOffset + length) < frameSize) {
  625.         // Nope, just copy bytes into buffer and return
  626.         memcpy(savedFramePtr + writeDeblockingOffset, bufferPtr, length);
  627.         writeDeblockingOffset += length;
  628.         return TRUE;
  629.       }
  630.  
  631.       /* Calculate bytes we want from the passed in buffer to fill a frame by
  632.          subtracting from full frame width the amount we have so far. This also
  633.          means the lastWriteCount is set to the correct amount of buffer we are
  634.          grabbing this time around.
  635.        */
  636.       PINDEX left = frameSize - writeDeblockingOffset;
  637.       memcpy(savedFramePtr + writeDeblockingOffset, bufferPtr, left);
  638.       writeDeblockingOffset = 0;
  639.  
  640.       // Write the saved frame out
  641.       if (!WriteFrame(line, savedFramePtr, frameSize, written))
  642.         return FALSE;
  643.  
  644.       bufferPtr += left;
  645.       length -= left;
  646.     }
  647.   }
  648.  
  649.   return TRUE;
  650. }
  651.  
  652.  
  653. unsigned OpalLineInterfaceDevice::GetAverageSignalLevel(unsigned, BOOL)
  654. {
  655.   return UINT_MAX;
  656. }
  657.  
  658.  
  659. BOOL OpalLineInterfaceDevice::EnableAudio(unsigned line, BOOL enabled)
  660. {
  661.   return line < GetLineCount() && enabled;
  662. }
  663.  
  664.  
  665. BOOL OpalLineInterfaceDevice::IsAudioEnabled(unsigned line)
  666. {
  667.   return line < GetLineCount();
  668. }
  669.  
  670.  
  671. BOOL OpalLineInterfaceDevice::SetRecordVolume(unsigned, unsigned)
  672. {
  673.   return FALSE;
  674. }
  675.  
  676. BOOL OpalLineInterfaceDevice::GetRecordVolume(unsigned, unsigned &)
  677. {
  678.   return FALSE;
  679. }
  680.  
  681.  
  682. BOOL OpalLineInterfaceDevice::SetPlayVolume(unsigned, unsigned)
  683. {
  684.   return FALSE;
  685. }
  686.  
  687. BOOL OpalLineInterfaceDevice::GetPlayVolume(unsigned, unsigned &)
  688. {
  689.   return FALSE;
  690. }
  691.  
  692.  
  693. OpalLineInterfaceDevice::AECLevels OpalLineInterfaceDevice::GetAEC(unsigned)
  694. {
  695.   return AECError;
  696. }
  697.  
  698.  
  699. BOOL OpalLineInterfaceDevice::SetAEC(unsigned, AECLevels)
  700. {
  701.   return FALSE;
  702. }
  703.  
  704. unsigned OpalLineInterfaceDevice::GetWinkDuration(unsigned)
  705. {
  706.   return 0;
  707. }
  708.  
  709.  
  710. BOOL OpalLineInterfaceDevice::SetWinkDuration(unsigned, unsigned)
  711. {
  712.   return FALSE;
  713. }
  714.  
  715.  
  716. BOOL OpalLineInterfaceDevice::GetVAD(unsigned)
  717. {
  718.   return FALSE;
  719. }
  720.  
  721.  
  722. BOOL OpalLineInterfaceDevice::SetVAD(unsigned, BOOL)
  723. {
  724.   return FALSE;
  725. }
  726.  
  727.  
  728. BOOL OpalLineInterfaceDevice::GetCallerID(unsigned, PString & id, BOOL)
  729. {
  730.   id = PString();
  731.   return FALSE;
  732. }
  733.  
  734.  
  735. BOOL OpalLineInterfaceDevice::SetCallerID(unsigned, const PString &)
  736. {
  737.   return FALSE;
  738. }
  739.  
  740. BOOL OpalLineInterfaceDevice::SendCallerIDOnCallWaiting(unsigned, const PString &)
  741. {
  742.   return FALSE;
  743. }
  744.  
  745.  
  746. BOOL OpalLineInterfaceDevice::SendVisualMessageWaitingIndicator(unsigned, BOOL)
  747. {
  748.   return FALSE;
  749. }
  750.  
  751. BOOL OpalLineInterfaceDevice::PlayDTMF(unsigned, const char *, DWORD, DWORD)
  752. {
  753.   return FALSE;
  754. }
  755.  
  756.  
  757. char OpalLineInterfaceDevice::ReadDTMF(unsigned)
  758. {
  759.   return '\0';
  760. }
  761.  
  762.  
  763. BOOL OpalLineInterfaceDevice::GetRemoveDTMF(unsigned)
  764. {
  765.   return FALSE;
  766. }
  767.  
  768.  
  769. BOOL OpalLineInterfaceDevice::SetRemoveDTMF(unsigned, BOOL)
  770. {
  771.   return FALSE;
  772. }
  773.  
  774.  
  775. unsigned OpalLineInterfaceDevice::IsToneDetected(unsigned)
  776. {
  777.   return NoTone;
  778. }
  779.  
  780.  
  781. unsigned OpalLineInterfaceDevice::WaitForToneDetect(unsigned line, unsigned timeout)
  782. {
  783.   PTRACE(2, "LID\tWaitForToneDetect");
  784.  
  785.   static const unsigned sampleRate = 25;
  786.  
  787.   timeout = (timeout+sampleRate-1)/sampleRate;
  788.  
  789.   unsigned retry = 0;
  790.   do {
  791.     unsigned tones = IsToneDetected(line);
  792.     if (tones != NoTone) {
  793.       PTRACE(2, "LID\tTone " << tones << " detected after " << (retry*sampleRate) << " ms");
  794.       return tones;
  795.     }
  796.  
  797.     PThread::Current()->Sleep(sampleRate);
  798.     retry++;
  799.   } while (retry < timeout);
  800.  
  801.   PTRACE(3, "LID\tTone detection timeout " << (retry*sampleRate) << " ms");
  802.   return NoTone;
  803. }
  804.  
  805.  
  806. BOOL OpalLineInterfaceDevice::WaitForTone(unsigned line,
  807.                                           CallProgressTones tone,
  808.                                           unsigned timeout)
  809. {
  810.   PTRACE(3, "LID\tWaitFor the tone " << tone );
  811.   BOOL res = WaitForToneDetect(line, timeout) & tone;
  812.   PTRACE(3, "LID\tWaitFor the tone " << tone << 
  813.      " is successfull-" << (res ? "YES" : "No"));
  814.   return res;
  815. }
  816.  
  817.  
  818. BOOL OpalLineInterfaceDevice::SetToneFilter(unsigned line,
  819.                                             CallProgressTones tone,
  820.                                             const PString & description)
  821. {
  822.   PString freqDesc, cadenceDesc;
  823.   PINDEX colon = description.Find(':');
  824.   if (colon == P_MAX_INDEX)
  825.     freqDesc = description;
  826.   else {
  827.     freqDesc = description.Left(colon);
  828.     cadenceDesc = description.Mid(colon+1);
  829.   }
  830.  
  831.   unsigned low_freq, high_freq;
  832.   PINDEX dash = freqDesc.Find('-');
  833.   if (dash == P_MAX_INDEX)
  834.     low_freq = high_freq = freqDesc.AsUnsigned();
  835.   else {
  836.     low_freq = freqDesc.Left(dash).AsUnsigned();
  837.     high_freq = freqDesc.Mid(dash+1).AsUnsigned();
  838.   }
  839.   if (low_freq  < 100 || low_freq  > 3000 ||
  840.       high_freq < 100 || high_freq > 3000 ||
  841.       low_freq > high_freq) {
  842.     PTRACE(1, "LID\tIllegal frequency specified: " << description);
  843.     return FALSE;
  844.   }
  845.  
  846.   PStringArray times = cadenceDesc.Tokenise("-");
  847.   PINDEX numCadences = (times.GetSize()+1)/2;
  848.   
  849.   PUnsignedArray onTimes(numCadences), offTimes(numCadences);
  850.   for (PINDEX i = 0; i < times.GetSize(); i++) {
  851.     double time = atof(times[i]);
  852.     if (time <= 0.01 || time > 10) {
  853.       PTRACE(1, "LID\tIllegal cadence time specified: " << description);
  854.       return FALSE;
  855.     }
  856.  
  857.     if ((i&1) == 0)
  858.       onTimes[i/2] = (unsigned)(time*1000);
  859.     else
  860.       offTimes[i/2] = (unsigned)(time*1000);
  861.   }
  862.  
  863.   return SetToneFilterParameters(line, tone, low_freq, high_freq,
  864.                                  numCadences, onTimes, offTimes);
  865. }
  866.  
  867.  
  868. BOOL OpalLineInterfaceDevice::SetToneFilterParameters(unsigned /*line*/,
  869.                                                       CallProgressTones /*tone*/,
  870.                                                       unsigned /*lowFrequency*/,
  871.                                                       unsigned /*highFrequency*/,
  872.                                                       PINDEX /*numCadences*/,
  873.                                                       const unsigned * /*onTimes*/,
  874.                                                       const unsigned * /*offTimes*/)
  875. {
  876.   return FALSE;
  877. }
  878.  
  879.  
  880. BOOL OpalLineInterfaceDevice::PlayTone(unsigned, CallProgressTones)
  881. {
  882.   return FALSE;
  883. }
  884.  
  885.  
  886. BOOL OpalLineInterfaceDevice::IsTonePlaying(unsigned)
  887. {
  888.   return FALSE;
  889. }
  890.  
  891.  
  892. BOOL OpalLineInterfaceDevice::StopTone(unsigned)
  893. {
  894.   return FALSE;
  895. }
  896.  
  897.  
  898. BOOL OpalLineInterfaceDevice::PlayAudio(unsigned /*line*/, const PString & /*filename*/)
  899. {
  900.   PTRACE(3, "LID\tBase Class PlayAudio method called, exiting with FALSE");
  901.   return FALSE;
  902. }
  903.  
  904.  
  905. BOOL OpalLineInterfaceDevice::StopAudio(unsigned /*line*/)
  906. {
  907.   PTRACE(3, "LID\tBase Class StopAudio method called, exiting with FALSE");
  908.   return FALSE;
  909. }
  910.     
  911.  
  912. OpalLineInterfaceDevice::CallProgressTones
  913.                 OpalLineInterfaceDevice::DialOut(unsigned line,
  914.                                                  const PString & number,
  915.                                                  BOOL requireTone)
  916. {
  917.   PTRACE(3, "LID\tDialOut to " << number);
  918.  
  919.   if (IsLineTerminal(line))
  920.     return NoTone;
  921.  
  922.   if (!SetLineOffHook(line))
  923.     return NoTone;
  924.  
  925.   // Should get dial tone within 2 seconds of going off hook
  926.   if (!WaitForTone(line, DialTone, 2000)) {
  927.     if (requireTone)
  928.       return DialTone;
  929.   }
  930.  
  931.   // Dial the string
  932.   PINDEX lastPos = 0;
  933.   PINDEX nextPos;
  934.   while ((nextPos = number.FindOneOf("!@,")) != P_MAX_INDEX) {
  935.     PlayDTMF(line, number(lastPos, nextPos-1));
  936.     lastPos = nextPos+1;
  937.     switch (number[nextPos]) {
  938.       case '!' :
  939.         if (!HookFlash(line))
  940.           return NoTone;
  941.         break;
  942.  
  943.       case '@' :
  944.         if (!WaitForTone(line, DialTone, 3000)) {
  945.           if (requireTone)
  946.             return DialTone;
  947.         }
  948.         break;
  949.  
  950.       case ',' :
  951.         PThread::Current()->Sleep(2000);
  952.         break;
  953.     }
  954.   }
  955.  
  956.   PlayDTMF(line, number.Mid(lastPos));
  957.  
  958.   // Wait for busy or ring back
  959.   unsigned tones;
  960.   while ((tones = WaitForToneDetect(line, 5000)) != NoTone) {
  961.     if (tones & BusyTone)
  962.       return BusyTone;
  963.     else if (tones & RingTone)
  964.       break;
  965.   }
  966.  
  967.   if (requireTone)
  968.     return NoTone;
  969.  
  970.   return RingTone;
  971. }
  972.  
  973. static struct {
  974.   const char * isoName;
  975.   unsigned dialCode;
  976.   OpalLineInterfaceDevice::T35CountryCodes t35Code;
  977.   const char * fullName;
  978.   const char * dialTone;
  979.   const char * ringTone;
  980.   const char * busyTone;
  981. } CountryInfo[] = {
  982.   { "AF", 93,   OpalLineInterfaceDevice::Afghanistan,           "Afghanistan" },
  983.   { "AL", 355,  OpalLineInterfaceDevice::Albania,               "Albania" },
  984.   { "DZ", 213,  OpalLineInterfaceDevice::Algeria,               "Algeria" },
  985.   { "AS", 684,  OpalLineInterfaceDevice::AmericanSamoa,         "American Samoa" },
  986.   { "AO", 244,  OpalLineInterfaceDevice::Angola,                "Angola" },
  987.   { "AI", 1264, OpalLineInterfaceDevice::Anguilla,              "Anguilla" },
  988.   { "AG", 1268, OpalLineInterfaceDevice::AntiguaAndBarbuda,     "Antigua and Barbuda" },
  989.   { "AR", 54,   OpalLineInterfaceDevice::Argentina,             "Argentina" },
  990.   { "AC", 247,  OpalLineInterfaceDevice::Ascension,             "Ascension Island" },
  991.   { "AU", 61,   OpalLineInterfaceDevice::Australia,             "Australia",            "425:0.1", "425:0.4-0.2-0.4-2", "425:0.375-0.375" },
  992.   { "AT", 43,   OpalLineInterfaceDevice::Austria,               "Austria" },
  993.   { "BS", 1242, OpalLineInterfaceDevice::Bahamas,               "Bahamas" },
  994.   { "BH", 973,  OpalLineInterfaceDevice::Bahrain,               "Bahrain" },
  995.   { "BD", 880,  OpalLineInterfaceDevice::Bangladesh,            "Bangladesh" },
  996.   { "BB", 1246, OpalLineInterfaceDevice::Barbados,              "Barbados" },
  997.   { "BE", 32,   OpalLineInterfaceDevice::Belgium,               "Belgium" },
  998.   { "BZ", 501,  OpalLineInterfaceDevice::Belize,                "Belize" },
  999.   { "BJ", 229,  OpalLineInterfaceDevice::Benin,                 "Benin" },
  1000.   { "BM", 1441, OpalLineInterfaceDevice::Bermudas,              "Bermudas" },
  1001.   { "BT", 975,  OpalLineInterfaceDevice::Bhutan,                "Bhutan" },
  1002.   { "BO", 591,  OpalLineInterfaceDevice::Bolivia,               "Bolivia" },
  1003.   { "BW", 267,  OpalLineInterfaceDevice::Botswana,              "Botswana" },
  1004.   { "BR", 55,   OpalLineInterfaceDevice::Brazil,                "Brazil" },
  1005.   { "xx", 0,    OpalLineInterfaceDevice::BritishAntarcticTerritory, "British Antarctic Territory" },
  1006.   { "IO", 246,  OpalLineInterfaceDevice::BritishIndianOceanTerritory, "British IndianOcean Territory" },
  1007.   { "VG", 1284, OpalLineInterfaceDevice::BritishVirginIslands,  "British Virgin Islands" },
  1008.   { "BN", 673,  OpalLineInterfaceDevice::BruneiDarussalam,      "Brunei Darussalam" },
  1009.   { "BG", 359,  OpalLineInterfaceDevice::Bulgaria,              "Bulgaria" },
  1010.   { "BF", 226,  OpalLineInterfaceDevice::BurkinaFaso,           "Burkina Faso" },
  1011.   { "BI", 257,  OpalLineInterfaceDevice::Burundi,               "Burundi" },
  1012.   { "xx", 0,    OpalLineInterfaceDevice::Byelorussia,           "Byelorussia" },
  1013.   { "KH", 855,  OpalLineInterfaceDevice::Cambodia,              "Cambodia" },
  1014.   { "CM", 237,  OpalLineInterfaceDevice::Cameroon,              "Cameroon" },
  1015.   { "CA", 1,    OpalLineInterfaceDevice::Canada,                "Canada" },
  1016.   { "CV", 238,  OpalLineInterfaceDevice::CapeVerde,             "Cape Verde" },
  1017.   { "KY", 1345, OpalLineInterfaceDevice::CaymanIslands,         "Cayman Islands" },
  1018.   { "CF", 236,  OpalLineInterfaceDevice::CentralAfricanRepublic,"Central African Republic" },
  1019.   { "TD", 235,  OpalLineInterfaceDevice::Chad,                  "Chad" },
  1020.   { "CL", 56,   OpalLineInterfaceDevice::Chile,                 "Chile" },
  1021.   { "CN", 86,   OpalLineInterfaceDevice::China,                 "China" },
  1022.   { "CO", 57,   OpalLineInterfaceDevice::Colombia,              "Colombia" },
  1023.   { "KM", 269,  OpalLineInterfaceDevice::Comoros,               "Comoros" },
  1024.   { "CG", 242,  OpalLineInterfaceDevice::Congo,                 "Congo" },
  1025.   { "CK", 682,  OpalLineInterfaceDevice::CookIslands,           "Cook Islands" },
  1026.   { "CR", 506,  OpalLineInterfaceDevice::CostaRica,             "Costa Rica" },
  1027.   { "CI", 225,  OpalLineInterfaceDevice::CotedIvoire,           "Cote dIvoire" },
  1028.   { "CU", 53,   OpalLineInterfaceDevice::Cuba,                  "Cuba" },
  1029.   { "CY", 357,  OpalLineInterfaceDevice::Cyprus,                "Cyprus" },
  1030.   { "CZ", 420,  OpalLineInterfaceDevice::Czechoslovakia,        "Czech Republic" },
  1031.   { "DK", 45,   OpalLineInterfaceDevice::Denmark,               "Denmark" },
  1032.   { "DJ", 253,  OpalLineInterfaceDevice::Djibouti,              "Djibouti" },
  1033.   { "DM", 1767, OpalLineInterfaceDevice::Dominica,              "Dominica" },
  1034.   { "DO", 1809, OpalLineInterfaceDevice::DominicanRepublic,     "Dominican Republic" },
  1035.   { "EC", 593,  OpalLineInterfaceDevice::Ecuador,               "Ecuador" },
  1036.   { "EG", 20,   OpalLineInterfaceDevice::Egypt,                 "Egypt" },
  1037.   { "SV", 503,  OpalLineInterfaceDevice::ElSalvador,            "El Salvador" },
  1038.   { "GQ", 240,  OpalLineInterfaceDevice::EquatorialGuinea,      "Equatorial Guinea" },
  1039.   { "ET", 251,  OpalLineInterfaceDevice::Ethiopia,              "Ethiopia" },
  1040.   { "FK", 500,  OpalLineInterfaceDevice::FalklandIslands,       "Falkland Islands" },
  1041.   { "FJ", 679,  OpalLineInterfaceDevice::Fiji,                  "Fiji" },
  1042.   { "FI", 358,  OpalLineInterfaceDevice::Finland,               "Finland" },
  1043.   { "FR", 33,   OpalLineInterfaceDevice::France,                "France" },
  1044.   { "PF", 689,  OpalLineInterfaceDevice::FrenchPolynesia,       "French Polynesia" },
  1045.   { "TF", 0,    OpalLineInterfaceDevice::FrenchSouthernAndAntarcticLands, "French Southern and Antarctic Lands" },
  1046.   { "GA", 241,  OpalLineInterfaceDevice::Gabon,                 "Gabon" },
  1047.   { "GM", 220,  OpalLineInterfaceDevice::Gambia,                "Gambia" },
  1048.   { "DE", 49,   OpalLineInterfaceDevice::Germany,               "Germany" },
  1049.   { "GH", 233,  OpalLineInterfaceDevice::Ghana,                 "Ghana" },
  1050.   { "GI", 350,  OpalLineInterfaceDevice::Gibraltar,             "Gibraltar" },
  1051.   { "GR", 30,   OpalLineInterfaceDevice::Greece,                "Greece" },
  1052.   { "GD", 1473, OpalLineInterfaceDevice::Grenada,               "Grenada" },
  1053.   { "GU", 1671, OpalLineInterfaceDevice::Guam,                  "Guam" },
  1054.   { "GT", 502,  OpalLineInterfaceDevice::Guatemala,             "Guatemala" },
  1055.   { "GY", 592,  OpalLineInterfaceDevice::Guayana,               "Guayana" },
  1056.   { "GG", 441,  OpalLineInterfaceDevice::Guernsey,              "Guernsey" },
  1057.   { "GN", 224,  OpalLineInterfaceDevice::Guinea,                "Guinea" },
  1058.   { "GW", 245,  OpalLineInterfaceDevice::GuineaBissau,          "Guinea Bissau" },
  1059.   { "HT", 509,  OpalLineInterfaceDevice::Haiti,                 "Haiti" },
  1060.   { "HN", 504,  OpalLineInterfaceDevice::Honduras,              "Honduras" },
  1061.   { "HK", 852,  OpalLineInterfaceDevice::Hongkong,              "Hong Kong" },
  1062.   { "HU", 36,   OpalLineInterfaceDevice::Hungary,               "Hungary" },
  1063.   { "IS", 354,  OpalLineInterfaceDevice::Iceland,               "Iceland" },
  1064.   { "IN", 91,   OpalLineInterfaceDevice::India,                 "India" },
  1065.   { "ID", 62,   OpalLineInterfaceDevice::Indonesia,             "Indonesia" },
  1066.   { "IR", 98,   OpalLineInterfaceDevice::Iran,                  "Iran" },
  1067.   { "IQ", 964,  OpalLineInterfaceDevice::Iraq,                  "Iraq" },
  1068.   { "IE", 353,  OpalLineInterfaceDevice::Ireland,               "Ireland" },
  1069.   { "IL", 972,  OpalLineInterfaceDevice::Israel,                "Israel" },
  1070.   { "IT", 39,   OpalLineInterfaceDevice::Italy,                 "Italy" },
  1071.   { "JM", 1876, OpalLineInterfaceDevice::Jamaica,               "Jamaica" },
  1072.   { "JP", 81,   OpalLineInterfaceDevice::Japan,                 "Japan" },
  1073.   { "JE", 442,  OpalLineInterfaceDevice::Jersey,                "Jersey" },
  1074.   { "JO", 962,  OpalLineInterfaceDevice::Jordan,                "Jordan" },
  1075.   { "KE", 254,  OpalLineInterfaceDevice::Kenya,                 "Kenya" },
  1076.   { "KI", 686,  OpalLineInterfaceDevice::Kiribati,              "Kiribati" },
  1077.   { "KR", 82,   OpalLineInterfaceDevice::KoreaRepublic,         "Korea, Republic of" },
  1078.   { "KP", 850,  OpalLineInterfaceDevice::DemocraticPeoplesRepublicOfKorea, "Korea, Democratic Peoples Republic of" },
  1079.   { "KW", 965,  OpalLineInterfaceDevice::Kuwait,                "Kuwait" },
  1080.   { "LA", 856,  OpalLineInterfaceDevice::Lao,                   "Lao" },
  1081.   { "LB", 961,  OpalLineInterfaceDevice::Lebanon,               "Lebanon" },
  1082.   { "LS", 266,  OpalLineInterfaceDevice::Lesotho,               "Lesotho" },
  1083.   { "LR", 231,  OpalLineInterfaceDevice::Liberia,               "Liberia" },
  1084.   { "LY", 218,  OpalLineInterfaceDevice::Libya,                 "Libya" },
  1085.   { "LI", 423,  OpalLineInterfaceDevice::Liechtenstein,         "Liechtenstein" },
  1086.   { "LU", 352,  OpalLineInterfaceDevice::Luxemborg,             "Luxemborg" },
  1087.   { "MO", 853,  OpalLineInterfaceDevice::Macao,                 "Macao" },
  1088.   { "MG", 261,  OpalLineInterfaceDevice::Madagascar,            "Madagascar" },
  1089.   { "MY", 60,   OpalLineInterfaceDevice::Malaysia,              "Malaysia" },
  1090.   { "MW", 265,  OpalLineInterfaceDevice::Malawi,                "Malawi" },
  1091.   { "MV", 960,  OpalLineInterfaceDevice::Maldives,              "Maldives" },
  1092.   { "ML", 223,  OpalLineInterfaceDevice::Mali,                  "Mali" },
  1093.   { "MT", 356,  OpalLineInterfaceDevice::Malta,                 "Malta" },
  1094.   { "MR", 222,  OpalLineInterfaceDevice::Mauritania,            "Mauritania" },
  1095.   { "MU", 230,  OpalLineInterfaceDevice::Mauritius,             "Mauritius" },
  1096.   { "MX", 52,   OpalLineInterfaceDevice::Mexico,                "Mexico" },
  1097.   { "MC", 377,  OpalLineInterfaceDevice::Monaco,                "Monaco" },
  1098.   { "MN", 976,  OpalLineInterfaceDevice::Mongolia,              "Mongolia" },
  1099.   { "MS", 1664, OpalLineInterfaceDevice::Montserrat,            "Montserrat" },
  1100.   { "MA", 212,  OpalLineInterfaceDevice::Morocco,               "Morocco" },
  1101.   { "MZ", 258,  OpalLineInterfaceDevice::Mozambique,            "Mozambique" },
  1102.   { "MM", 95,   OpalLineInterfaceDevice::Myanmar,               "Myanmar" },
  1103.   { "NR", 674,  OpalLineInterfaceDevice::Nauru,                 "Nauru" },
  1104.   { "NP", 977,  OpalLineInterfaceDevice::Nepal,                 "Nepal" },
  1105.   { "NL", 31,   OpalLineInterfaceDevice::Netherlands,           "Netherlands",          "425:0.1", "425:1.0-4.0", "425:0.5-0.5" },
  1106.   { "AN", 599,  OpalLineInterfaceDevice::NetherlandsAntilles,   "Netherlands Antilles" },
  1107.   { "NC", 687,  OpalLineInterfaceDevice::NewCaledonia,          "New Caledonia" },
  1108.   { "NZ", 64,   OpalLineInterfaceDevice::NewZealand,            "New Zealand" },
  1109.   { "NI", 505,  OpalLineInterfaceDevice::Nicaragua,             "Nicaragua" },
  1110.   { "NE", 227,  OpalLineInterfaceDevice::Niger,                 "Niger" },
  1111.   { "NG", 234,  OpalLineInterfaceDevice::Nigeria,               "Nigeria" },
  1112.   { "NO", 47,   OpalLineInterfaceDevice::Norway,                "Norway" },
  1113.   { "OM", 968,  OpalLineInterfaceDevice::Oman,                  "Oman" },
  1114.   { "PK", 92,   OpalLineInterfaceDevice::Pakistan,              "Pakistan" },
  1115.   { "PA", 507,  OpalLineInterfaceDevice::Panama,                "Panama" },
  1116.   { "PG", 675,  OpalLineInterfaceDevice::PapuaNewGuinea,        "Papua New Guinea" },
  1117.   { "PY", 595,  OpalLineInterfaceDevice::Paraguay,              "Paraguay" },
  1118.   { "PE", 51,   OpalLineInterfaceDevice::Peru,                  "Peru" },
  1119.   { "PH", 63,   OpalLineInterfaceDevice::Philippines,           "Philippines" },
  1120.   { "PL", 48,   OpalLineInterfaceDevice::Poland,                "Poland" },
  1121.   { "PT", 351,  OpalLineInterfaceDevice::Portugal,              "Portugal" },
  1122.   { "PR", 1787, OpalLineInterfaceDevice::PuertoRico,            "Puerto Rico" },
  1123.   { "QA", 974,  OpalLineInterfaceDevice::Qatar,                 "Qatar" },
  1124.   { "RO", 40,   OpalLineInterfaceDevice::Romania,               "Romania" },
  1125.   { "RU", 7,    OpalLineInterfaceDevice::USSR,                  "Russia" },
  1126.   { "RW", 250,  OpalLineInterfaceDevice::Rwanda,                "Rwanda" },
  1127.   { "xx", 0,    OpalLineInterfaceDevice::SaintCroix,            "Saint Croix" },
  1128.   { "SH", 290,  OpalLineInterfaceDevice::SaintHelenaAndAscension, "Saint Helena and Ascension" },
  1129.   { "KN", 1869, OpalLineInterfaceDevice::SaintKittsAndNevis,    "Saint Kitts and Nevis" },
  1130.   { "LC", 1758, OpalLineInterfaceDevice::SaintLucia,            "Saint Lucia" },
  1131.   { "xx", 0,    OpalLineInterfaceDevice::SaintThomas,           "Saint Thomas" },
  1132.   { "VC", 1784, OpalLineInterfaceDevice::SaintVicentAndTheGrenadines, "Saint Vicent and the Grenadines" },
  1133.   { "SM", 378,  OpalLineInterfaceDevice::SanMarino,             "San Marino" },
  1134.   { "ST", 239,  OpalLineInterfaceDevice::SaoTomeAndPrincipe,    "Sao Tome and Principe" },
  1135.   { "SA", 966,  OpalLineInterfaceDevice::SaudiArabia,           "Saudi Arabia" },
  1136.   { "SN", 221,  OpalLineInterfaceDevice::Senegal,               "Senegal" },
  1137.   { "SC", 248,  OpalLineInterfaceDevice::Seychelles,            "Seychelles" },
  1138.   { "SL", 232,  OpalLineInterfaceDevice::SierraLeone,           "Sierra Leone" },
  1139.   { "SG", 65,   OpalLineInterfaceDevice::Singapore,             "Singapore",            "425:0.1", "425:0.4-0.2-0.4-2", "425:0.75-0.75"},
  1140.   { "SB", 677,  OpalLineInterfaceDevice::SolomonIslands,        "Solomon Islands" },
  1141.   { "SO", 252,  OpalLineInterfaceDevice::Somalia,               "Somalia" },
  1142.   { "ZA", 27,   OpalLineInterfaceDevice::SouthAfrica,           "South Africa" },
  1143.   { "ES", 34,   OpalLineInterfaceDevice::Spain,                 "Spain" },
  1144.   { "LK", 94,   OpalLineInterfaceDevice::SriLanka,              "Sri Lanka" },
  1145.   { "SD", 249,  OpalLineInterfaceDevice::Sudan,                 "Sudan" },
  1146.   { "SR", 597,  OpalLineInterfaceDevice::Suriname,              "Suriname" },
  1147.   { "SZ", 268,  OpalLineInterfaceDevice::Swaziland,             "Swaziland" },
  1148.   { "SE", 46,   OpalLineInterfaceDevice::Sweden,                "Sweden" },
  1149.   { "CH", 41,   OpalLineInterfaceDevice::Switzerland,           "Switzerland" },
  1150.   { "SY", 963,  OpalLineInterfaceDevice::Syria,                 "Syria" },
  1151.   { "TZ", 255,  OpalLineInterfaceDevice::Tanzania,              "Tanzania" },
  1152.   { "TH", 66,   OpalLineInterfaceDevice::Thailand,              "Thailand" },
  1153.   { "TG", 228,  OpalLineInterfaceDevice::Togo,                  "Togo" },
  1154.   { "TO", 676,  OpalLineInterfaceDevice::Tonga,                 "Tonga" },
  1155.   { "TT", 1868, OpalLineInterfaceDevice::TrinidadAndTobago,     "Trinidad and Tobago" },
  1156.   { "TN", 216,  OpalLineInterfaceDevice::Tunisia,               "Tunisia" },
  1157.   { "TR", 90,   OpalLineInterfaceDevice::Turkey,                "Turkey" },
  1158.   { "TC", 1649, OpalLineInterfaceDevice::TurksAndCaicosIslands, "Turks and Caicos Islands" },
  1159.   { "TV", 688,  OpalLineInterfaceDevice::Tuvalu,                "Tuvalu" },
  1160.   { "UG", 256,  OpalLineInterfaceDevice::Uganda,                "Uganda" },
  1161.   { "UA", 380,  OpalLineInterfaceDevice::Ukraine,               "Ukraine" },
  1162.   { "AE", 971,  OpalLineInterfaceDevice::UnitedArabEmirates,    "United Arab Emirates" },
  1163.   { "GB", 44,   OpalLineInterfaceDevice::UnitedKingdom,         "United Kingdom",       "350-440:0.1", "400-450:0.4-0.2-0.4-2", "400:0.375-0.375" },
  1164.   { "US", 1,    OpalLineInterfaceDevice::UnitedStates,          "United States",        "350-440:0.1", "440-480:2.0-4.0",       "480-620:0.5-0.5" },
  1165.   { "UY", 598,  OpalLineInterfaceDevice::Uruguay,               "Uruguay" },
  1166.   { "VU", 678,  OpalLineInterfaceDevice::Vanuatu,               "Vanuatu" },
  1167.   { "VA", 379,  OpalLineInterfaceDevice::VaticanCityState,      "Vatican City State" },
  1168.   { "VE", 58,   OpalLineInterfaceDevice::Venezuela,             "Venezuela" },
  1169.   { "VN", 84,   OpalLineInterfaceDevice::VietNam,               "Viet Nam" },
  1170.   { "WF", 681,  OpalLineInterfaceDevice::WallisAndFutuna,       "Wallis and Futuna" },
  1171.   { "WS", 685,  OpalLineInterfaceDevice::WesternSamoa,          "Western Samoa" },
  1172.   { "YE", 967,  OpalLineInterfaceDevice::Yemen,                 "Yemen" },
  1173.   { "YU", 381,  OpalLineInterfaceDevice::Yugoslavia,            "Yugoslavia" },
  1174.   { "xx", 0,    OpalLineInterfaceDevice::Zaire,                 "Zaire" },
  1175.   { "ZM", 260,  OpalLineInterfaceDevice::Zambia,                "Zambia" },
  1176.   { "ZW", 263,  OpalLineInterfaceDevice::Zimbabwe,              "Zimbabwe" }
  1177. };
  1178.  
  1179. OpalLineInterfaceDevice::T35CountryCodes OpalLineInterfaceDevice::GetCountryCode(const PString & str)
  1180. {
  1181.   for (PINDEX i = 0; i < PARRAYSIZE(CountryInfo); i++)
  1182.     if (str *= CountryInfo[i].fullName)
  1183.       return CountryInfo[i].t35Code;
  1184.  
  1185.   return OpalLineInterfaceDevice::UnknownCountry;
  1186. }
  1187.  
  1188.  
  1189. PString OpalLineInterfaceDevice::GetCountryCodeName(T35CountryCodes c) 
  1190. {
  1191.   for (PINDEX i = 0; i < PARRAYSIZE(CountryInfo); i++)
  1192.     if (CountryInfo[i].t35Code == c)
  1193.       return CountryInfo[i].fullName;
  1194.  
  1195.   return "<Unknown>";
  1196. }
  1197.  
  1198.  
  1199. PString OpalLineInterfaceDevice::GetCountryCodeName() const
  1200.   return GetCountryCodeName(countryCode);
  1201. }
  1202.  
  1203.  
  1204. BOOL OpalLineInterfaceDevice::SetCountryCode(T35CountryCodes country)
  1205. {
  1206.   countryCode = country;
  1207.  
  1208.   unsigned line;
  1209.   for (line = 0; line < GetLineCount(); line++)
  1210.     SetToneFilter(line, CNGTone, "1100:0.25");
  1211.  
  1212.   for (PINDEX i = 0; i < PARRAYSIZE(CountryInfo); i++) {
  1213.     if (CountryInfo[i].t35Code == country) {
  1214.       PTRACE(2, "LID\tCountry set to " << CountryInfo[i].fullName);
  1215.       for (line = 0; line < GetLineCount(); line++) {
  1216.         if (CountryInfo[i].dialTone != NULL)
  1217.           SetToneFilter(line, DialTone, CountryInfo[i].dialTone);
  1218.         if (CountryInfo[i].ringTone != NULL)
  1219.           SetToneFilter(line, RingTone, CountryInfo[i].ringTone);
  1220.         if (CountryInfo[i].busyTone != NULL)
  1221.           SetToneFilter(line, BusyTone, CountryInfo[i].busyTone);
  1222.       }
  1223.       return TRUE;
  1224.     }
  1225.   }
  1226.  
  1227.   PTRACE(2, "LID\tCountry set to " << GetCountryCodeName());
  1228.   return TRUE;
  1229. }
  1230.  
  1231.  
  1232. PStringList OpalLineInterfaceDevice::GetCountryCodeNameList() const
  1233. {
  1234.   PStringList list;
  1235.   list.AppendString("United States");
  1236.   return list;
  1237. }
  1238.  
  1239.  
  1240. static PCaselessString DeSpaced(const PString & orig)
  1241. {
  1242.   PString str = orig.Trim();
  1243.  
  1244.   PINDEX space = 0;
  1245.   while ((space = str.Find(' ')) != P_MAX_INDEX)
  1246.     str.Delete(space, 1);
  1247.  
  1248.   return str;
  1249. }
  1250.  
  1251.  
  1252. BOOL OpalLineInterfaceDevice::SetCountryCodeName(const PString & countryName)
  1253. {
  1254.   PTRACE(4, "IXJ\tSetting country code name to " << countryName);
  1255.   PCaselessString spacelessAndCaseless = DeSpaced(countryName);
  1256.   if (spacelessAndCaseless.IsEmpty())
  1257.     return FALSE;
  1258.  
  1259.   if (isdigit(spacelessAndCaseless[0]))
  1260.     return SetCountryCode((T35CountryCodes)spacelessAndCaseless.AsUnsigned());
  1261.  
  1262.   PINDEX i;
  1263.   if (spacelessAndCaseless[0] == '+') {
  1264.     unsigned code = spacelessAndCaseless.AsUnsigned();
  1265.     for (i = 0; i < PARRAYSIZE(CountryInfo); i++)
  1266.       if (code == CountryInfo[i].dialCode)
  1267.         return SetCountryCode(CountryInfo[i].t35Code);
  1268.   }
  1269.   else if (spacelessAndCaseless.GetLength() == 2) {
  1270.     for (i = 0; i < PARRAYSIZE(CountryInfo); i++)
  1271.       if (spacelessAndCaseless == CountryInfo[i].isoName)
  1272.         return SetCountryCode(CountryInfo[i].t35Code);
  1273.   }
  1274.   else {
  1275.     for (i = 0; i < PARRAYSIZE(CountryInfo); i++)
  1276.       if (spacelessAndCaseless == DeSpaced(CountryInfo[i].fullName))
  1277.         return SetCountryCode(CountryInfo[i].t35Code);
  1278.   }
  1279.  
  1280.   SetCountryCode(UnknownCountry);
  1281.   return FALSE;
  1282. }
  1283.  
  1284.  
  1285. PString OpalLineInterfaceDevice::GetErrorText() const
  1286. {
  1287.   return PChannel::GetErrorText(PChannel::Miscellaneous, osError);
  1288. }
  1289.  
  1290.  
  1291. void OpalLineInterfaceDevice::PrintOn(ostream & strm) const
  1292. {
  1293.   strm << GetName();
  1294. }
  1295.  
  1296.  
  1297. /////////////////////////////////////////////////////////////////////////////
  1298.  
  1299. static struct {
  1300.   const char * name;
  1301.  
  1302.   unsigned bytesPerFrame;
  1303.   unsigned rxFramesInPacket;
  1304.   unsigned txFramesInPacket;
  1305.   BOOL     g7231annexA;
  1306.  
  1307.   H245_AudioCapability::Choices capabilitySubtype;
  1308.  
  1309. } CodecTypeInfo[] = {
  1310.   // Do not alter the order of the next four entries with understanding what
  1311.   // H323_LIDCapability::OnReceivedPDU() does with them!
  1312. #define G7231A_63_INDEX 1
  1313.   { OPAL_G7231A_5k3,   24,   8,  3, TRUE,  H245_AudioCapability::e_g7231 },
  1314.   { OPAL_G7231A_6k3,   24,   8,  3, TRUE,  H245_AudioCapability::e_g7231 },
  1315.   { OPAL_G7231_5k3,    24,   8,  3, FALSE, H245_AudioCapability::e_g7231 },
  1316.   { OPAL_G7231_6k3,    24,   8,  3, FALSE, H245_AudioCapability::e_g7231 },
  1317.  
  1318.   { OPAL_G729,         10,  24,  6, FALSE, H245_AudioCapability::e_g729 },
  1319.   { OPAL_G729A,        10,  24,  6, FALSE, H245_AudioCapability::e_g729AnnexA },
  1320.   { OPAL_G729B,        10,  24,  6, FALSE, H245_AudioCapability::e_g729wAnnexB },
  1321.   { OPAL_G729AB,       10,  24,  6, FALSE, H245_AudioCapability::e_g729AnnexAwAnnexB },
  1322.   { OPAL_GSM0610,      33,   7,  4, FALSE, H245_AudioCapability::e_gsmFullRate },
  1323.   { OPAL_G728,          5,  96, 20, FALSE, H245_AudioCapability::e_g728 },
  1324.   { OPAL_G711_ULAW_64K, 8, 240, 30, FALSE, H245_AudioCapability::e_g711Ulaw64k },
  1325.   { OPAL_G711_ALAW_64K, 8, 240, 30, FALSE, H245_AudioCapability::e_g711Alaw64k },
  1326. };
  1327.  
  1328.  
  1329. H323_REGISTER_CAPABILITY_FUNCTION(H323_LID_G711_ALaw_Capability, OPAL_G711_ALAW_64K"{hw}", H323_NO_EP_VAR)
  1330. {
  1331.   return new H323_LIDCapability(OpalG711ALaw);
  1332. }
  1333.  
  1334. H323_REGISTER_CAPABILITY_FUNCTION(H323_LID_G711_uLaw_Capability, OPAL_G711_ULAW_64K"{hw}", H323_NO_EP_VAR)
  1335. {
  1336.   return new H323_LIDCapability(OpalG711uLaw);
  1337. }
  1338.  
  1339. H323_REGISTER_CAPABILITY_FUNCTION(H323_LID_G728_Capability, OPAL_G728"{hw}", H323_NO_EP_VAR)
  1340. {
  1341.   return new H323_LIDCapability(OpalG728);
  1342. }
  1343.  
  1344. H323_REGISTER_CAPABILITY_FUNCTION(H323_LID_GSM0610_Capability, OPAL_GSM0610"{hw}", H323_NO_EP_VAR)
  1345. {
  1346.   return new H323_LIDCapability(OpalGSM0610);
  1347. }
  1348.  
  1349. H323_REGISTER_CAPABILITY_FUNCTION(H323_LID_G729_Capability, OPAL_G729"{hw}", H323_NO_EP_VAR)
  1350. {
  1351.   return new H323_LIDCapability(OpalG729);
  1352. }
  1353.  
  1354. H323_REGISTER_CAPABILITY_FUNCTION(H323_LID_G729A_Capability, OPAL_G729A"{hw}", H323_NO_EP_VAR)
  1355. {
  1356.   return new H323_LIDCapability(OpalG729A);
  1357. }
  1358.  
  1359. H323_REGISTER_CAPABILITY_FUNCTION(H323_LID_G729B_Capability, OPAL_G729B"{hw}", H323_NO_EP_VAR)
  1360. {
  1361.   return new H323_LIDCapability(OpalG729B);
  1362. }
  1363.  
  1364. H323_REGISTER_CAPABILITY_FUNCTION(H323_LID_G729AB_Capability, OPAL_G729AB"{hw}", H323_NO_EP_VAR)
  1365. {
  1366.   return new H323_LIDCapability(OpalG729AB);
  1367. }
  1368.  
  1369. H323_REGISTER_CAPABILITY_FUNCTION(H323_LID_G7231_6k3_Capability, OPAL_G7231_6k3"{hw}", H323_NO_EP_VAR)
  1370. {
  1371.   return new H323_LIDCapability(OpalG7231_6k3);
  1372. }
  1373.  
  1374. H323_REGISTER_CAPABILITY_FUNCTION(H323_LID_G7231_5k3_Capability, OPAL_G7231_5k3"{hw}", H323_NO_EP_VAR)
  1375. {
  1376.   return new H323_LIDCapability(OpalG7231_5k3);
  1377. }
  1378.  
  1379. H323_REGISTER_CAPABILITY_FUNCTION(H323_LID_G7231A_6k3_Capability, OPAL_G7231A_6k3"{hw}", H323_NO_EP_VAR)
  1380. {
  1381.   return new H323_LIDCapability(OpalG7231A_6k3);
  1382. }
  1383.  
  1384. H323_REGISTER_CAPABILITY_FUNCTION(H323_LID_G7231A_5k3_Capability, OPAL_G7231A_5k3"{hw}", H323_NO_EP_VAR)
  1385. {
  1386.   return new H323_LIDCapability(OpalG7231A_5k3);
  1387. }
  1388.  
  1389. #define G7231_CISCO OPAL_G7231A_6k3"-Cisco{hw}"
  1390. H323_REGISTER_CAPABILITY(H323_CiscoG7231aLIDCapability, G7231_CISCO);
  1391.  
  1392.  
  1393. /////////////////////////////////////////////////////////////////////////////
  1394.  
  1395. OpalLineChannel::OpalLineChannel(OpalLineInterfaceDevice & dev,
  1396.                                  unsigned line,
  1397.                                  const H323AudioCodec & codec)
  1398.   : device(dev)
  1399. {
  1400.   lineNumber = line;
  1401.   reading = codec.GetDirection() == H323Codec::Encoder;
  1402.   OpalMediaFormat mediaFormat = OpalPCM16;
  1403.  
  1404.   if (codec.IsDescendant(H323_LIDCodec::Class())) {
  1405.     OpalMediaFormat::List mediaFormats = device.GetMediaFormats();
  1406.     for (PINDEX i = 0; i < mediaFormats.GetSize(); i++) {
  1407.       if (mediaFormats[i] == codec.GetMediaFormat())
  1408.         mediaFormat = codec.GetMediaFormat();
  1409.     }
  1410.   }
  1411.  
  1412.   if (reading) {
  1413.     if (!device.SetReadFormat(lineNumber, mediaFormat))
  1414.       return;
  1415.     useDeblocking = mediaFormat.GetFrameSize() != device.GetReadFrameSize(lineNumber);
  1416.   }
  1417.   else {
  1418.     if (!device.SetWriteFormat(lineNumber, mediaFormat))
  1419.       return;
  1420.     useDeblocking = mediaFormat.GetFrameSize() != device.GetWriteFrameSize(lineNumber);
  1421.   }
  1422.  
  1423.   PTRACE(3, "LID\tCodec set to " << mediaFormat << ", frame size: rd="
  1424.          << device.GetReadFrameSize(lineNumber) << " wr="
  1425.          << device.GetWriteFrameSize(lineNumber) << ", "
  1426.          << (useDeblocking ? "needs" : "no") << " reblocking.");
  1427.   os_handle = 1;
  1428. }
  1429.  
  1430.  
  1431. OpalLineChannel::~OpalLineChannel()
  1432. {
  1433.   Close();
  1434. }
  1435.  
  1436.  
  1437. PString OpalLineChannel::GetName() const
  1438. {
  1439.   return device.GetName() + psprintf("-%u", lineNumber);
  1440. }
  1441.  
  1442.  
  1443. BOOL OpalLineChannel::Close()
  1444. {
  1445.   if (!IsOpen())
  1446.     return FALSE;
  1447.  
  1448.   os_handle = -1;
  1449.  
  1450.   if (reading)
  1451.     return device.StopReadCodec(lineNumber);
  1452.   else
  1453.     return device.StopWriteCodec(lineNumber);
  1454. }
  1455.  
  1456.  
  1457. BOOL OpalLineChannel::Read(void * buffer, PINDEX length)
  1458. {
  1459.   lastReadCount = 0;
  1460.  
  1461.   if (!reading)
  1462.     return SetErrorValues(Miscellaneous, EINVAL, LastReadError);
  1463.  
  1464.   if (useDeblocking) {
  1465.     device.SetReadFrameSize(lineNumber, length);
  1466.     if (device.ReadBlock(lineNumber, buffer, length)) {
  1467.       lastReadCount = length;
  1468.       return TRUE;
  1469.     }
  1470.   }
  1471.   else {
  1472.     if (device.ReadFrame(lineNumber, buffer, lastReadCount))
  1473.       return TRUE;
  1474.   }
  1475.  
  1476.   int osError = device.GetErrorNumber();
  1477.   PTRACE_IF(1, osError != 0, "LID\tDevice read frame error: " << device.GetErrorText());
  1478.  
  1479.   return SetErrorValues(Miscellaneous, osError, LastReadError);
  1480. }
  1481.  
  1482.  
  1483. BOOL OpalLineChannel::Write(const void * buffer, PINDEX length)
  1484. {
  1485.   lastWriteCount = 0;
  1486.  
  1487.   if (reading)
  1488.     return SetErrorValues(Miscellaneous, EINVAL, LastWriteError);
  1489.  
  1490.   if (useDeblocking) {
  1491.     device.SetWriteFrameSize(lineNumber, length);
  1492.     if (device.WriteBlock(lineNumber, buffer, length)) {
  1493.       lastWriteCount = length;
  1494.       return TRUE;
  1495.     }
  1496.   }
  1497.   else {
  1498.     if (device.WriteFrame(lineNumber, buffer, length, lastWriteCount))
  1499.       return TRUE;
  1500.   }
  1501.  
  1502.   int osError = device.GetErrorNumber();
  1503.   PTRACE_IF(1, osError != 0, "LID\tDevice write frame error: " << device.GetErrorText());
  1504.  
  1505.   return SetErrorValues(Miscellaneous, osError, LastWriteError);
  1506. }
  1507.  
  1508.  
  1509. ///////////////////////////////////////////////////////////////////////////////
  1510.  
  1511. void H323_LIDCapability::AddAllCapabilities(const OpalLineInterfaceDevice & device,
  1512.                                             H323Capabilities & capabilities,
  1513.                                             PINDEX descriptorNum,
  1514.                                             PINDEX simultaneous)
  1515. {
  1516.   OpalMediaFormat::List codecsAvailable = device.GetMediaFormats();
  1517.   for (PINDEX c = 0; c < codecsAvailable.GetSize(); c++) {
  1518.     H323_LIDCapability * cap = new H323_LIDCapability(codecsAvailable[c]);
  1519.     if (cap->IsValid() && !capabilities.FindCapability(*cap))
  1520.       capabilities.SetCapability(descriptorNum, simultaneous, cap);
  1521.     else
  1522.       delete cap;
  1523.     if (codecsAvailable[c] == OpalG7231A_6k3)
  1524.       capabilities.SetCapability(descriptorNum, simultaneous,
  1525.                                  new H323_CiscoG7231aLIDCapability);
  1526.   }
  1527. }
  1528.  
  1529.  
  1530. H323_LIDCapability::H323_LIDCapability(const OpalMediaFormat & fmt)
  1531.   : H323AudioCapability(0, 0),
  1532.     mediaFormat(fmt)
  1533. {
  1534.   codecTableIndex = 0;
  1535.  
  1536.   while (IsValid()) {
  1537.     if (mediaFormat == CodecTypeInfo[codecTableIndex].name) {
  1538.       rxFramesInPacket = CodecTypeInfo[codecTableIndex].rxFramesInPacket;
  1539.       txFramesInPacket = CodecTypeInfo[codecTableIndex].txFramesInPacket;
  1540.       break;
  1541.     }
  1542.  
  1543.     codecTableIndex++;
  1544.   }
  1545. }
  1546.  
  1547.  
  1548. BOOL H323_LIDCapability::IsValid() const
  1549. {
  1550.   return codecTableIndex < PARRAYSIZE(CodecTypeInfo);
  1551. }
  1552.  
  1553.  
  1554. PObject::Comparison H323_LIDCapability::Compare(const PObject & obj) const
  1555. {
  1556.   Comparison result = H323AudioCapability::Compare(obj);
  1557.   if (result != EqualTo)
  1558.     return result;
  1559.  
  1560.   PINDEX otherIndex = ((const H323_LIDCapability &)obj).codecTableIndex;
  1561.   if (CodecTypeInfo[codecTableIndex].g7231annexA < CodecTypeInfo[otherIndex].g7231annexA)
  1562.     return LessThan;
  1563.   if (CodecTypeInfo[codecTableIndex].g7231annexA > CodecTypeInfo[otherIndex].g7231annexA)
  1564.     return GreaterThan;
  1565.   return EqualTo;
  1566. }
  1567.  
  1568.  
  1569. PObject * H323_LIDCapability::Clone() const
  1570. {
  1571.   return new H323_LIDCapability(*this);
  1572. }
  1573.  
  1574.  
  1575. PString H323_LIDCapability::GetFormatName() const
  1576. {
  1577.   return mediaFormat + "{hw}";
  1578. }
  1579.  
  1580.  
  1581. unsigned H323_LIDCapability::GetSubType() const
  1582. {
  1583.   return CodecTypeInfo[codecTableIndex].capabilitySubtype;
  1584. }
  1585.  
  1586.  
  1587. H323Codec * H323_LIDCapability::CreateCodec(H323Codec::Direction direction) const
  1588. {
  1589.   return new H323_LIDCodec(mediaFormat,
  1590.                            direction,
  1591.                            direction == H323Codec::Encoder ? txFramesInPacket : rxFramesInPacket,
  1592.                            codecTableIndex);
  1593. }
  1594.  
  1595.  
  1596. BOOL H323_LIDCapability::OnSendingPDU(H245_AudioCapability & pdu,
  1597.                                       unsigned packetSize) const
  1598. {
  1599.   pdu.SetTag(GetSubType());
  1600.  
  1601.   switch (pdu.GetTag()) {
  1602.     case H245_AudioCapability::e_gsmFullRate :
  1603.     {
  1604.       H245_GSMAudioCapability & gsm = pdu;
  1605.       gsm.m_audioUnitSize = packetSize*33;
  1606.       break;
  1607.     }
  1608.     case H245_AudioCapability::e_g7231 :
  1609.     {
  1610.       H245_AudioCapability_g7231 & g7231 = pdu;
  1611.       g7231.m_maxAl_sduAudioFrames = packetSize;
  1612.       g7231.m_silenceSuppression = CodecTypeInfo[codecTableIndex].g7231annexA;
  1613.       break;
  1614.     }
  1615.     default :
  1616.     {
  1617.       PASN_Integer & value = pdu;
  1618.       value = packetSize;
  1619.     }
  1620.   }
  1621.  
  1622.   return TRUE;
  1623. }
  1624.  
  1625.  
  1626. BOOL H323_LIDCapability::OnReceivedPDU(const H245_AudioCapability & pdu,
  1627.                                        unsigned & packetSize)
  1628. {
  1629.   if (pdu.GetTag() != GetSubType())
  1630.     return FALSE;
  1631.  
  1632.   switch (pdu.GetTag()) {
  1633.     case H245_AudioCapability::e_gsmFullRate :
  1634.     {
  1635.       const H245_GSMAudioCapability & gsm = pdu;
  1636.       packetSize = gsm.m_audioUnitSize/33;
  1637.       break;
  1638.     }
  1639.     case H245_AudioCapability::e_g7231 :
  1640.     {
  1641.       const H245_AudioCapability_g7231 & g7231 = pdu;
  1642.       packetSize = g7231.m_maxAl_sduAudioFrames;
  1643.  
  1644.       BOOL g7231annexA = g7231.m_silenceSuppression;
  1645.       if (g7231annexA != CodecTypeInfo[codecTableIndex].g7231annexA) {
  1646.         // Move to the other G.723.1 version
  1647.         codecTableIndex += (g7231annexA ? -2 : 2);
  1648.         mediaFormat = CodecTypeInfo[codecTableIndex].name;
  1649.       }
  1650.       break;
  1651.     }
  1652.     default :
  1653.     {
  1654.       const PASN_Integer & value = pdu;
  1655.       packetSize = value;
  1656.     }
  1657.   }
  1658.  
  1659.   return TRUE;
  1660. }
  1661.  
  1662.  
  1663. /////////////////////////////////////////////////////////////////////////////
  1664.  
  1665. H323_CiscoG7231aLIDCapability::H323_CiscoG7231aLIDCapability()
  1666.   : H323NonStandardAudioCapability(1, 1, 181, 0, 18, (const BYTE*)"G7231ar", 7)
  1667. {
  1668. }
  1669.  
  1670.  
  1671. PObject * H323_CiscoG7231aLIDCapability::Clone() const
  1672. {
  1673.   return new H323_CiscoG7231aLIDCapability(*this);
  1674. }
  1675.  
  1676.  
  1677. PString H323_CiscoG7231aLIDCapability::GetFormatName() const
  1678. {
  1679.   return G7231_CISCO;
  1680. }
  1681.  
  1682.  
  1683. H323Codec * H323_CiscoG7231aLIDCapability::CreateCodec(H323Codec::Direction direction) const
  1684. {
  1685.   return new H323_LIDCodec(OpalG7231A_6k3, direction, 1, G7231A_63_INDEX);
  1686. }
  1687.  
  1688.  
  1689. /////////////////////////////////////////////////////////////////////////////
  1690.  
  1691. H323_LIDCodec::H323_LIDCodec(const char * fmt,
  1692.                              Direction direction,
  1693.                              unsigned numFrames,
  1694.                              PINDEX index)
  1695.   : H323AudioCodec(fmt, direction)
  1696. {
  1697.   codecTableIndex = index;
  1698.   packetSize = CodecTypeInfo[index].bytesPerFrame;
  1699.  
  1700.   /* Special case for G.711 encoder, note this helps with optimisation of
  1701.     sound data but will break if remote does not send the maximum number of
  1702.     bytes that it said it could. It is legal for the remote end to do so
  1703.     though no endpoints seem to actually do that.
  1704.    */
  1705.   if (packetSize == 8) {
  1706.     packetSize *= numFrames;
  1707.     samplesPerFrame *= numFrames;
  1708.   }
  1709.  
  1710.   missedCount = 0;
  1711.   lastSID[0] = 2;
  1712.   lastFrameWasSignal = TRUE;
  1713.  
  1714.   PTRACE(3, "LID\tCreated codec: pt=" << mediaFormat.GetPayloadType()
  1715.          << ", bytes=" << packetSize << ", samples=" << mediaFormat.GetFrameTime());
  1716. }
  1717.  
  1718.  
  1719. BOOL H323_LIDCodec::Read(BYTE * buffer, unsigned & length, RTP_DataFrame &)
  1720. {
  1721.   PWaitAndSignal mutex(rawChannelMutex);
  1722.  
  1723.   // This reads to an H323_IxJChannel class
  1724.   PINDEX count;
  1725.   if (!ReadRaw(buffer, packetSize, count))
  1726.     return FALSE;
  1727.  
  1728.   // In the case of G.723.1 remember the last SID frame we sent and send
  1729.   // it again if the hardware sends us a CNG frame.
  1730.   if (mediaFormat.GetPayloadType() == RTP_DataFrame::G7231) {
  1731.     switch (count) {
  1732.       case 1 : // CNG frame
  1733.         memcpy(buffer, lastSID, 4);
  1734.         count = 4;
  1735.         lastFrameWasSignal = FALSE;
  1736.         break;
  1737.       case 4 :
  1738.         if ((*buffer&3) == 2)
  1739.           memcpy(lastSID, buffer, 4);
  1740.         lastFrameWasSignal = FALSE;
  1741.         break;
  1742.       default :
  1743.         lastFrameWasSignal = TRUE;
  1744.     }
  1745.   }
  1746.  
  1747.   length = DetectSilence() ? 0 : count;
  1748.   return TRUE;
  1749. }
  1750.  
  1751.  
  1752. BOOL H323_LIDCodec::Write(const BYTE * buffer,
  1753.                           unsigned length,
  1754.                           const RTP_DataFrame & /*frame*/,
  1755.                           unsigned & written)
  1756. {
  1757.   // This writes to an H323_IxJChannel class
  1758.   if (length > packetSize)
  1759.     length = packetSize;
  1760.  
  1761.   // Check for writing silence
  1762.   PBYTEArray silenceBuffer;
  1763.   if (length != 0)
  1764.     missedCount = 0;
  1765.   else {
  1766.     switch (mediaFormat.GetPayloadType()) {
  1767.       case RTP_DataFrame::G7231 :
  1768.         if (missedCount++ < 4) {
  1769.           static const BYTE g723_erasure_frame[24] = { 0xff, 0xff, 0xff, 0xff };
  1770.           buffer = g723_erasure_frame;
  1771.           length = 24;
  1772.         }
  1773.         else {
  1774.           static const BYTE g723_cng_frame[4] = { 3 };
  1775.           buffer = g723_cng_frame;
  1776.           length = 1;
  1777.         }
  1778.         break;
  1779.  
  1780.       case RTP_DataFrame::PCMU :
  1781.       case RTP_DataFrame::PCMA :
  1782.         buffer = silenceBuffer.GetPointer(packetSize);
  1783.         memset((void *)buffer, 0xff, packetSize);
  1784.         length = packetSize;
  1785.         break;
  1786.  
  1787.       case RTP_DataFrame::G729 :
  1788.         if (mediaFormat.Find('B') != P_MAX_INDEX) {
  1789.           static const BYTE g729_sid_frame[2] = { 1 };
  1790.           buffer = g729_sid_frame;
  1791.           length = 2;
  1792.           break;
  1793.         }
  1794.         // Else fall into default case
  1795.  
  1796.       default :
  1797.         buffer = silenceBuffer.GetPointer(packetSize); // Fills with zeros
  1798.         length = packetSize;
  1799.         break;
  1800.     }
  1801.   }
  1802.  
  1803.   PWaitAndSignal mutex(rawChannelMutex);
  1804.  
  1805.   if (!rawDataChannel->Write(buffer, length))
  1806.     return FALSE;
  1807.  
  1808.   written = rawDataChannel->GetLastWriteCount();
  1809.   return TRUE;
  1810. }
  1811.  
  1812.  
  1813. BOOL H323_LIDCodec::IsRawDataChannelNative() const
  1814. {
  1815.   return TRUE;
  1816. }
  1817.  
  1818.  
  1819. BOOL H323_LIDCodec::DetectSilence()
  1820. {
  1821.   // Can never have silence if NoSilenceDetection
  1822.   if (silenceDetectMode == NoSilenceDetection)
  1823.     return FALSE;
  1824.  
  1825.   if (!CodecTypeInfo[codecTableIndex].g7231annexA)
  1826.     return H323AudioCodec::DetectSilence();
  1827.  
  1828.   // Utilise the codecs own silence detection algorithm
  1829.  
  1830.   // If no change ie still talking or still silent, resent frame counter
  1831.   if (inTalkBurst == lastFrameWasSignal)
  1832.     framesReceived = 0;
  1833.   else {
  1834.     framesReceived++;
  1835.     // If have had enough consecutive frames talking/silent, swap modes.
  1836.     if (framesReceived >= (inTalkBurst ? silenceDeadbandFrames : signalDeadbandFrames)) {
  1837.       inTalkBurst = !inTalkBurst;
  1838.       PTRACE(4, "Codec\tSilence detection transition: "
  1839.              << (inTalkBurst ? "Talk" : "Silent"));
  1840.     }
  1841.   }
  1842.  
  1843.   return !inTalkBurst;
  1844. }
  1845.  
  1846.  
  1847. unsigned H323_LIDCodec::GetAverageSignalLevel()
  1848. {
  1849.   PWaitAndSignal mutex(rawChannelMutex);
  1850.  
  1851.   return ((OpalLineChannel*)rawDataChannel)->GetDevice().GetAverageSignalLevel(0, direction == Decoder);
  1852. }
  1853.  
  1854.  
  1855. /////////////////////////////////////////////////////////////////////////////
  1856.