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