2 * Adium is the legal property of its developers, whose names are listed in the copyright file included
3 * with this source distribution.
5 * This program is free software; you can redistribute it and/or modify it under the terms of the GNU
6 * General Public License as published by the Free Software Foundation; either version 2 of the License,
7 * or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
10 * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
11 * Public License for more details.
13 * You should have received a copy of the GNU General Public License along with this program; if not,
14 * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 #import <Adium/AIObject.h>
18 #import <QuickTime/QuickTime.h>
20 #import "AIVideoConf.h"
21 #import "QTConnection.h"
22 #import "QTRTPConnection.h"
25 @implementation QTRTPConnection
27 ////////////////////////////////////////////////////////////////////////////////
28 #pragma mark Constructors / Initialization
29 ////////////////////////////////////////////////////////////////////////////////
31 + (id) createWithProtocol:(VCProtocol)proto payload:(VCPayload*)pt from:(VCTransport*)local to:(VCTransport*)remote;
33 return [[[self alloc] initWithProtocol:proto payload:pt from:local to:remote] autorelease];
36 - (id) initWithProtocol:(VCProtocol)proto payload:(VCPayload*)pt from:(VCTransport*)local to:(VCTransport*)remote;
38 NSAssert(proto == VC_RTP, @"QTRTPConnection initilized with a protocol different from RTP.");
53 ////////////////////////////////////////////////////////////////////////////////
54 #pragma mark SDP Generation
55 ////////////////////////////////////////////////////////////////////////////////
56 - (NSString*) generateSDPInStream
63 - (NSString*) generateSDPOutStream
67 const char *strSessionName = "outrtpstream";
68 const char *strDescription = "Audio output RTP stream";
69 const char *strUrl = "http://www.adiumx.com";
70 const char *strEmail = "none@adiumx.com";
72 const int ipVersion = 4; // We only support IP version 4
76 const char *ipDestination = [[mRemote valueForKey:@"mIP"] cString];
77 const char *ipSource = [[mLocal valueForKey:@"mIP"] cString];
78 int port = (int)[mLocal valueForKey:@"mPort"];
79 int payloadType = (int)[((VCPayload*)[mLocal valueForKey:@"mPayload"]) valueForKey:@"mId"];
85 "o=- * * IN IP%d %s\r\n" // Source
86 "s=%s\r\n" // Session name
87 "i=%s\r\n" // Description
90 "t=0 0\r\n" // Duration
91 "a=tool:Adium\r\n" // Other
92 "c=IN IP%d %s/%d\r\n" // Destination
93 "m=audio %d RTP/AVP %d\r\n", // Content description
100 ipVersion, ipDestination, ttl,
103 return [NSString stringWithCString:outStr];
109 @implementation QTAudioRTPConnection
112 ////////////////////////////////////////////////////////////////////////////////
113 #pragma mark Streams Handlers
114 ////////////////////////////////////////////////////////////////////////////////
117 * Broadcast notification handler.
119 ComponentResult outAudioRTPStreamNotifHandler (ComponentResult inErr,
120 OSType inNotificationType,
121 void *inNotificationParams,
123 QTSStatusParams* tempStatus;
125 switch (inNotificationType) {
126 case kQTSNewPresentationNotification:
129 case kQTSPrerollAckNotification:
130 QTSPresStart ((QTSPresentation)inRefCon, kQTSAllStreams, 0L );
133 case kQTSStreamChangedNotification:
136 case kQTSErrorNotification:
137 // ShowErr (macWindow, inErr, ”kQTSErrorNotification”);
140 case kQTSNewPresDetectedNotification:
141 case kQTSNewStreamNotification:
142 case kQTSStreamGoneNotification:
143 case kQTSStartAckNotification:
144 case kQTSStopAckNotification:
147 case kQTSStatusNotification:
148 tempStatus = (QTSStatusParams *)inNotificationParams;
157 ////////////////////////////////////////////////////////////////////////////////
158 #pragma mark Streams Management
159 ////////////////////////////////////////////////////////////////////////////////
162 * Create the output stream.
163 * This method creates and starts the output stream for broadcasting audio withb RTP.
165 - (OSErr) startOutAudioRTPStream
167 QTSPresParams presParams;
168 QTSMediaParams mediaParams;
169 QTSNotificationUPP sNotificationUPP;
170 NSString *outStream = [self generateSDPOutStream];
171 const char *sdpDataPtr = [outStream cString];
172 SInt64 sdpDataLength = (SInt64)[outStream length];
175 // Note: this API is almost undocumented. There is only one example,
176 // called "qtbroadcast"... [as]
178 mOutputStream = kQTSInvalidPresentation;
180 // Initialize the media params
181 memset (&presParams, 0, sizeof(presParams));
182 err = QTSInitializeMediaParams (&mediaParams);
187 // Video params: we don't have any video
189 // mediaParams.v.width = (Fixed)(myWidth<<16);
190 // mediaParams.v.height = (Fixed)(myHeight<<16);
192 // set the window that Sequence Grabber will draw into:
194 // mediaParams.v.gWorld = GetDialogPort(gMonitor);
195 // mediaParams.v.gdHandle = myGD;
197 // Audio params: simple volume params
198 mediaParams.a.leftVolume = kFullVolume;
199 mediaParams.a.rightVolume = kFullVolume;
201 // Other parameters that can be set:
203 // mediaParams.a.bassLevel;
204 // mediaParams.a.trebleLevel;
205 // mediaParams.a.frequencyBandsCount;
206 // mediaParams.a.frequencyBands;
207 // mediaParams.a.levelMeteringEnabled;
210 (QTSNotificationUPP) NewQTSNotificationUPP (outAudioRTPStreamNotifHandler);
212 presParams.version = kQTSPresParamsVersion1;
214 // Set the presentation flags: use Sequence Grabber, don't display blue Q movie, and send data
215 presParams.flags = kQTSAutoModeFlag
216 | kQTSDontShowStatusFlag
218 presParams.timeScale = 0; // kDefaultPresTimeScale;
219 presParams.mediaParams = &mediaParams;
221 // Fill these in to get status notifications
222 presParams.notificationProc = sNotificationUPP;
223 presParams.notificationRefCon = 0L; // no refcon yet
225 // Create the presentation
226 err = QTSNewPresentationFromData (kQTSSDPDataType,
235 // If you want to see what the Sequence Grabber is capturing, call
236 // QTSPresPreview before starting the broadcast. As we are only capturing audio,
239 // err = QTSPresPreview (presentation, kQTSAllStreams, nil, kFixed1, 0);
246 * Destroy the output stream
248 - (OSErr) stopOutAudioRTPStream
252 if (mOutputStream != kQTSInvalidPresentation) {
253 err = QTSPresStop(mOutputStream, kQTSAllStreams, 0L);
256 err = QTSDisposePresentation(mOutputStream, 0L);
259 mOutputStream = kQTSInvalidPresentation;
267 * Start the input audio RTP stream
269 - (OSErr) startInAudioRTPStream
272 Movie sdpMovieInfo = NULL;
273 Handle dataRef = NULL;
274 ComponentInstance dataRefHandler = NULL;
276 void *sdpData = NULL;
278 PointerDataRefRecord ptrDataRefRec;
279 unsigned char myChar = 0;
280 Handle fileNameHndl = NULL;
281 Str255 fileName = "instream.sdp";
283 // TODO: Fille the sdpData and sdpDataLen
285 ptrDataRefRec.data = sdpData;
286 ptrDataRefRec.dataLength = sdpDataLen;
288 // create a data reference handle for our data
289 err = PtrToHand( &ptrDataRefRec, &dataRef, sizeof(PointerDataRefRecord));
294 // Get a data handler for our data reference
295 err = OpenADataHandler (dataRef, /* data reference */
296 PointerDataHandlerSubType, /* data ref. type */
297 NULL, /* anchor data ref. */
298 (OSType)0, /* anchor data ref. type */
299 NULL, /* time base for data handler */
300 kDataHCanRead, /* flag for data handler usage */
301 &dataRefHandler); /* returns the data handler */
306 // create a handle with our file name string
308 // if we were passed a null string, then we need to add this null
309 // string (a single 0 byte) to the handle
310 if (fileName == NULL) {
311 err = PtrToHand (&myChar, &fileNameHndl, sizeof(myChar));
313 err = PtrToHand (fileName, &fileNameHndl, fileName[0] + 1);
319 // set the data ref extension for the data ref handler
320 err = DataHSetDataRefExtension (dataRefHandler, /* data ref. handler */
321 fileNameHndl, /* data ref. extension to add */
322 kDataRefExtensionFileName);
324 // dispose old data ref handle because it does not contain our new changes
325 DisposeHandle(dataRef);
328 // re-acquire data reference from the data handler to get the new changes
329 err = DataHGetDataRef(dataRefHandler, &dataRef);
334 // This is the preferred system for QuickTime 6. QuickTime 7 includes
335 // the new function NewMovieFromProperties, but we prefer to keep the
336 // compatibility [as].
337 err = NewMovieFromDataRef (&sdpMovieInfo,
344 mInputStream = sdpMovieInfo;
350 * Destroy the output audio RTP stream
352 - (OSErr) stopInAudioRTPStream
358 ////////////////////////////////////////////////////////////////////////////////
359 #pragma mark Connection Protocol
360 ////////////////////////////////////////////////////////////////////////////////
363 [self startInAudioRTPStream];
364 [self startOutAudioRTPStream];
370 [self stopInAudioRTPStream];
371 [self stopOutAudioRTPStream];
375 ////////////////////////////////////////////////////////////////////////////////
376 #pragma mark Connection Properties: Volume, etc.
377 ////////////////////////////////////////////////////////////////////////////////
380 * Output Volume control.
382 - (void) setOutVolumeTo:(int)vol
388 * Input Volume control.
390 - (void) setMicVolumeTo:(int)vol
396 ////////////////////////////////////////////////////////////////////////////////
397 #pragma mark QuickTime General Information
398 ////////////////////////////////////////////////////////////////////////////////
399 + (NSArray*) getSupportedAudioPayloads
401 // List of audio payload types supported by default by QuickTime for audio.
402 // It can be obtained from QTStreamingComponents.h
404 // NOTE: There should be some function that gives the list by quering the
405 // codecs installed on the system...
407 NSArray* res = [NSArray arrayWithObjects:
408 /* 8kHz PCM mu-law mono */
409 [VCAudioPayload createWithId:kRTPPayload_PCMU name:@"PCMU" channels:1 clockrate:8000],
410 /* 8kHz CELP (Fed Std 1016) mono */
411 [VCAudioPayload createWithId:kRTPPayload_1016 name:@"1016" channels:1 clockrate:8000],
412 /* 8kHz G.721 ADPCM mono */
413 [VCAudioPayload createWithId:kRTPPayload_G721 name:@"G721" channels:1 clockrate:8000],
415 [VCAudioPayload createWithId:kRTPPayload_GSM name:@"GSM" channels:1 clockrate:8000],
416 /* 8kHz G.723 ADPCM mono */
417 [VCAudioPayload createWithId:kRTPPayload_G723 name:@"G723" channels:1 clockrate:8000],
418 /* 8kHz Intel DVI ADPCM mono */
419 [VCAudioPayload createWithId:kRTPPayload_DVI_8 name:@"DVI 8" channels:1 clockrate:8000],
420 /* 16kHz Intel DVI ADPCM mono */
421 [VCAudioPayload createWithId:kRTPPayload_DVI_16 name:@"DVI 16" channels:1 clockrate:16000],
423 [VCAudioPayload createWithId:kRTPPayload_LPC name:@"LPC" channels:1 clockrate:8000],
424 /* 8kHz PCM a-law mono */
425 [VCAudioPayload createWithId:kRTPPayload_PCMA name:@"PCMA" channels:1 clockrate:8000],
426 /* 44.1kHz 16-bit linear stereo */
427 [VCAudioPayload createWithId:kRTPPayload_L16_44_2 name:@"L16 44 2" channels:2 clockrate:44100],
428 /* 44.1kHz 16-bit linear mono */
429 [VCAudioPayload createWithId:kRTPPayload_L16_44_1 name:@"L16 44 1" channels:1 clockrate:44100],
430 /* 8kHz PureVoice mono (QCELP) */
431 [VCAudioPayload createWithId:kRTPPayload_PureVoice name:@"PureVoice" channels:1 clockrate:8000],
432 /* MPEG I and II audio */
433 [VCAudioPayload createWithId:kRTPPayload_MPEGAUDIO name:@"MPEGAUDIO" channels:1 clockrate:90000],
434 /* 11kHz Intel DVI ADPCM mono */
435 [VCAudioPayload createWithId:kRTPPayload_DVI_11 name:@"DVI 11" channels:1 clockrate:11025],
436 /* 22kHz Intel DVI ADPCM mono */
437 [VCAudioPayload createWithId:kRTPPayload_DVI_22 name:@"DVI 22" channels:1 clockrate:22050],