]> git.sesse.net Git - vlc/blob - modules/gui/macosx/open.m
* Added myself to list of authors of these files. i had forgotten to do this.
[vlc] / modules / gui / macosx / open.m
1 /*****************************************************************************
2  * open.m: MacOS X plugin for vlc
3  *****************************************************************************
4  * Copyright (C) 2002 VideoLAN
5  * $Id: open.m,v 1.16 2003/01/26 14:53:08 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 <sys/param.h>                                    /* for MAXPATHLEN */
31 #include <string.h>
32
33 #include <paths.h>
34 #include <IOKit/IOKitLib.h>
35 #include <IOKit/IOBSD.h>
36 #include <IOKit/storage/IOMedia.h>
37 #include <IOKit/storage/IOCDMedia.h>
38 #include <IOKit/storage/IODVDMedia.h>
39
40 #import <Cocoa/Cocoa.h>
41
42 #include <vlc/vlc.h>
43 #include <vlc/intf.h>
44
45 #include "netutils.h"
46
47 #import "intf.h"
48 #import "playlist.h"
49 #import "open.h"
50
51 /*****************************************************************************
52  * GetEjectableMediaOfClass 
53  *****************************************************************************/
54 NSArray *GetEjectableMediaOfClass( const char *psz_class )
55 {
56     io_object_t next_media;
57     mach_port_t master_port;
58     kern_return_t kern_result;
59     NSArray *o_devices = nil;
60     NSMutableArray *p_list = nil;
61     io_iterator_t media_iterator;
62     CFMutableDictionaryRef classes_to_match;
63
64     kern_result = IOMasterPort( MACH_PORT_NULL, &master_port );
65     if( kern_result != KERN_SUCCESS )
66     {
67         return( nil );
68     }
69     
70     classes_to_match = IOServiceMatching( psz_class );
71     if( classes_to_match == NULL )
72     {
73         return( nil );
74     }
75     
76     CFDictionarySetValue( classes_to_match, CFSTR( kIOMediaEjectable ), 
77                           kCFBooleanTrue );
78     
79     kern_result = IOServiceGetMatchingServices( master_port, classes_to_match, 
80                                                 &media_iterator );
81     if( kern_result != KERN_SUCCESS )
82     {
83         return( nil );
84     }
85
86     p_list = [NSMutableArray arrayWithCapacity: 1];
87     
88     next_media = IOIteratorNext( media_iterator );
89     if( next_media != NULL )
90     {
91         char psz_buf[0x32];
92         size_t dev_path_length;
93         CFTypeRef str_bsd_path;
94     
95         do
96         {
97             str_bsd_path = IORegistryEntryCreateCFProperty( next_media,
98                                                             CFSTR( kIOBSDName ),
99                                                             kCFAllocatorDefault,
100                                                             0 );
101             if( str_bsd_path == NULL )
102             {
103                 IOObjectRelease( next_media );
104                 continue;
105             }
106             
107             snprintf( psz_buf, sizeof(psz_buf), "%s%c", _PATH_DEV, 'r' );
108             dev_path_length = strlen( psz_buf );
109             
110             if( CFStringGetCString( str_bsd_path,
111                                     (char*)&psz_buf + dev_path_length,
112                                     sizeof(psz_buf) - dev_path_length,
113                                     kCFStringEncodingASCII ) )
114             {
115                 [p_list addObject: [NSString stringWithCString: psz_buf]];
116             }
117             
118             CFRelease( str_bsd_path );
119             
120             IOObjectRelease( next_media );
121         
122         } while( ( next_media = IOIteratorNext( media_iterator ) ) != NULL );
123     }
124     
125     IOObjectRelease( media_iterator );
126
127     o_devices = [NSArray arrayWithArray: p_list];
128
129     return( o_devices );
130 }
131
132 /*****************************************************************************
133  * VLCOpen implementation 
134  *****************************************************************************/
135 @implementation VLCOpen
136
137 - (void)awakeFromNib
138 {
139     intf_thread_t * p_intf = [NSApp getIntf];
140     char * psz_sout = config_GetPsz( p_intf, "sout" );
141
142     if ( psz_sout != NULL && *psz_sout )
143     {
144         [o_sout_cbox setState: YES];
145
146         NSRect s_rect = [o_panel frame];
147         s_rect.size.height = OPEN_PANEL_FULL_HEIGHT + WINDOW_TITLE_HEIGHT;
148         [o_panel setFrame: s_rect display: NO];
149
150         NSPoint s_point;
151         s_point.x = 0;
152         s_point.y = 0;
153         [[o_panel contentView] setBoundsOrigin: s_point];
154     }
155     else
156     {
157         [o_sout_cbox setState: NO];
158
159         NSRect s_rect = [o_panel frame];
160         s_rect.size.height = OPEN_PANEL_SHORT_HEIGHT + WINDOW_TITLE_HEIGHT;
161         [o_panel setFrame: s_rect display: NO];
162
163         NSPoint s_point;
164         s_point.x = 0;
165         s_point.y = OPEN_PANEL_FULL_HEIGHT - OPEN_PANEL_SHORT_HEIGHT;
166         [[o_panel contentView] setBoundsOrigin: s_point];
167     }
168     free(psz_sout);
169
170     [o_panel setTitle: _NS("Open Source")];
171     [o_mrl_lbl setTitle: _NS("Media Resource Locator (MRL)")];
172     [o_ckbox_enqueue setTitle: _NS("Only enqueue in playlist. Do not play.")];
173
174     [o_btn_ok setTitle: _NS("OK")];
175     [o_btn_cancel setTitle: _NS("Cancel")];
176
177     [[o_tabview tabViewItemAtIndex: 0] setLabel: _NS("File")];
178     [[o_tabview tabViewItemAtIndex: 1] setLabel: _NS("Disc")];
179     [[o_tabview tabViewItemAtIndex: 2] setLabel: _NS("Network")];
180
181     [o_file_btn_browse setTitle: _NS("Browse...")];
182     [o_file_stream setTitle: _NS("Treat as a pipe rather than as a file")];
183
184     [o_file_sub_btn_browse setTitle: _NS("Browse...")];
185     [o_file_sub_ckbox setTitle: _NS("Load subtitles")];
186
187     [o_disc_device_lbl setStringValue: _NS("Device name")];
188     [o_disc_title_lbl setStringValue: _NS("Title")];
189     [o_disc_chapter_lbl setStringValue: _NS("Chapter")];
190     [o_disc_videots_btn_browse setStringValue: _NS("Browse...")];
191     [o_disc_dvd_menus setTitle: _NS("Use DVD menus (EXPERIMENTAL)")];
192
193     [[o_disc_type cellAtRow:0 column:0] setTitle: _NS("VIDEO_TS folder")];
194     [[o_disc_type cellAtRow:1 column:0] setTitle: _NS("DVD")];
195     [[o_disc_type cellAtRow:2 column:0] setTitle: _NS("VCD")];
196
197     [o_net_udp_port_lbl setStringValue: _NS("Port")];
198     [o_net_udpm_addr_lbl setStringValue: _NS("Address")];
199     [o_net_udpm_port_lbl setStringValue: _NS("Port")];
200     [o_net_cs_addr_lbl setStringValue: _NS("Address")];
201     [o_net_cs_port_lbl setStringValue: _NS("Port")];
202     [o_net_http_url_lbl setStringValue: _NS("URL")];
203
204     [[o_net_mode cellAtRow:0 column:0] setTitle: _NS("UDP/RTP")];
205     [[o_net_mode cellAtRow:1 column:0] setTitle: _NS("UDP/RTP Multicast")];
206     [[o_net_mode cellAtRow:2 column:0] setTitle: _NS("Channel server")];
207     [[o_net_mode cellAtRow:3 column:0] setTitle: _NS("HTTP/FTP/MMS")];
208
209     [o_net_udp_port setIntValue: config_GetInt( p_intf, "server-port" )];
210     [o_net_udp_port_stp setIntValue: config_GetInt( p_intf, "server-port" )];
211     [o_net_cs_port setIntValue: config_GetInt( p_intf, "channel-port" )];
212     [o_net_cs_port_stp setIntValue: config_GetInt( p_intf, "channel-port" )];
213
214     [o_sout_cbox setTitle: _NS("Stream output")];
215     [o_sout_mrl_lbl setTitle: _NS("Stream output MRL")];
216     [[o_sout_access cellAtRow:0 column:0] setTitle: _NS("File")];
217     [[o_sout_access cellAtRow:1 column:0] setTitle: _NS("UDP")];
218     [[o_sout_access cellAtRow:2 column:0] setTitle: _NS("RTP")];
219
220     [o_sout_file_btn_browse setStringValue: _NS("Browse...")];
221     [o_sout_udp_addr_lbl setStringValue: _NS("Address")];
222     [o_sout_udp_port_lbl setStringValue: _NS("Port")];
223
224     [[o_sout_mux cellAtRow:0 column:0] setTitle: _NS("AVI")];
225     [[o_sout_mux cellAtRow:0 column:1] setTitle: _NS("PS")];
226     [[o_sout_mux cellAtRow:0 column:2] setTitle: _NS("TS")];
227
228     [[NSNotificationCenter defaultCenter] addObserver: self
229         selector: @selector(openFilePathChanged:)
230         name: NSControlTextDidChangeNotification
231         object: o_file_path];
232
233     [[NSNotificationCenter defaultCenter] addObserver: self
234         selector: @selector(openDiscInfoChanged:)
235         name: NSControlTextDidChangeNotification
236         object: o_disc_device];
237     [[NSNotificationCenter defaultCenter] addObserver: self
238         selector: @selector(openDiscInfoChanged:)
239         name: NSControlTextDidChangeNotification
240         object: o_disc_title];
241     [[NSNotificationCenter defaultCenter] addObserver: self
242         selector: @selector(openDiscInfoChanged:)
243         name: NSControlTextDidChangeNotification
244         object: o_disc_chapter];
245     [[NSNotificationCenter defaultCenter] addObserver: self
246         selector: @selector(openDiscInfoChanged:)
247         name: NSControlTextDidChangeNotification
248         object: o_disc_videots_folder];
249
250     [[NSNotificationCenter defaultCenter] addObserver: self
251         selector: @selector(openNetInfoChanged:)
252         name: NSControlTextDidChangeNotification
253         object: o_net_udp_port];
254     [[NSNotificationCenter defaultCenter] addObserver: self
255         selector: @selector(openNetInfoChanged:)
256         name: NSControlTextDidChangeNotification
257         object: o_net_udpm_addr];
258     [[NSNotificationCenter defaultCenter] addObserver: self
259         selector: @selector(openNetInfoChanged:)
260         name: NSControlTextDidChangeNotification
261         object: o_net_udpm_port];
262     [[NSNotificationCenter defaultCenter] addObserver: self
263         selector: @selector(openNetInfoChanged:)
264         name: NSControlTextDidChangeNotification
265         object: o_net_cs_addr];
266     [[NSNotificationCenter defaultCenter] addObserver: self
267         selector: @selector(openNetInfoChanged:)
268         name: NSControlTextDidChangeNotification
269         object: o_net_cs_port];
270     [[NSNotificationCenter defaultCenter] addObserver: self
271         selector: @selector(openNetInfoChanged:)
272         name: NSControlTextDidChangeNotification
273         object: o_net_http_url];
274
275     [[NSNotificationCenter defaultCenter] addObserver: self
276         selector: @selector(soutInfoChanged:)
277         name: NSControlTextDidChangeNotification
278         object: o_sout_file_path];
279     [[NSNotificationCenter defaultCenter] addObserver: self
280         selector: @selector(soutInfoChanged:)
281         name: NSControlTextDidChangeNotification
282         object: o_sout_udp_addr];
283     [[NSNotificationCenter defaultCenter] addObserver: self
284         selector: @selector(soutInfoChanged:)
285         name: NSControlTextDidChangeNotification
286         object: o_sout_udp_port];
287 }
288
289 - (void)openTarget:(int)i_type
290 {
291     int i_result;
292
293     [o_tabview selectTabViewItemAtIndex: i_type];
294     [o_ckbox_enqueue setState: NSOffState];
295     [o_file_sub_path setStringValue: @""];
296     [o_file_sub_ckbox setState: NSOffState];
297     [o_file_sub_path setEnabled: NO];
298     [o_file_sub_btn_browse setEnabled: NO];
299     
300     i_result = [NSApp runModalForWindow: o_panel];
301     [o_panel close];
302
303     if( i_result )
304     {
305         NSString *o_sout = [o_sout_mrl stringValue];
306         intf_thread_t * p_intf = [NSApp getIntf];
307         
308         if ( [o_sout_cbox state] )
309         {
310             config_PutPsz( p_intf, "sout", [o_sout lossyCString] );
311         }
312
313         NSString *o_source = [o_mrl stringValue];
314         BOOL b_enq = [o_ckbox_enqueue state] == NSOnState ? YES : NO;
315         NSString *subPath = [o_file_sub_path stringValue];
316         
317         [o_playlist appendArray: 
318             [NSArray arrayWithObject: o_source] atPos: -1 enqueue:b_enq];
319         
320         if (([o_file_sub_ckbox state] == NSOnState) && !([subPath isEqualTo: @""]))
321             config_PutPsz( p_intf, "sub-file", strdup( [subPath cString] ) );
322     }
323
324     [self soutModeChanged: nil];
325 }
326
327 - (void)tabView:(NSTabView *)o_tv didSelectTabViewItem:(NSTabViewItem *)o_tvi
328 {
329     NSString *o_label = [o_tvi label];
330
331     if( [o_label isEqualToString: _NS("File")] )
332     {
333         [self openFilePathChanged: nil];
334     }
335     else if( [o_label isEqualToString: _NS("Disc")] )
336     {
337         [self openDiscTypeChanged: nil];
338     }
339     else if( [o_label isEqualToString: _NS("Network")] )
340     {
341         [self openNetModeChanged: nil];
342     }  
343 }
344
345 - (IBAction)openFileGeneric:(id)sender
346 {
347     [self openFilePathChanged: nil];
348     [self openTarget: 0];
349 }
350
351 - (IBAction)openDisc:(id)sender
352 {
353     [self openDiscTypeChanged: nil];
354     [self openTarget: 1];
355 }
356
357 - (IBAction)openNet:(id)sender
358 {
359     [self openNetModeChanged: nil];
360     [self openTarget: 2];
361 }
362
363 - (void)openFilePathChanged:(NSNotification *)o_notification
364 {
365     NSString *o_mrl_string;
366     NSString *o_filename = [o_file_path stringValue];
367     NSString *o_ext = [o_filename pathExtension];
368     vlc_bool_t b_stream = [o_file_stream state];
369
370     if ([o_ext isEqualToString: @"bin"] ||
371         [o_ext isEqualToString: @"cue"] ||
372         [o_ext isEqualToString: @"vob"] ||
373         [o_ext isEqualToString: @"iso"])
374     {
375         o_mrl_string = o_filename;
376     }
377     else
378     {
379         o_mrl_string = [NSString stringWithFormat: @"%s://%@",
380                         b_stream ? "stream" : "file",
381                         o_filename];
382     }
383     [o_mrl setStringValue: o_mrl_string]; 
384 }
385
386 - (IBAction)openFileBrowse:(id)sender
387 {
388     NSOpenPanel *o_open_panel = [NSOpenPanel openPanel];
389     
390     [o_open_panel setAllowsMultipleSelection: NO];
391     [o_open_panel setTitle: _NS("Open File")];
392     [o_open_panel setPrompt: _NS("Open")];
393
394     if( [o_open_panel runModalForDirectory: nil 
395             file: nil types: nil] == NSOKButton )
396     {
397         NSString *o_filename = [[o_open_panel filenames] objectAtIndex: 0];
398         [o_file_path setStringValue: o_filename];
399         [self openFilePathChanged: nil];
400     }
401 }
402
403 - (IBAction)openFileStreamChanged:(id)sender
404 {
405     [self openFilePathChanged: nil];
406 }
407
408 - (IBAction)loadSubsChanged:(id)sender
409 {
410     if ([o_file_sub_ckbox state] == NSOnState)
411     {
412         [o_file_sub_path setEnabled:YES];
413         [o_file_sub_btn_browse setEnabled:YES];
414     }
415     else
416     {
417         [o_file_sub_path setEnabled:NO];
418         [o_file_sub_btn_browse setEnabled:NO];
419     }
420 }
421
422 - (IBAction)openSubBrowse:(id)sender
423 {
424     NSOpenPanel *o_open_panel = [NSOpenPanel openPanel];
425     
426     [o_open_panel setAllowsMultipleSelection: NO];
427     [o_open_panel setTitle: _NS("Open File")];
428     [o_open_panel setPrompt: _NS("Open")];
429
430     if( [o_open_panel runModalForDirectory: nil 
431             file: nil types: nil] == NSOKButton )
432     {
433         NSString *o_filename = [[o_open_panel filenames] objectAtIndex: 0];
434         [o_file_sub_path setStringValue: o_filename];
435     }
436 }
437
438 - (IBAction)openDiscTypeChanged:(id)sender
439 {
440     NSString *o_type;
441     vlc_bool_t b_device, b_menus, b_title_chapter;
442     
443     [o_disc_device removeAllItems];
444     b_title_chapter = ![o_disc_dvd_menus state];
445     
446     o_type = [[o_disc_type selectedCell] title];
447
448     if ( [o_type isEqualToString: _NS("VIDEO_TS folder")] )
449     {
450         b_device = 0; b_menus = 1;
451     }
452     else
453     {
454         NSArray *o_devices;
455         NSString *o_disc;
456         const char *psz_class = NULL;
457         b_device = 1;
458
459         if ( [o_type isEqualToString: _NS("VCD")] )
460         {
461             psz_class = kIOCDMediaClass;
462             o_disc = o_type;
463             b_menus = 0; b_title_chapter = 1;
464             [o_disc_dvd_menus setState: FALSE];
465         }
466         else
467         {
468             psz_class = kIODVDMediaClass;
469             o_disc = o_type;
470             b_menus = 1;
471         }
472     
473         o_devices = GetEjectableMediaOfClass( psz_class );
474         if ( o_devices != nil )
475         {
476             int i_devices = [o_devices count];
477         
478             if ( i_devices )
479             {
480                 int i;
481         
482                 for( i = 0; i < i_devices; i++ )
483                 {
484                     [o_disc_device 
485                         addItemWithObjectValue: [o_devices objectAtIndex: i]];
486                 }
487
488                 [o_disc_device selectItemAtIndex: 0];
489             }
490             else
491             {
492                 [o_disc_device setStringValue: 
493                     [NSString stringWithFormat: _NS("No %@s found"), o_disc]];
494             }
495         }
496     }
497
498     [o_disc_device setEnabled: b_device];
499     [o_disc_title setEnabled: b_title_chapter];
500     [o_disc_title_stp setEnabled: b_title_chapter];
501     [o_disc_chapter setEnabled: b_title_chapter];
502     [o_disc_chapter_stp setEnabled: b_title_chapter];
503     [o_disc_videots_folder setEnabled: !b_device];
504     [o_disc_videots_btn_browse setEnabled: !b_device];
505     [o_disc_dvd_menus setEnabled: b_menus];
506
507     [self openDiscInfoChanged: nil];
508 }
509
510 - (IBAction)openDiscStepperChanged:(id)sender
511 {
512     int i_tag = [sender tag];
513
514     if( i_tag == 0 )
515     {
516         [o_disc_title setIntValue: [o_disc_title_stp intValue]];
517     }
518     else if( i_tag == 1 )
519     {
520         [o_disc_chapter setIntValue: [o_disc_chapter_stp intValue]];
521     }
522
523     [self openDiscInfoChanged: nil];
524 }
525
526 - (void)openDiscInfoChanged:(NSNotification *)o_notification
527 {
528     NSString *o_type;
529     NSString *o_device;
530     NSString *o_videots;
531     NSString *o_mrl_string;
532     int i_title, i_chapter;
533     vlc_bool_t b_menus;
534
535     o_type = [[o_disc_type selectedCell] title];
536     o_device = [o_disc_device stringValue];
537     i_title = [o_disc_title intValue];
538     i_chapter = [o_disc_chapter intValue];
539     o_videots = [o_disc_videots_folder stringValue];
540     b_menus = [o_disc_dvd_menus state];
541
542     if ( [o_type isEqualToString: _NS("VCD")] )
543     {
544         if ( [o_device isEqualToString:
545                 [NSString stringWithFormat: _NS("No %@s found"), o_type]] )
546             o_device = @"";
547         o_mrl_string = [NSString stringWithFormat: @"vcd://%@@%i,%i",
548                         o_device, i_title, i_chapter]; 
549     }
550     else if ( [o_type isEqualToString: _NS("DVD")] )
551     {
552         if ( [o_device isEqualToString:
553                 [NSString stringWithFormat: _NS("No %@s found"), o_type]] )
554             o_device = @"";
555         if ( b_menus )
556             o_mrl_string = [NSString stringWithFormat: @"dvdplay://%@",
557                             o_device]; 
558         else
559             o_mrl_string = [NSString stringWithFormat: @"dvdold://%@@%i,%i",
560                             o_device, i_title, i_chapter]; 
561     }
562     else /* VIDEO_TS folder */
563     {
564         if ( b_menus )
565             o_mrl_string = [NSString stringWithFormat: @"dvdplay://%@",
566                             o_videots]; 
567         else
568             o_mrl_string = [NSString stringWithFormat: @"dvdread://%@@%i,%i",
569                             o_videots, i_title, i_chapter]; 
570     }
571
572     [o_mrl setStringValue: o_mrl_string]; 
573 }
574
575 - (IBAction)openDiscMenusChanged:(id)sender
576 {
577     [self openDiscInfoChanged: nil];
578     [self openDiscTypeChanged: nil];
579 }
580
581 - (IBAction)openVTSBrowse:(id)sender
582 {
583     NSOpenPanel *o_open_panel = [NSOpenPanel openPanel];
584
585     [o_open_panel setAllowsMultipleSelection: NO];
586     [o_open_panel setCanChooseFiles: NO];
587     [o_open_panel setCanChooseDirectories: YES];
588     [o_open_panel setTitle: _NS("Open VIDEO_TS Directory")];
589     [o_open_panel setPrompt: _NS("Open")];
590
591     if( [o_open_panel runModalForDirectory: nil
592             file: nil types: nil] == NSOKButton )
593     {
594         NSString *o_dirname = [[o_open_panel filenames] objectAtIndex: 0];
595         [o_disc_videots_folder setStringValue: o_dirname];
596         [self openDiscInfoChanged: nil];
597     }
598 }
599
600 - (IBAction)openNetModeChanged:(id)sender
601 {
602     NSString *o_mode;
603     BOOL b_udp = FALSE;
604     BOOL b_udpm = FALSE;
605     BOOL b_cs = FALSE;
606     BOOL b_http = FALSE;
607
608     o_mode = [[o_net_mode selectedCell] title];
609
610     if( [o_mode isEqualToString: _NS("UDP/RTP")] ) b_udp = TRUE;   
611     else if( [o_mode isEqualToString: _NS("UDP/RTP Multicast")] ) b_udpm = TRUE;
612     else if( [o_mode isEqualToString: _NS("Channel server")] ) b_cs = TRUE;
613     else if( [o_mode isEqualToString: _NS("HTTP/FTP/MMS")] ) b_http = TRUE;
614
615     [o_net_udp_port setEnabled: b_udp];
616     [o_net_udp_port_stp setEnabled: b_udp];
617     [o_net_udpm_addr setEnabled: b_udpm];
618     [o_net_udpm_port setEnabled: b_udpm];
619     [o_net_udpm_port_stp setEnabled: b_udpm];
620     [o_net_cs_addr setEnabled: b_cs];
621     [o_net_cs_port setEnabled: b_cs]; 
622     [o_net_cs_port_stp setEnabled: b_cs]; 
623     [o_net_http_url setEnabled: b_http];
624
625     [self openNetInfoChanged: nil];
626 }
627
628 - (IBAction)openNetStepperChanged:(id)sender
629 {
630     int i_tag = [sender tag];
631
632     if( i_tag == 0 )
633     {
634         [o_net_udp_port setIntValue: [o_net_udp_port_stp intValue]];
635     }
636     else if( i_tag == 1 )
637     {
638         [o_net_udpm_port setIntValue: [o_net_udpm_port_stp intValue]];
639     }
640     else if( i_tag == 2 )
641     {
642         [o_net_cs_port setIntValue: [o_net_cs_port_stp intValue]];
643     }
644
645     [self openNetInfoChanged: nil];
646 }
647
648 - (void)openNetInfoChanged:(NSNotification *)o_notification
649 {
650     NSString *o_mode;
651     vlc_bool_t b_channel;
652     NSString *o_mrl_string = [NSString string];
653     intf_thread_t * p_intf = [NSApp getIntf];
654
655     o_mode = [[o_net_mode selectedCell] title];
656
657     b_channel = (vlc_bool_t)[o_mode isEqualToString: _NS("Channel server")]; 
658     config_PutInt( p_intf, "network-channel", b_channel );
659
660     if( [o_mode isEqualToString: _NS("UDP/RTP")] )
661     {
662         int i_port = [o_net_udp_port intValue];
663
664         o_mrl_string = [NSString stringWithString: @"udp://"]; 
665
666         if( i_port != config_GetInt( p_intf, "server-port" ) )
667         {
668             o_mrl_string = 
669                 [o_mrl_string stringByAppendingFormat: @"@:%i", i_port]; 
670         } 
671     }
672     else if( [o_mode isEqualToString: _NS("UDP/RTP Multicast")] ) 
673     {
674         NSString *o_addr = [o_net_udpm_addr stringValue];
675         int i_port = [o_net_udpm_port intValue];
676
677         o_mrl_string = [NSString stringWithFormat: @"udp://@%@", o_addr]; 
678
679         if( i_port != config_GetInt( p_intf, "server-port" ) )
680         {
681             o_mrl_string = 
682                 [o_mrl_string stringByAppendingFormat: @":%i", i_port]; 
683         } 
684     }
685     else if( [o_mode isEqualToString: _NS("Channel server")] )
686     {
687         NSString *o_addr = [o_net_cs_addr stringValue];
688         int i_port = [o_net_cs_port intValue];
689
690         if( p_intf->p_vlc->p_channel == NULL )
691         {
692             network_ChannelCreate( p_intf );
693         } 
694
695         config_PutPsz( p_intf, "channel-server", [o_addr lossyCString] ); 
696         if( i_port < 65536 )
697         {
698             config_PutInt( p_intf, "channel-port", i_port );
699         }
700
701         /* FIXME: we should use a playlist server instead */
702         o_mrl_string = [NSString stringWithString: @"udp://"];
703     }
704     else if( [o_mode isEqualToString: _NS("HTTP/FTP/MMS")] )
705     {
706         NSString *o_url = [o_net_http_url stringValue];
707
708         if ( ![o_url hasPrefix:@"http:"] && ![o_url hasPrefix:@"ftp:"]
709               && ![o_url hasPrefix:@"mms"] )
710             o_mrl_string = [NSString stringWithFormat: @"http://%@", o_url];
711         else
712             o_mrl_string = o_url;
713     }
714
715     [o_mrl setStringValue: o_mrl_string];
716 }
717
718 - (IBAction)soutChanged:(id)sender;
719 {
720     [self soutModeChanged: nil];
721
722     if ( [o_sout_cbox state] )
723     {
724         NSPoint s_point;
725         s_point.x = 0;
726         s_point.y = 0;
727         [[o_panel contentView] setBoundsOrigin: s_point];
728         [[o_panel contentView] setNeedsDisplay: YES];
729
730         NSRect s_rect = [o_panel frame];
731         s_rect.size.height = OPEN_PANEL_FULL_HEIGHT + WINDOW_TITLE_HEIGHT;
732         s_rect.origin.y -= OPEN_PANEL_FULL_HEIGHT - OPEN_PANEL_SHORT_HEIGHT;
733         [o_panel setFrame: s_rect display: YES animate: NO];
734     }
735     else
736     {
737         NSPoint s_point;
738         s_point.x = 0;
739         s_point.y = OPEN_PANEL_FULL_HEIGHT - OPEN_PANEL_SHORT_HEIGHT;
740         [[o_panel contentView] setBoundsOrigin: s_point];
741         [[o_panel contentView] setNeedsDisplay: YES];
742
743         NSRect s_rect = [o_panel frame];
744         s_rect.size.height = OPEN_PANEL_SHORT_HEIGHT + WINDOW_TITLE_HEIGHT;
745         s_rect.origin.y += OPEN_PANEL_FULL_HEIGHT - OPEN_PANEL_SHORT_HEIGHT;
746         [o_panel setFrame: s_rect display: YES animate:NO];
747     }
748 }
749
750 - (IBAction)soutFileBrowse:(id)sender
751 {
752     NSSavePanel *o_save_panel = [NSSavePanel savePanel];
753     NSString *o_mux_string;
754     if ( [[[o_sout_mux selectedCell] title] isEqualToString: _NS("PS")] )
755         o_mux_string = @"vob";
756     else
757         o_mux_string = @"ts";
758
759     NSString * o_name = [NSString stringWithFormat: @"vlc-output.%@",
760                          o_mux_string];
761
762     [o_save_panel setTitle: _NS("Save File")];
763     [o_save_panel setPrompt: _NS("Save")];
764
765     if( [o_save_panel runModalForDirectory: nil
766             file: o_name] == NSOKButton )
767     {
768         NSString *o_filename = [o_save_panel filename];
769         [o_sout_file_path setStringValue: o_filename];
770         [self soutInfoChanged: nil];
771     }
772 }
773
774 - (void)soutModeChanged:(NSNotification *)o_notification
775 {
776     NSString *o_mode;
777     BOOL b_file = FALSE;
778     BOOL b_net = FALSE;
779
780     o_mode = [[o_sout_access selectedCell] title];
781
782     if( [o_mode isEqualToString: _NS("File")] ) b_file = TRUE;   
783     else if( [o_mode isEqualToString: _NS("UDP")] ) b_net = TRUE;
784     else if( [o_mode isEqualToString: _NS("RTP")] ) b_net = TRUE;
785
786     [o_sout_file_path setEnabled: b_file];
787     [o_sout_file_btn_browse setEnabled: b_file];
788     [o_sout_udp_addr setEnabled: b_net];
789     [o_sout_udp_port setEnabled: b_net];
790     [o_sout_udp_port_stp setEnabled: b_net];
791     [[o_sout_mux cellAtRow:0 column: 0] setEnabled: !b_net];
792     [[o_sout_mux cellAtRow:0 column: 1] setEnabled: !b_net];
793
794     if ( b_net )
795     {
796         [[o_sout_mux cellAtRow: 0 column:2] setState: YES];
797     }
798
799     [self soutInfoChanged: nil];
800 }
801
802 - (void)soutInfoChanged:(NSNotification *)o_notification
803 {
804     NSString *o_mode;
805     NSString *o_mux;
806     NSString *o_mrl_string;
807     NSString *o_mux_string;
808
809     o_mode = [[o_sout_access selectedCell] title];
810     o_mux = [[o_sout_mux selectedCell] title];
811
812     if ( [o_mux isEqualToString: _NS("AVI")] ) o_mux_string = @"avi";
813     else if ( [o_mux isEqualToString: _NS("PS")] ) o_mux_string = @"ps";
814     else o_mux_string = @"ts";
815
816     if ( [o_mode isEqualToString: _NS("File")] )
817     {
818         o_mrl_string = [NSString stringWithFormat: @"file/%@://%@",
819                         o_mux_string, [o_sout_file_path stringValue]];
820     }
821     else if ( [o_mode isEqualToString: _NS("UDP")] )
822     {
823         o_mrl_string = [NSString stringWithFormat: @"udp/%@://%@:%i",
824                         o_mux_string, [o_sout_udp_addr stringValue],
825                         [o_sout_udp_port intValue]];
826     }
827     else
828     {
829         o_mrl_string = [NSString stringWithFormat: @"rtp/%@://%@:%i",
830                         o_mux_string, [o_sout_udp_addr stringValue],
831                         [o_sout_udp_port intValue]];
832     }
833
834
835     [o_sout_mrl setStringValue: o_mrl_string];
836 }
837
838 - (IBAction)soutStepperChanged:(id)sender
839 {
840     [o_sout_udp_port setIntValue: [o_net_udp_port_stp intValue]];
841
842     [self soutInfoChanged: nil];
843 }
844
845 - (IBAction)openFile:(id)sender
846 {
847     NSOpenPanel *o_open_panel = [NSOpenPanel openPanel];
848     
849     [o_open_panel setAllowsMultipleSelection: YES];
850     [o_open_panel setTitle: _NS("Open File")];
851     [o_open_panel setPrompt: _NS("Open")];
852     
853     if( [o_open_panel runModalForDirectory: nil
854             file: nil types: nil] == NSOKButton )
855     {
856         intf_thread_t * p_intf = [NSApp getIntf];
857         config_PutPsz( p_intf, "sout", NULL );
858         [o_playlist appendArray: [o_open_panel filenames] atPos: -1 enqueue:NO];
859     }
860 }
861
862 - (IBAction)panelCancel:(id)sender
863 {
864     [NSApp stopModalWithCode: 0];
865 }
866
867 - (IBAction)panelOk:(id)sender
868 {
869     if( [[o_mrl stringValue] length] )
870     {
871         [NSApp stopModalWithCode: 1];
872     }
873     else
874     {
875         NSBeep();
876     }
877 }
878
879 @end