]> git.sesse.net Git - vlc/blob - modules/gui/macosx/output.m
* modules/gui/macosx/playlist.?: implemented Save 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.15 2003/09/22 03:40:05 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_sap_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: @"96", @"128", @"192", @"256", @"512", nil];
119     NSArray *o_v_bitrates = [NSArray arrayWithObjects:
120         @"100", @"150", @"200", @"400", @"500", @"750", @"1000", @"2000", @"3000", nil];
121     NSArray *o_a_codecs = [NSArray arrayWithObjects:
122         @"mpga", @"mp3 ", @"a52 ", @"vorb", nil];
123     NSArray *o_v_codecs = [NSArray arrayWithObjects:
124         @"mp1v", @"mp2v", @"mp4v", @"DIV1", @"DIV2", @"DIV3", @"H263", @"I263", @"WMV1", @"WMV2", @"MJPG", 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_btn_browse setTitle: _NS("Browse...")]; 
135     [o_stream_address_lbl setStringValue: _NS("Address")];
136     [o_stream_port_lbl setStringValue: _NS("Port")];
137     [o_stream_ttl_lbl setStringValue: _NS("TTL")];
138     [[o_stream_type itemAtIndex: 0] setTitle: _NS("HTTP")];
139     [[o_stream_type itemAtIndex: 1] setTitle: _NS("MMSH")];
140     [[o_stream_type itemAtIndex: 2] setTitle: _NS("UDP")];
141     [[o_stream_type itemAtIndex: 3] setTitle: _NS("RTP")];
142     [o_stream_type_lbl setStringValue: _NS("Type")];
143     
144     [o_mux_lbl setStringValue: _NS("Encapsulation Method")];
145     [o_mux_selector removeAllItems];
146     [o_mux_selector addItemsWithTitles: o_muxers];
147     
148     [o_transcode_lbl setTitle: _NS("Transcode options")];
149     [o_transcode_video_chkbox setTitle: _NS("Video")];
150     [o_transcode_video_selector removeAllItems];
151     [o_transcode_video_selector addItemsWithTitles: o_v_codecs];
152     [o_transcode_video_bitrate_lbl setStringValue: _NS("Bitrate (kb/s)")];
153     [o_transcode_video_bitrate removeAllItems];
154     [o_transcode_video_bitrate addItemsWithObjectValues: o_v_bitrates];
155     [o_transcode_audio_chkbox setTitle: _NS("Audio")];
156     [o_transcode_audio_selector removeAllItems];
157     [o_transcode_audio_selector addItemsWithTitles: o_a_codecs];
158     [o_transcode_audio_bitrate_lbl setStringValue: _NS("Bitrate (kb/s)")];
159     [o_transcode_audio_bitrate removeAllItems];
160     [o_transcode_audio_bitrate addItemsWithObjectValues: o_a_bitrates];
161     [o_transcode_audio_channels_lbl setStringValue: _NS("Channels")];
162     [o_transcode_audio_channels removeAllItems];
163     [o_transcode_audio_channels addItemsWithObjectValues: o_a_channels];
164     
165     [o_misc_lbl setTitle: _NS("Miscellaneous Options")];
166     [o_sap_chkbox setTitle: _NS("Announce streams via SAP Channel:")];
167 }
168
169 - (IBAction)outputChanged:(id)sender;
170 {
171     if ([o_output_ckbox state] == NSOnState)
172     {
173         [o_output_settings setEnabled:YES];
174     }
175     else
176     {
177         [o_output_settings setEnabled:NO];
178     }
179 }
180
181 - (IBAction)outputSettings:(id)sender
182 {
183     [NSApp beginSheet: o_output_sheet
184         modalForWindow: o_open_panel
185         modalDelegate: self
186         didEndSelector: NULL
187         contextInfo: nil];
188 }
189
190 - (IBAction)outputCloseSheet:(id)sender
191 {
192     [o_output_sheet orderOut:sender];
193     [NSApp endSheet: o_output_sheet];
194 }
195
196 - (void)outputMethodChanged:(NSNotification *)o_notification
197 {
198     NSString *o_mode;
199     o_mode = [[o_method selectedCell] title];
200     
201     [o_sap_chkbox setEnabled: NO];
202     [o_sap_name setEnabled: NO];
203     [[o_mux_selector itemAtIndex: 0] setEnabled: YES];
204
205     if( [o_mode isEqualToString: _NS("File")] )
206     {
207         [o_file_field setEnabled: YES];
208         [o_btn_browse setEnabled: YES];
209         [o_stream_address setEnabled: NO];
210         [o_stream_port setEnabled: NO];
211         [o_stream_ttl setEnabled: NO];
212         [o_stream_port_stp setEnabled: NO];
213         [o_stream_ttl_stp setEnabled: NO];
214         [o_stream_type setEnabled: NO];
215         [o_mux_selector setEnabled: YES];
216         [[o_mux_selector itemAtIndex: 1] setEnabled: YES]; // MPEG PS
217         [[o_mux_selector itemAtIndex: 2] setEnabled: YES]; // MPEG 1
218         [[o_mux_selector itemAtIndex: 3] setEnabled: YES]; // Ogg
219         [[o_mux_selector itemAtIndex: 4] setEnabled: YES]; // AVI
220         [[o_mux_selector itemAtIndex: 5] setEnabled: YES]; // ASF
221         [[o_mux_selector itemAtIndex: 6] setEnabled: YES]; // MPEG 4
222         [[o_mux_selector itemAtIndex: 7] setEnabled: YES]; // QuickTime
223     }
224     else if( [o_mode isEqualToString: _NS("Stream")] )
225     {
226         [o_file_field setEnabled: NO];
227         [o_btn_browse setEnabled: NO];
228         [o_stream_port setEnabled: YES];
229         [o_stream_port_stp setEnabled: YES];
230         [o_stream_type setEnabled: YES];
231         [o_mux_selector setEnabled: YES];
232         
233         o_mode = [o_stream_type titleOfSelectedItem];
234         
235         if( [o_mode isEqualToString: _NS("HTTP")] )
236         {
237             [o_stream_address setEnabled: YES];
238             [o_stream_ttl setEnabled: NO];
239             [o_stream_ttl_stp setEnabled: NO];
240             [[o_mux_selector itemAtIndex: 1] setEnabled: YES];
241             [[o_mux_selector itemAtIndex: 2] setEnabled: YES];
242             [[o_mux_selector itemAtIndex: 3] setEnabled: YES];
243             [[o_mux_selector itemAtIndex: 4] setEnabled: NO];
244             [[o_mux_selector itemAtIndex: 5] setEnabled: NO];
245             [[o_mux_selector itemAtIndex: 6] setEnabled: NO];
246             [[o_mux_selector itemAtIndex: 7] setEnabled: NO];
247         }
248         else if( [o_mode isEqualToString: _NS("MMSH")] )
249         {
250             [o_stream_address setEnabled: YES];
251             [o_stream_ttl setEnabled: NO];
252             [o_stream_ttl_stp setEnabled: NO];
253             [[o_mux_selector itemAtIndex: 0] setEnabled: NO];
254             [[o_mux_selector itemAtIndex: 1] setEnabled: NO];
255             [[o_mux_selector itemAtIndex: 2] setEnabled: NO];
256             [[o_mux_selector itemAtIndex: 3] setEnabled: NO];
257             [[o_mux_selector itemAtIndex: 4] setEnabled: NO];
258             [[o_mux_selector itemAtIndex: 5] setEnabled: YES];
259             [[o_mux_selector itemAtIndex: 6] setEnabled: NO];
260             [[o_mux_selector itemAtIndex: 7] setEnabled: NO];
261         }
262         else if( [o_mode isEqualToString: _NS("UDP")] )
263         {
264             [o_stream_address setEnabled: YES];
265             [o_stream_ttl setEnabled: YES];
266             [o_stream_ttl_stp setEnabled: YES];
267             [[o_mux_selector itemAtIndex: 1] setEnabled: NO];
268             [[o_mux_selector itemAtIndex: 2] setEnabled: NO];
269             [[o_mux_selector itemAtIndex: 3] setEnabled: NO];
270             [[o_mux_selector itemAtIndex: 4] setEnabled: NO];
271             [[o_mux_selector itemAtIndex: 5] setEnabled: NO];
272             [[o_mux_selector itemAtIndex: 6] setEnabled: NO];
273             [[o_mux_selector itemAtIndex: 7] setEnabled: NO];
274             [o_sap_chkbox setEnabled: YES];
275             [o_sap_name setEnabled: YES];
276         }
277         else if( [o_mode isEqualToString: _NS("RTP")] )
278         {
279             [o_stream_address setEnabled: YES];
280             [o_stream_ttl setEnabled: YES];
281             [o_stream_ttl_stp setEnabled: YES];
282             [[o_mux_selector itemAtIndex: 1] setEnabled: NO];
283             [[o_mux_selector itemAtIndex: 2] setEnabled: NO];
284             [[o_mux_selector itemAtIndex: 3] setEnabled: NO];
285             [[o_mux_selector itemAtIndex: 4] setEnabled: NO];
286             [[o_mux_selector itemAtIndex: 5] setEnabled: NO];
287             [[o_mux_selector itemAtIndex: 6] setEnabled: NO];
288             [[o_mux_selector itemAtIndex: 7] setEnabled: NO];
289         }
290     }
291     if( ![[o_mux_selector selectedItem] isEnabled] )
292     {
293         [o_mux_selector selectItemAtIndex: 0];
294     }
295     [self outputInfoChanged: nil];
296 }
297
298 - (void)outputInfoChanged:(NSNotification *)o_notification
299 {
300     NSString *o_mode, *o_mux, *o_mux_string, *o_sap;
301     NSMutableString *o_mrl_string = [NSMutableString stringWithString:@"#"];
302
303     [o_mrl_string appendString: o_transcode];
304     if( [o_display state] == NSOnState )
305     {
306         [o_mrl_string appendString: @"duplicate{dst=display,dst="];
307     }
308
309     o_mode = [[o_method selectedCell] title];
310     o_mux = [o_mux_selector titleOfSelectedItem];
311
312     if ( [o_mux isEqualToString: _NS("AVI")] ) o_mux_string = @"avi";
313     else if ( [o_mux isEqualToString: _NS("Ogg")] ) o_mux_string = @"ogg";
314     else if ( [o_mux isEqualToString: _NS("MPEG PS")] ) o_mux_string = @"ps";
315     else if ( [o_mux isEqualToString: _NS("MPEG 4")] ) o_mux_string = @"mp4";
316     else if ( [o_mux isEqualToString: _NS("MPEG 1")] ) o_mux_string = @"mpeg1";
317     else if ( [o_mux isEqualToString: _NS("Quicktime")] ) o_mux_string = @"mov";
318     else if ( [o_mux isEqualToString: _NS("ASF")] ) o_mux_string = @"asf";
319     else o_mux_string = @"ts";
320
321     if( [o_mode isEqualToString: _NS("File")] )
322     {
323         [o_mrl_string appendFormat:
324                         @"std{access=file,mux=%@,url=\"%@\"}",
325                         o_mux_string, [o_file_field stringValue]];
326     }
327     else if( [o_mode isEqualToString: _NS("Stream")] )
328     {
329         o_mode = [o_stream_type titleOfSelectedItem];
330         o_sap = @"";
331         
332         if ( [o_mode isEqualToString: _NS("HTTP")] )
333             o_mode = @"http";
334         else if ( [o_mode isEqualToString: _NS("MMSH")] )
335         {
336             if ( [o_mux isEqualToString: _NS("ASF")] ) o_mux_string = @"asfh";
337             o_mode = @"mmsh";
338         }
339         else if ( [o_mode isEqualToString: _NS("UDP")] )
340         {
341             o_mode = @"udp";
342             if( [o_sap_chkbox state] == NSOnState )
343             {
344                 o_sap = @",sap";
345                 if ( ![[o_sap_name stringValue] isEqualToString: @""] )
346                     o_sap = [NSString stringWithFormat:@",sap=%@", [o_sap_name stringValue]];
347             }
348         }
349         else if ( [o_mode isEqualToString: _NS("RTP")] )
350             o_mode = @"rtp";
351             
352         [o_mrl_string appendFormat:
353                         @"std{access=%@,mux=%@,url=\"%@:%@\"%@}",
354                         o_mode, o_mux_string, [o_stream_address stringValue],
355                         [o_stream_port stringValue], o_sap];
356     }
357     if( [o_display state] == NSOnState )
358     {
359         [o_mrl_string appendString: @"}"];
360     }
361     [self setMRL:o_mrl_string];
362 }
363
364 - (void)TTLChanged:(NSNotification *)o_notification
365 {
366     intf_thread_t * p_intf = [NSApp getIntf];
367     config_PutInt( p_intf, "ttl", [o_stream_ttl intValue] );
368 }
369
370 - (IBAction)outputFileBrowse:(id)sender
371 {
372     NSSavePanel *o_save_panel = [NSSavePanel savePanel];
373     NSString *o_mux_string;
374     if ( [[o_mux_selector titleOfSelectedItem] isEqualToString: _NS("MPEG PS")] )
375         o_mux_string = @"vob";
376     else if ( [[o_mux_selector titleOfSelectedItem] isEqualToString: _NS("MPEG 1")] )
377         o_mux_string = @"mpg";
378     else if ( [[o_mux_selector titleOfSelectedItem] isEqualToString: _NS("AVI")] )
379         o_mux_string = @"avi";
380     else if ( [[o_mux_selector titleOfSelectedItem] isEqualToString: _NS("ASF")] )
381         o_mux_string = @"asf";
382     else if ( [[o_mux_selector titleOfSelectedItem] isEqualToString: _NS("Ogg")] )
383         o_mux_string = @"ogm";
384     else if ( [[o_mux_selector titleOfSelectedItem] isEqualToString: _NS("MPEG 4")] )
385         o_mux_string = @"mp4";
386     else if ( [[o_mux_selector titleOfSelectedItem] isEqualToString: _NS("Quicktime")] )
387         o_mux_string = @"mov";
388     else
389         o_mux_string = @"ts";
390
391     NSString * o_name = [NSString stringWithFormat: @"vlc-output.%@",
392                          o_mux_string];
393
394     [o_save_panel setTitle: _NS("Save File")];
395     [o_save_panel setPrompt: _NS("Save")];
396
397     if( [o_save_panel runModalForDirectory: nil
398             file: o_name] == NSOKButton )
399     {
400         NSString *o_filename = [o_save_panel filename];
401         [o_file_field setStringValue: o_filename];
402         [self outputInfoChanged: nil];
403     }
404 }
405
406 - (IBAction)streamPortStepperChanged:(id)sender
407 {
408     [o_stream_port setIntValue: [o_stream_port_stp intValue]];
409     [self outputInfoChanged: nil];
410 }
411
412 - (IBAction)streamTTLStepperChanged:(id)sender
413 {
414     [o_stream_ttl setIntValue: [o_stream_ttl_stp intValue]];
415     [self TTLChanged:nil];
416 }
417
418 - (void)transcodeChanged:(NSNotification *)o_notification
419 {
420     if( [o_transcode_video_chkbox state] == NSOnState )
421     {
422         [o_transcode_video_selector setEnabled: YES];
423         [o_transcode_video_bitrate setEnabled: YES];
424     }
425     else
426     {
427         [o_transcode_video_selector setEnabled: NO];
428         [o_transcode_video_bitrate setEnabled: NO];
429     }
430     if( [o_transcode_audio_chkbox state] == NSOnState )
431     {
432         [o_transcode_audio_selector setEnabled: YES];
433         [o_transcode_audio_bitrate setEnabled: YES];
434         [o_transcode_audio_channels setEnabled: YES];
435     }
436     else
437     {
438         [o_transcode_audio_selector setEnabled: NO];
439         [o_transcode_audio_bitrate setEnabled: NO];
440         [o_transcode_audio_channels setEnabled: NO];
441     }
442
443     [self transcodeInfoChanged:nil];
444 }
445
446 - (void)transcodeInfoChanged:(NSNotification *)o_notification
447 {
448     NSMutableString *o_transcode_string;
449     
450     if( [o_transcode_video_chkbox state] == NSOnState ||
451         [o_transcode_audio_chkbox state] == NSOnState )
452     {
453         o_transcode_string = [NSMutableString stringWithString:@"transcode{"];
454         if ( [o_transcode_video_chkbox state] == NSOnState )
455         {
456             [o_transcode_string appendFormat: @"vcodec=\"%@\",vb=\"%@\"",
457                 [o_transcode_video_selector titleOfSelectedItem],
458                 [o_transcode_video_bitrate stringValue]];
459             if ( [o_transcode_audio_chkbox state] == NSOnState )
460             {
461                 [o_transcode_string appendString: @","];
462             }
463         }
464         if ( [o_transcode_audio_chkbox state] == NSOnState )
465         {
466             [o_transcode_string appendFormat: @"acodec=\"%@\",ab=\"%@\"",
467                 [o_transcode_audio_selector titleOfSelectedItem],
468                 [o_transcode_audio_bitrate stringValue]];
469         }
470         [o_transcode_string appendString:@"}:"];
471     }
472     else
473     {
474         o_transcode_string = [NSString stringWithString:@""];
475     }
476     [self setTranscode: o_transcode_string];
477     [self outputInfoChanged:nil];
478 }
479
480 - (IBAction)sapChanged:(id)sender
481 {
482     [o_sap_name setEnabled: [o_sap_chkbox state]];
483     [self outputInfoChanged: nil];
484 }
485
486
487
488 @end