Utilise new MergeSym feature to no longer overwrite the source .DEF file when buildin...
[openh323.git] / src / rfc2833.cxx
blob1fc23f2d61e0701e694020a4c3c306f3d6b62e73
1 /*
2 * rfc2833.cxx
4 * Open Phone Abstraction Library (OPAL)
5 * Formally known as the Open H323 project.
7 * Copyright (c) 2001 Equivalence Pty. Ltd.
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/
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.
19 * The Original Code is Open Phone Abstraction Library.
21 * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
23 * Contributor(s): ______________________________________.
25 * $Log$
26 * Revision 1.4 2003/06/03 05:02:18 rjongbloed
27 * Added comment and test for NULL pointer parameter.
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.
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.
38 * Revision 1.1 2002/01/23 05:06:23 robertj
39 * Added RFC2833 support as separate class
43 #include <ptlib.h>
45 #ifdef __GNUC__
46 #pragma implementation "rfc2833.h"
47 #endif
49 #include "rfc2833.h"
52 static const char RFC2833Table1Events[] = "0123456789*#ABCD!";
55 #define new PNEW
58 ///////////////////////////////////////////////////////////////////////////////
60 OpalRFC2833Info::OpalRFC2833Info(char t, unsigned d, unsigned ts)
62 tone = t;
63 duration = d;
64 timestamp = ts;
68 ///////////////////////////////////////////////////////////////////////////////
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
81 PTRACE(3, "RFC2833\tHandler created");
83 payloadType = RTP_DataFrame::IllegalPayloadType;
84 receiveComplete = TRUE;
85 receiveTimestamp = 0;
86 receiveTimer.SetNotifier(PCREATE_NOTIFIER(ReceiveTimeout));
88 transmitState = TransmitIdle;
89 transmitTimestamp = 0;
90 transmitTimer.SetNotifier(PCREATE_NOTIFIER(TransmitEnded));
94 BOOL OpalRFC2833::SendTone(char tone, unsigned duration)
96 if (!BeginTransmit(tone))
97 return FALSE;
99 transmitTimer = duration;
100 return TRUE;
104 BOOL OpalRFC2833::BeginTransmit(char tone)
106 PWaitAndSignal m(mutex);
108 const char * theChar = strchr(RFC2833Table1Events, tone);
109 if (theChar == NULL) {
110 PTRACE(1, "RFC2833\tInvalid tone character.");
111 return FALSE;
114 if (transmitState != TransmitIdle) {
115 PTRACE(1, "RFC2833\tAttempt to send tone while currently sending.");
116 return FALSE;
119 transmitCode = (BYTE)(theChar-RFC2833Table1Events);
120 transmitState = TransmitActive;
121 transmitTimestamp = 0;
122 PTRACE(3, "RFC2833\tBegin transmit tone='" << tone << '\'');
123 return TRUE;
127 BOOL OpalRFC2833::EndTransmit()
129 PWaitAndSignal m(mutex);
131 if (transmitState != TransmitActive) {
132 PTRACE(1, "RFC2833\tAttempt to stop send tone while not sending.");
133 return FALSE;
136 transmitState = TransmitEnding;
137 PTRACE(3, "RFC2833\tEnd transmit tone='" << RFC2833Table1Events[transmitCode] << '\'');
138 return TRUE;
142 void OpalRFC2833::OnStartReceive(char tone)
144 OpalRFC2833Info info(tone);
145 receiveNotifier(info, 0);
149 void OpalRFC2833::OnEndReceive(char tone, unsigned duration, unsigned timestamp)
151 OpalRFC2833Info info(tone, duration, timestamp);
152 receiveNotifier(info, 0);
156 void OpalRFC2833::ReceivedPacket(RTP_DataFrame & frame, INT)
158 if (frame.GetPayloadType() != payloadType)
159 return;
161 PINDEX payloadSize = frame.GetPayloadSize();
162 // Zero the payload size so the channel processing ignores this packet
163 frame.SetPayloadSize(0);
165 if (payloadSize < 4) {
166 PTRACE_IF(1, payloadSize > 0,
167 "RFC2833\tIgnoring packet, too small: " << frame.GetPayloadSize());
168 return;
171 const BYTE * payload = frame.GetPayloadPtr();
172 if (payload[0] >= sizeof(RFC2833Table1Events)-1) {
173 PTRACE(2, "RFC2833\tIgnoring packet, unsupported event.");
174 return;
177 PWaitAndSignal m(mutex);
179 receivedTone = RFC2833Table1Events[payload[0]];
180 receivedDuration = (payload[2]<<8) + payload[3];
182 unsigned timestamp = frame.GetTimestamp();
183 if (receiveTimestamp != timestamp) {
184 PTRACE(3, "RFC2833\tReceived start tone=" << receivedTone);
185 OnStartReceive(receivedTone);
187 // Starting a new event.
188 receiveTimestamp = timestamp;
189 receiveComplete = FALSE;
190 receiveTimer = 150;
192 else {
193 receiveTimer = 150;
194 if (receiveComplete) {
195 PTRACE(3, "RFC2833\tIgnoring duplicate packet.");
196 return;
200 if ((payload[1]&0x80) == 0) {
201 PTRACE(1, "RFC2833\tIgnoring packet, not end of event.");
202 return;
205 receiveComplete = TRUE;
206 receiveTimer.Stop();
208 PTRACE(3, "RFC2833\tReceived end tone=" << receivedTone << " duration=" << receivedDuration);
209 OnEndReceive(receivedTone, receivedDuration, receiveTimestamp);
213 void OpalRFC2833::ReceiveTimeout(PTimer &, INT)
215 PWaitAndSignal m(mutex);
217 if (receiveComplete)
218 return;
220 receiveComplete = TRUE;
221 PTRACE(3, "RFC2833\tTimeout tone=" << receivedTone << " duration=" << receivedDuration);
222 OnEndReceive(receivedTone, receivedDuration, receiveTimestamp);
226 void OpalRFC2833::TransmitPacket(RTP_DataFrame & frame, INT param)
228 if (transmitState == TransmitIdle)
229 return;
231 // Set flag to force a packet to be sent.
232 if (param != 0)
233 *(BOOL *)param = TRUE;
235 PWaitAndSignal m(mutex);
237 //frame.SetMarker(transmitTimestamp == 0);
239 unsigned actualTimestamp = frame.GetTimestamp();
240 if (transmitTimestamp == 0)
241 transmitTimestamp = actualTimestamp;
242 frame.SetTimestamp(transmitTimestamp);
244 frame.SetPayloadType(payloadType);
245 frame.SetPayloadSize(4);
247 BYTE * payload = frame.GetPayloadPtr();
248 payload[0] = transmitCode;
250 payload[1] = 7; // Volume
251 if (transmitState == TransmitEnding) {
252 payload[1] |= 0x80;
253 transmitState = TransmitIdle;
256 unsigned duration = actualTimestamp - transmitTimestamp;
257 payload[2] = (BYTE)(duration>>8);
258 payload[3] = (BYTE) duration ;
260 PTRACE(4, "RFC2833\tInserting packet: ts=" << transmitTimestamp
261 << " code='" << RFC2833Table1Events[transmitCode] << "'"
262 " duration=" << duration << ' '
263 << (transmitState == TransmitIdle ? "ending" : "continuing"));
267 void OpalRFC2833::TransmitEnded(PTimer &, INT)
269 EndTransmit();
273 /////////////////////////////////////////////////////////////////////////////