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
19 * The Original Code is Open Phone Abstraction Library.
21 * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
23 * Contributor(s): ______________________________________.
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.
38 * Revision 1.1 2002/01/23 05:06:23 robertj
39 * Added RFC2833 support as separate class
46 #pragma implementation "rfc2833.h"
52 static const char RFC2833Table1Events
[] = "0123456789*#ABCD!";
58 ///////////////////////////////////////////////////////////////////////////////
60 OpalRFC2833Info::OpalRFC2833Info(char t
, unsigned d
, unsigned ts
)
68 ///////////////////////////////////////////////////////////////////////////////
70 OpalRFC2833::OpalRFC2833(const PNotifier
& rx
)
71 : receiveNotifier(rx
),
73 #pragma warning(disable:4355)
75 receiveHandler(PCREATE_NOTIFIER(ReceivedPacket
)),
76 transmitHandler(PCREATE_NOTIFIER(TransmitPacket
))
78 #pragma warning(default:4355)
81 PTRACE(3, "RFC2833\tHandler created");
83 payloadType
= RTP_DataFrame::IllegalPayloadType
;
84 receiveComplete
= TRUE
;
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
))
99 transmitTimer
= duration
;
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.");
114 if (transmitState
!= TransmitIdle
) {
115 PTRACE(1, "RFC2833\tAttempt to send tone while currently sending.");
119 transmitCode
= (BYTE
)(theChar
-RFC2833Table1Events
);
120 transmitState
= TransmitActive
;
121 transmitTimestamp
= 0;
122 PTRACE(3, "RFC2833\tBegin transmit tone='" << tone
<< '\'');
127 BOOL
OpalRFC2833::EndTransmit()
129 PWaitAndSignal
m(mutex
);
131 if (transmitState
!= TransmitActive
) {
132 PTRACE(1, "RFC2833\tAttempt to stop send tone while not sending.");
136 transmitState
= TransmitEnding
;
137 PTRACE(3, "RFC2833\tEnd transmit tone='" << RFC2833Table1Events
[transmitCode
] << '\'');
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
)
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());
171 const BYTE
* payload
= frame
.GetPayloadPtr();
172 if (payload
[0] >= sizeof(RFC2833Table1Events
)-1) {
173 PTRACE(2, "RFC2833\tIgnoring packet, unsupported event.");
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
;
194 if (receiveComplete
) {
195 PTRACE(3, "RFC2833\tIgnoring duplicate packet.");
200 if ((payload
[1]&0x80) == 0) {
201 PTRACE(1, "RFC2833\tIgnoring packet, not end of event.");
205 receiveComplete
= TRUE
;
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
);
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
)
231 // Set flag to force a packet to be sent.
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
) {
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
)
273 /////////////////////////////////////////////////////////////////////////////