]> git.sesse.net Git - vlc/blob - modules/gui/macosx/output.m
* New icon for the playlist
[vlc] / modules / gui / macosx / output.m
1 /*****************************************************************************
2  * output.m: MacOS X Output Dialog
3  *****************************************************************************
4  * Copyright (C) 2002-2003 VideoLAN
5  * $Id: output.m,v 1.17 2003/12/11 16:00:09 hartman Exp $
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  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  * 
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
24  *****************************************************************************/
25
26 /*****************************************************************************
27  * Preamble
28  *****************************************************************************/
29 #include <stdlib.h>                                      /* malloc(), free() */
30 #include <string.h>
31
32 #include "intf.h"
33 #include "output.h"
34
35 /*****************************************************************************
36  * VLCOutput implementation 
37  *****************************************************************************/
38 @implementation VLCOutput
39
40 - (id)init
41 {
42     self = [super init];
43     o_mrl = [[NSString alloc] init];
44     o_transcode = [[NSString alloc] init];
45     return self;
46 }
47
48 - (void)dealloc
49 {
50     [o_mrl release];
51     [o_transcode release];
52     [super dealloc];
53 }
54
55 - (void)setMRL:(NSString *)o_mrl_string
56 {
57     [o_mrl autorelease];
58     o_mrl = [o_mrl_string copy];
59 }
60
61 - (NSString *)getMRL
62 {
63     return [o_mrl copy];
64 }
65
66 - (void)setTranscode:(NSString *)o_transcode_string
67 {
68     [o_transcode autorelease];
69     o_transcode = [o_transcode_string copy];
70 }
71
72 - (void)awakeFromNib
73 {
74     [self initStrings];
75     
76     [[NSNotificationCenter defaultCenter] addObserver: self
77         selector: @selector(outputInfoChanged:)
78         name: NSControlTextDidChangeNotification
79         object: o_file_field];
80     [[NSNotificationCenter defaultCenter] addObserver: self
81         selector: @selector(outputInfoChanged:)
82         name: NSControlTextDidChangeNotification
83         object: o_stream_address];
84     [[NSNotificationCenter defaultCenter] addObserver: self
85         selector: @selector(outputInfoChanged:)
86         name: NSControlTextDidChangeNotification
87         object: o_stream_port];
88     [[NSNotificationCenter defaultCenter] addObserver: self
89         selector: @selector(TTLChanged:)
90         name: NSControlTextDidChangeNotification
91         object: o_stream_ttl];
92     [[NSNotificationCenter defaultCenter] addObserver: self
93         selector: @selector(transcodeInfoChanged:)
94         name: NSControlTextDidChangeNotification
95         object: o_transcode_video_bitrate];
96     [[NSNotificationCenter defaultCenter] addObserver: self
97         selector: @selector(transcodeInfoChanged:)
98         name: NSControlTextDidChangeNotification
99         object: o_transcode_audio_bitrate];
100     [[NSNotificationCenter defaultCenter] addObserver: self
101         selector: @selector(transcodeInfoChanged:)
102         name: NSControlTextDidChangeNotification
103         object: o_transcode_audio_channels];
104     [[NSNotificationCenter defaultCenter] addObserver: self
105         selector: @selector(transcodeInfoChanged:)
106         name: NSControlTextDidChangeNotification
107         object: o_channel_name];
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", 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_a_codecs = [NSArray arrayWithObjects: @"mpga", @"mp3 ", @"a52 ", @"vorb", @"flac", @"spx ", nil];
123     NSArray *o_v_codecs = [NSArray arrayWithObjects: @"mp1v", @"mp2v", @"mp4v", @"DIV1",
124         @"DIV2", @"DIV3", @"H263", @"I263", @"WMV1", @"WMV2", @"MJPG", @"theo", nil];
125     
126     [o_output_ckbox setTitle: _NS("Advanced output:")];
127     [o_output_settings setTitle: _NS("Settings...")];
128     [o_btn_ok setTitle: _NS("OK")];
129     
130     [o_options_lbl setTitle: _NS("Output Options")];
131     [o_display setTitle: _NS("Screen")];
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: _NS("TTL")];
139     [[o_stream_type itemAtIndex: 0] setTitle: _NS("HTTP")];
140     [[o_stream_type itemAtIndex: 1] setTitle: _NS("MMSH")];
141     [[o_stream_type itemAtIndex: 2] setTitle: _NS("UDP")];
142     [[o_stream_type itemAtIndex: 3] setTitle: _NS("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("Transcode 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_audio_chkbox setTitle: _NS("Audio")];
157     [o_transcode_audio_selector removeAllItems];
158     [o_transcode_audio_selector addItemsWithTitles: o_a_codecs];
159     [o_transcode_audio_bitrate_lbl setStringValue: _NS("Bitrate (kb/s)")];
160     [o_transcode_audio_bitrate removeAllItems];
161     [o_transcode_audio_bitrate addItemsWithObjectValues: o_a_bitrates];
162     [o_transcode_audio_channels_lbl setStringValue: _NS("Channels")];
163     [o_transcode_audio_channels removeAllItems];
164     [o_transcode_audio_channels addItemsWithObjectValues: o_a_channels];
165     
166     [o_misc_lbl setTitle: _NS("Stream Announcing")];
167     [o_sap_chkbox setTitle: _NS("SAP announce")];
168     [o_slp_chkbox setTitle: _NS("SLP announce")];
169     [o_channel_name_lbl setStringValue: _NS("Channel Name")];
170 }
171
172 - (IBAction)outputChanged:(id)sender;
173 {
174     if ([o_output_ckbox state] == NSOnState)
175     {
176         [o_output_settings setEnabled:YES];
177     }
178     else
179     {
180         [o_output_settings setEnabled:NO];
181     }
182 }
183
184 - (IBAction)outputSettings:(id)sender
185 {
186     [NSApp beginSheet: o_output_sheet
187         modalForWindow: o_open_panel
188         modalDelegate: self
189         didEndSelector: NULL
190         contextInfo: nil];
191 }
192
193 - (IBAction)outputCloseSheet:(id)sender
194 {
195     [o_output_sheet orderOut:sender];
196     [NSApp endSheet: o_output_sheet];
197 }
198
199 - (void)outputMethodChanged:(NSNotification *)o_notification
200 {
201     NSString *o_mode;
202     o_mode = [[o_method selectedCell] title];
203     
204     [o_sap_chkbox setEnabled: NO];
205     [o_slp_chkbox setEnabled: NO];
206     [o_channel_name setEnabled: NO];
207     [[o_mux_selector itemAtIndex: 0] setEnabled: YES];
208
209     if( [o_mode isEqualToString: _NS("File")] )
210     {
211         [o_file_field setEnabled: YES];
212         [o_btn_browse setEnabled: YES];
213         [o_dump_chkbox setEnabled: YES];
214         [o_stream_address setEnabled: NO];
215         [o_stream_port setEnabled: NO];
216         [o_stream_ttl setEnabled: NO];
217         [o_stream_port_stp setEnabled: NO];
218         [o_stream_ttl_stp setEnabled: NO];
219         [o_stream_type setEnabled: NO];
220         [o_mux_selector setEnabled: YES];
221         [[o_mux_selector itemAtIndex: 1] setEnabled: YES]; // MPEG PS
222         [[o_mux_selector itemAtIndex: 2] setEnabled: YES]; // MPEG 1
223         [[o_mux_selector itemAtIndex: 3] setEnabled: YES]; // Ogg
224         [[o_mux_selector itemAtIndex: 4] setEnabled: YES]; // AVI
225         [[o_mux_selector itemAtIndex: 5] setEnabled: YES]; // ASF
226         [[o_mux_selector itemAtIndex: 6] setEnabled: YES]; // MPEG 4
227         [[o_mux_selector itemAtIndex: 7] setEnabled: YES]; // QuickTime
228     }
229     else if( [o_mode isEqualToString: _NS("Stream")] )
230     {
231         [o_file_field setEnabled: NO];
232         [o_dump_chkbox setEnabled: NO];
233         [o_btn_browse setEnabled: NO];
234         [o_stream_port setEnabled: YES];
235         [o_stream_port_stp setEnabled: YES];
236         [o_stream_type setEnabled: YES];
237         [o_mux_selector setEnabled: YES];
238         
239         o_mode = [o_stream_type titleOfSelectedItem];
240         
241         if( [o_mode isEqualToString: _NS("HTTP")] )
242         {
243             [o_stream_address setEnabled: YES];
244             [o_stream_ttl setEnabled: NO];
245             [o_stream_ttl_stp setEnabled: NO];
246             [[o_mux_selector itemAtIndex: 1] setEnabled: YES];
247             [[o_mux_selector itemAtIndex: 2] setEnabled: YES];
248             [[o_mux_selector itemAtIndex: 3] setEnabled: YES];
249             [[o_mux_selector itemAtIndex: 4] setEnabled: NO];
250             [[o_mux_selector itemAtIndex: 5] setEnabled: NO];
251             [[o_mux_selector itemAtIndex: 6] setEnabled: NO];
252             [[o_mux_selector itemAtIndex: 7] setEnabled: NO];
253         }
254         else if( [o_mode isEqualToString: _NS("MMSH")] )
255         {
256             [o_stream_address setEnabled: YES];
257             [o_stream_ttl setEnabled: NO];
258             [o_stream_ttl_stp setEnabled: NO];
259             [[o_mux_selector itemAtIndex: 0] setEnabled: NO];
260             [[o_mux_selector itemAtIndex: 1] setEnabled: NO];
261             [[o_mux_selector itemAtIndex: 2] setEnabled: NO];
262             [[o_mux_selector itemAtIndex: 3] setEnabled: NO];
263             [[o_mux_selector itemAtIndex: 4] setEnabled: NO];
264             [[o_mux_selector itemAtIndex: 5] setEnabled: YES];
265             [[o_mux_selector itemAtIndex: 6] setEnabled: NO];
266             [[o_mux_selector itemAtIndex: 7] setEnabled: NO];
267         }
268         else if( [o_mode isEqualToString: _NS("UDP")] )
269         {
270             [o_stream_address setEnabled: YES];
271             [o_stream_ttl setEnabled: YES];
272             [o_stream_ttl_stp setEnabled: YES];
273             [[o_mux_selector itemAtIndex: 1] setEnabled: NO];
274             [[o_mux_selector itemAtIndex: 2] setEnabled: NO];
275             [[o_mux_selector itemAtIndex: 3] setEnabled: NO];
276             [[o_mux_selector itemAtIndex: 4] setEnabled: NO];
277             [[o_mux_selector itemAtIndex: 5] setEnabled: NO];
278             [[o_mux_selector itemAtIndex: 6] setEnabled: NO];
279             [[o_mux_selector itemAtIndex: 7] setEnabled: NO];
280             [o_sap_chkbox setEnabled: YES];
281             [o_slp_chkbox setEnabled: YES];
282             [o_channel_name setEnabled: YES];
283         }
284         else if( [o_mode isEqualToString: _NS("RTP")] )
285         {
286             [o_stream_address setEnabled: YES];
287             [o_stream_ttl setEnabled: YES];
288             [o_stream_ttl_stp setEnabled: YES];
289             [[o_mux_selector itemAtIndex: 1] setEnabled: NO];
290             [[o_mux_selector itemAtIndex: 2] setEnabled: NO];
291             [[o_mux_selector itemAtIndex: 3] setEnabled: NO];
292             [[o_mux_selector itemAtIndex: 4] setEnabled: NO];
293             [[o_mux_selector itemAtIndex: 5] setEnabled: NO];
294             [[o_mux_selector itemAtIndex: 6] setEnabled: NO];
295             [[o_mux_selector itemAtIndex: 7] setEnabled: NO];
296         }
297     }
298     if( ![[o_mux_selector selectedItem] isEnabled] )
299     {
300         [o_mux_selector selectItemAtIndex: 0];
301     }
302     [self outputInfoChanged: nil];
303 }
304
305 - (void)outputInfoChanged:(NSNotification *)o_notification
306 {
307     NSString *o_mode, *o_mux, *o_mux_string, *o_announce;
308     NSMutableString *o_mrl_string = [NSMutableString stringWithString:@":sout=#"];
309
310     [o_mrl_string appendString: o_transcode];
311     if( [o_display state] == NSOnState )
312     {
313         [o_mrl_string appendString: @"duplicate{dst=display,dst="];
314     }
315
316     o_mode = [[o_method selectedCell] title];
317     o_mux = [o_mux_selector titleOfSelectedItem];
318
319     if ( [o_mux isEqualToString: _NS("AVI")] ) o_mux_string = @"avi";
320     else if ( [o_mux isEqualToString: _NS("Ogg")] ) o_mux_string = @"ogg";
321     else if ( [o_mux isEqualToString: _NS("MPEG PS")] ) o_mux_string = @"ps";
322     else if ( [o_mux isEqualToString: _NS("MPEG 4")] ) o_mux_string = @"mp4";
323     else if ( [o_mux isEqualToString: _NS("MPEG 1")] ) o_mux_string = @"mpeg1";
324     else if ( [o_mux isEqualToString: _NS("Quicktime")] ) o_mux_string = @"mov";
325     else if ( [o_mux isEqualToString: _NS("ASF")] ) o_mux_string = @"asf";
326     else o_mux_string = @"ts";
327
328     if( [o_mode isEqualToString: _NS("File")] )
329     {
330         if( [o_dump_chkbox state] == NSOnState )
331         {
332             o_mrl_string = [NSMutableString stringWithFormat:
333                             @":demux=demuxdump :demuxdump-file=\"%@\"",
334                             [o_file_field stringValue]];
335             [self setMRL:o_mrl_string];
336             return;
337         }
338         else
339         {
340                 [o_mrl_string appendFormat:
341                         @"std{access=file,mux=%@,url=\"%@\"}",
342                         o_mux_string, [o_file_field stringValue]];
343         }
344     }
345     else if( [o_mode isEqualToString: _NS("Stream")] )
346     {
347         o_mode = [o_stream_type titleOfSelectedItem];
348         o_announce = @"";
349         
350         if ( [o_mode isEqualToString: _NS("HTTP")] )
351             o_mode = @"http";
352         else if ( [o_mode isEqualToString: _NS("MMSH")] )
353         {
354             if ( [o_mux isEqualToString: _NS("ASF")] ) o_mux_string = @"asfh";
355             o_mode = @"mmsh";
356         }
357         else if ( [o_mode isEqualToString: _NS("UDP")] )
358         {
359             o_mode = @"udp";
360             if( [o_sap_chkbox state] == NSOnState )
361             {
362                 if ( ![[o_channel_name stringValue] isEqualToString: @""] )
363                     o_announce = [NSString stringWithFormat:@",sap=%@", [o_channel_name stringValue]];
364                 else
365                     o_announce = @",sap";
366             }
367             if( [o_slp_chkbox state] == NSOnState )
368             {
369                 if ( ![[o_channel_name stringValue] isEqualToString: @""] )
370                     o_announce = [o_announce stringByAppendingFormat:@",slp=%@",
371                         [o_channel_name stringValue]];
372                 else
373                     o_announce = [o_announce stringByAppendingString: @",slp"];
374             }
375         }
376         else if ( [o_mode isEqualToString: _NS("RTP")] )
377             o_mode = @"rtp";
378             
379         [o_mrl_string appendFormat:
380                         @"std{access=%@,mux=%@,url=\"%@:%@\"%@}",
381                         o_mode, o_mux_string, [o_stream_address stringValue],
382                         [o_stream_port stringValue], o_announce];
383     }
384     if( [o_display state] == NSOnState )
385     {
386         [o_mrl_string appendString: @"}"];
387     }
388     [self setMRL:o_mrl_string];
389 }
390
391 - (void)TTLChanged:(NSNotification *)o_notification
392 {
393     intf_thread_t * p_intf = [NSApp getIntf];
394     config_PutInt( p_intf, "ttl", [o_stream_ttl intValue] );
395 }
396
397 - (IBAction)outputFileBrowse:(id)sender
398 {
399     NSSavePanel *o_save_panel = [NSSavePanel savePanel];
400     NSString *o_mux_string;
401     if ( [[o_mux_selector titleOfSelectedItem] isEqualToString: _NS("MPEG PS")] )
402         o_mux_string = @"vob";
403     else if ( [[o_mux_selector titleOfSelectedItem] isEqualToString: _NS("MPEG 1")] )
404         o_mux_string = @"mpg";
405     else if ( [[o_mux_selector titleOfSelectedItem] isEqualToString: _NS("AVI")] )
406         o_mux_string = @"avi";
407     else if ( [[o_mux_selector titleOfSelectedItem] isEqualToString: _NS("ASF")] )
408         o_mux_string = @"asf";
409     else if ( [[o_mux_selector titleOfSelectedItem] isEqualToString: _NS("Ogg")] )
410         o_mux_string = @"ogm";
411     else if ( [[o_mux_selector titleOfSelectedItem] isEqualToString: _NS("MPEG 4")] )
412         o_mux_string = @"mp4";
413     else if ( [[o_mux_selector titleOfSelectedItem] isEqualToString: _NS("Quicktime")] )
414         o_mux_string = @"mov";
415     else
416         o_mux_string = @"ts";
417
418     NSString * o_name = [NSString stringWithFormat: @"vlc-output.%@",
419                          o_mux_string];
420
421     [o_save_panel setTitle: _NS("Save File")];
422     [o_save_panel setPrompt: _NS("Save")];
423
424     if( [o_save_panel runModalForDirectory: nil
425             file: o_name] == NSOKButton )
426     {
427         NSString *o_filename = [o_save_panel filename];
428         [o_file_field setStringValue: o_filename];
429         [self outputInfoChanged: nil];
430     }
431 }
432
433 - (IBAction)streamPortStepperChanged:(id)sender
434 {
435     [o_stream_port setIntValue: [o_stream_port_stp intValue]];
436     [self outputInfoChanged: nil];
437 }
438
439 - (IBAction)streamTTLStepperChanged:(id)sender
440 {
441     [o_stream_ttl setIntValue: [o_stream_ttl_stp intValue]];
442     [self TTLChanged:nil];
443 }
444
445 - (void)transcodeChanged:(NSNotification *)o_notification
446 {
447     if( [o_transcode_video_chkbox state] == NSOnState )
448     {
449         [o_transcode_video_selector setEnabled: YES];
450         [o_transcode_video_bitrate setEnabled: YES];
451     }
452     else
453     {
454         [o_transcode_video_selector setEnabled: NO];
455         [o_transcode_video_bitrate setEnabled: NO];
456     }
457     if( [o_transcode_audio_chkbox state] == NSOnState )
458     {
459         [o_transcode_audio_selector setEnabled: YES];
460         [o_transcode_audio_bitrate setEnabled: YES];
461         [o_transcode_audio_channels setEnabled: YES];
462     }
463     else
464     {
465         [o_transcode_audio_selector setEnabled: NO];
466         [o_transcode_audio_bitrate setEnabled: NO];
467         [o_transcode_audio_channels setEnabled: NO];
468     }
469
470     [self transcodeInfoChanged:nil];
471 }
472
473 - (void)transcodeInfoChanged:(NSNotification *)o_notification
474 {
475     NSMutableString *o_transcode_string;
476     
477     if( [o_transcode_video_chkbox state] == NSOnState ||
478         [o_transcode_audio_chkbox state] == NSOnState )
479     {
480         o_transcode_string = [NSMutableString stringWithString:@"transcode{"];
481         if ( [o_transcode_video_chkbox state] == NSOnState )
482         {
483             [o_transcode_string appendFormat: @"vcodec=\"%@\",vb=\"%@\"",
484                 [o_transcode_video_selector titleOfSelectedItem],
485                 [o_transcode_video_bitrate stringValue]];
486             if ( [o_transcode_audio_chkbox state] == NSOnState )
487             {
488                 [o_transcode_string appendString: @","];
489             }
490         }
491         if ( [o_transcode_audio_chkbox state] == NSOnState )
492         {
493             [o_transcode_string appendFormat: @"acodec=\"%@\",ab=\"%@\"",
494                 [o_transcode_audio_selector titleOfSelectedItem],
495                 [o_transcode_audio_bitrate stringValue]];
496         }
497         [o_transcode_string appendString:@"}:"];
498     }
499     else
500     {
501         o_transcode_string = [NSString stringWithString:@""];
502     }
503     [self setTranscode: o_transcode_string];
504     [self outputInfoChanged:nil];
505 }
506
507 - (IBAction)announceChanged:(id)sender
508 {
509     [o_channel_name setEnabled: [o_sap_chkbox state] || [o_slp_chkbox state]];
510     [self outputInfoChanged: nil];
511 }
512
513 @end