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