05856b532aac603a88ce3ddfdd307fce53d3f9c9
[vlc.git] / 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.2 2003/05/10 10:32:29 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 - (void)setTranscode:(NSString *)o_transcode_string
62 {
63     [o_transcode autorelease];
64     o_transcode = [o_transcode_string copy];
65 }
66
67 - (void)awakeFromNib
68 {
69     intf_thread_t * p_intf = [NSApp getIntf];
70     char * psz_sout = config_GetPsz( p_intf, "sout" );
71
72     if ( psz_sout != NULL && *psz_sout )
73     {
74         [o_output_ckbox setState: YES];
75     }
76     else
77     {
78         [o_output_ckbox setState: NO];
79     }
80     free(psz_sout);
81
82     [self initStrings];
83     
84     [[NSNotificationCenter defaultCenter] addObserver: self
85         selector: @selector(outputInfoChanged:)
86         name: NSControlTextDidChangeNotification
87         object: o_file_field];
88     [[NSNotificationCenter defaultCenter] addObserver: self
89         selector: @selector(outputInfoChanged:)
90         name: NSControlTextDidChangeNotification
91         object: o_stream_address];
92     [[NSNotificationCenter defaultCenter] addObserver: self
93         selector: @selector(outputInfoChanged:)
94         name: NSControlTextDidChangeNotification
95         object: o_stream_port];
96     [[NSNotificationCenter defaultCenter] addObserver: self
97         selector: @selector(TTLChanged:)
98         name: NSControlTextDidChangeNotification
99         object: o_stream_ttl];
100     [[NSNotificationCenter defaultCenter] addObserver: self
101         selector: @selector(transcodeInfoChanged:)
102         name: NSControlTextDidChangeNotification
103         object: o_transcode_video_bitrate];
104     [[NSNotificationCenter defaultCenter] addObserver: self
105         selector: @selector(transcodeInfoChanged:)
106         name: NSControlTextDidChangeNotification
107         object: o_transcode_audio_bitrate];
108
109     [o_mux_selector setAutoenablesItems: NO];
110     [self transcodeChanged:nil];
111 }
112
113 - (void)initStrings
114 {
115     [o_output_ckbox setTitle: _NS("Advanced output:")];
116     [o_output_settings setTitle: _NS("Settings...")];
117     [o_btn_ok setTitle: _NS("OK")];
118     
119     [o_options_lbl setTitle: _NS("Output Options")];
120     [o_display setTitle: _NS("Screen")];
121     [[o_method cellAtRow:0 column:0] setTitle: _NS("File")];
122     [[o_method cellAtRow:1 column:0] setTitle: _NS("Stream")];
123     [o_btn_browse setTitle: _NS("Browse...")]; 
124     [o_stream_address_lbl setStringValue: _NS("Address")];
125     [o_stream_port_lbl setStringValue: _NS("Port")];
126     [o_stream_ttl_lbl setStringValue: _NS("TTL")];
127     [[o_stream_type itemAtIndex: 0] setTitle: _NS("HTTP")];
128     [[o_stream_type itemAtIndex: 1] setTitle: _NS("UDP")];
129     [[o_stream_type itemAtIndex: 2] setTitle: _NS("RTP")];
130     [o_stream_type_lbl setStringValue: _NS("Type")];
131     
132     [o_mux_lbl setStringValue: _NS("Encapsulation Method")];
133     [[o_mux_selector itemAtIndex: 0] setTitle: _NS("MPEG TS")];
134     [[o_mux_selector itemAtIndex: 1] setTitle: _NS("MPEG PS")];
135     [[o_mux_selector itemAtIndex: 2] setTitle: _NS("AVI")];
136     [[o_mux_selector itemAtIndex: 3] setTitle: _NS("Ogg")];
137     [[o_mux_selector itemAtIndex: 4] setTitle: _NS("mp4")];
138     
139     [o_transcode_lbl setTitle: _NS("Transcode options")];
140     [o_transcode_video_chkbox setTitle: _NS("Video")];
141     [[o_transcode_video_selector itemAtIndex: 0] setTitle: @"mpgv"];
142     [[o_transcode_video_selector itemAtIndex: 1] setTitle: @"mp4v"];
143     [[o_transcode_video_selector itemAtIndex: 2] setTitle: @"DIV1"];
144     [[o_transcode_video_selector itemAtIndex: 3] setTitle: @"DIV2"];
145     [[o_transcode_video_selector itemAtIndex: 4] setTitle: @"DIV3"];
146     [[o_transcode_video_selector itemAtIndex: 5] setTitle: @"H263"];
147     [[o_transcode_video_selector itemAtIndex: 6] setTitle: @"I263"];
148     [[o_transcode_video_selector itemAtIndex: 7] setTitle: @"WMV1"];
149     [o_transcode_video_bitrate_lbl setStringValue: _NS("Bitrate (bps)")];
150     [o_transcode_audio_chkbox setTitle: _NS("Audio")];
151     [[o_transcode_audio_selector itemAtIndex: 0] setTitle: _NS("mpga")];
152     [[o_transcode_audio_selector itemAtIndex: 1] setTitle: _NS("a52 ")];
153     [o_transcode_audio_bitrate_lbl setStringValue: _NS("Bitrate (bps)")];
154 }
155
156 - (IBAction)outputChanged:(id)sender;
157 {
158     if ([o_output_ckbox state] == NSOnState)
159     {
160         [o_output_settings setEnabled:YES];
161     }
162     else
163     {
164         intf_thread_t * p_intf = [NSApp getIntf];
165         config_PutPsz( p_intf, "sout", NULL );
166         [o_output_settings setEnabled:NO];
167     }
168 }
169
170 - (IBAction)outputSettings:(id)sender
171 {
172     [NSApp beginSheet: o_output_sheet
173         modalForWindow: o_open_panel
174         modalDelegate: self
175         didEndSelector: NULL
176         contextInfo: nil];
177 }
178
179 - (IBAction)outputCloseSheet:(id)sender
180 {
181     intf_thread_t * p_intf = [NSApp getIntf];
182     config_PutPsz( p_intf, "sout", [o_mrl lossyCString] );
183     
184     [o_output_sheet orderOut:sender];
185     [NSApp endSheet: o_output_sheet];
186 }
187
188 - (void)outputMethodChanged:(NSNotification *)o_notification
189 {
190     NSString *o_mode;
191
192     o_mode = [[o_method selectedCell] title];
193
194     if( [o_mode isEqualToString: _NS("File")] )
195     {
196         [o_file_field setEnabled: YES];
197         [o_btn_browse setEnabled: YES];
198         [o_stream_address setEnabled: NO];
199         [o_stream_port setEnabled: NO];
200         [o_stream_ttl setEnabled: NO];
201         [o_stream_port_stp setEnabled: NO];
202         [o_stream_ttl_stp setEnabled: NO];
203         [o_stream_type setEnabled: NO];
204         [o_mux_selector setEnabled: YES];
205         [[o_mux_selector itemAtIndex: 1] setEnabled: YES];
206         [[o_mux_selector itemAtIndex: 2] setEnabled: YES];
207         [[o_mux_selector itemAtIndex: 3] setEnabled: YES];
208         [[o_mux_selector itemAtIndex: 4] setEnabled: YES];
209     }
210     else if( [o_mode isEqualToString: _NS("Stream")] )
211     {
212         [o_file_field setEnabled: NO];
213         [o_btn_browse setEnabled: NO];
214         [o_stream_port setEnabled: YES];
215         [o_stream_port_stp setEnabled: YES];
216         [o_stream_type setEnabled: YES];
217         [o_mux_selector setEnabled: YES];
218         
219         o_mode = [o_stream_type titleOfSelectedItem];
220         
221         if( [o_mode isEqualToString: _NS("HTTP")] )
222         {
223             [o_stream_address setEnabled: YES];
224             [o_stream_ttl setEnabled: NO];
225             [o_stream_ttl_stp setEnabled: NO];
226             [[o_mux_selector itemAtIndex: 1] setEnabled: YES];
227             [[o_mux_selector itemAtIndex: 2] setEnabled: NO];
228             [[o_mux_selector itemAtIndex: 3] setEnabled: YES];
229             [[o_mux_selector itemAtIndex: 4] setEnabled: NO];
230         }
231         else if( [o_mode isEqualToString: _NS("UDP")] )
232         {
233             [o_stream_address setEnabled: YES];
234             [o_stream_ttl setEnabled: YES];
235             [o_stream_ttl_stp setEnabled: YES];
236             [[o_mux_selector itemAtIndex: 1] setEnabled: NO];
237             [[o_mux_selector itemAtIndex: 2] setEnabled: NO];
238             [[o_mux_selector itemAtIndex: 3] setEnabled: NO];
239             [[o_mux_selector itemAtIndex: 4] setEnabled: NO];
240         }
241         else if( [o_mode isEqualToString: _NS("RTP")] )
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: NO];
247             [[o_mux_selector itemAtIndex: 2] setEnabled: NO];
248             [[o_mux_selector itemAtIndex: 3] setEnabled: NO];
249             [[o_mux_selector itemAtIndex: 4] setEnabled: NO];
250         }
251     }
252     if( ![[o_mux_selector selectedItem] isEnabled] )
253     {
254         [o_mux_selector selectItemAtIndex: 0];
255     }
256     [self outputInfoChanged: nil];
257 }
258
259 - (void)outputInfoChanged:(NSNotification *)o_notification
260 {
261     NSString *o_mode, *o_mux, *o_mux_string;
262     NSMutableString *o_mrl_string = [NSMutableString stringWithString:@"#"];
263
264     if( [o_display state] == NSOnState )
265     {
266         [o_mrl_string appendString: @"display:"];
267     }
268     [o_mrl_string appendString: o_transcode];
269
270     o_mode = [[o_method selectedCell] title];
271     o_mux = [o_mux_selector titleOfSelectedItem];
272
273     if ( [o_mux isEqualToString: _NS("AVI")] ) o_mux_string = @"avi";
274     else if ( [o_mux isEqualToString: _NS("Ogg")] ) o_mux_string = @"ogg";
275     else if ( [o_mux isEqualToString: _NS("MPEG PS")] ) o_mux_string = @"ps";
276     else if ( [o_mux isEqualToString: _NS("mp4")] ) o_mux_string = @"mp4";
277     else o_mux_string = @"ts";
278
279     if( [o_mode isEqualToString: _NS("File")] )
280     {
281         [o_mrl_string appendFormat:
282                         @"dst=std{access=file,mux=%@,url=\"%@\"},",
283                         o_mux_string, [o_file_field stringValue]];
284     }
285     else if( [o_mode isEqualToString: _NS("Stream")] )
286     {
287         o_mode = [o_stream_type titleOfSelectedItem];
288         
289         if ( [o_mode isEqualToString: _NS("HTTP")] ) o_mode = @"http";
290         else if ( [o_mode isEqualToString: _NS("UDP")] )
291             o_mode = @"udp";
292         else if ( [o_mode isEqualToString: _NS("RTP")] )
293             o_mode = @"rtp";
294             
295         [o_mrl_string appendFormat:
296                         @"dst=std{access=%@,mux=%@,url=\"%@:%@\"},",
297                         o_mode, o_mux_string, [o_stream_address stringValue],
298                         [o_stream_port stringValue]];
299     }
300     [o_mrl_string appendString: @"}:"];
301     [self setMRL:o_mrl_string];
302 }
303
304 - (void)TTLChanged:(NSNotification *)o_notification
305 {
306     intf_thread_t * p_intf = [NSApp getIntf];
307     config_PutInt( p_intf, "ttl", [o_stream_ttl intValue] );
308 }
309
310 - (IBAction)outputFileBrowse:(id)sender
311 {
312     NSSavePanel *o_save_panel = [NSSavePanel savePanel];
313     NSString *o_mux_string;
314     if ( [[o_mux_selector titleOfSelectedItem] isEqualToString: _NS("MPEG PS")] )
315         o_mux_string = @"vob";
316     else if ( [[o_mux_selector titleOfSelectedItem] isEqualToString: _NS("AVI")] )
317         o_mux_string = @"avi";
318     else if ( [[o_mux_selector titleOfSelectedItem] isEqualToString: _NS("Ogg")] )
319         o_mux_string = @"ogm";
320     else if ( [[o_mux_selector titleOfSelectedItem] isEqualToString: _NS("mp4")] )
321         o_mux_string = @"mp4";
322     else
323         o_mux_string = @"ts";
324
325     NSString * o_name = [NSString stringWithFormat: @"vlc-output.%@",
326                          o_mux_string];
327
328     [o_save_panel setTitle: _NS("Save File")];
329     [o_save_panel setPrompt: _NS("Save")];
330
331     if( [o_save_panel runModalForDirectory: nil
332             file: o_name] == NSOKButton )
333     {
334         NSString *o_filename = [o_save_panel filename];
335         [o_file_field setStringValue: o_filename];
336         [self outputInfoChanged: nil];
337     }
338 }
339
340 - (IBAction)streamPortStepperChanged:(id)sender
341 {
342     [o_stream_port setIntValue: [o_stream_port_stp intValue]];
343     [self outputInfoChanged: nil];
344 }
345
346 - (IBAction)streamTTLStepperChanged:(id)sender
347 {
348     [o_stream_ttl setIntValue: [o_stream_ttl_stp intValue]];
349     [self TTLChanged:nil];
350 }
351
352 - (void)transcodeChanged:(NSNotification *)o_notification
353 {
354     if( [o_transcode_video_chkbox state] == NSOnState )
355     {
356         [o_transcode_video_selector setEnabled: YES];
357         [o_transcode_video_bitrate setEnabled: YES];
358     }
359     else
360     {
361         [o_transcode_video_selector setEnabled: NO];
362         [o_transcode_video_bitrate setEnabled: NO];
363     }
364     if( [o_transcode_audio_chkbox state] == NSOnState )
365     {
366         [o_transcode_audio_selector setEnabled: YES];
367         [o_transcode_audio_bitrate setEnabled: YES];
368     }
369     else
370     {
371         [o_transcode_audio_selector setEnabled: NO];
372         [o_transcode_audio_bitrate setEnabled: NO];
373     }
374
375     [self transcodeInfoChanged:nil];
376 }
377
378 - (void)transcodeInfoChanged:(NSNotification *)o_notification
379 {
380     NSMutableString *o_transcode_string;
381     
382     if( [o_transcode_video_chkbox state] == NSOnState ||
383         [o_transcode_audio_chkbox state] == NSOnState )
384     {
385         o_transcode_string = [NSMutableString stringWithString:@"transcode{"];
386         if ( [o_transcode_video_chkbox state] == NSOnState )
387         {
388             [o_transcode_string appendFormat: @"vcodec=\"%@\",vb=\"%@\",",
389                 [o_transcode_video_selector titleOfSelectedItem],
390                 [o_transcode_video_bitrate stringValue]];
391         }
392         if ( [o_transcode_audio_chkbox state] == NSOnState )
393         {
394             [o_transcode_string appendFormat: @"acodec=\"%@\",ab=\"%@\",",
395                 [o_transcode_audio_selector titleOfSelectedItem],
396                 [o_transcode_audio_bitrate stringValue]];
397         }
398     }
399     else
400     {
401         o_transcode_string = [NSString stringWithString:@"duplicate{"];
402     }
403     [self setTranscode: o_transcode_string];
404     [self outputInfoChanged:nil];
405 }
406
407 @end