]> git.sesse.net Git - vlc/blob - modules/gui/macosx/output.m
* 10.2 compilation fix
[vlc] / modules / gui / macosx / output.m
1 /*****************************************************************************
2  * output.m: MacOS X Output Dialog
3  *****************************************************************************
4  * Copyright (C) 2002-2003 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
8  *          Christophe Massiot <massiot@via.ecp.fr>
9  *          Derk-Jan Hartman <thedj@users.sourceforge.net>
10  *          Benjamin Pracht <bigben AT videolan DOT org>
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
25  *****************************************************************************/
26
27 /*****************************************************************************
28  * Preamble
29  *****************************************************************************/
30 #include <stdlib.h>                                      /* malloc(), free() */
31 #include <string.h>
32
33 #include "intf.h"
34 #include "output.h"
35
36 /*****************************************************************************
37  * VLCOutput implementation 
38  *****************************************************************************/
39 @implementation VLCOutput
40
41 - (id)init
42 {
43     self = [super init];
44     o_mrl = [[NSArray alloc] init];
45     o_transcode = [[NSString alloc] init];
46     return self;
47 }
48
49 - (void)dealloc
50 {
51     [o_mrl release];
52     [o_transcode release];
53     [super dealloc];
54 }
55
56 - (void)setMRL:(NSArray *)o_mrl_array
57 {
58     [o_mrl autorelease];
59     o_mrl = [o_mrl_array copy];
60 }
61
62 - (NSArray *)getMRL
63 {
64     return [o_mrl copy];
65 }
66
67 - (void)setTranscode:(NSString *)o_transcode_string
68 {
69     [o_transcode autorelease];
70     o_transcode = [o_transcode_string copy];
71 }
72
73 - (void)awakeFromNib
74 {
75     [self initStrings];
76
77     [[NSNotificationCenter defaultCenter] addObserver: self
78         selector: @selector(outputInfoChanged:)
79         name: NSControlTextDidChangeNotification
80         object: o_file_field];
81     [[NSNotificationCenter defaultCenter] addObserver: self
82         selector: @selector(outputInfoChanged:)
83         name: NSControlTextDidChangeNotification
84         object: o_stream_address];
85     [[NSNotificationCenter defaultCenter] addObserver: self
86         selector: @selector(outputInfoChanged:)
87         name: NSControlTextDidChangeNotification
88         object: o_stream_port];
89     [[NSNotificationCenter defaultCenter] addObserver: self
90         selector: @selector(TTLChanged:)
91         name: NSControlTextDidChangeNotification
92         object: o_stream_ttl];
93     [[NSNotificationCenter defaultCenter] addObserver: self
94         selector: @selector(transcodeInfoChanged:)
95         name: NSControlTextDidChangeNotification
96         object: o_transcode_video_bitrate];
97     [[NSNotificationCenter defaultCenter] addObserver: self
98         selector: @selector(transcodeInfoChanged:)
99         name: NSControlTextDidChangeNotification
100         object: o_transcode_video_scale];
101     [[NSNotificationCenter defaultCenter] addObserver: self
102         selector: @selector(transcodeInfoChanged:)
103         name: NSControlTextDidChangeNotification
104         object: o_transcode_audio_bitrate];
105     [[NSNotificationCenter defaultCenter] addObserver: self
106         selector: @selector(transcodeInfoChanged:)
107         name: NSControlTextDidChangeNotification
108         object: o_transcode_audio_channels];
109     [[NSNotificationCenter defaultCenter] addObserver: self
110         selector: @selector(transcodeInfoChanged:)
111         name: NSControlTextDidChangeNotification
112         object: o_channel_name];
113     [[NSNotificationCenter defaultCenter] addObserver: self
114         selector: @selector(transcodeInfoChanged:)
115         name: NSControlTextDidChangeNotification
116         object: o_sdp_url];
117
118     [o_mux_selector setAutoenablesItems: NO];
119     [self transcodeChanged:nil];
120 }
121
122 - (void)initStrings
123 {
124     NSArray *o_muxers = [NSArray arrayWithObjects: @"MPEG TS", @"MPEG PS", @"MPEG 1",
125         @"Ogg", @"AVI", @"ASF", @"MPEG 4", @"Quicktime", @"Raw", nil];
126     NSArray *o_a_channels = [NSArray arrayWithObjects: @"1", @"2", @"4", @"6", nil];
127     NSArray *o_a_bitrates = [NSArray arrayWithObjects: @"16", @"32", @"64", @"96",
128         @"128", @"192", @"256", @"512", nil];
129     NSArray *o_v_bitrates = [NSArray arrayWithObjects: @"16", @"32", @"64", @"96",
130         @"128", @"192", @"256", @"384", @"512", @"768", @"1024", @"2048", @"3072", nil];
131     NSArray *o_v_scales = [NSArray arrayWithObjects: @"0.25",@"0.5",@"0.75",@"1",@"1.25",@"1.5",@"1.75",@"2",nil];
132     NSArray *o_a_codecs = [NSArray arrayWithObjects: @"mpga", @"mp3 ", @"mp4a", @"a52 ", @"vorb", @"flac", @"spx ", nil];
133     NSArray *o_v_codecs = [NSArray arrayWithObjects: @"mp1v", @"mp2v", @"mp4v", @"DIV1",
134         @"DIV2", @"DIV3", @"h263", @"h264", @"WMV1", @"WMV2", @"MJPG", @"theo", nil];
135
136     [o_output_ckbox setTitle: _NS("Advanced output:")];
137     [o_output_settings setTitle: _NS("Settings...")];
138     [o_btn_ok setTitle: _NS("OK")];
139
140     [o_options_lbl setTitle: _NS("Output Options")];
141     [o_display setTitle: _NS("Play locally")];
142     [[o_method cellAtRow:0 column:0] setTitle: _NS("File")];
143     [[o_method cellAtRow:1 column:0] setTitle: _NS("Stream")];
144     [o_dump_chkbox setTitle: _NS("Dump raw input")];
145     [o_btn_browse setTitle: _NS("Browse...")]; 
146     [o_stream_address_lbl setStringValue: _NS("Address")];
147     [o_stream_port_lbl setStringValue: _NS("Port")];
148     [o_stream_ttl_lbl setStringValue: @"TTL"];
149     [[o_stream_type itemAtIndex: 0] setTitle: @"HTTP"];
150     [[o_stream_type itemAtIndex: 1] setTitle: @"MMSH"];
151     [[o_stream_type itemAtIndex: 2] setTitle: @"UDP"];
152     [[o_stream_type itemAtIndex: 3] setTitle: @"RTP"];
153     [o_stream_type_lbl setStringValue: _NS("Type")];
154
155     [o_mux_lbl setStringValue: _NS("Encapsulation Method")];
156     [o_mux_selector removeAllItems];
157     [o_mux_selector addItemsWithTitles: o_muxers];
158
159     [o_transcode_lbl setTitle: _NS("Transcode options")];
160     [o_transcode_video_chkbox setTitle: _NS("Video")];
161     [o_transcode_video_selector removeAllItems];
162     [o_transcode_video_selector addItemsWithTitles: o_v_codecs];
163     [o_transcode_video_bitrate_lbl setStringValue: _NS("Bitrate (kb/s)")];
164     [o_transcode_video_bitrate removeAllItems];
165     [o_transcode_video_bitrate addItemsWithObjectValues: o_v_bitrates];
166     [o_transcode_video_scale_lbl setStringValue: _NS("Scale")];
167     [o_transcode_video_scale removeAllItems];
168     [o_transcode_video_scale addItemsWithObjectValues: o_v_scales];
169     [o_transcode_video_scale selectItemWithObjectValue: @"1"];
170     [o_transcode_audio_chkbox setTitle: _NS("Audio")];
171     [o_transcode_audio_selector removeAllItems];
172     [o_transcode_audio_selector addItemsWithTitles: o_a_codecs];
173     [o_transcode_audio_bitrate_lbl setStringValue: _NS("Bitrate (kb/s)")];
174     [o_transcode_audio_bitrate removeAllItems];
175     [o_transcode_audio_bitrate addItemsWithObjectValues: o_a_bitrates];
176     [o_transcode_audio_channels_lbl setStringValue: _NS("Channels")];
177     [o_transcode_audio_channels removeAllItems];
178     [o_transcode_audio_channels addItemsWithObjectValues: o_a_channels];
179
180     [o_misc_lbl setTitle: _NS("Stream Announcing")];
181     [o_sap_chkbox setTitle: _NS("SAP announce")];
182     [o_slp_chkbox setTitle: _NS("SLP announce")];
183     [o_rtsp_chkbox setTitle: _NS("RTSP announce")];
184     [o_http_chkbox setTitle:_NS("HTTP announce")];
185     [o_file_chkbox setTitle:_NS("Export SDP as file")];
186
187     [o_channel_name_lbl setStringValue: _NS("Channel Name")];
188     [o_sdp_url_lbl setStringValue: _NS("SDP URL")];
189 }
190
191 - (IBAction)outputChanged:(id)sender;
192 {
193     if ([o_output_ckbox state] == NSOnState)
194     {
195         [o_output_settings setEnabled:YES];
196     }
197     else
198     {
199         [o_output_settings setEnabled:NO];
200     }
201 }
202
203 - (IBAction)outputSettings:(id)sender
204 {
205     [NSApp beginSheet: o_output_sheet
206         modalForWindow: o_open_panel
207         modalDelegate: self
208         didEndSelector: NULL
209         contextInfo: nil];
210 }
211
212 - (IBAction)outputCloseSheet:(id)sender
213 {
214     [o_output_sheet orderOut:sender];
215     [NSApp endSheet: o_output_sheet];
216 }
217
218 - (void)outputMethodChanged:(NSNotification *)o_notification
219 {
220     NSString *o_mode;
221     o_mode = [[o_method selectedCell] title];
222
223     [o_sap_chkbox setEnabled: NO];
224     [o_slp_chkbox setEnabled: NO];
225     [o_http_chkbox setEnabled: NO];
226     [o_rtsp_chkbox setEnabled: NO];
227     [o_file_chkbox setEnabled: NO];
228     [o_channel_name setEnabled: NO];
229     [o_sdp_url setEnabled: NO];
230     [[o_mux_selector itemAtIndex: 0] setEnabled: YES];
231
232     if( [o_mode isEqualToString: _NS("File")] )
233     {
234         [o_file_field setEnabled: YES];
235         [o_btn_browse setEnabled: YES];
236         [o_dump_chkbox setEnabled: YES];
237         [o_stream_address setEnabled: NO];
238         [o_stream_port setEnabled: NO];
239         [o_stream_ttl setEnabled: NO];
240         [o_stream_port_stp setEnabled: NO];
241         [o_stream_ttl_stp setEnabled: NO];
242         [o_stream_type setEnabled: NO];
243         [o_mux_selector setEnabled: YES];
244         [[o_mux_selector itemAtIndex: 1] setEnabled: YES]; // MPEG PS
245         [[o_mux_selector itemAtIndex: 2] setEnabled: YES]; // MPEG 1
246         [[o_mux_selector itemAtIndex: 3] setEnabled: YES]; // Ogg
247         [[o_mux_selector itemAtIndex: 4] setEnabled: YES]; // AVI
248         [[o_mux_selector itemAtIndex: 5] setEnabled: YES]; // ASF
249         [[o_mux_selector itemAtIndex: 6] setEnabled: YES]; // MPEG 4
250         [[o_mux_selector itemAtIndex: 7] setEnabled: YES]; // QuickTime
251         [[o_mux_selector itemAtIndex: 8] setEnabled: YES]; // Raw
252     }
253     else if( [o_mode isEqualToString: _NS("Stream")] )
254     {
255         [o_file_field setEnabled: NO];
256         [o_dump_chkbox setEnabled: NO];
257         [o_btn_browse setEnabled: NO];
258         [o_stream_port setEnabled: YES];
259         [o_stream_port_stp setEnabled: YES];
260         [o_stream_type setEnabled: YES];
261         [o_mux_selector setEnabled: YES];
262
263         o_mode = [o_stream_type titleOfSelectedItem];
264
265         if( [o_mode isEqualToString: @"HTTP"] )
266         {
267             [o_stream_address setEnabled: YES];
268             [o_stream_ttl setEnabled: NO];
269             [o_stream_ttl_stp setEnabled: NO];
270             [[o_mux_selector itemAtIndex: 1] setEnabled: YES];
271             [[o_mux_selector itemAtIndex: 2] setEnabled: YES];
272             [[o_mux_selector itemAtIndex: 3] setEnabled: YES];
273             [[o_mux_selector itemAtIndex: 4] setEnabled: NO];
274             [[o_mux_selector itemAtIndex: 5] setEnabled: YES];
275             [[o_mux_selector itemAtIndex: 6] setEnabled: NO];
276             [[o_mux_selector itemAtIndex: 7] setEnabled: NO];
277             [[o_mux_selector itemAtIndex: 8] setEnabled: YES];
278         }
279         else if( [o_mode isEqualToString: @"MMSH"] )
280         {
281             [o_stream_address setEnabled: YES];
282             [o_stream_ttl setEnabled: NO];
283             [o_stream_ttl_stp setEnabled: NO];
284             [[o_mux_selector itemAtIndex: 0] setEnabled: NO];
285             [[o_mux_selector itemAtIndex: 1] setEnabled: NO];
286             [[o_mux_selector itemAtIndex: 2] setEnabled: NO];
287             [[o_mux_selector itemAtIndex: 3] setEnabled: NO];
288             [[o_mux_selector itemAtIndex: 4] setEnabled: NO];
289             [[o_mux_selector itemAtIndex: 5] setEnabled: YES];
290             [[o_mux_selector itemAtIndex: 6] setEnabled: NO];
291             [[o_mux_selector itemAtIndex: 7] setEnabled: NO];
292             [[o_mux_selector itemAtIndex: 8] setEnabled: NO];
293             [o_mux_selector selectItemAtIndex: 5];
294         }
295         else if( [o_mode isEqualToString: @"UDP"] )
296         {
297             [o_stream_address setEnabled: YES];
298             [o_stream_ttl setEnabled: YES];
299             [o_stream_ttl_stp setEnabled: YES];
300             [[o_mux_selector itemAtIndex: 1] setEnabled: NO];
301             [[o_mux_selector itemAtIndex: 2] setEnabled: NO];
302             [[o_mux_selector itemAtIndex: 3] setEnabled: NO];
303             [[o_mux_selector itemAtIndex: 4] setEnabled: NO];
304             [[o_mux_selector itemAtIndex: 5] setEnabled: NO];
305             [[o_mux_selector itemAtIndex: 6] setEnabled: NO];
306             [[o_mux_selector itemAtIndex: 7] setEnabled: NO];
307             [[o_mux_selector itemAtIndex: 8] setEnabled: YES];
308             [o_sap_chkbox setEnabled: YES];
309             [o_slp_chkbox setEnabled: YES];
310             [o_channel_name setEnabled: YES];
311         }
312         else if( [o_mode isEqualToString: @"RTP"] )
313         {
314             [o_stream_address setEnabled: YES];
315             [o_stream_ttl setEnabled: YES];
316             [o_stream_ttl_stp setEnabled: YES];
317             [[o_mux_selector itemAtIndex: 0] setEnabled: NO];
318             [[o_mux_selector itemAtIndex: 1] setEnabled: NO];
319             [[o_mux_selector itemAtIndex: 2] setEnabled: NO];
320             [[o_mux_selector itemAtIndex: 3] setEnabled: NO];
321             [[o_mux_selector itemAtIndex: 4] setEnabled: NO];
322             [[o_mux_selector itemAtIndex: 5] setEnabled: NO];
323             [[o_mux_selector itemAtIndex: 6] setEnabled: NO];
324             [[o_mux_selector itemAtIndex: 7] setEnabled: NO];
325             [[o_mux_selector itemAtIndex: 8] setEnabled: YES];
326             [o_mux_selector selectItemAtIndex: 8];
327             [o_sap_chkbox setEnabled: YES];
328             [o_slp_chkbox setEnabled: NO];
329             [o_rtsp_chkbox setEnabled: YES];
330             [o_http_chkbox setEnabled: YES];
331             [o_file_chkbox setEnabled: YES];
332             [o_channel_name setEnabled: YES];
333         }
334     }
335
336     if( ![[o_mux_selector selectedItem] isEnabled] && ![o_mode isEqualToString: @"RTP"] )
337     {
338         [o_mux_selector selectItemAtIndex: 0];
339     }
340     else if (![[o_mux_selector selectedItem] isEnabled] && [o_mode isEqualToString: @"RTP"] )
341     {
342         [o_mux_selector selectItemAtIndex: 8];
343     }
344     [self outputInfoChanged: nil];
345 }
346
347 - (void)outputInfoChanged:(NSNotification *)o_notification
348 {
349     NSString *o_mode, *o_mux, *o_mux_string;
350     NSMutableString *o_announce = [NSMutableString stringWithString:@""];
351     NSMutableString *o_mrl_string = [NSMutableString stringWithString:@":sout=#"];
352     NSArray *o_sout_options;
353
354     [o_mrl_string appendString: o_transcode];
355     if( [o_display state] == NSOnState )
356     {
357         [o_mrl_string appendString: @"duplicate{dst=display,dst="];
358     }
359
360     o_mode = [[o_method selectedCell] title];
361     o_mux = [o_mux_selector titleOfSelectedItem];
362
363     if ( [o_mux isEqualToString: @"AVI"] ) o_mux_string = @"avi";
364     else if ( [o_mux isEqualToString: @"Ogg"] ) o_mux_string = @"ogg";
365     else if ( [o_mux isEqualToString: @"MPEG PS"] ) o_mux_string = @"ps";
366     else if ( [o_mux isEqualToString: @"MPEG 4"] ) o_mux_string = @"mp4";
367     else if ( [o_mux isEqualToString: @"MPEG 1"] ) o_mux_string = @"mpeg1";
368     else if ( [o_mux isEqualToString: @"Quicktime"] ) o_mux_string = @"mov";
369     else if ( [o_mux isEqualToString: @"ASF"] ) o_mux_string = @"asf";
370     else if ( [o_mux isEqualToString: @"Raw"] ) o_mux_string = @"raw";
371     else o_mux_string = @"ts";
372
373     if( [o_mode isEqualToString: _NS("File")] )
374     {
375         if( [o_dump_chkbox state] == NSOnState )
376         {
377             NSMutableArray * o_sout_options;
378             o_sout_options = [NSArray arrayWithObjects:
379                                     [NSString stringWithString:
380                                     @":demux=dump"],
381                                     [NSString stringWithFormat:
382                                     @":demuxdump-file=%@",
383                                     [o_file_field stringValue]],
384                                     nil];
385             [self setMRL:o_sout_options];
386             return;
387         }
388         else
389         {
390                 [o_mrl_string appendFormat:
391                         @"std{access=file,mux=%@,url=\"%@\"}",
392                         o_mux_string, [o_file_field stringValue]];
393         }
394     }
395     else if( [o_mode isEqualToString: _NS("Stream")] )
396     {
397         o_mode = [o_stream_type titleOfSelectedItem];
398
399         if ( [o_mode isEqualToString: @"HTTP"] )
400             o_mode = @"http";
401         else if ( [o_mode isEqualToString: @"MMSH"] )
402         {
403             if ( [o_mux isEqualToString: @"ASF"] ) o_mux_string = @"asfh";
404             o_mode = @"mmsh";
405         }
406         else if ( [o_mode isEqualToString: @"UDP"] )
407         {
408             o_mode = @"udp";
409             if( [o_sap_chkbox state] == NSOnState )
410             {
411                 if ( ![[o_channel_name stringValue] isEqualToString: @""] )
412                     [o_announce appendFormat:
413                         @",sap,name=%@", [o_channel_name stringValue]];
414                 else
415                     [o_announce appendFormat:@",sap"];
416             }
417             if( [o_slp_chkbox state] == NSOnState )
418             {
419                if ( ![[o_channel_name stringValue] isEqualToString: @""] )
420                     [o_announce appendFormat:@
421                             "slp,name=%@",[o_channel_name stringValue]];
422                 else
423                     [o_announce appendString: @",slp"];
424             }
425         }
426         if ( ![o_mode isEqualToString: @"RTP"] )
427         {
428             /* split up the hostname and the following path to paste the
429              * port correctly. Not need, if there isn't any path following the
430              * hostname. */
431             NSArray * o_urlItems = [[o_stream_address stringValue] \
432                 componentsSeparatedByString: @"/"];
433             NSMutableString * o_finalStreamAddress;
434             o_finalStreamAddress = [[NSMutableString alloc] init];
435             
436             if ([o_urlItems count] == 1)
437             {
438                 [o_finalStreamAddress appendFormat: @"\"%@:%@\"", \
439                     [o_stream_address stringValue],[o_stream_port stringValue]];
440             }
441             else
442             {
443                 [o_finalStreamAddress appendFormat: @"\"%@:%@", [o_urlItems \
444                     objectAtIndex: 0], [o_stream_port stringValue]];
445                 unsigned int x;
446                 x = 1;
447                 while (x != [o_urlItems count])
448                 {
449                     [o_finalStreamAddress appendFormat: @"/%@", [o_urlItems \
450                         objectAtIndex: x]];
451                     x = (x + 1);
452                 }
453                 [o_finalStreamAddress appendString: @"\""];
454             }
455             
456             [o_mrl_string appendFormat:
457                         @"std{access=%@,mux=%@,url=%@%@}",
458                         o_mode, o_mux_string, o_finalStreamAddress, o_announce];
459         }
460         else
461         {
462             NSString * o_stream_name;
463
464             if (![[o_channel_name stringValue] isEqualToString: @""] )
465             {
466                 o_stream_name = [NSString stringWithFormat:@",name=%@",
467                                 [o_channel_name stringValue]];
468             }
469             else
470             {
471                 o_stream_name = @"";
472             }
473
474             if ( [o_sap_chkbox state] == NSOnState )
475             {
476                 [o_announce appendString: @",sdp=sap"];
477             }
478             if ([o_rtsp_chkbox state] == NSOnState )
479             {
480                 [o_announce appendFormat:@",sdp=\"rtsp://%@\"",[o_sdp_url stringValue]];
481
482             }
483             if ([o_http_chkbox state] == NSOnState )
484             {
485                 [o_announce appendFormat:@",sdp=\"http://%@\"",[o_sdp_url stringValue]];
486             }
487             if ([o_file_chkbox state] == NSOnState )
488             {
489                 [o_announce appendFormat:@",sdp=\"file://%@\"",[o_sdp_url stringValue]];
490             }
491             [o_mrl_string appendFormat:
492                         @"rtp{dst=\"%@\",port=%@%@%@}",[o_stream_address stringValue],
493                         [o_stream_port stringValue], o_stream_name, o_announce];
494         }
495
496     }
497     if( [o_display state] == NSOnState )
498     {
499         [o_mrl_string appendString: @"}"];
500     }
501     o_sout_options = [NSArray arrayWithObjects: o_mrl_string,nil];
502     [self setMRL:o_sout_options];
503 }
504
505 - (void)TTLChanged:(NSNotification *)o_notification
506 {
507     intf_thread_t * p_intf = VLCIntf;
508     config_PutInt( p_intf, "ttl", [o_stream_ttl intValue] );
509 }
510
511 - (IBAction)outputFileBrowse:(id)sender
512 {
513     NSSavePanel *o_save_panel = [NSSavePanel savePanel];
514     NSString *o_mux_string;
515     if ( [[o_mux_selector titleOfSelectedItem] isEqualToString: @"MPEG PS"] )
516         o_mux_string = @"vob";
517     else if ( [[o_mux_selector titleOfSelectedItem] isEqualToString: @"MPEG 1"] )
518         o_mux_string = @"mpg";
519     else if ( [[o_mux_selector titleOfSelectedItem] isEqualToString: @"AVI"] )
520         o_mux_string = @"avi";
521     else if ( [[o_mux_selector titleOfSelectedItem] isEqualToString: @"ASF"] )
522         o_mux_string = @"asf";
523     else if ( [[o_mux_selector titleOfSelectedItem] isEqualToString: @"Ogg"] )
524         o_mux_string = @"ogm";
525     else if ( [[o_mux_selector titleOfSelectedItem] isEqualToString: @"MPEG 4"] )
526         o_mux_string = @"mp4";
527     else if ( [[o_mux_selector titleOfSelectedItem] isEqualToString: @"Quicktime"] )
528         o_mux_string = @"mov";
529     else if ( [[o_mux_selector titleOfSelectedItem] isEqualToString: @"Raw"] )
530         o_mux_string = @"raw";
531     else
532         o_mux_string = @"ts";
533
534     NSString * o_name = [NSString stringWithFormat: @"vlc-output.%@",
535                          o_mux_string];
536
537     [o_save_panel setTitle: _NS("Save File")];
538     [o_save_panel setPrompt: _NS("Save")];
539
540     if( [o_save_panel runModalForDirectory: nil
541             file: o_name] == NSOKButton )
542     {
543         NSString *o_filename = [o_save_panel filename];
544         [o_file_field setStringValue: o_filename];
545         [self outputInfoChanged: nil];
546     }
547 }
548
549 - (IBAction)streamPortStepperChanged:(id)sender
550 {
551     [o_stream_port setIntValue: [o_stream_port_stp intValue]];
552     [self outputInfoChanged: nil];
553 }
554
555 - (IBAction)streamTTLStepperChanged:(id)sender
556 {
557     [o_stream_ttl setIntValue: [o_stream_ttl_stp intValue]];
558     [self TTLChanged:nil];
559 }
560
561 - (void)transcodeChanged:(NSNotification *)o_notification
562 {
563     if( [o_transcode_video_chkbox state] == NSOnState )
564     {
565         [o_transcode_video_selector setEnabled: YES];
566         [o_transcode_video_bitrate setEnabled: YES];
567         [o_transcode_video_scale setEnabled: YES];
568     }
569     else
570     {
571         [o_transcode_video_selector setEnabled: NO];
572         [o_transcode_video_bitrate setEnabled: NO];
573         [o_transcode_video_scale setEnabled: NO];
574     }
575     if( [o_transcode_audio_chkbox state] == NSOnState )
576     {
577         [o_transcode_audio_selector setEnabled: YES];
578         [o_transcode_audio_bitrate setEnabled: YES];
579         [o_transcode_audio_channels setEnabled: YES];
580     }
581     else
582     {
583         [o_transcode_audio_selector setEnabled: NO];
584         [o_transcode_audio_bitrate setEnabled: NO];
585         [o_transcode_audio_channels setEnabled: NO];
586     }
587
588     [self transcodeInfoChanged:nil];
589 }
590
591 - (void)transcodeInfoChanged:(NSNotification *)o_notification
592 {
593     NSMutableString *o_transcode_string;
594
595     if( [o_transcode_video_chkbox state] == NSOnState ||
596         [o_transcode_audio_chkbox state] == NSOnState )
597     {
598         o_transcode_string = [NSMutableString stringWithString:@"transcode{"];
599         if ( [o_transcode_video_chkbox state] == NSOnState )
600         {
601             [o_transcode_string appendFormat: @"vcodec=\"%@\",vb=\"%@\",scale=\"%@\"",
602                 [o_transcode_video_selector titleOfSelectedItem],
603                 [o_transcode_video_bitrate stringValue],
604                 [o_transcode_video_scale stringValue]];
605             if ( [o_transcode_audio_chkbox state] == NSOnState )
606             {
607                 [o_transcode_string appendString: @","];
608             }
609         }
610         if ( [o_transcode_audio_chkbox state] == NSOnState )
611         {
612             [o_transcode_string appendFormat: @"acodec=\"%@\",ab=\"%@\"",
613                 [o_transcode_audio_selector titleOfSelectedItem],
614                 [o_transcode_audio_bitrate stringValue]];
615             if ( ![[o_transcode_audio_channels stringValue]
616                                             isEqualToString: @""])
617             {
618                 [o_transcode_string appendFormat: @",channels=\"%@\"",
619                                    [o_transcode_audio_channels stringValue]];
620             }
621         }
622         [o_transcode_string appendString:@"}:"];
623     }
624     else
625     {
626         o_transcode_string = [NSString stringWithString:@""];
627     }
628     [self setTranscode: o_transcode_string];
629     [self outputInfoChanged:nil];
630 }
631
632 - (IBAction)announceChanged:(id)sender
633 {
634     NSString *o_mode;
635     o_mode = [[o_stream_type selectedCell] title];
636     [o_channel_name setEnabled: [o_sap_chkbox state] || [o_slp_chkbox state]
637                 || [o_mode isEqualToString: @"RTP"]];
638
639     if ([o_mode isEqualToString: @"RTP"])
640     {
641 /*        if ([[sender title] isEqualToString: _NS("SAP announce")])
642         {
643             [o_rtsp_chkbox setState:NSOffState];
644             [o_http_chkbox setState:NSOffState];
645         }*/
646         if ([[sender title] isEqualToString:_NS("RTSP announce")])
647         {
648 //            [o_sap_chkbox setState:NSOffState];
649             [o_http_chkbox setState:NSOffState];
650             [o_file_chkbox setState:NSOffState];
651         }
652         else if ([[sender title] isEqualToString:_NS("HTTP announce")])
653         {
654 //            [o_sap_chkbox setState:NSOffState];
655             [o_rtsp_chkbox setState:NSOffState];
656             [o_file_chkbox setState:NSOffState];
657         }
658         else if ([[sender title] isEqualToString:_NS("Export SDP as file")])
659         {
660             [o_rtsp_chkbox setState:NSOffState];
661             [o_http_chkbox setState:NSOffState];
662         }
663
664         if ( [o_rtsp_chkbox state] == NSOnState ||
665                             [o_http_chkbox state] == NSOnState ||
666                             [o_file_chkbox state] == NSOnState )
667         {
668             [o_sdp_url setEnabled: YES];
669         }
670         else
671         {
672             [o_sdp_url setEnabled: NO];
673         }
674     }
675     [self outputInfoChanged: nil];
676 }
677
678 @end