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