]> git.sesse.net Git - vlc/blob - modules/gui/macosx/open.m
macosx: trust the user that s/he knows what s/he's doing when opening a VIDEO_TS...
[vlc] / modules / gui / macosx / open.m
1 /*****************************************************************************
2  * open.m: Open dialogues for VLC's MacOS X port
3  *****************************************************************************
4  * Copyright (C) 2002-2012 VLC authors and VideoLAN
5  * $Id$
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  *          Benjamin Pracht <bigben at videolan dot org>
11  *          Felix Paul Kühne <fkuehne at videolan dot org>
12  *
13  * This program is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 2 of the License, or
16  * (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
26  *****************************************************************************/
27
28 /*****************************************************************************
29  * Preamble
30  *****************************************************************************/
31 #import <stdlib.h>                                      /* malloc(), free() */
32 #import <sys/param.h>                                    /* for MAXPATHLEN */
33
34 #import "CompatibilityFixes.h"
35
36 #import <paths.h>
37 #import <IOKit/IOBSD.h>
38 #import <IOKit/storage/IOMedia.h>
39 #import <IOKit/storage/IOCDMedia.h>
40 #import <IOKit/storage/IODVDMedia.h>
41 #import <IOKit/storage/IOBDMedia.h>
42 #import <Cocoa/Cocoa.h>
43 #import <QTKit/QTKit.h>
44
45 #import "intf.h"
46 #import "playlist.h"
47 #import "open.h"
48 #import "output.h"
49 #import "eyetv.h"
50
51 #import <vlc_url.h>
52
53 NSArray *qtkvideoDevices;
54 NSArray *qtkaudioDevices;
55 #define setEyeTVUnconnected \
56 [o_capture_lbl setStringValue: _NS("No device is selected")]; \
57 [o_capture_long_lbl setStringValue: _NS("No device is selected.\n\nChoose available device in above pull-down menu\n.")]; \
58 [o_capture_lbl displayIfNeeded]; \
59 [o_capture_long_lbl displayIfNeeded]; \
60 [self showCaptureView: o_capture_label_view]
61
62 struct display_info_t
63 {
64     CGRect rect;
65     CGDirectDisplayID id;
66 };
67
68 /*****************************************************************************
69  * VLCOpen implementation
70  *****************************************************************************/
71 @implementation VLCOpen
72
73 static VLCOpen *_o_sharedMainInstance = nil;
74
75 + (VLCOpen *)sharedInstance
76 {
77     return _o_sharedMainInstance ? _o_sharedMainInstance : [[self alloc] init];
78 }
79
80 - (id)init
81 {
82     if( _o_sharedMainInstance) {
83         [self dealloc];
84     } else {
85         _o_sharedMainInstance = [super init];
86         p_intf = VLCIntf;
87     }
88
89     return _o_sharedMainInstance;
90 }
91
92 - (void)dealloc
93 {
94     [o_specialMediaFolders release];
95     [o_opticalDevices release];
96     if( o_file_slave_path )
97         [o_file_slave_path release];
98     [o_mrl release];
99     if (o_sub_path)
100         [o_sub_path release];
101     [o_currentOpticalMediaIconView release];
102     [o_currentOpticalMediaView release];
103     int i;
104     for( i = 0; i < [o_displayInfos count]; i ++ )
105     {
106         NSValue *v = [o_displayInfos objectAtIndex:i];
107         free( [v pointerValue] );
108     }
109     [o_displayInfos removeAllObjects];
110     [o_displayInfos release];
111
112     [super dealloc];
113 }
114
115 - (void)awakeFromNib
116 {
117     if (OSX_LION)
118         [o_panel setCollectionBehavior: NSWindowCollectionBehaviorFullScreenAuxiliary];
119
120     [o_panel setTitle: _NS("Open Source")];
121     [o_mrl_lbl setStringValue: _NS("Media Resource Locator (MRL)")];
122
123     [o_btn_ok setTitle: _NS("Open")];
124     [o_btn_cancel setTitle: _NS("Cancel")];
125
126     [[o_tabview tabViewItemAtIndex: 0] setLabel: _NS("File")];
127     [[o_tabview tabViewItemAtIndex: 1] setLabel: _NS("Disc")];
128     [[o_tabview tabViewItemAtIndex: 2] setLabel: _NS("Network")];
129     [[o_tabview tabViewItemAtIndex: 3] setLabel: _NS("Capture")];
130
131     [o_file_name setStringValue: @""];
132     [o_file_name_stub setStringValue: _NS("Choose a file")];
133     [o_file_icon_well setImage: [NSImage imageNamed:@"generic"]];
134     [o_file_btn_browse setTitle: _NS("Browse...")];
135     [o_file_stream setTitle: _NS("Treat as a pipe rather than as a file")];
136     [o_file_stream setHidden: NO];
137     [o_file_slave_ckbox setTitle: _NS("Play another media synchronously")];
138     [o_file_slave_select_btn setTitle: _NS("Choose...")];
139     [o_file_slave_filename_lbl setStringValue: @""];
140     [o_file_slave_icon_well setImage: NULL];
141     [o_file_subtitles_filename_lbl setStringValue: @""];
142     [o_file_subtitles_icon_well setImage: NULL];
143
144     [o_disc_selector_pop removeAllItems];
145     [o_disc_selector_pop setHidden: NO];
146     NSString *o_videots = _NS("Open VIDEO_TS folder");
147     NSString *o_bdmv = _NS("Open BDMV folder");
148     [o_disc_nodisc_lbl setStringValue: _NS("Insert Disc")];
149     [o_disc_nodisc_videots_btn setTitle: o_videots];
150     [o_disc_nodisc_bdmv_btn setTitle: o_bdmv];
151     [o_disc_audiocd_lbl setStringValue: _NS("Audio CD")];
152     [o_disc_audiocd_trackcount_lbl setStringValue: @""];
153     [o_disc_audiocd_videots_btn setTitle: o_videots];
154     [o_disc_audiocd_bdmv_btn setTitle: o_bdmv];
155     [o_disc_dvd_lbl setStringValue: @""];
156     [o_disc_dvd_disablemenus_btn setTitle: _NS("Disable DVD menus")];
157     [o_disc_dvd_videots_btn setTitle: o_videots];
158     [o_disc_dvd_bdmv_btn setTitle: o_bdmv];
159     [o_disc_dvdwomenus_lbl setStringValue: @""];
160     [o_disc_dvdwomenus_enablemenus_btn setTitle: _NS("Enable DVD menus")];
161     [o_disc_dvdwomenus_videots_btn setTitle: o_videots];
162     [o_disc_dvdwomenus_bdmv_btn setTitle: o_bdmv];
163     [o_disc_dvdwomenus_title_lbl setStringValue: _NS("Title")];
164     [o_disc_dvdwomenus_chapter_lbl setStringValue: _NS("Chapter")];
165     [o_disc_vcd_title_lbl setStringValue: _NS("Title")];
166     [o_disc_vcd_chapter_lbl setStringValue: _NS("Chapter")];
167     [o_disc_vcd_videots_btn setTitle: o_videots];
168     [o_disc_vcd_bdmv_btn setTitle: o_bdmv];
169     [o_disc_bd_videots_btn setTitle: o_videots];
170     [o_disc_bd_bdmv_btn setTitle: o_bdmv];
171
172     [o_net_udp_port_lbl setStringValue: _NS("Port")];
173     [o_net_udpm_addr_lbl setStringValue: _NS("IP Address")];
174     [o_net_udpm_port_lbl setStringValue: _NS("Port")];
175     [o_net_http_url_lbl setStringValue: _NS("URL")];
176     [o_net_help_lbl setStringValue: _NS("To Open a usual network stream (HTTP, RTSP, RTMP, MMS, FTP, etc.), just enter the URL in the field above. If you want to open a RTP or UDP stream, press the button below.")];
177     [o_net_help_udp_lbl setStringValue: _NS("If you want to open a multicast stream, enter the respective IP address given by the stream provider. In unicast mode, VLC will use your machine's IP automatically.\n\nTo open a stream using a different protocol, just press Cancel to close this sheet.")];
178     [o_net_udp_cancel_btn setTitle: _NS("Cancel")];
179     [o_net_udp_ok_btn setTitle: _NS("Open")];
180     [o_net_openUDP_btn setTitle: _NS("Open RTP/UDP Stream")];
181     [o_net_udp_mode_lbl setStringValue: _NS("Mode")];
182     [o_net_udp_protocol_lbl setStringValue: _NS("Protocol")];
183     [o_net_udp_address_lbl setStringValue: _NS("Address")];
184
185     [[o_net_mode cellAtRow:0 column:0] setTitle: _NS("Unicast")];
186     [[o_net_mode cellAtRow:1 column:0] setTitle: _NS("Multicast")];
187
188     [o_net_udp_port setIntValue: config_GetInt( p_intf, "server-port" )];
189     [o_net_udp_port_stp setIntValue: config_GetInt( p_intf, "server-port" )];
190
191     [o_eyetv_chn_bgbar setUsesThreadedAnimation: YES];
192
193     [o_capture_mode_pop removeAllItems];
194     [o_capture_mode_pop addItemWithTitle: _NS("Video Device")];
195     [o_capture_mode_pop addItemWithTitle: _NS("Audio Device")];
196     [o_capture_mode_pop addItemWithTitle: _NS("Screen")];
197     [o_capture_mode_pop addItemWithTitle: @"EyeTV"];
198     [o_screen_long_lbl setStringValue: _NS("This input allows you to save, stream or display your current screen contents.")];
199     [o_screen_fps_lbl setStringValue: _NS("Frames per Second:")];
200     [o_screen_screen_lbl setStringValue: _NS("Screen:")];
201     [o_screen_left_lbl setStringValue: _NS("Subscreen left:")];
202     [o_screen_top_lbl setStringValue: _NS("Subscreen top:")];
203     [o_screen_width_lbl setStringValue: _NS("Subscreen width:")];
204     [o_screen_height_lbl setStringValue: _NS("Subscreen height:")];
205     [o_screen_follow_mouse_ckb setTitle: _NS("Follow the mouse")];
206     [o_eyetv_currentChannel_lbl setStringValue: _NS("Current channel:")];
207     [o_eyetv_previousProgram_btn setTitle: _NS("Previous Channel")];
208     [o_eyetv_nextProgram_btn setTitle: _NS("Next Channel")];
209     [o_eyetv_chn_status_txt setStringValue: _NS("Retrieving Channel Info...")];
210     [o_eyetv_noInstance_lbl setStringValue: _NS("EyeTV is not launched")];
211     [o_eyetv_noInstanceLong_lbl setStringValue: _NS("VLC could not connect to EyeTV.\nMake sure that you installed VLC's EyeTV plugin.")];
212     [o_eyetv_launchEyeTV_btn setTitle: _NS("Launch EyeTV now")];
213     [o_eyetv_getPlugin_btn setTitle: _NS("Download Plugin")];
214     [o_qtk_long_lbl setStringValue: _NS("This input allows you to process input signals from QuickTime-compatible video devices.\nSimultaneous live Audio input is not supported.")];
215     [o_capture_width_lbl setStringValue: _NS("Image width:")];
216     [o_capture_height_lbl setStringValue: _NS("Image height:")];
217
218     [self qtkvideoDevices];
219     [o_qtk_device_pop removeAllItems];
220     msg_Dbg( VLCIntf, "Found %lu video capture devices", [qtkvideoDevices count] );
221
222     if([qtkvideoDevices count] >= 1)
223     {
224         if (!qtk_currdevice_uid) {
225             qtk_currdevice_uid = [[[QTCaptureDevice defaultInputDeviceWithMediaType: QTMediaTypeVideo] uniqueID]
226                                                                 stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
227         }
228         NSUInteger deviceCount = [qtkvideoDevices count];
229         for(int ivideo = 0; ivideo < deviceCount; ivideo++){
230             QTCaptureDevice *qtk_device;
231             qtk_device = [qtkvideoDevices objectAtIndex:ivideo];
232             [o_qtk_device_pop addItemWithTitle: [qtk_device localizedDisplayName]];
233             if([[[qtk_device uniqueID]stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] isEqualToString:qtk_currdevice_uid]){
234                 [o_qtk_device_pop selectItemAtIndex:ivideo];
235             }
236         }
237     }
238     else
239     {
240         [o_qtk_device_pop addItemWithTitle: _NS("None")];
241         [qtk_currdevice_uid release];
242     }
243
244     [self qtkaudioDevices];
245     [o_qtkaudio_device_pop removeAllItems];
246     msg_Dbg( VLCIntf, "Found %lu audio capture devices", [qtkaudioDevices count] );
247
248     if([qtkaudioDevices count] >= 1)
249     {
250         if (!qtkaudio_currdevice_uid) {
251             qtkaudio_currdevice_uid = [[[QTCaptureDevice defaultInputDeviceWithMediaType: QTMediaTypeSound] uniqueID]
252                                   stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
253         }
254         NSUInteger deviceCount = [qtkaudioDevices count];
255         for(int iaudio = 0; iaudio < deviceCount; iaudio++){
256             QTCaptureDevice *qtkaudio_device;
257             qtkaudio_device = [qtkaudioDevices objectAtIndex:iaudio];
258             [o_qtkaudio_device_pop addItemWithTitle: [qtkaudio_device localizedDisplayName]];
259             if([[[qtkaudio_device uniqueID]stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] isEqualToString:qtkaudio_currdevice_uid]){
260                 [o_qtkaudio_device_pop selectItemAtIndex:iaudio];
261             }
262         }
263     }
264     else
265     {
266         [o_qtkaudio_device_pop addItemWithTitle: _NS("None")];
267         [qtkaudio_currdevice_uid release];
268     }
269
270     [self setSubPanel];
271
272     [[NSNotificationCenter defaultCenter] addObserver: self
273         selector: @selector(openNetInfoChanged:)
274         name: NSControlTextDidChangeNotification
275         object: o_net_udp_port];
276     [[NSNotificationCenter defaultCenter] addObserver: self
277         selector: @selector(openNetInfoChanged:)
278         name: NSControlTextDidChangeNotification
279         object: o_net_udpm_addr];
280     [[NSNotificationCenter defaultCenter] addObserver: self
281         selector: @selector(openNetInfoChanged:)
282         name: NSControlTextDidChangeNotification
283         object: o_net_udpm_port];
284     [[NSNotificationCenter defaultCenter] addObserver: self
285         selector: @selector(openNetInfoChanged:)
286         name: NSControlTextDidChangeNotification
287         object: o_net_http_url];
288
289     [[NSDistributedNotificationCenter defaultCenter] addObserver: self
290                                                         selector: @selector(eyetvChanged:)
291                                                             name: NULL
292                                                           object: @"VLCEyeTVSupport"
293                                               suspensionBehavior: NSNotificationSuspensionBehaviorDeliverImmediately];
294
295     [[NSNotificationCenter defaultCenter] addObserver: self
296                                              selector: @selector(screenFPSfieldChanged:)
297                                                  name: NSControlTextDidChangeNotification
298                                                object: o_screen_fps_fld];
299
300     /* register clicks on text fields */
301     [[NSNotificationCenter defaultCenter] addObserver: self
302                                              selector: @selector(textFieldWasClicked:)
303                                                  name: @"VLCOpenTextFieldWasClicked"
304                                                object: nil];
305
306     /* we want to be notified about removed or added media */
307     o_specialMediaFolders = [[NSMutableArray alloc] init];
308     o_opticalDevices = [[NSMutableArray alloc] init];
309     o_displayInfos = [[NSMutableArray alloc] init];
310     NSWorkspace *sharedWorkspace = [NSWorkspace sharedWorkspace];
311
312     [[sharedWorkspace notificationCenter] addObserver:self selector:@selector(scanOpticalMedia:) name:NSWorkspaceDidMountNotification object:nil];
313     [[sharedWorkspace notificationCenter] addObserver:self selector:@selector(scanOpticalMedia:) name:NSWorkspaceDidUnmountNotification object:nil];
314     [self performSelector:@selector(scanOpticalMedia:) withObject:nil afterDelay:2.0];
315     [self performSelector:@selector(qtkChanged:) withObject:nil afterDelay:2.5];
316     [self performSelector:@selector(qtkAudioChanged:) withObject:nil afterDelay:3.0];
317
318     [self setMRL: @""];
319 }
320
321 - (void)setMRL:(NSString *)newMRL
322 {
323     [o_mrl release];
324     o_mrl = newMRL;
325     [o_mrl retain];
326     [o_mrl_fld setStringValue: newMRL];
327     if ([o_mrl length] > 0)
328         [o_btn_ok setEnabled: YES];
329     else
330         [o_btn_ok setEnabled: NO];
331 }
332
333 - (NSString *)MRL
334 {
335     return o_mrl;
336 }
337
338 - (void)setSubPanel
339 {
340     int i_index;
341     module_config_t * p_item;
342
343     [o_file_sub_ckbox setTitle: _NS("Load subtitles file:")];
344     [o_file_sub_path_lbl setStringValue: _NS("Choose a file")];
345     [o_file_sub_path_lbl setHidden: NO];
346     [o_file_sub_path_fld setStringValue: @""];
347     [o_file_sub_btn_settings setTitle: _NS("Choose...")];
348     [o_file_sub_btn_browse setTitle: _NS("Browse...")];
349     [o_file_sub_override setTitle: _NS("Override parameters")];
350     [o_file_sub_delay_lbl setStringValue: _NS("Delay")];
351     [o_file_sub_delay_stp setEnabled: NO];
352     [o_file_sub_fps_lbl setStringValue: _NS("FPS")];
353     [o_file_sub_fps_stp setEnabled: NO];
354     [o_file_sub_encoding_lbl setStringValue: _NS("Subtitles encoding")];
355     [o_file_sub_encoding_pop removeAllItems];
356     [o_file_sub_size_lbl setStringValue: _NS("Font size")];
357     [o_file_sub_size_pop removeAllItems];
358     [o_file_sub_align_lbl setStringValue: _NS("Subtitles alignment")];
359     [o_file_sub_align_pop removeAllItems];
360     [o_file_sub_ok_btn setStringValue: _NS("OK")];
361     [o_file_sub_font_box setTitle: _NS("Font Properties")];
362     [o_file_sub_file_box setTitle: _NS("Subtitle File")];
363
364     p_item = config_FindConfig( VLC_OBJECT(p_intf), "subsdec-encoding" );
365
366     if( p_item )
367     {
368         for( i_index = 0; p_item->ppsz_list && p_item->ppsz_list[i_index];
369              i_index++ )
370         {
371             [o_file_sub_encoding_pop addItemWithTitle:
372                 [NSString stringWithUTF8String: p_item->ppsz_list[i_index]]];
373         }
374         [o_file_sub_encoding_pop selectItemWithTitle:
375                 [NSString stringWithUTF8String: p_item->value.psz]];
376     }
377
378     p_item = config_FindConfig( VLC_OBJECT(p_intf), "subsdec-align" );
379
380     if ( p_item )
381     {
382         for ( i_index = 0; i_index < p_item->i_list; i_index++ )
383         {
384             [o_file_sub_align_pop addItemWithTitle:
385              _NS(p_item->ppsz_list_text[i_index])];
386         }
387         [o_file_sub_align_pop selectItemAtIndex: p_item->value.i];
388     }
389
390     p_item = config_FindConfig( VLC_OBJECT(p_intf), "freetype-rel-fontsize" );
391
392     if ( p_item )
393     {
394         for ( i_index = 0; i_index < p_item->i_list; i_index++ )
395         {
396             [o_file_sub_size_pop addItemWithTitle: _NS(p_item->ppsz_list_text[i_index])];
397             if ( p_item->value.i == p_item->pi_list[i_index] )
398             {
399                 [o_file_sub_size_pop selectItemAtIndex: i_index];
400             }
401         }
402     }
403 }
404
405 - (void)openTarget:(int)i_type
406 {
407     int i_result;
408
409     b_autoplay = config_GetInt( VLCIntf, "macosx-autoplay" );
410
411     [o_tabview selectTabViewItemAtIndex: i_type];
412     [o_file_sub_ckbox setState: NSOffState];
413
414     i_result = [NSApp runModalForWindow: o_panel];
415     [o_panel close];
416
417     if( i_result )
418     {
419         NSMutableDictionary *o_dic;
420         NSMutableArray *o_options = [NSMutableArray array];
421
422         o_dic = [NSMutableDictionary dictionaryWithObject: [self MRL] forKey: @"ITEM_URL"];
423         if( [o_file_sub_ckbox state] == NSOnState )
424         {
425             module_config_t * p_item;
426
427             [o_options addObject: [NSString stringWithFormat: @"sub-file=%@", o_sub_path]];
428             if( [o_file_sub_override state] == NSOnState )
429             {
430                 [o_options addObject: [NSString stringWithFormat: @"sub-delay=%i", (int)( [o_file_sub_delay intValue] * 10 )]];
431                 [o_options addObject: [NSString stringWithFormat: @"sub-fps=%f", [o_file_sub_fps floatValue]]];
432             }
433             [o_options addObject: [NSString stringWithFormat:
434                     @"subsdec-encoding=%@",
435                     [o_file_sub_encoding_pop titleOfSelectedItem]]];
436             [o_options addObject: [NSString stringWithFormat:
437                     @"subsdec-align=%li",
438                     [o_file_sub_align_pop indexOfSelectedItem]]];
439
440             p_item = config_FindConfig( VLC_OBJECT(p_intf),
441                                             "freetype-rel-fontsize" );
442
443             if ( p_item )
444             {
445                 [o_options addObject: [NSString stringWithFormat:
446                     @"freetype-rel-fontsize=%i",
447                     p_item->pi_list[[o_file_sub_size_pop indexOfSelectedItem]]]];
448             }
449         }
450         if( [o_output_ckbox state] == NSOnState )
451         {
452             NSUInteger count = [[o_sout_options mrl] count];
453             for (NSUInteger i = 0 ; i < count ; i++)
454             {
455                 [o_options addObject: [NSString stringWithString: [[(VLCOutput *)o_sout_options mrl] objectAtIndex: i]]];
456             }
457         }
458         if( [o_file_slave_ckbox state] && o_file_slave_path )
459            [o_options addObject: [NSString stringWithFormat: @"input-slave=%@", o_file_slave_path]];
460         if( [[[o_tabview selectedTabViewItem] label] isEqualToString: _NS("Capture")] )
461         {
462             if( [[[o_capture_mode_pop selectedItem] title] isEqualToString: _NS("Screen")] )
463             {
464                 int selected_index = [o_screen_screen_pop indexOfSelectedItem];
465                 NSValue *v = [o_displayInfos objectAtIndex:selected_index];
466                 struct display_info_t *item = ( struct display_info_t * )[v pointerValue];
467
468                 [o_options addObject: [NSString stringWithFormat: @"screen-fps=%f", [o_screen_fps_fld floatValue]]];
469                 [o_options addObject: [NSString stringWithFormat: @"screen-display-id=%i", item->id]];
470                 [o_options addObject: [NSString stringWithFormat: @"screen-left=%i", [o_screen_left_fld intValue]]];
471                 [o_options addObject: [NSString stringWithFormat: @"screen-top=%i", [o_screen_top_fld intValue]]];
472                 [o_options addObject: [NSString stringWithFormat: @"screen-width=%i", [o_screen_width_fld intValue]]];
473                 [o_options addObject: [NSString stringWithFormat: @"screen-height=%i", [o_screen_height_fld intValue]]];
474                 if( [o_screen_follow_mouse_ckb intValue] == YES )
475                     [o_options addObject: @"screen-follow-mouse"];
476                 else
477                     [o_options addObject: @"no-screen-follow-mouse"];
478             }
479             else if( [[[o_capture_mode_pop selectedItem] title] isEqualToString: _NS("Video Device")] )
480             {
481                 [o_options addObject: [NSString stringWithFormat: @"qtcapture-width=%i", [o_capture_width_fld intValue]]];
482                 [o_options addObject: [NSString stringWithFormat: @"qtcapture-height=%i", [o_capture_height_fld intValue]]];
483             }
484         }
485
486         /* apply the options to our item(s) */
487         [o_dic setObject: (NSArray *)[o_options copy] forKey: @"ITEM_OPTIONS"];
488         if( b_autoplay )
489             [[[VLCMain sharedInstance] playlist] appendArray: [NSArray arrayWithObject: o_dic] atPos: -1 enqueue:NO];
490         else
491             [[[VLCMain sharedInstance] playlist] appendArray: [NSArray arrayWithObject: o_dic] atPos: -1 enqueue:YES];
492     }
493 }
494
495 - (IBAction)screenChanged:(id)sender
496 {
497     int selected_index = [o_screen_screen_pop indexOfSelectedItem];
498     if( selected_index >= [o_displayInfos count] ) return;
499
500     NSValue *v = [o_displayInfos objectAtIndex:selected_index];
501     struct display_info_t *item = ( struct display_info_t * )[v pointerValue];
502
503     [o_screen_left_stp setMaxValue: item->rect.size.width];
504     [o_screen_top_stp setMaxValue: item->rect.size.height];
505     [o_screen_width_stp setMaxValue: item->rect.size.width];
506     [o_screen_height_stp setMaxValue: item->rect.size.height];
507 }
508
509 - (IBAction)qtkChanged:(id)sender
510 {
511     NSInteger i_selectedDevice = [o_qtk_device_pop indexOfSelectedItem];
512     if( [qtkvideoDevices count] >= 1 )
513     {
514         NSValue *sizes = [[[[qtkvideoDevices objectAtIndex:i_selectedDevice] formatDescriptions] objectAtIndex: 0] attributeForKey: QTFormatDescriptionVideoEncodedPixelsSizeAttribute];
515
516         [o_capture_width_fld setIntValue: [sizes sizeValue].width];
517         [o_capture_height_fld setIntValue: [sizes sizeValue].height];
518         [o_capture_width_stp setIntValue: [o_capture_width_fld intValue]];
519         [o_capture_height_stp setIntValue: [o_capture_height_fld intValue]];
520         qtk_currdevice_uid = [[(QTCaptureDevice *)[qtkvideoDevices objectAtIndex:i_selectedDevice] uniqueID] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
521         [self setMRL:[NSString stringWithFormat:@"qtcapture://%@", qtk_currdevice_uid]];
522     }
523 }
524
525 - (IBAction)qtkAudioChanged:(id)sender
526 {
527     NSInteger i_selectedDevice = [o_qtkaudio_device_pop indexOfSelectedItem];
528     if( [qtkaudioDevices count] >= 1 )
529     {
530         qtkaudio_currdevice_uid = [[(QTCaptureDevice *)[qtkaudioDevices objectAtIndex:i_selectedDevice] uniqueID] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
531         [self setMRL:[NSString stringWithFormat:@"qtsound://%@", qtkaudio_currdevice_uid]];
532     }
533 }
534
535 - (void)tabView:(NSTabView *)o_tv didSelectTabViewItem:(NSTabViewItem *)o_tvi
536 {
537     NSString *o_label = [o_tvi label];
538
539     if( [o_label isEqualToString: _NS("File")] )
540     {
541         [self openFilePathChanged: nil];
542     }
543     else if( [o_label isEqualToString: _NS("Disc")] )
544     {
545         [self scanOpticalMedia: nil];
546     }
547     else if( [o_label isEqualToString: _NS("Network")] )
548     {
549         [self openNetInfoChanged: nil];
550     }
551     else if( [o_label isEqualToString: _NS("Capture")] )
552     {
553         [self openCaptureModeChanged: nil];
554     }
555 }
556
557 - (IBAction)expandMRLfieldAction:(id)sender
558 {
559     NSRect o_win_rect, o_view_rect;
560     o_win_rect = [o_panel frame];
561     o_view_rect = [o_mrl_view frame];
562
563     if( [o_mrl_btn state] == NSOffState )
564     {
565         /* we need to collaps, restore the panel size */
566         o_win_rect.size.height = o_win_rect.size.height - o_view_rect.size.height;
567         o_win_rect.origin.y = ( o_win_rect.origin.y + o_view_rect.size.height ) - o_view_rect.size.height;
568
569         /* remove the MRL view */
570         [o_mrl_view removeFromSuperview];
571     } else {
572         /* we need to expand */
573         [o_mrl_view setFrame: NSMakeRect( 0,
574                                          [o_mrl_btn frame].origin.y,
575                                          o_view_rect.size.width,
576                                          o_view_rect.size.height )];
577         [o_mrl_view setNeedsDisplay: NO];
578         [o_mrl_view setAutoresizesSubviews: YES];
579
580         /* enlarge panel size for MRL view */
581         o_win_rect.size.height = o_win_rect.size.height + o_view_rect.size.height;
582     }
583
584     [[o_panel animator] setFrame: o_win_rect display:YES];
585 //    [o_panel displayIfNeeded];
586     if( [o_mrl_btn state] == NSOnState )
587         [[o_panel contentView] addSubview: o_mrl_view];
588 }
589
590 - (IBAction)inputSlaveAction:(id)sender
591 {
592     if( sender == o_file_slave_ckbox )
593         [o_file_slave_select_btn setEnabled: [o_file_slave_ckbox state]];
594     else
595     {
596         NSOpenPanel *o_open_panel;
597         o_open_panel = [NSOpenPanel openPanel];
598         [o_open_panel setCanChooseFiles: YES];
599         [o_open_panel setCanChooseDirectories: NO];
600         if( [o_open_panel runModal] == NSOKButton )
601         {
602             if( o_file_slave_path )
603                 [o_file_slave_path release];
604             o_file_slave_path = [[[o_open_panel URLs] objectAtIndex: 0] path];
605             [o_file_slave_path retain];
606         }
607     }
608     if( o_file_slave_path && [o_file_slave_ckbox state] == NSOnState)
609     {
610         [o_file_slave_filename_lbl setStringValue: [[NSFileManager defaultManager] displayNameAtPath:o_file_slave_path]];
611         [o_file_slave_icon_well setImage: [[NSWorkspace sharedWorkspace] iconForFile: o_file_slave_path]];
612     }
613     else
614     {
615         [o_file_slave_filename_lbl setStringValue: @""];
616         [o_file_slave_icon_well setImage: NULL];
617     }
618 }
619
620 - (void)openFileGeneric
621 {
622     [self openFilePathChanged: nil];
623     [self openTarget: 0];
624 }
625
626 - (void)openDisc
627 {
628     [o_specialMediaFolders removeAllObjects];
629     [o_opticalDevices removeAllObjects];
630     [self scanOpticalMedia: nil];
631     [self openTarget: 1];
632 }
633
634 - (void)openNet
635 {
636     [self openNetInfoChanged: nil];
637     [self openTarget: 2];
638 }
639
640 - (void)openCapture
641 {
642     [self openCaptureModeChanged: nil];
643     [self openTarget: 3];
644 }
645
646 - (void)openFilePathChanged:(NSNotification *)o_notification
647 {
648     if ( o_file_path && [o_file_path length] > 0 )
649     {
650         bool b_stream = [o_file_stream state];
651         BOOL b_dir = NO;
652
653         [[NSFileManager defaultManager] fileExistsAtPath:o_file_path isDirectory:&b_dir];
654
655         char *psz_uri = make_URI([o_file_path UTF8String], "file");
656         if( !psz_uri ) return;
657
658         NSMutableString *o_mrl_string = [NSMutableString stringWithUTF8String: psz_uri ];
659         NSRange offile = [o_mrl_string rangeOfString:@"file"];
660         free( psz_uri );
661
662         if( b_dir )
663             [o_mrl_string replaceCharactersInRange:offile withString: @"directory"];
664         else if( b_stream )
665             [o_mrl_string replaceCharactersInRange:offile withString: @"stream"];
666
667         [o_file_name setStringValue: [[NSFileManager defaultManager] displayNameAtPath:o_file_path]];
668         [o_file_name_stub setHidden: YES];
669         [o_file_stream setHidden: NO];
670         [o_file_icon_well setImage: [[NSWorkspace sharedWorkspace] iconForFile: o_file_path]];
671         [o_file_icon_well setHidden: NO];
672         [self setMRL: o_mrl_string];
673     }
674     else
675     {
676         [o_file_name setStringValue: @""];
677         [o_file_name_stub setHidden: NO];
678         [o_file_stream setHidden: YES];
679         [o_file_icon_well setImage: [NSImage imageNamed:@"generic"]];
680         [self setMRL: @""];
681     }
682 }
683
684 - (IBAction)openFileBrowse:(id)sender
685 {
686     NSOpenPanel *o_open_panel = [NSOpenPanel openPanel];
687
688     [o_open_panel setAllowsMultipleSelection: NO];
689     [o_open_panel setCanChooseDirectories: YES];
690     [o_open_panel setTitle: _NS("Open File")];
691     [o_open_panel setPrompt: _NS("Open")];
692
693     [o_open_panel beginSheetForDirectory:nil
694         file:nil
695         types:nil
696         modalForWindow:[sender window]
697         modalDelegate: self
698         didEndSelector: @selector(pathChosenInPanel:
699                         withReturn:
700                         contextInfo:)
701         contextInfo: nil];
702 }
703
704 - (void)pathChosenInPanel: (NSOpenPanel *) sheet withReturn:(int)returnCode contextInfo:(void  *)contextInfo
705 {
706     if (returnCode == NSFileHandlingPanelOKButton)
707     {
708         if( o_file_path )
709             [o_file_path release];
710         o_file_path = [[[sheet URLs] objectAtIndex: 0] path];
711         [o_file_path retain];
712         [self openFilePathChanged: nil];
713     }
714 }
715
716 - (IBAction)openFileStreamChanged:(id)sender
717 {
718     [self openFilePathChanged: nil];
719 }
720
721 - (void)showOpticalMediaView: theView withIcon:(NSImage *)icon
722 {
723     NSRect o_view_rect;
724     o_view_rect = [theView frame];
725     [theView setFrame: NSMakeRect( 233, 0, o_view_rect.size.width, o_view_rect.size.height)];
726     [theView setAutoresizesSubviews: YES];
727     if (o_currentOpticalMediaView)
728     {
729         [[[[o_tabview tabViewItemAtIndex: [o_tabview indexOfTabViewItemWithIdentifier:@"optical"]] view] animator] replaceSubview: o_currentOpticalMediaView with: theView];
730         [o_currentOpticalMediaView release];
731     }
732     else
733         [[[[o_tabview tabViewItemAtIndex: [o_tabview indexOfTabViewItemWithIdentifier:@"optical"]] view] animator] addSubview: theView];
734     o_currentOpticalMediaView = theView;
735     [o_currentOpticalMediaView retain];
736
737     NSImageView *imageView;
738     imageView = [[NSImageView alloc] init];
739     [imageView setFrame: NSMakeRect( 53, 61, 128, 128 )];
740     [icon setSize: NSMakeSize(128,128)];
741     [imageView setImage: icon];
742     if (o_currentOpticalMediaIconView)
743     {
744         [[[[o_tabview tabViewItemAtIndex: [o_tabview indexOfTabViewItemWithIdentifier:@"optical"]] view] animator] replaceSubview: o_currentOpticalMediaIconView with: imageView];
745         [o_currentOpticalMediaIconView release];
746     }
747     else
748          [[[[o_tabview tabViewItemAtIndex: [o_tabview indexOfTabViewItemWithIdentifier:@"optical"]] view] animator] addSubview: imageView];
749     o_currentOpticalMediaIconView = imageView;
750     [o_currentOpticalMediaIconView retain];
751     [o_currentOpticalMediaView setNeedsDisplay: YES];
752     [o_currentOpticalMediaIconView setNeedsDisplay: YES];
753     [[[o_tabview tabViewItemAtIndex: [o_tabview indexOfTabViewItemWithIdentifier:@"optical"]] view] setNeedsDisplay: YES];
754     [[[o_tabview tabViewItemAtIndex: [o_tabview indexOfTabViewItemWithIdentifier:@"optical"]] view] displayIfNeeded];
755 }
756
757 - (NSString *) getBSDNodeFromMountPath:(NSString *)mountPath
758 {
759     OSStatus err;
760     FSRef ref;
761     FSVolumeRefNum actualVolume;
762     err = FSPathMakeRef ( (const UInt8 *) [mountPath fileSystemRepresentation], &ref, NULL );
763
764     // get a FSVolumeRefNum from mountPath
765     if ( noErr == err ) {
766         FSCatalogInfo   catalogInfo;
767         err = FSGetCatalogInfo ( &ref,
768                                 kFSCatInfoVolume,
769                                 &catalogInfo,
770                                 NULL,
771                                 NULL,
772                                 NULL
773                                 );
774         if ( noErr == err ) {
775             actualVolume = catalogInfo.volume;
776         }
777     }
778
779     GetVolParmsInfoBuffer volumeParms;
780     err = FSGetVolumeParms( actualVolume, &volumeParms, sizeof(volumeParms) );
781     if ( noErr != err ) {
782         msg_Err( p_intf, "error retrieving volume params, bailing out" );
783         return @"";
784     }
785
786     NSString *bsdName = [NSString stringWithUTF8String:(char *)volumeParms.vMDeviceID];
787     return [NSString stringWithFormat:@"/dev/r%@", bsdName];
788 }
789
790 - (char *)getVolumeTypeFromMountPath:(NSString *)mountPath
791 {
792     OSStatus err;
793     FSRef ref;
794     FSVolumeRefNum actualVolume;
795     err = FSPathMakeRef ( (const UInt8 *) [mountPath fileSystemRepresentation], &ref, NULL );
796
797     // get a FSVolumeRefNum from mountPath
798     if ( noErr == err ) {
799         FSCatalogInfo   catalogInfo;
800         err = FSGetCatalogInfo ( &ref,
801                                 kFSCatInfoVolume,
802                                 &catalogInfo,
803                                 NULL,
804                                 NULL,
805                                 NULL
806                                 );
807         if ( noErr == err ) {
808             actualVolume = catalogInfo.volume;
809         }
810     }
811
812     GetVolParmsInfoBuffer volumeParms;
813     err = FSGetVolumeParms( actualVolume, &volumeParms, sizeof(volumeParms) );
814
815     CFMutableDictionaryRef matchingDict;
816     io_service_t service;
817
818     matchingDict = IOBSDNameMatching(kIOMasterPortDefault, 0, volumeParms.vMDeviceID);
819     service = IOServiceGetMatchingService(kIOMasterPortDefault, matchingDict);
820
821     char *returnValue;
822     if (IO_OBJECT_NULL != service) {
823         if (IOObjectConformsTo(service, kIOCDMediaClass)) {
824             returnValue = kVLCMediaAudioCD;
825         }
826         else if(IOObjectConformsTo(service, kIODVDMediaClass))
827             returnValue = kVLCMediaDVD;
828         else if(IOObjectConformsTo(service, kIOBDMediaClass))
829             returnValue = kVLCMediaBD;
830         else
831         {
832             if ([mountPath rangeOfString:@"VIDEO_TS" options:NSCaseInsensitiveSearch | NSBackwardsSearch].location != NSNotFound)
833                 returnValue = kVLCMediaVideoTSFolder;
834             else if ([mountPath rangeOfString:@"BDMV" options:NSCaseInsensitiveSearch | NSBackwardsSearch].location != NSNotFound)
835                 returnValue = kVLCMediaBDMVFolder;
836             else
837             {
838                 // NSFileManager is not thread-safe, don't use defaultManager outside of the main thread
839                 NSFileManager * fm = [[NSFileManager alloc] init];
840                 NSArray * topLevelItems;
841                 topLevelItems = [fm subpathsOfDirectoryAtPath: mountPath error: NULL];
842                 [fm release];
843
844                 NSUInteger itemCount = [topLevelItems count];
845                 for (int i = 0; i < itemCount; i++) {
846                     if([[topLevelItems objectAtIndex:i] rangeOfString:@"SVCD"].location != NSNotFound) {
847                         returnValue = kVLCMediaSVCD;
848                         break;
849                     }
850                     if([[topLevelItems objectAtIndex:i] rangeOfString:@"VCD"].location != NSNotFound) {
851                         returnValue = kVLCMediaVCD;
852                         break;
853                     }
854                 }
855                 if(!returnValue)
856                     returnValue = kVLCMediaVideoTSFolder;
857             }
858         }
859
860         IOObjectRelease(service);
861     }
862     return returnValue;
863 }
864
865 - (void)showOpticalAtPath: (NSString *)o_opticalDevicePath
866 {
867     NSAutoreleasePool * o_pool = [[NSAutoreleasePool alloc] init];
868
869     char *diskType = [self getVolumeTypeFromMountPath:o_opticalDevicePath];
870
871     if (diskType == kVLCMediaDVD || diskType == kVLCMediaVideoTSFolder)
872     {
873         [o_disc_dvd_lbl setStringValue: [[NSFileManager defaultManager] displayNameAtPath:o_opticalDevicePath]];
874         [o_disc_dvdwomenus_lbl setStringValue: [o_disc_dvd_lbl stringValue]];
875         NSString *pathToOpen;
876         if (diskType == kVLCMediaVideoTSFolder)
877             pathToOpen = o_opticalDevicePath;
878         else
879             pathToOpen = [self getBSDNodeFromMountPath: o_opticalDevicePath];
880         if (!b_nodvdmenus) {
881             [self setMRL: [NSString stringWithFormat: @"dvdnav://%@", pathToOpen]];
882             [self showOpticalMediaView: o_disc_dvd_view withIcon: [[NSWorkspace sharedWorkspace] iconForFile: o_opticalDevicePath]];
883         } else {
884             [self setMRL: [NSString stringWithFormat: @"dvdread://%@#%i:%i-", pathToOpen, [o_disc_dvdwomenus_title intValue], [o_disc_dvdwomenus_chapter intValue]]];
885             [self showOpticalMediaView: o_disc_dvdwomenus_view withIcon: [[NSWorkspace sharedWorkspace] iconForFile: o_opticalDevicePath]];
886         }
887     }
888     else if (diskType == kVLCMediaAudioCD)
889     {
890         [o_disc_audiocd_lbl setStringValue: [[NSFileManager defaultManager] displayNameAtPath: o_opticalDevicePath]];
891         [o_disc_audiocd_trackcount_lbl setStringValue: [NSString stringWithFormat:_NS("%i tracks"), [[[NSFileManager defaultManager] subpathsOfDirectoryAtPath: o_opticalDevicePath error:NULL] count] - 1]]; // minus .TOC.plist
892         [self showOpticalMediaView: o_disc_audiocd_view withIcon: [[NSWorkspace sharedWorkspace] iconForFile: o_opticalDevicePath]];
893         [self setMRL: [NSString stringWithFormat: @"cdda://%@", [self getBSDNodeFromMountPath: o_opticalDevicePath]]];
894     }
895     else if (diskType == kVLCMediaVCD)
896     {
897         [o_disc_vcd_lbl setStringValue: [[NSFileManager defaultManager] displayNameAtPath: o_opticalDevicePath]];
898         [self showOpticalMediaView: o_disc_vcd_view withIcon: [[NSWorkspace sharedWorkspace] iconForFile: o_opticalDevicePath]];
899         [self setMRL: [NSString stringWithFormat: @"vcd://%@#%i:%i", [self getBSDNodeFromMountPath: o_opticalDevicePath], [o_disc_vcd_title intValue], [o_disc_vcd_chapter intValue]]];
900     }
901     else if (diskType == kVLCMediaSVCD)
902     {
903         [o_disc_vcd_lbl setStringValue: [[NSFileManager defaultManager] displayNameAtPath: o_opticalDevicePath]];
904         [self showOpticalMediaView: o_disc_vcd_view withIcon: [[NSWorkspace sharedWorkspace] iconForFile: o_opticalDevicePath]];
905         [self setMRL: [NSString stringWithFormat: @"vcd://%@@%i:%i", [self getBSDNodeFromMountPath: o_opticalDevicePath], [o_disc_vcd_title intValue], [o_disc_vcd_chapter intValue]]];
906     }
907     else if (diskType == kVLCMediaBD || diskType == kVLCMediaBDMVFolder)
908     {
909         [o_disc_bd_lbl setStringValue: [[NSFileManager defaultManager] displayNameAtPath: o_opticalDevicePath]];
910         [self showOpticalMediaView: o_disc_bd_view withIcon: [[NSWorkspace sharedWorkspace] iconForFile: o_opticalDevicePath]];
911         [self setMRL: [NSString stringWithFormat: @"bluray://%@", o_opticalDevicePath]];
912     }
913     else
914     {
915         msg_Warn( VLCIntf, "unknown disk type, no idea what to display" );
916         [self showOpticalMediaView: o_disc_nodisc_view withIcon: [NSImage imageNamed:@"NSApplicationIcon"]];
917     }
918
919     [o_pool release];
920 }
921
922 - (void)showSelectedOpticalDisc
923 {
924     NSString *o_opticalDevicePath = [o_opticalDevices objectAtIndex:[o_disc_selector_pop indexOfSelectedItem]];
925     [NSThread detachNewThreadSelector:@selector(showOpticalAtPath:) toTarget:self withObject:o_opticalDevicePath];
926 }
927
928 - (void)scanOpticalMedia:(NSNotification *)o_notification
929 {
930     [o_opticalDevices removeAllObjects];
931     [o_disc_selector_pop removeAllItems];
932     [o_opticalDevices addObjectsFromArray: [[NSWorkspace sharedWorkspace] mountedRemovableMedia]];
933     [o_opticalDevices addObjectsFromArray: o_specialMediaFolders];
934     if ([o_opticalDevices count] > 0) {
935         NSUInteger deviceCount = [o_opticalDevices count];
936         for (NSUInteger i = 0; i < deviceCount ; i++)
937             [o_disc_selector_pop addItemWithTitle: [[NSFileManager defaultManager] displayNameAtPath:[o_opticalDevices objectAtIndex: i]]];
938
939         if ([o_disc_selector_pop numberOfItems] <= 1)
940             [o_disc_selector_pop setHidden: YES];
941         else
942             [o_disc_selector_pop setHidden: NO];
943
944         [self showSelectedOpticalDisc];
945     }
946     else
947     {
948         msg_Dbg( VLCIntf, "no optical media found" );
949         [o_disc_selector_pop setHidden: YES];
950         [self showOpticalMediaView: o_disc_nodisc_view withIcon: [NSImage imageNamed: @"NSApplicationIcon"]];
951     }
952 }
953
954 - (IBAction)discSelectorChanged:(id)sender
955 {
956     [self showSelectedOpticalDisc];
957 }
958
959 - (IBAction)openSpecialMediaFolder:(id)sender
960 {
961     /* this is currently for VIDEO_TS and BDMV folders */
962     NSOpenPanel *o_open_panel = [NSOpenPanel openPanel];
963
964     [o_open_panel setAllowsMultipleSelection: NO];
965     [o_open_panel setCanChooseFiles: NO];
966     [o_open_panel setCanChooseDirectories: YES];
967     [o_open_panel setTitle: [sender title]];
968     [o_open_panel setPrompt: _NS("Open")];
969
970     if ([o_open_panel runModal] == NSOKButton)
971     {
972         NSString *o_path = [[[o_open_panel URLs] objectAtIndex: 0] path];
973         if ([o_path length] > 0 )
974         {
975             [o_specialMediaFolders addObject: o_path];
976             [self scanOpticalMedia: nil];
977         }
978     }
979 }
980
981 - (IBAction)dvdreadOptionChanged:(id)sender
982 {
983     if (sender == o_disc_dvdwomenus_enablemenus_btn) {
984         b_nodvdmenus = NO;
985         [self setMRL: [NSString stringWithFormat: @"dvdnav://%@", [self getBSDNodeFromMountPath:[o_opticalDevices objectAtIndex: [o_disc_selector_pop indexOfSelectedItem]]]]];
986         [self showOpticalMediaView: o_disc_dvd_view withIcon: [o_currentOpticalMediaIconView image]];
987         return;
988     }
989     if (sender == o_disc_dvd_disablemenus_btn) {
990         b_nodvdmenus = YES;
991         [self showOpticalMediaView: o_disc_dvdwomenus_view withIcon: [o_currentOpticalMediaIconView image]];
992     }
993
994     if (sender == o_disc_dvdwomenus_title)
995         [o_disc_dvdwomenus_title_stp setIntValue: [o_disc_dvdwomenus_title intValue]];
996     if (sender == o_disc_dvdwomenus_title_stp)
997         [o_disc_dvdwomenus_title setIntValue: [o_disc_dvdwomenus_title_stp intValue]];
998     if (sender == o_disc_dvdwomenus_chapter)
999         [o_disc_dvdwomenus_chapter_stp setIntValue: [o_disc_dvdwomenus_chapter intValue]];
1000     if (sender == o_disc_dvdwomenus_chapter_stp)
1001         [o_disc_dvdwomenus_chapter setIntValue: [o_disc_dvdwomenus_chapter_stp intValue]];
1002
1003     [self setMRL: [NSString stringWithFormat: @"dvdread://%@#%i:%i-", [self getBSDNodeFromMountPath:[o_opticalDevices objectAtIndex: [o_disc_selector_pop indexOfSelectedItem]]], [o_disc_dvdwomenus_title intValue], [o_disc_dvdwomenus_chapter intValue]]];
1004 }
1005
1006 - (IBAction)vcdOptionChanged:(id)sender
1007 {
1008     if (sender == o_disc_vcd_title)
1009         [o_disc_vcd_title_stp setIntValue: [o_disc_vcd_title intValue]];
1010     if (sender == o_disc_vcd_title_stp)
1011         [o_disc_vcd_title setIntValue: [o_disc_vcd_title_stp intValue]];
1012     if (sender == o_disc_vcd_chapter)
1013         [o_disc_vcd_chapter_stp setIntValue: [o_disc_vcd_chapter intValue]];
1014     if (sender == o_disc_vcd_chapter_stp)
1015         [o_disc_vcd_chapter setIntValue: [o_disc_vcd_chapter_stp intValue]];
1016
1017     [self setMRL: [NSString stringWithFormat: @"vcd://%@@%i:%i", [self getBSDNodeFromMountPath:[o_opticalDevices objectAtIndex: [o_disc_selector_pop indexOfSelectedItem]]], [o_disc_vcd_title intValue], [o_disc_vcd_chapter intValue]]];
1018 }
1019
1020 - (void)textFieldWasClicked:(NSNotification *)o_notification
1021 {
1022     if( [o_notification object] == o_net_udp_port )
1023         [o_net_mode selectCellAtRow: 0 column: 0];
1024     else if( [o_notification object] == o_net_udpm_addr ||
1025              [o_notification object] == o_net_udpm_port )
1026         [o_net_mode selectCellAtRow: 1 column: 0];
1027     else
1028         [o_net_mode selectCellAtRow: 2 column: 0];
1029
1030     [self openNetInfoChanged: nil];
1031 }
1032
1033 - (IBAction)openNetModeChanged:(id)sender
1034 {
1035     if( sender == o_net_mode )
1036     {
1037         if( [[sender selectedCell] tag] == 0 )
1038             [o_panel makeFirstResponder: o_net_udp_port];
1039         else if ( [[sender selectedCell] tag] == 1 )
1040             [o_panel makeFirstResponder: o_net_udpm_addr];
1041         else
1042             msg_Warn( p_intf, "Unknown sender tried to change UDP/RTP mode" );
1043     }
1044
1045     [self openNetInfoChanged: nil];
1046 }
1047
1048 - (IBAction)openNetStepperChanged:(id)sender
1049 {
1050     int i_tag = [sender tag];
1051
1052     if( i_tag == 0 )
1053     {
1054         [o_net_udp_port setIntValue: [o_net_udp_port_stp intValue]];
1055         [[NSNotificationCenter defaultCenter] postNotificationName: @"VLCOpenTextFieldWasClicked"
1056                                                             object: o_net_udp_port];
1057         [o_panel makeFirstResponder: o_net_udp_port];
1058     }
1059     else if( i_tag == 1 )
1060     {
1061         [o_net_udpm_port setIntValue: [o_net_udpm_port_stp intValue]];
1062         [[NSNotificationCenter defaultCenter] postNotificationName: @"VLCOpenTextFieldWasClicked"
1063                                                             object: o_net_udpm_port];
1064         [o_panel makeFirstResponder: o_net_udpm_port];
1065     }
1066
1067     [self openNetInfoChanged: nil];
1068 }
1069
1070 - (void)openNetInfoChanged:(NSNotification *)o_notification
1071 {
1072     NSString *o_mrl_string = [NSString string];
1073
1074     if( [o_net_udp_panel isVisible] )
1075     {
1076         NSString *o_mode;
1077         o_mode = [[o_net_mode selectedCell] title];
1078
1079         if( [o_mode isEqualToString: _NS("Unicast")] )
1080         {
1081             int i_port = [o_net_udp_port intValue];
1082
1083             if( [[o_net_udp_protocol_mat selectedCell] tag] == 0 )
1084                 o_mrl_string = @"udp://";
1085             else
1086                 o_mrl_string = @"rtp://";
1087
1088             if( i_port != config_GetInt( p_intf, "server-port" ) )
1089             {
1090                 o_mrl_string =
1091                     [o_mrl_string stringByAppendingFormat: @"@:%i", i_port];
1092             }
1093         }
1094         else if( [o_mode isEqualToString: _NS("Multicast")] )
1095         {
1096             NSString *o_addr = [o_net_udpm_addr stringValue];
1097             int i_port = [o_net_udpm_port intValue];
1098
1099             if( [[o_net_udp_protocol_mat selectedCell] tag] == 0 )
1100                 o_mrl_string = [NSString stringWithFormat: @"udp://@%@", o_addr];
1101             else
1102                 o_mrl_string = [NSString stringWithFormat: @"rtp://@%@", o_addr];
1103
1104             if( i_port != config_GetInt( p_intf, "server-port" ) )
1105             {
1106                 o_mrl_string =
1107                     [o_mrl_string stringByAppendingFormat: @":%i", i_port];
1108             }
1109         }
1110     }
1111     else
1112     {
1113         o_mrl_string = [o_net_http_url stringValue];
1114     }
1115     [self setMRL: o_mrl_string];
1116 }
1117
1118 - (IBAction)openNetUDPButtonAction:(id)sender
1119 {
1120     if( sender == o_net_openUDP_btn )
1121     {
1122         [NSApp beginSheet: o_net_udp_panel
1123            modalForWindow: o_panel
1124             modalDelegate: self
1125            didEndSelector: NULL
1126               contextInfo: nil];
1127         [self openNetInfoChanged: nil];
1128     }
1129     else if( sender == o_net_udp_cancel_btn )
1130     {
1131         [o_net_udp_panel orderOut: sender];
1132         [NSApp endSheet: o_net_udp_panel];
1133     }
1134     else if( sender == o_net_udp_ok_btn )
1135     {
1136         NSString *o_mrl_string = [NSString string];
1137         if( [[[o_net_mode selectedCell] title] isEqualToString: _NS("Unicast")] )
1138         {
1139             int i_port = [o_net_udp_port intValue];
1140
1141             if( [[o_net_udp_protocol_mat selectedCell] tag] == 0 )
1142                 o_mrl_string = @"udp://";
1143             else
1144                 o_mrl_string = @"rtp://";
1145
1146             if( i_port != config_GetInt( p_intf, "server-port" ) )
1147             {
1148                 o_mrl_string =
1149                 [o_mrl_string stringByAppendingFormat: @"@:%i", i_port];
1150             }
1151         }
1152         else if( [[[o_net_mode selectedCell] title] isEqualToString: _NS("Multicast")] )
1153         {
1154             NSString *o_addr = [o_net_udpm_addr stringValue];
1155             int i_port = [o_net_udpm_port intValue];
1156
1157             if( [[o_net_udp_protocol_mat selectedCell] tag] == 0 )
1158                 o_mrl_string = [NSString stringWithFormat: @"udp://@%@", o_addr];
1159             else
1160                 o_mrl_string = [NSString stringWithFormat: @"rtp://@%@", o_addr];
1161
1162             if( i_port != config_GetInt( p_intf, "server-port" ) )
1163             {
1164                 o_mrl_string =
1165                 [o_mrl_string stringByAppendingFormat: @":%i", i_port];
1166             }
1167         }
1168         [self setMRL: o_mrl_string];
1169         [o_net_http_url setStringValue: o_mrl_string];
1170         [o_net_udp_panel orderOut: sender];
1171         [NSApp endSheet: o_net_udp_panel];
1172     }
1173 }
1174
1175 - (void)openFile
1176 {
1177     NSOpenPanel *o_open_panel = [NSOpenPanel openPanel];
1178     b_autoplay = config_GetInt( VLCIntf, "macosx-autoplay" );
1179
1180     [o_open_panel setAllowsMultipleSelection: YES];
1181     [o_open_panel setCanChooseDirectories: YES];
1182     [o_open_panel setTitle: _NS("Open File")];
1183     [o_open_panel setPrompt: _NS("Open")];
1184
1185     if( [o_open_panel runModal] == NSOKButton )
1186     {
1187         NSArray * o_urls = [o_open_panel URLs];
1188         NSUInteger count = [o_urls count];
1189         NSMutableArray *o_values = [NSMutableArray arrayWithCapacity:count];
1190         NSMutableArray *o_array = [NSMutableArray arrayWithCapacity:count];
1191         for( NSUInteger i = 0; i < count; i++ )
1192         {
1193             [o_values addObject: [[o_urls objectAtIndex: i] path]];
1194         }
1195         [o_values sortUsingSelector:@selector(caseInsensitiveCompare:)];
1196
1197         for( NSUInteger i = 0; i < count; i++ )
1198         {
1199             NSDictionary *o_dic;
1200             char *psz_uri = make_URI([[o_values objectAtIndex:i] UTF8String], "file");
1201             if( !psz_uri )
1202                 continue;
1203
1204             o_dic = [NSDictionary dictionaryWithObject:[NSString stringWithCString:psz_uri encoding:NSUTF8StringEncoding] forKey:@"ITEM_URL"];
1205
1206             free( psz_uri );
1207
1208             [o_array addObject: o_dic];
1209         }
1210         if( b_autoplay )
1211             [[[VLCMain sharedInstance] playlist] appendArray: o_array atPos: -1 enqueue:NO];
1212         else
1213             [[[VLCMain sharedInstance] playlist] appendArray: o_array atPos: -1 enqueue:YES];
1214     }
1215 }
1216
1217 - (void)showCaptureView: theView
1218 {
1219     NSRect o_view_rect;
1220     o_view_rect = [theView frame];
1221     [theView setFrame: NSMakeRect( 0, -10, o_view_rect.size.width, o_view_rect.size.height)];
1222     [theView setAutoresizesSubviews: YES];
1223     if (o_currentCaptureView)
1224     {
1225         [[[[o_tabview tabViewItemAtIndex: 3] view] animator] replaceSubview: o_currentCaptureView with: theView];
1226         [o_currentCaptureView release];
1227     }
1228     else
1229     {
1230         [[[[o_tabview tabViewItemAtIndex: 3] view] animator] addSubview: theView];
1231     }
1232     o_currentCaptureView = theView;
1233     [o_currentCaptureView retain];
1234 }
1235
1236 - (IBAction)openCaptureModeChanged:(id)sender
1237 {
1238     if( [[[o_capture_mode_pop selectedItem] title] isEqualToString: @"EyeTV"] )
1239     {
1240         if( [[[VLCMain sharedInstance] eyeTVController] isEyeTVrunning] == YES )
1241         {
1242             if( [[[VLCMain sharedInstance] eyeTVController] isDeviceConnected] == YES )
1243             {
1244                 [self showCaptureView: o_eyetv_running_view];
1245                 [self setupChannelInfo];
1246             }
1247             else
1248             {
1249                 setEyeTVUnconnected;
1250             }
1251         }
1252         else
1253             [self showCaptureView: o_eyetv_notLaunched_view];
1254         [self setMRL: @""];
1255     }
1256     else if( [[[o_capture_mode_pop selectedItem] title] isEqualToString: _NS("Screen")] )
1257     {
1258         [self showCaptureView: o_screen_view];
1259         [self setMRL: @"screen://"];
1260         [o_screen_height_fld setIntValue: config_GetInt( p_intf, "screen-height" )];
1261         [o_screen_width_fld setIntValue: config_GetInt( p_intf, "screen-width" )];
1262         [o_screen_fps_fld setFloatValue: config_GetFloat( p_intf, "screen-fps" )];
1263         [o_screen_left_fld setIntValue: config_GetInt( p_intf, "screen-left" )];
1264         [o_screen_top_fld setIntValue: config_GetInt( p_intf, "screen-top" )];
1265         [o_screen_follow_mouse_ckb setIntValue: config_GetInt( p_intf, "screen-follow-mouse" )];
1266
1267         int screen_index = config_GetInt( p_intf, "screen-index" );
1268         int display_id = config_GetInt( p_intf, "screen-display-id" );
1269         unsigned int i, displayCount = 0;
1270         CGLError returnedError;
1271         struct display_info_t *item;
1272         NSValue *v;
1273
1274         returnedError = CGGetOnlineDisplayList( 0, NULL, &displayCount );
1275         if( !returnedError )
1276         {
1277             CGDirectDisplayID *ids;
1278             ids = ( CGDirectDisplayID * )malloc( displayCount * sizeof( CGDirectDisplayID ) );
1279             returnedError = CGGetOnlineDisplayList( displayCount, ids, &displayCount );
1280             if( !returnedError )
1281             {
1282                 for( i = 0; i < [o_displayInfos count]; i ++ )
1283                 {
1284                     v = [o_displayInfos objectAtIndex:i];
1285                     free( [v pointerValue] );
1286                 }
1287                 [o_displayInfos removeAllObjects];
1288                 [o_screen_screen_pop removeAllItems];
1289                 for( i = 0; i < displayCount; i ++ )
1290                 {
1291                     item = ( struct display_info_t * )malloc( sizeof( struct display_info_t ) );
1292                     item->id = ids[i];
1293                     item->rect = CGDisplayBounds( item->id );
1294                     [o_screen_screen_pop addItemWithTitle: [NSString stringWithFormat:@"Screen %d (%dx%d)", i + 1, (int)item->rect.size.width, (int)item->rect.size.height]];
1295                     v = [NSValue valueWithPointer:item];
1296                     [o_displayInfos addObject:v];
1297                     if( i == 0 || display_id == item->id || screen_index - 1 == i )
1298                     {
1299                         [o_screen_screen_pop selectItemAtIndex: i];
1300                         [o_screen_left_stp setMaxValue: item->rect.size.width];
1301                         [o_screen_top_stp setMaxValue: item->rect.size.height];
1302                         [o_screen_width_stp setMaxValue: item->rect.size.width];
1303                         [o_screen_height_stp setMaxValue: item->rect.size.height];
1304                     }
1305                 }
1306             }
1307             free( ids );
1308         }
1309     }
1310     else if( [[[o_capture_mode_pop selectedItem] title] isEqualToString: _NS("Video Device")] )
1311     {
1312         [self showCaptureView: o_qtk_view];
1313         if ([o_capture_width_fld intValue] <= 0)
1314             [self qtkChanged:nil];
1315
1316         if(!qtk_currdevice_uid)
1317             [self setMRL: @""];
1318         else
1319             [self setMRL:[NSString stringWithFormat:@"qtcapture://%@", qtk_currdevice_uid]];
1320     }
1321     else if( [[[o_capture_mode_pop selectedItem] title] isEqualToString: _NS("Audio Device")] )
1322     {
1323         [self showCaptureView: o_qtkaudio_view];
1324         [self qtkAudioChanged:nil];
1325
1326         if(!qtkaudio_currdevice_uid)
1327             [self setMRL: @""];
1328         else
1329             [self setMRL:[NSString stringWithFormat:@"qtsound://%@", qtkaudio_currdevice_uid]];
1330     }
1331 }
1332
1333 - (void)screenFPSfieldChanged:(NSNotification *)o_notification
1334 {
1335     [o_screen_fps_stp setFloatValue: [o_screen_fps_fld floatValue]];
1336     if( [[o_screen_fps_fld stringValue] isEqualToString: @""] )
1337         [o_screen_fps_fld setFloatValue: 1.0];
1338     [self setMRL: @"screen://"];
1339 }
1340
1341 - (IBAction)eyetvSwitchChannel:(id)sender
1342 {
1343     if( sender == o_eyetv_nextProgram_btn )
1344     {
1345         int chanNum = [[[VLCMain sharedInstance] eyeTVController] switchChannelUp: YES];
1346         [o_eyetv_channels_pop selectItemWithTag:chanNum];
1347         [self setMRL: [NSString stringWithFormat:@"eyetv:// :eyetv-channel=%d", chanNum]];
1348     }
1349     else if( sender == o_eyetv_previousProgram_btn )
1350     {
1351         int chanNum = [[[VLCMain sharedInstance] eyeTVController] switchChannelUp: NO];
1352         [o_eyetv_channels_pop selectItemWithTag:chanNum];
1353         [self setMRL: [NSString stringWithFormat:@"eyetv:// :eyetv-channel=%d", chanNum]];
1354     }
1355     else if( sender == o_eyetv_channels_pop )
1356     {
1357         int chanNum = [[sender selectedItem] tag];
1358         [[[VLCMain sharedInstance] eyeTVController] selectChannel:chanNum];
1359         [self setMRL: [NSString stringWithFormat:@"eyetv:// :eyetv-channel=%d", chanNum]];
1360     }
1361     else
1362         msg_Err( VLCIntf, "eyetvSwitchChannel sent by unknown object" );
1363 }
1364
1365 - (IBAction)eyetvLaunch:(id)sender
1366 {
1367     [[[VLCMain sharedInstance] eyeTVController] launchEyeTV];
1368 }
1369
1370 - (IBAction)eyetvGetPlugin:(id)sender
1371 {
1372     [[NSWorkspace sharedWorkspace] openURL: [NSURL URLWithString: @"http://www.videolan.org/vlc/eyetv"]];
1373 }
1374
1375 - (void)eyetvChanged:(NSNotification *)o_notification
1376 {
1377     if( [[o_notification name] isEqualToString: @"DeviceAdded"] )
1378     {
1379         msg_Dbg( VLCIntf, "eyetv device was added" );
1380         [self showCaptureView: o_eyetv_running_view];
1381         [self setupChannelInfo];
1382     }
1383     else if( [[o_notification name] isEqualToString: @"DeviceRemoved"] )
1384     {
1385         /* leave the channel selection like that,
1386          * switch to our "no device" tab */
1387         msg_Dbg( VLCIntf, "eyetv device was removed" );
1388         setEyeTVUnconnected;
1389     }
1390     else if( [[o_notification name] isEqualToString: @"PluginQuit"] )
1391     {
1392         /* switch to the "launch eyetv" tab */
1393         msg_Dbg( VLCIntf, "eyetv was terminated" );
1394         [self showCaptureView: o_eyetv_notLaunched_view];
1395     }
1396     else if( [[o_notification name] isEqualToString: @"PluginInit"] )
1397     {
1398         /* we got no device yet */
1399         msg_Dbg( VLCIntf, "eyetv was launched, no device yet" );
1400         setEyeTVUnconnected;
1401     }
1402 }
1403
1404 /* little helper method, since this code needs to be run by multiple objects */
1405 - (void)setupChannelInfo
1406 {
1407     /* set up channel selection */
1408     [o_eyetv_channels_pop removeAllItems];
1409     [o_eyetv_chn_bgbar setHidden: NO];
1410     [o_eyetv_chn_bgbar animate: self];
1411     [o_eyetv_chn_status_txt setStringValue: _NS("Retrieving Channel Info...")];
1412     [o_eyetv_chn_status_txt setHidden: NO];
1413
1414     /* retrieve info */
1415     NSEnumerator *channels = [[[VLCMain sharedInstance] eyeTVController] allChannels];
1416     int x = -2;
1417     [[[o_eyetv_channels_pop menu] addItemWithTitle: _NS("Composite input")
1418                                                action: nil
1419                                         keyEquivalent: @""] setTag:x++];
1420     [[[o_eyetv_channels_pop menu] addItemWithTitle: _NS("S-Video input")
1421                                                action: nil
1422                                         keyEquivalent: @""] setTag:x++];
1423     if( channels )
1424     {
1425         NSString *channel;
1426         [[o_eyetv_channels_pop menu] addItem: [NSMenuItem separatorItem]];
1427         while( channel = [channels nextObject] )
1428         {
1429             /* we have to add items this way, because we accept duplicates
1430              * additionally, we save a bit of time */
1431             [[[o_eyetv_channels_pop menu] addItemWithTitle: channel
1432                                                    action: nil
1433                                             keyEquivalent: @""] setTag:++x];
1434         }
1435         /* make Tuner the default */
1436         [o_eyetv_channels_pop selectItemWithTag:[[[VLCMain sharedInstance] eyeTVController] currentChannel]];
1437     }
1438
1439     /* clean up GUI */
1440     [o_eyetv_chn_bgbar setHidden: YES];
1441     [o_eyetv_chn_status_txt setHidden: YES];
1442 }
1443
1444 - (IBAction)subsChanged:(id)sender
1445 {
1446     if ([o_file_sub_ckbox state] == NSOnState)
1447     {
1448         [o_file_sub_btn_settings setEnabled:YES];
1449         if (o_sub_path) {
1450             [o_file_subtitles_filename_lbl setStringValue: [[NSFileManager defaultManager] displayNameAtPath:o_sub_path]];
1451             [o_file_subtitles_icon_well setImage: [[NSWorkspace sharedWorkspace] iconForFile:o_sub_path]];
1452         }
1453     }
1454     else
1455     {
1456         [o_file_sub_btn_settings setEnabled:NO];
1457         [o_file_subtitles_filename_lbl setStringValue: @""];
1458         [o_file_subtitles_icon_well setImage: NULL];
1459     }
1460 }
1461
1462 - (IBAction)subSettings:(id)sender
1463 {
1464     [NSApp beginSheet: o_file_sub_sheet
1465         modalForWindow: [sender window]
1466         modalDelegate: self
1467         didEndSelector: NULL
1468         contextInfo: nil];
1469 }
1470
1471 - (IBAction)subCloseSheet:(id)sender
1472 {
1473     [self subsChanged: nil];
1474     [o_file_sub_sheet orderOut:sender];
1475     [NSApp endSheet: o_file_sub_sheet];
1476 }
1477
1478 - (IBAction)subFileBrowse:(id)sender
1479 {
1480     NSOpenPanel *o_open_panel = [NSOpenPanel openPanel];
1481
1482     [o_open_panel setAllowsMultipleSelection: NO];
1483     [o_open_panel setTitle: _NS("Open File")];
1484     [o_open_panel setPrompt: _NS("Open")];
1485
1486     if( [o_open_panel runModal] == NSOKButton )
1487     {
1488         o_sub_path = [[[o_open_panel URLs] objectAtIndex: 0] path];
1489         [o_sub_path retain];
1490         [o_file_subtitles_filename_lbl setStringValue: [[NSFileManager defaultManager] displayNameAtPath:o_sub_path]];
1491         [o_file_sub_path_fld setStringValue: [o_file_subtitles_filename_lbl stringValue]];
1492         [o_file_sub_path_lbl setHidden: YES];
1493         [o_file_subtitles_icon_well setImage: [[NSWorkspace sharedWorkspace] iconForFile:o_sub_path]];
1494         [o_file_sub_icon_view setImage: [o_file_subtitles_icon_well image]];
1495     }
1496     else
1497     {
1498         [o_file_sub_path_lbl setHidden: NO];
1499         [o_file_sub_path_fld setStringValue:@""];
1500         [o_file_subtitles_filename_lbl setStringValue:@""];
1501         [o_file_subtitles_icon_well setImage: nil];
1502         [o_file_sub_icon_view setImage: nil];
1503     }
1504 }
1505
1506 - (IBAction)subOverride:(id)sender
1507 {
1508     BOOL b_state = [o_file_sub_override state];
1509     [o_file_sub_delay setEnabled: b_state];
1510     [o_file_sub_delay_stp setEnabled: b_state];
1511     [o_file_sub_fps setEnabled: b_state];
1512     [o_file_sub_fps_stp setEnabled: b_state];
1513 }
1514
1515 - (IBAction)subDelayStepperChanged:(id)sender
1516 {
1517     [o_file_sub_delay setIntValue: [o_file_sub_delay_stp intValue]];
1518 }
1519
1520 - (IBAction)subFpsStepperChanged:(id)sender;
1521 {
1522     [o_file_sub_fps setFloatValue: [o_file_sub_fps_stp floatValue]];
1523 }
1524
1525 - (IBAction)panelCancel:(id)sender
1526 {
1527     [NSApp stopModalWithCode: 0];
1528 }
1529
1530 - (IBAction)panelOk:(id)sender
1531 {
1532     if( [[self MRL] length] )
1533         [NSApp stopModalWithCode: 1];
1534     else
1535         NSBeep();
1536 }
1537
1538 - (NSArray *)qtkvideoDevices
1539 {
1540     if ( !qtkvideoDevices )
1541         [self qtkrefreshVideoDevices];
1542     return qtkvideoDevices;
1543 }
1544
1545 - (void)qtkrefreshVideoDevices
1546 {
1547     [qtkvideoDevices release];
1548     qtkvideoDevices = [[[QTCaptureDevice inputDevicesWithMediaType:QTMediaTypeVideo] arrayByAddingObjectsFromArray:[QTCaptureDevice inputDevicesWithMediaType:QTMediaTypeMuxed]] retain];
1549 }
1550
1551 - (NSArray *)qtkaudioDevices
1552 {
1553     if ( !qtkaudioDevices )
1554         [self qtkrefreshAudioDevices];
1555     return qtkaudioDevices;
1556 }
1557
1558 - (void)qtkrefreshAudioDevices
1559 {
1560     [qtkaudioDevices release];
1561     qtkaudioDevices = [[[QTCaptureDevice inputDevicesWithMediaType:QTMediaTypeSound] arrayByAddingObjectsFromArray:[QTCaptureDevice inputDevicesWithMediaType:QTMediaTypeMuxed]] retain];
1562 }
1563
1564 @end
1565
1566 @implementation VLCOpenTextField
1567
1568 - (void)mouseDown:(NSEvent *)theEvent
1569 {
1570     [[NSNotificationCenter defaultCenter] postNotificationName: @"VLCOpenTextFieldWasClicked"
1571                                                         object: self];
1572     [super mouseDown: theEvent];
1573 }
1574
1575 @end