Now, groups can retrieve a list of the contacts in that group. I probably should...
[adiumx.git] / Plugins / QuickTime / QTRTPConnection.m
blobed9ca884c38c59da940dd3109fd052e9ae576174
1 /* 
2  * Adium is the legal property of its developers, whose names are listed in the copyright file included
3  * with this source distribution.
4  * 
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.
8  * 
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.
12  * 
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.
15  */
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.");
39         
40         self = [super init];
41         
42         if (self)
43         {
44                 mPayload = pt;
45                 mProtocol = proto;
46                 mLocal = local;
47                 mRemote = remote;
48         }
49         
50         return self;    
53 ////////////////////////////////////////////////////////////////////////////////
54 #pragma mark                    SDP Generation
55 ////////////////////////////////////////////////////////////////////////////////
56 - (NSString*) generateSDPInStream
58         // TODO
59         return nil;
63 - (NSString*) generateSDPOutStream
66         // Constants
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";
71         
72         const int        ipVersion              = 4;    // We only support IP version 4
73         const int        ttl                    = 126;
75         // Variables
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"];
80         
81         char            *outStr;
82         
83         asprintf (&outStr,
84                           "v=0\r\n"
85                           "o=- * * IN IP%d %s\r\n"              // Source
86                           "s=%s\r\n"                                    // Session name
87                           "i=%s\r\n"                                    // Description
88                           "u=%s\r\n"                                    // URL
89                           "e=%s\r\n"                                    // Email
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
94                           
95                           ipVersion, ipSource,
96                           strSessionName,
97                           strDescription,
98                           strUrl,
99                           strEmail,
100                           ipVersion, ipDestination, ttl,
101                           port, payloadType);
102         
103         return [NSString stringWithCString:outStr];
106 @end
109 @implementation QTAudioRTPConnection
112 ////////////////////////////////////////////////////////////////////////////////
113 #pragma mark                   Streams Handlers
114 ////////////////////////////////////////////////////////////////////////////////
117  * Broadcast notification handler.
118  */
119 ComponentResult outAudioRTPStreamNotifHandler (ComponentResult inErr,
120                                                                                            OSType inNotificationType,
121                                                                                            void *inNotificationParams,
122                                                                                            void *inRefCon) {
123         QTSStatusParams* tempStatus;
125         switch (inNotificationType) {
126                 case kQTSNewPresentationNotification:
127                         break;
128                         
129                 case kQTSPrerollAckNotification:
130                         QTSPresStart ((QTSPresentation)inRefCon, kQTSAllStreams, 0L );
131                         break;
132                         
133                 case kQTSStreamChangedNotification:
134                         break;
135                         
136                 case kQTSErrorNotification:
137 //                      ShowErr (macWindow, inErr, ”kQTSErrorNotification”);
138                         break;
139                         
140                 case kQTSNewPresDetectedNotification:
141                 case kQTSNewStreamNotification:
142                 case kQTSStreamGoneNotification:
143                 case kQTSStartAckNotification:
144                 case kQTSStopAckNotification:
145                         break;
146                         
147                 case kQTSStatusNotification:
148                         tempStatus = (QTSStatusParams *)inNotificationParams;
149                         break;
150                 default:
151                         break;
152         }
153         
154         return noErr;   
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.
164  */
165 - (OSErr) startOutAudioRTPStream
166 {       
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];
173         OSErr                            err                            = noErr;
174         
175         // Note: this API is almost undocumented. There is only one example,
176         // called "qtbroadcast"... [as]
177         
178         mOutputStream = kQTSInvalidPresentation;
179         
180         // Initialize the media params
181         memset (&presParams, 0, sizeof(presParams));    
182         err = QTSInitializeMediaParams (&mediaParams);
183         if (err != noErr) {
184                 goto bail;              
185         }
186         
187         // Video params: we don't have any video
188         //
189         // mediaParams.v.width = (Fixed)(myWidth<<16);
190         // mediaParams.v.height = (Fixed)(myHeight<<16);
191         //
192         // set the window that Sequence Grabber will draw into:
193         //
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;
200         
201         // Other parameters that can be set:
202         //
203         // mediaParams.a.bassLevel;
204         // mediaParams.a.trebleLevel;
205         // mediaParams.a.frequencyBandsCount;
206         // mediaParams.a.frequencyBands;
207         // mediaParams.a.levelMeteringEnabled;
208         
209         sNotificationUPP =
210                 (QTSNotificationUPP) NewQTSNotificationUPP (outAudioRTPStreamNotifHandler);
211         
212         presParams.version                              = kQTSPresParamsVersion1;
213         
214         // Set the presentation flags: use Sequence Grabber, don't display blue Q movie, and send data
215         presParams.flags                                = kQTSAutoModeFlag
216                                                                         | kQTSDontShowStatusFlag
217                                                                         | kQTSSendMediaFlag;
218         presParams.timeScale                    = 0; // kDefaultPresTimeScale;
219         presParams.mediaParams                  = &mediaParams;
220         
221         // Fill these in to get status notifications
222         presParams.notificationProc             = sNotificationUPP;
223         presParams.notificationRefCon   = 0L;   // no refcon yet
224         
225         // Create the presentation
226         err = QTSNewPresentationFromData (kQTSSDPDataType,
227                                                                           sdpDataPtr,
228                                                                           &sdpDataLength,
229                                                                           &presParams,
230                                                                           &mOutputStream);
231         if (err != noErr) {
232                 goto bail;              
233         }
234         
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,
237         // skip this step...
238         //
239         // err = QTSPresPreview (presentation, kQTSAllStreams, nil, kFixed1, 0);
241 bail:
242         return err;
246  * Destroy the output stream
247  */
248 - (OSErr) stopOutAudioRTPStream
250         OSErr err = noErr;
251         
252         if (mOutputStream != kQTSInvalidPresentation) {
253                 err = QTSPresStop(mOutputStream, kQTSAllStreams, 0L);
254                 
255                 if (err != noErr) {
256                         err = QTSDisposePresentation(mOutputStream, 0L);                        
257                 }
258                 
259                 mOutputStream = kQTSInvalidPresentation;
260         }
261         
262         return(err);    
267  * Start the input audio RTP stream
268  */
269 - (OSErr) startInAudioRTPStream
271     OSErr                                        err                    = noErr;
272         Movie                                    sdpMovieInfo   = NULL;
273         Handle                                   dataRef                = NULL;
274         ComponentInstance                dataRefHandler = NULL;
275     OSType                                       dataRefType;
276     void                                        *sdpData                = NULL;
277         Size                                     sdpDataLen             = 0;
278         PointerDataRefRecord     ptrDataRefRec;
279     unsigned char                        myChar                 = 0;
280     Handle                                       fileNameHndl   = NULL;
281         Str255                                   fileName               = "instream.sdp";
283         // TODO: Fille the sdpData and sdpDataLen
284         
285         ptrDataRefRec.data                      = sdpData;
286         ptrDataRefRec.dataLength        = sdpDataLen;
287         
288         // create a data reference handle for our data
289         err = PtrToHand( &ptrDataRefRec, &dataRef, sizeof(PointerDataRefRecord));
290         if (err != noErr) {
291                 goto bail;      
292         }
293         
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 */
302         if (err != noErr) {
303                 goto bail;      
304         }
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));               
312         } else {
313         err = PtrToHand (fileName, &fileNameHndl, fileName[0] + 1);             
314         }
315     if (err != noErr) {
316                 goto bail;      
317         }       
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);
323         
324         // dispose old data ref handle because it does not contain our new changes
325         DisposeHandle(dataRef);
326         dataRef = NULL;
328         // re-acquire data reference from the data handler to get the new changes
329         err = DataHGetDataRef(dataRefHandler, &dataRef);
330         if (err != noErr) {
331                 goto bail;      
332         }       
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,
338                                                            newMovieActive, 
339                                                            nil,
340                                                            dataRef,
341                                                            dataRefType);                
343 bail:
344         mInputStream = sdpMovieInfo;
346         return err;
350  * Destroy the output audio RTP stream
351  */
352 - (OSErr) stopInAudioRTPStream
354         // TODO
355         return noErr;
356 }       
358 ////////////////////////////////////////////////////////////////////////////////
359 #pragma mark                     Connection Protocol
360 ////////////////////////////////////////////////////////////////////////////////
361 - (BOOL) start 
363         [self startInAudioRTPStream];
364         [self startOutAudioRTPStream];
365         return TRUE;
368 - (BOOL) stop
370         [self stopInAudioRTPStream];
371         [self stopOutAudioRTPStream];
372         return TRUE;
375 ////////////////////////////////////////////////////////////////////////////////
376 #pragma mark              Connection Properties: Volume, etc.
377 ////////////////////////////////////////////////////////////////////////////////
380  * Output Volume control.
381  */
382 - (void) setOutVolumeTo:(int)vol 
384         // TODO
388  * Input Volume control.
389  */
390 - (void) setMicVolumeTo:(int)vol
392         // TODO
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
403         //
404         // NOTE: There should be some function that gives the list by quering the
405         //       codecs installed on the system...
406         //
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],
414                 /* 8kHz GSM mono */
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],
422                 /* 8kHz LPC */
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],
438                 
439                 nil];
440         
441         return res;
444 @end