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 / rfc2833.cxx < prev    next >
C/C++ Source or Header  |  2003-06-03  |  7KB  |  274 lines

  1. /*
  2.  * rfc2833.cxx
  3.  *
  4.  * Open Phone Abstraction Library (OPAL)
  5.  * Formally known as the Open H323 project.
  6.  *
  7.  * Copyright (c) 2001 Equivalence Pty. Ltd.
  8.  *
  9.  * The contents of this file are subject to the Mozilla Public License
  10.  * Version 1.0 (the "License"); you may not use this file except in
  11.  * compliance with the License. You may obtain a copy of the License at
  12.  * http://www.mozilla.org/MPL/
  13.  *
  14.  * Software distributed under the License is distributed on an "AS IS"
  15.  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
  16.  * the License for the specific language governing rights and limitations
  17.  * under the License.
  18.  *
  19.  * The Original Code is Open Phone Abstraction Library.
  20.  *
  21.  * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
  22.  *
  23.  * Contributor(s): ______________________________________.
  24.  *
  25.  * $Log: rfc2833.cxx,v $
  26.  * Revision 1.4  2003/06/03 05:02:18  rjongbloed
  27.  * Added comment and test for NULL pointer parameter.
  28.  *
  29.  * Revision 1.3  2002/05/08 04:39:57  robertj
  30.  * Fixed problem with receiving RFC2833 data, was still trying to process it as
  31.  *   codec and upsettign the channel receiver code.
  32.  *
  33.  * Revision 1.2  2002/02/19 06:32:38  robertj
  34.  * Allowed for RTP filter functions to force output of packet, or prevent it
  35.  *   from being sent overriding the n frames per packet algorithm.
  36.  * Added more tracing.
  37.  *
  38.  * Revision 1.1  2002/01/23 05:06:23  robertj
  39.  * Added RFC2833 support as separate class
  40.  *
  41.  */
  42.  
  43. #include <ptlib.h>
  44.  
  45. #ifdef __GNUC__
  46. #pragma implementation "rfc2833.h"
  47. #endif
  48.  
  49. #include "rfc2833.h"
  50.  
  51.  
  52. static const char RFC2833Table1Events[] = "0123456789*#ABCD!";
  53.  
  54.  
  55. #define new PNEW
  56.  
  57.  
  58. ///////////////////////////////////////////////////////////////////////////////
  59.  
  60. OpalRFC2833Info::OpalRFC2833Info(char t, unsigned d, unsigned ts)
  61. {
  62.   tone = t;
  63.   duration = d;
  64.   timestamp = ts;
  65. }
  66.  
  67.  
  68. ///////////////////////////////////////////////////////////////////////////////
  69.  
  70. OpalRFC2833::OpalRFC2833(const PNotifier & rx)
  71.   : receiveNotifier(rx),
  72. #ifdef _MSC_VER
  73. #pragma warning(disable:4355)
  74. #endif
  75.     receiveHandler(PCREATE_NOTIFIER(ReceivedPacket)),
  76.     transmitHandler(PCREATE_NOTIFIER(TransmitPacket))
  77. #ifdef _MSC_VER
  78. #pragma warning(default:4355)
  79. #endif
  80. {
  81.   PTRACE(3, "RFC2833\tHandler created");
  82.  
  83.   payloadType = RTP_DataFrame::IllegalPayloadType;
  84.   receiveComplete = TRUE;
  85.   receiveTimestamp = 0;
  86.   receiveTimer.SetNotifier(PCREATE_NOTIFIER(ReceiveTimeout));
  87.  
  88.   transmitState = TransmitIdle;
  89.   transmitTimestamp = 0;
  90.   transmitTimer.SetNotifier(PCREATE_NOTIFIER(TransmitEnded));
  91. }
  92.  
  93.  
  94. BOOL OpalRFC2833::SendTone(char tone, unsigned duration)
  95. {
  96.   if (!BeginTransmit(tone))
  97.     return FALSE;
  98.  
  99.   transmitTimer = duration;
  100.   return TRUE;
  101. }
  102.  
  103.  
  104. BOOL OpalRFC2833::BeginTransmit(char tone)
  105. {
  106.   PWaitAndSignal m(mutex);
  107.  
  108.   const char * theChar = strchr(RFC2833Table1Events, tone);
  109.   if (theChar == NULL) {
  110.     PTRACE(1, "RFC2833\tInvalid tone character.");
  111.     return FALSE;
  112.   }
  113.  
  114.   if (transmitState != TransmitIdle) {
  115.     PTRACE(1, "RFC2833\tAttempt to send tone while currently sending.");
  116.     return FALSE;
  117.   }
  118.  
  119.   transmitCode = (BYTE)(theChar-RFC2833Table1Events);
  120.   transmitState = TransmitActive;
  121.   transmitTimestamp = 0;
  122.   PTRACE(3, "RFC2833\tBegin transmit tone='" << tone << '\'');
  123.   return TRUE;
  124. }
  125.  
  126.  
  127. BOOL OpalRFC2833::EndTransmit()
  128. {
  129.   PWaitAndSignal m(mutex);
  130.  
  131.   if (transmitState != TransmitActive) {
  132.     PTRACE(1, "RFC2833\tAttempt to stop send tone while not sending.");
  133.     return FALSE;
  134.   }
  135.  
  136.   transmitState = TransmitEnding;
  137.   PTRACE(3, "RFC2833\tEnd transmit tone='" << RFC2833Table1Events[transmitCode] << '\'');
  138.   return TRUE;
  139. }
  140.  
  141.  
  142. void OpalRFC2833::OnStartReceive(char tone)
  143. {
  144.   OpalRFC2833Info info(tone);
  145.   receiveNotifier(info, 0);
  146. }
  147.  
  148.  
  149. void OpalRFC2833::OnEndReceive(char tone, unsigned duration, unsigned timestamp)
  150. {
  151.   OpalRFC2833Info info(tone, duration, timestamp);
  152.   receiveNotifier(info, 0);
  153. }
  154.  
  155.  
  156. void OpalRFC2833::ReceivedPacket(RTP_DataFrame & frame, INT)
  157. {
  158.   if (frame.GetPayloadType() != payloadType)
  159.     return;
  160.  
  161.   PINDEX payloadSize = frame.GetPayloadSize();
  162.   // Zero the payload size so the channel processing ignores this packet
  163.   frame.SetPayloadSize(0);
  164.  
  165.   if (payloadSize < 4) {
  166.     PTRACE_IF(1, payloadSize > 0,
  167.               "RFC2833\tIgnoring packet, too small: " << frame.GetPayloadSize());
  168.     return;
  169.   }
  170.  
  171.   const BYTE * payload = frame.GetPayloadPtr();
  172.   if (payload[0] >= sizeof(RFC2833Table1Events)-1) {
  173.     PTRACE(2, "RFC2833\tIgnoring packet, unsupported event.");
  174.     return;
  175.   }
  176.  
  177.   PWaitAndSignal m(mutex);
  178.  
  179.   receivedTone = RFC2833Table1Events[payload[0]];
  180.   receivedDuration = (payload[2]<<8) + payload[3];
  181.  
  182.   unsigned timestamp = frame.GetTimestamp();
  183.   if (receiveTimestamp != timestamp) {
  184.     PTRACE(3, "RFC2833\tReceived start tone=" << receivedTone);
  185.     OnStartReceive(receivedTone);
  186.  
  187.     // Starting a new event.
  188.     receiveTimestamp = timestamp;
  189.     receiveComplete = FALSE;
  190.     receiveTimer = 150;
  191.   }
  192.   else {
  193.     receiveTimer = 150;
  194.     if (receiveComplete) {
  195.       PTRACE(3, "RFC2833\tIgnoring duplicate packet.");
  196.       return;
  197.     }
  198.   }
  199.  
  200.   if ((payload[1]&0x80) == 0) {
  201.     PTRACE(1, "RFC2833\tIgnoring packet, not end of event.");
  202.     return;
  203.   }
  204.  
  205.   receiveComplete = TRUE;
  206.   receiveTimer.Stop();
  207.  
  208.   PTRACE(3, "RFC2833\tReceived end tone=" << receivedTone << " duration=" << receivedDuration);
  209.   OnEndReceive(receivedTone, receivedDuration, receiveTimestamp);
  210. }
  211.  
  212.  
  213. void OpalRFC2833::ReceiveTimeout(PTimer &, INT)
  214. {
  215.   PWaitAndSignal m(mutex);
  216.  
  217.   if (receiveComplete)
  218.     return;
  219.  
  220.   receiveComplete = TRUE;
  221.   PTRACE(3, "RFC2833\tTimeout tone=" << receivedTone << " duration=" << receivedDuration);
  222.   OnEndReceive(receivedTone, receivedDuration, receiveTimestamp);
  223. }
  224.  
  225.  
  226. void OpalRFC2833::TransmitPacket(RTP_DataFrame & frame, INT param)
  227. {
  228.   if (transmitState == TransmitIdle)
  229.     return;
  230.  
  231.   // Set flag to force a packet to be sent.
  232.   if (param != 0)
  233.     *(BOOL *)param = TRUE;
  234.  
  235.   PWaitAndSignal m(mutex);
  236.  
  237.   //frame.SetMarker(transmitTimestamp == 0);
  238.  
  239.   unsigned actualTimestamp = frame.GetTimestamp();
  240.   if (transmitTimestamp == 0)
  241.     transmitTimestamp = actualTimestamp;
  242.   frame.SetTimestamp(transmitTimestamp);
  243.  
  244.   frame.SetPayloadType(payloadType);
  245.   frame.SetPayloadSize(4);
  246.  
  247.   BYTE * payload = frame.GetPayloadPtr();
  248.   payload[0] = transmitCode;
  249.  
  250.   payload[1] = 7;  // Volume
  251.   if (transmitState == TransmitEnding) {
  252.     payload[1] |= 0x80;
  253.     transmitState = TransmitIdle;
  254.   }
  255.  
  256.   unsigned duration = actualTimestamp - transmitTimestamp;
  257.   payload[2] = (BYTE)(duration>>8);
  258.   payload[3] = (BYTE) duration    ;
  259.  
  260.   PTRACE(4, "RFC2833\tInserting packet: ts=" << transmitTimestamp
  261.          << " code='" << RFC2833Table1Events[transmitCode] << "'"
  262.             " duration=" << duration << ' '
  263.          << (transmitState == TransmitIdle ? "ending" : "continuing"));
  264. }
  265.  
  266.  
  267. void OpalRFC2833::TransmitEnded(PTimer &, INT)
  268. {
  269.   EndTransmit();
  270. }
  271.  
  272.  
  273. /////////////////////////////////////////////////////////////////////////////
  274.