]> git.sesse.net Git - vlc/blobdiff - modules/gui/macosx/open.m
macosx: Repack module_config_t.
[vlc] / modules / gui / macosx / open.m
index c370b7b48059928d417541c9c6904072a17f34a4..6f7d4b84b4d085e02f81b1105332b0916bf6420d 100644 (file)
 
 #import <vlc_url.h>
 
-NSArray               *qtkvideoDevices;
+NSArray *qtkvideoDevices;
+NSArray *qtkaudioDevices;
 #define setEyeTVUnconnected \
 [o_capture_lbl setStringValue: _NS("No device is selected")]; \
-[o_capture_long_lbl setStringValue: _NS("No device is selected.\n\nChoose available device in above pull-down menu\n.")]; \
+[o_capture_long_lbl setStringValue: _NS("No device is selected.\n\nChoose available device in above pull-down menu.\n")]; \
 [o_capture_lbl displayIfNeeded]; \
 [o_capture_long_lbl displayIfNeeded]; \
 [self showCaptureView: o_capture_label_view]
 
-#define kVLCMediaAudioCD "AudioCD"
-#define kVLCMediaDVD "DVD"
-#define kVLCMediaVCD "VCD"
-#define kVLCMediaSVCD "SVCD"
-#define kVLCMediaBD "Bluray"
-#define kVLCMediaVideoTSFolder "VIDEO_TS"
-#define kVLCMediaBDMVFolder "BDMV"
-#define kVLCMediaUnknown "Unknown"
-
+struct display_info_t
+{
+    CGRect rect;
+    CGDirectDisplayID id;
+};
 
 /*****************************************************************************
  * VLCOpen implementation
  *****************************************************************************/
 @implementation VLCOpen
 
+#pragma mark -
+#pragma mark Init
+
 static VLCOpen *_o_sharedMainInstance = nil;
 
 + (VLCOpen *)sharedInstance
@@ -88,7 +88,7 @@ static VLCOpen *_o_sharedMainInstance = nil;
         _o_sharedMainInstance = [super init];
         p_intf = VLCIntf;
     }
+
     return _o_sharedMainInstance;
 }
 
@@ -103,6 +103,15 @@ static VLCOpen *_o_sharedMainInstance = nil;
         [o_sub_path release];
     [o_currentOpticalMediaIconView release];
     [o_currentOpticalMediaView release];
+    int i;
+    for( i = 0; i < [o_displayInfos count]; i ++ )
+    {
+        NSValue *v = [o_displayInfos objectAtIndex:i];
+        free( [v pointerValue] );
+    }
+    [o_displayInfos removeAllObjects];
+    [o_displayInfos release];
+
     [super dealloc];
 }
 
@@ -134,6 +143,11 @@ static VLCOpen *_o_sharedMainInstance = nil;
     [o_file_slave_icon_well setImage: NULL];
     [o_file_subtitles_filename_lbl setStringValue: @""];
     [o_file_subtitles_icon_well setImage: NULL];
+    [o_file_custom_timing_ckb setTitle: _NS("Custom playback")];
+    [o_file_starttime_lbl setStringValue: _NS("Start time")];
+    [o_file_starttime_fld setStringValue: @""];
+    [o_file_stoptime_lbl setStringValue: _NS("Stop time")];
+    [o_file_stoptime_fld setStringValue: @""];
 
     [o_disc_selector_pop removeAllItems];
     [o_disc_selector_pop setHidden: NO];
@@ -185,13 +199,13 @@ static VLCOpen *_o_sharedMainInstance = nil;
     [o_eyetv_chn_bgbar setUsesThreadedAnimation: YES];
 
     [o_capture_mode_pop removeAllItems];
-    [o_capture_mode_pop addItemWithTitle: _NS("Capture Device")];
-       // our screen capture module isn't Lion-compatible, so let's hide it from the user if needed (trac #4799)
-       if( NSAppKitVersionNumber < 1115.2 )
-               [o_capture_mode_pop addItemWithTitle: _NS("Screen")];
+    [o_capture_mode_pop addItemWithTitle: _NS("Video Device")];
+    [o_capture_mode_pop addItemWithTitle: _NS("Audio Device")];
+    [o_capture_mode_pop addItemWithTitle: _NS("Screen")];
     [o_capture_mode_pop addItemWithTitle: @"EyeTV"];
     [o_screen_long_lbl setStringValue: _NS("This input allows you to save, stream or display your current screen contents.")];
     [o_screen_fps_lbl setStringValue: _NS("Frames per Second:")];
+    [o_screen_screen_lbl setStringValue: _NS("Screen:")];
     [o_screen_left_lbl setStringValue: _NS("Subscreen left:")];
     [o_screen_top_lbl setStringValue: _NS("Subscreen top:")];
     [o_screen_width_lbl setStringValue: _NS("Subscreen width:")];
@@ -205,15 +219,16 @@ static VLCOpen *_o_sharedMainInstance = nil;
     [o_eyetv_noInstanceLong_lbl setStringValue: _NS("VLC could not connect to EyeTV.\nMake sure that you installed VLC's EyeTV plugin.")];
     [o_eyetv_launchEyeTV_btn setTitle: _NS("Launch EyeTV now")];
     [o_eyetv_getPlugin_btn setTitle: _NS("Download Plugin")];
-    [o_qtk_long_lbl setStringValue: _NS("This input allows you to process input signals from QuickTime-compatible video devices.\nLive Audio input is not supported.")];
+    [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.")];
     [o_capture_width_lbl setStringValue: _NS("Image width:")];
     [o_capture_height_lbl setStringValue: _NS("Image height:")];
 
     [self qtkvideoDevices];
     [o_qtk_device_pop removeAllItems];
-    msg_Dbg( VLCIntf, "Found %lu capture devices", [qtkvideoDevices count] );
-       if([qtkvideoDevices count] >= 1)
-               {
+    msg_Dbg( VLCIntf, "Found %lu video capture devices", [qtkvideoDevices count] );
+
+    if([qtkvideoDevices count] >= 1)
+    {
         if (!qtk_currdevice_uid) {
             qtk_currdevice_uid = [[[QTCaptureDevice defaultInputDeviceWithMediaType: QTMediaTypeVideo] uniqueID]
                                                                 stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
@@ -228,12 +243,37 @@ static VLCOpen *_o_sharedMainInstance = nil;
             }
         }
     }
-       else
-       {
-               [o_qtk_device_pop addItemWithTitle: _NS("None")];
+    else
+    {
+        [o_qtk_device_pop addItemWithTitle: _NS("None")];
         [qtk_currdevice_uid release];
-       }
+    }
 
+    [self qtkaudioDevices];
+    [o_qtkaudio_device_pop removeAllItems];
+    msg_Dbg( VLCIntf, "Found %lu audio capture devices", [qtkaudioDevices count] );
+
+    if([qtkaudioDevices count] >= 1)
+    {
+        if (!qtkaudio_currdevice_uid) {
+            qtkaudio_currdevice_uid = [[[QTCaptureDevice defaultInputDeviceWithMediaType: QTMediaTypeSound] uniqueID]
+                                  stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
+        }
+        NSUInteger deviceCount = [qtkaudioDevices count];
+        for(int iaudio = 0; iaudio < deviceCount; iaudio++){
+            QTCaptureDevice *qtkaudio_device;
+            qtkaudio_device = [qtkaudioDevices objectAtIndex:iaudio];
+            [o_qtkaudio_device_pop addItemWithTitle: [qtkaudio_device localizedDisplayName]];
+            if([[[qtkaudio_device uniqueID]stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] isEqualToString:qtkaudio_currdevice_uid]){
+                [o_qtkaudio_device_pop selectItemAtIndex:iaudio];
+            }
+        }
+    }
+    else
+    {
+        [o_qtkaudio_device_pop addItemWithTitle: _NS("None")];
+        [qtkaudio_currdevice_uid release];
+    }
 
     [self setSubPanel];
 
@@ -274,10 +314,14 @@ static VLCOpen *_o_sharedMainInstance = nil;
     /* we want to be notified about removed or added media */
     o_specialMediaFolders = [[NSMutableArray alloc] init];
     o_opticalDevices = [[NSMutableArray alloc] init];
+    o_displayInfos = [[NSMutableArray alloc] init];
     NSWorkspace *sharedWorkspace = [NSWorkspace sharedWorkspace];
-       [[sharedWorkspace notificationCenter] addObserver:self selector:@selector(scanOpticalMedia:) name:NSWorkspaceDidMountNotification object:nil];
-       [[sharedWorkspace notificationCenter] addObserver:self selector:@selector(scanOpticalMedia:) name:NSWorkspaceDidUnmountNotification object:nil];
-    [self scanOpticalMedia:nil];
+
+    [[sharedWorkspace notificationCenter] addObserver:self selector:@selector(scanOpticalMedia:) name:NSWorkspaceDidMountNotification object:nil];
+    [[sharedWorkspace notificationCenter] addObserver:self selector:@selector(scanOpticalMedia:) name:NSWorkspaceDidUnmountNotification object:nil];
+    [self performSelector:@selector(scanOpticalMedia:) withObject:nil afterDelay:2.0];
+    [self performSelector:@selector(qtkChanged:) withObject:nil afterDelay:2.5];
+    [self performSelector:@selector(qtkAudioChanged:) withObject:nil afterDelay:3.0];
 
     [self setMRL: @""];
 }
@@ -329,11 +373,11 @@ static VLCOpen *_o_sharedMainInstance = nil;
 
     if( p_item )
     {
-        for( i_index = 0; p_item->ppsz_list && p_item->ppsz_list[i_index];
+        for( i_index = 0; p_item->list.psz && p_item->list.psz[i_index];
              i_index++ )
         {
             [o_file_sub_encoding_pop addItemWithTitle:
-                [NSString stringWithUTF8String: p_item->ppsz_list[i_index]]];
+                [NSString stringWithUTF8String: p_item->list.psz[i_index]]];
         }
         [o_file_sub_encoding_pop selectItemWithTitle:
                 [NSString stringWithUTF8String: p_item->value.psz]];
@@ -343,11 +387,10 @@ static VLCOpen *_o_sharedMainInstance = nil;
 
     if ( p_item )
     {
-        for ( i_index = 0; i_index < p_item->i_list; i_index++ )
+        for ( i_index = 0; i_index < p_item->list_count; i_index++ )
         {
             [o_file_sub_align_pop addItemWithTitle:
-                [NSString stringWithUTF8String:
-                p_item->ppsz_list_text[i_index]]];
+             _NS(p_item->list_text[i_index])];
         }
         [o_file_sub_align_pop selectItemAtIndex: p_item->value.i];
     }
@@ -356,12 +399,10 @@ static VLCOpen *_o_sharedMainInstance = nil;
 
     if ( p_item )
     {
-        for ( i_index = 0; i_index < p_item->i_list; i_index++ )
+        for ( i_index = 0; i_index < p_item->list_count; i_index++ )
         {
-            [o_file_sub_size_pop addItemWithTitle:
-                [NSString stringWithUTF8String:
-                p_item->ppsz_list_text[i_index]]];
-            if ( p_item->value.i == p_item->pi_list[i_index] )
+            [o_file_sub_size_pop addItemWithTitle: _NS(p_item->list_text[i_index])];
+            if ( p_item->value.i == p_item->list.i[i_index] )
             {
                 [o_file_sub_size_pop selectItemAtIndex: i_index];
             }
@@ -377,7 +418,7 @@ static VLCOpen *_o_sharedMainInstance = nil;
 
     [o_tabview selectTabViewItemAtIndex: i_type];
     [o_file_sub_ckbox setState: NSOffState];
+
     i_result = [NSApp runModalForWindow: o_panel];
     [o_panel close];
 
@@ -401,7 +442,7 @@ static VLCOpen *_o_sharedMainInstance = nil;
                     @"subsdec-encoding=%@",
                     [o_file_sub_encoding_pop titleOfSelectedItem]]];
             [o_options addObject: [NSString stringWithFormat:
-                    @"subsdec-align=%i",
+                    @"subsdec-align=%li",
                     [o_file_sub_align_pop indexOfSelectedItem]]];
 
             p_item = config_FindConfig( VLC_OBJECT(p_intf),
@@ -411,9 +452,30 @@ static VLCOpen *_o_sharedMainInstance = nil;
             {
                 [o_options addObject: [NSString stringWithFormat:
                     @"freetype-rel-fontsize=%i",
-                    p_item->pi_list[[o_file_sub_size_pop indexOfSelectedItem]]]];
+                    p_item->list.i[[o_file_sub_size_pop indexOfSelectedItem]]]];
             }
         }
+        NSArray * components = [[o_file_starttime_fld stringValue] componentsSeparatedByString:@":"];
+        NSUInteger componentCount = [components count];
+        NSInteger tempValue;
+        if( componentCount == 1 )
+            tempValue = 1000000 * ( [[components objectAtIndex:0] intValue] );
+        else if( componentCount == 2 )
+            tempValue = 1000000 * ( [[components objectAtIndex:0] intValue] * 60 + [[components objectAtIndex:1] intValue] );
+        else if( componentCount == 3 )
+            tempValue = 1000000 * ( [[components objectAtIndex:0] intValue] * 3600 + [[components objectAtIndex:1] intValue] * 60 + [[components objectAtIndex:2] intValue] );
+        if (tempValue > 0)
+            [o_options addObject: [NSString stringWithFormat:@"start-time=%li", tempValue]];
+        components = [[o_file_stoptime_fld stringValue] componentsSeparatedByString:@":"];
+        componentCount = [components count];
+        if( componentCount == 1 )
+            tempValue = 1000000 * ( [[components objectAtIndex:0] intValue] );
+        else if( componentCount == 2 )
+            tempValue = 1000000 * ( [[components objectAtIndex:0] intValue] * 60 + [[components objectAtIndex:1] intValue] );
+        else if( componentCount == 3 )
+            tempValue = 1000000 * ( [[components objectAtIndex:0] intValue] * 3600 + [[components objectAtIndex:1] intValue] * 60 + [[components objectAtIndex:2] intValue] );
+        if (tempValue > 0)
+            [o_options addObject: [NSString stringWithFormat:@"stop-time=%li", tempValue]];
         if( [o_output_ckbox state] == NSOnState )
         {
             NSUInteger count = [[o_sout_options mrl] count];
@@ -428,7 +490,12 @@ static VLCOpen *_o_sharedMainInstance = nil;
         {
             if( [[[o_capture_mode_pop selectedItem] title] isEqualToString: _NS("Screen")] )
             {
+                int selected_index = [o_screen_screen_pop indexOfSelectedItem];
+                NSValue *v = [o_displayInfos objectAtIndex:selected_index];
+                struct display_info_t *item = ( struct display_info_t * )[v pointerValue];
+
                 [o_options addObject: [NSString stringWithFormat: @"screen-fps=%f", [o_screen_fps_fld floatValue]]];
+                [o_options addObject: [NSString stringWithFormat: @"screen-display-id=%i", item->id]];
                 [o_options addObject: [NSString stringWithFormat: @"screen-left=%i", [o_screen_left_fld intValue]]];
                 [o_options addObject: [NSString stringWithFormat: @"screen-top=%i", [o_screen_top_fld intValue]]];
                 [o_options addObject: [NSString stringWithFormat: @"screen-width=%i", [o_screen_width_fld intValue]]];
@@ -438,7 +505,7 @@ static VLCOpen *_o_sharedMainInstance = nil;
                 else
                     [o_options addObject: @"no-screen-follow-mouse"];
             }
-            else if( [[[o_capture_mode_pop selectedItem] title] isEqualToString: _NS("Capture Device")] )
+            else if( [[[o_capture_mode_pop selectedItem] title] isEqualToString: _NS("Video Device")] )
             {
                 [o_options addObject: [NSString stringWithFormat: @"qtcapture-width=%i", [o_capture_width_fld intValue]]];
                 [o_options addObject: [NSString stringWithFormat: @"qtcapture-height=%i", [o_capture_height_fld intValue]]];
@@ -454,23 +521,49 @@ static VLCOpen *_o_sharedMainInstance = nil;
     }
 }
 
+- (IBAction)screenChanged:(id)sender
+{
+    int selected_index = [o_screen_screen_pop indexOfSelectedItem];
+    if( selected_index >= [o_displayInfos count] ) return;
+
+    NSValue *v = [o_displayInfos objectAtIndex:selected_index];
+    struct display_info_t *item = ( struct display_info_t * )[v pointerValue];
+
+    [o_screen_left_stp setMaxValue: item->rect.size.width];
+    [o_screen_top_stp setMaxValue: item->rect.size.height];
+    [o_screen_width_stp setMaxValue: item->rect.size.width];
+    [o_screen_height_stp setMaxValue: item->rect.size.height];
+}
+
 - (IBAction)qtkChanged:(id)sender
 {
-       NSInteger i_selectedDevice = [o_qtk_device_pop indexOfSelectedItem];
-       if (i_selectedDevice > ([qtkvideoDevices count] - 1))
-       {
-               NSValue *sizes = [[[[qtkvideoDevices objectAtIndex:i_selectedDevice] formatDescriptions] objectAtIndex: 0] attributeForKey: QTFormatDescriptionVideoEncodedPixelsSizeAttribute];
-
-               [o_capture_width_fld setIntValue: [sizes sizeValue].width];
-               [o_capture_height_fld setIntValue: [sizes sizeValue].height];
-               [o_capture_width_stp setIntValue: [o_capture_width_fld intValue]];
-               [o_capture_height_stp setIntValue: [o_capture_height_fld intValue]];
-               qtk_currdevice_uid = [[(QTCaptureDevice *)[qtkvideoDevices objectAtIndex:i_selectedDevice] uniqueID]
-                                                         stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
-               [self setMRL:[NSString stringWithFormat:@"qtcapture://%@", qtk_currdevice_uid]];
-       }
+    NSInteger i_selectedDevice = [o_qtk_device_pop indexOfSelectedItem];
+    if( [qtkvideoDevices count] >= 1 )
+    {
+        NSValue *sizes = [[[[qtkvideoDevices objectAtIndex:i_selectedDevice] formatDescriptions] objectAtIndex: 0] attributeForKey: QTFormatDescriptionVideoEncodedPixelsSizeAttribute];
+
+        [o_capture_width_fld setIntValue: [sizes sizeValue].width];
+        [o_capture_height_fld setIntValue: [sizes sizeValue].height];
+        [o_capture_width_stp setIntValue: [o_capture_width_fld intValue]];
+        [o_capture_height_stp setIntValue: [o_capture_height_fld intValue]];
+        qtk_currdevice_uid = [[(QTCaptureDevice *)[qtkvideoDevices objectAtIndex:i_selectedDevice] uniqueID] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
+        [self setMRL:[NSString stringWithFormat:@"qtcapture://%@", qtk_currdevice_uid]];
+    }
+}
+
+- (IBAction)qtkAudioChanged:(id)sender
+{
+    NSInteger i_selectedDevice = [o_qtkaudio_device_pop indexOfSelectedItem];
+    if( [qtkaudioDevices count] >= 1 )
+    {
+        qtkaudio_currdevice_uid = [[(QTCaptureDevice *)[qtkaudioDevices objectAtIndex:i_selectedDevice] uniqueID] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
+        [self setMRL:[NSString stringWithFormat:@"qtsound://%@", qtkaudio_currdevice_uid]];
+    }
 }
 
+#pragma mark -
+#pragma mark Main Actions
+
 - (void)tabView:(NSTabView *)o_tv didSelectTabViewItem:(NSTabViewItem *)o_tvi
 {
     NSString *o_label = [o_tvi label];
@@ -526,36 +619,6 @@ static VLCOpen *_o_sharedMainInstance = nil;
         [[o_panel contentView] addSubview: o_mrl_view];
 }
 
-- (IBAction)inputSlaveAction:(id)sender
-{
-    if( sender == o_file_slave_ckbox )
-        [o_file_slave_select_btn setEnabled: [o_file_slave_ckbox state]];
-    else
-    {
-        NSOpenPanel *o_open_panel;
-        o_open_panel = [NSOpenPanel openPanel];
-        [o_open_panel setCanChooseFiles: YES];
-        [o_open_panel setCanChooseDirectories: NO];
-        if( [o_open_panel runModal] == NSOKButton )
-        {
-            if( o_file_slave_path )
-                [o_file_slave_path release];
-            o_file_slave_path = [[[o_open_panel URLs] objectAtIndex: 0] path];
-            [o_file_slave_path retain];
-        }
-    }
-    if( o_file_slave_path && [o_file_slave_ckbox state] == NSOnState)
-    {
-        [o_file_slave_filename_lbl setStringValue: [[NSFileManager defaultManager] displayNameAtPath:o_file_slave_path]];
-        [o_file_slave_icon_well setImage: [[NSWorkspace sharedWorkspace] iconForFile: o_file_slave_path]];
-    }
-    else
-    {
-        [o_file_slave_filename_lbl setStringValue: @""];
-        [o_file_slave_icon_well setImage: NULL];
-    }
-}
-
 - (void)openFileGeneric
 {
     [self openFilePathChanged: nil];
@@ -582,6 +645,51 @@ static VLCOpen *_o_sharedMainInstance = nil;
     [self openTarget: 3];
 }
 
+- (void)openFile
+{
+    NSOpenPanel *o_open_panel = [NSOpenPanel openPanel];
+    b_autoplay = config_GetInt( VLCIntf, "macosx-autoplay" );
+
+    [o_open_panel setAllowsMultipleSelection: YES];
+    [o_open_panel setCanChooseDirectories: YES];
+    [o_open_panel setTitle: _NS("Open File")];
+    [o_open_panel setPrompt: _NS("Open")];
+
+    if( [o_open_panel runModal] == NSOKButton )
+    {
+        NSArray * o_urls = [o_open_panel URLs];
+        NSUInteger count = [o_urls count];
+        NSMutableArray *o_values = [NSMutableArray arrayWithCapacity:count];
+        NSMutableArray *o_array = [NSMutableArray arrayWithCapacity:count];
+        for( NSUInteger i = 0; i < count; i++ )
+        {
+            [o_values addObject: [[o_urls objectAtIndex: i] path]];
+        }
+        [o_values sortUsingSelector:@selector(caseInsensitiveCompare:)];
+
+        for( NSUInteger i = 0; i < count; i++ )
+        {
+            NSDictionary *o_dic;
+            char *psz_uri = make_URI([[o_values objectAtIndex:i] UTF8String], "file");
+            if( !psz_uri )
+                continue;
+
+            o_dic = [NSDictionary dictionaryWithObject:[NSString stringWithCString:psz_uri encoding:NSUTF8StringEncoding] forKey:@"ITEM_URL"];
+
+            free( psz_uri );
+
+            [o_array addObject: o_dic];
+        }
+        if( b_autoplay )
+            [[[VLCMain sharedInstance] playlist] appendArray: o_array atPos: -1 enqueue:NO];
+        else
+            [[[VLCMain sharedInstance] playlist] appendArray: o_array atPos: -1 enqueue:YES];
+    }
+}
+
+#pragma mark -
+#pragma mark File Panel
+
 - (void)openFilePathChanged:(NSNotification *)o_notification
 {
     if ( o_file_path && [o_file_path length] > 0 )
@@ -623,7 +731,7 @@ static VLCOpen *_o_sharedMainInstance = nil;
 - (IBAction)openFileBrowse:(id)sender
 {
     NSOpenPanel *o_open_panel = [NSOpenPanel openPanel];
+
     [o_open_panel setAllowsMultipleSelection: NO];
     [o_open_panel setCanChooseDirectories: YES];
     [o_open_panel setTitle: _NS("Open File")];
@@ -657,6 +765,48 @@ static VLCOpen *_o_sharedMainInstance = nil;
     [self openFilePathChanged: nil];
 }
 
+- (IBAction)inputSlaveAction:(id)sender
+{
+    if( sender == o_file_slave_ckbox )
+        [o_file_slave_select_btn setEnabled: [o_file_slave_ckbox state]];
+    else
+    {
+        NSOpenPanel *o_open_panel;
+        o_open_panel = [NSOpenPanel openPanel];
+        [o_open_panel setCanChooseFiles: YES];
+        [o_open_panel setCanChooseDirectories: NO];
+        if( [o_open_panel runModal] == NSOKButton )
+        {
+            if( o_file_slave_path )
+                [o_file_slave_path release];
+            o_file_slave_path = [[[o_open_panel URLs] objectAtIndex: 0] path];
+            [o_file_slave_path retain];
+        }
+    }
+    if( o_file_slave_path && [o_file_slave_ckbox state] == NSOnState)
+    {
+        [o_file_slave_filename_lbl setStringValue: [[NSFileManager defaultManager] displayNameAtPath:o_file_slave_path]];
+        [o_file_slave_icon_well setImage: [[NSWorkspace sharedWorkspace] iconForFile: o_file_slave_path]];
+    }
+    else
+    {
+        [o_file_slave_filename_lbl setStringValue: @""];
+        [o_file_slave_icon_well setImage: NULL];
+    }
+}
+
+- (IBAction)fileTimeCustomization:(id)sender
+{
+    BOOL b_value = [o_file_custom_timing_ckb state];
+    [o_file_starttime_fld setEnabled: b_value];
+    [o_file_starttime_lbl setEnabled: b_value];
+    [o_file_stoptime_fld setEnabled: b_value];
+    [o_file_stoptime_lbl setEnabled: b_value];
+}
+
+#pragma mark -
+#pragma mark Optical Media Panel
+
 - (void)showOpticalMediaView: theView withIcon:(NSImage *)icon
 {
     NSRect o_view_rect;
@@ -717,13 +867,13 @@ static VLCOpen *_o_sharedMainInstance = nil;
 
     GetVolParmsInfoBuffer volumeParms;
     err = FSGetVolumeParms( actualVolume, &volumeParms, sizeof(volumeParms) );
-    if ( noErr != err ) {
-        msg_Err( p_intf, "error retrieving volume params, bailing out" );
-        return @"";
+    if ( noErr == err )
+    {
+        NSString *bsdName = [NSString stringWithUTF8String:(char *)volumeParms.vMDeviceID];
+        return [NSString stringWithFormat:@"/dev/r%@", bsdName];
     }
 
-    NSString *bsdName = [NSString stringWithUTF8String:(char *)volumeParms.vMDeviceID];
-    return [NSString stringWithFormat:@"/dev/r%@", bsdName];
+    return @"";
 }
 
 - (char *)getVolumeTypeFromMountPath:(NSString *)mountPath
@@ -751,8 +901,8 @@ static VLCOpen *_o_sharedMainInstance = nil;
     GetVolParmsInfoBuffer volumeParms;
     err = FSGetVolumeParms( actualVolume, &volumeParms, sizeof(volumeParms) );
 
-    CFMutableDictionaryRef     matchingDict;
-    io_service_t                       service;
+    CFMutableDictionaryRef matchingDict;
+    io_service_t service;
 
     matchingDict = IOBSDNameMatching(kIOMasterPortDefault, 0, volumeParms.vMDeviceID);
     service = IOServiceGetMatchingService(kIOMasterPortDefault, matchingDict);
@@ -768,27 +918,51 @@ static VLCOpen *_o_sharedMainInstance = nil;
             returnValue = kVLCMediaBD;
         else
         {
-            if ([mountPath rangeOfString:@"VIDEO_TS"].location != NSNotFound)
+            if ([mountPath rangeOfString:@"VIDEO_TS" options:NSCaseInsensitiveSearch | NSBackwardsSearch].location != NSNotFound)
                 returnValue = kVLCMediaVideoTSFolder;
-            else if ([mountPath rangeOfString:@"BDMV"].location != NSNotFound)
+            else if ([mountPath rangeOfString:@"BDMV" options:NSCaseInsensitiveSearch | NSBackwardsSearch].location != NSNotFound)
                 returnValue = kVLCMediaBDMVFolder;
             else
             {
-                NSArray * topLevelItems;
-                topLevelItems = [[NSFileManager defaultManager] subpathsOfDirectoryAtPath: mountPath error: NULL];
-                NSUInteger itemCount = [topLevelItems count];
-                for (int i = 0; i < itemCount; i++) {
-                    if([[topLevelItems objectAtIndex:i] rangeOfString:@"SVCD"].location != NSNotFound) {
-                        returnValue = kVLCMediaSVCD;
-                        break;
-                    }
-                    if([[topLevelItems objectAtIndex:i] rangeOfString:@"VCD"].location != NSNotFound) {
-                        returnValue = kVLCMediaVCD;
-                        break;
+                // NSFileManager is not thread-safe, don't use defaultManager outside of the main thread
+                NSFileManager * fm = [[NSFileManager alloc] init];
+
+                NSArray *dirContents = [fm contentsOfDirectoryAtPath:mountPath error:nil];
+                for (int i = 0; i < [dirContents count]; i++)
+                {
+                    NSString *currentFile = [dirContents objectAtIndex:i];
+                    NSString *fullPath = [mountPath stringByAppendingPathComponent:currentFile];
+
+                    BOOL isDir;
+                    if ([fm fileExistsAtPath:fullPath isDirectory:&isDir] && isDir)
+                    {
+                        if ([currentFile caseInsensitiveCompare:@"SVCD"] == NSOrderedSame)
+                        {
+                            returnValue = kVLCMediaSVCD;
+                            break;
+                        }
+                        if ([currentFile caseInsensitiveCompare:@"VCD"] == NSOrderedSame)
+                        {
+                            returnValue = kVLCMediaVCD;
+                            break;
+                        }
+                        if ([currentFile caseInsensitiveCompare:@"BDMV"] == NSOrderedSame)
+                        {
+                            returnValue = kVLCMediaBDMVFolder;
+                            break;
+                        }
+                        if ([currentFile caseInsensitiveCompare:@"VIDEO_TS"] == NSOrderedSame)
+                        {
+                            returnValue = kVLCMediaVideoTSFolder;
+                            break;
+                        }
                     }
                 }
+
+                [fm release];
+
                 if(!returnValue)
-                    returnValue = kVLCMediaUnknown;
+                    returnValue = kVLCMediaVideoTSFolder;
             }
         }
 
@@ -797,64 +971,53 @@ static VLCOpen *_o_sharedMainInstance = nil;
     return returnValue;
 }
 
-- (void)showOpticalAtIndex: (NSNumber *)n_index
+- (void)showOpticalAtPath: (NSString *)o_opticalDevicePath
 {
     NSAutoreleasePool * o_pool = [[NSAutoreleasePool alloc] init];
 
-    if (!o_opticalDevices)
-        return;
-
-    if ([o_opticalDevices count] == 0)
-        return;
-
-    unsigned int index = [n_index intValue];
-       id o_currentOpticalDevice = [o_opticalDevices objectAtIndex: index];
-    char *diskType = [self getVolumeTypeFromMountPath:o_currentOpticalDevice];
+    char *diskType = [self getVolumeTypeFromMountPath:o_opticalDevicePath];
 
     if (diskType == kVLCMediaDVD || diskType == kVLCMediaVideoTSFolder)
     {
-        [o_disc_dvd_lbl setStringValue: [[NSFileManager defaultManager] displayNameAtPath:o_currentOpticalDevice]];
+        [o_disc_dvd_lbl setStringValue: [[NSFileManager defaultManager] displayNameAtPath:o_opticalDevicePath]];
         [o_disc_dvdwomenus_lbl setStringValue: [o_disc_dvd_lbl stringValue]];
         NSString *pathToOpen;
         if (diskType == kVLCMediaVideoTSFolder)
-            pathToOpen = o_currentOpticalDevice;
+            pathToOpen = o_opticalDevicePath;
         else
-            pathToOpen = [self getBSDNodeFromMountPath: o_currentOpticalDevice];
+            pathToOpen = [self getBSDNodeFromMountPath: o_opticalDevicePath];
         if (!b_nodvdmenus) {
             [self setMRL: [NSString stringWithFormat: @"dvdnav://%@", pathToOpen]];
-            [self showOpticalMediaView: o_disc_dvd_view withIcon: [[NSWorkspace sharedWorkspace] iconForFile: o_currentOpticalDevice]];
+            [self showOpticalMediaView: o_disc_dvd_view withIcon: [[NSWorkspace sharedWorkspace] iconForFile: o_opticalDevicePath]];
         } else {
-            [self setMRL: [NSString stringWithFormat: @"dvdread://%@@%i:%i-", pathToOpen, [o_disc_dvdwomenus_title intValue], [o_disc_dvdwomenus_chapter intValue]]];
-            [self showOpticalMediaView: o_disc_dvdwomenus_view withIcon: [[NSWorkspace sharedWorkspace] iconForFile: o_currentOpticalDevice]];
+            [self setMRL: [NSString stringWithFormat: @"dvdread://%@#%i:%i-", pathToOpen, [o_disc_dvdwomenus_title intValue], [o_disc_dvdwomenus_chapter intValue]]];
+            [self showOpticalMediaView: o_disc_dvdwomenus_view withIcon: [[NSWorkspace sharedWorkspace] iconForFile: o_opticalDevicePath]];
         }
     }
     else if (diskType == kVLCMediaAudioCD)
     {
-        [o_disc_audiocd_lbl setStringValue: [[NSFileManager defaultManager] displayNameAtPath: o_currentOpticalDevice]];
-        [o_disc_audiocd_trackcount_lbl setStringValue: [NSString stringWithFormat:_NS("%i tracks"), [[[NSFileManager defaultManager] subpathsOfDirectoryAtPath: o_currentOpticalDevice error:NULL] count] - 1]]; // minus .TOC.plist
-        [self showOpticalMediaView: o_disc_audiocd_view withIcon: [[NSWorkspace sharedWorkspace] iconForFile: o_currentOpticalDevice]];
-        [self setMRL: [NSString stringWithFormat: @"cdda://%@", [self getBSDNodeFromMountPath: o_currentOpticalDevice]]];
+        [o_disc_audiocd_lbl setStringValue: [[NSFileManager defaultManager] displayNameAtPath: o_opticalDevicePath]];
+        [o_disc_audiocd_trackcount_lbl setStringValue: [NSString stringWithFormat:_NS("%i tracks"), [[[NSFileManager defaultManager] subpathsOfDirectoryAtPath: o_opticalDevicePath error:NULL] count] - 1]]; // minus .TOC.plist
+        [self showOpticalMediaView: o_disc_audiocd_view withIcon: [[NSWorkspace sharedWorkspace] iconForFile: o_opticalDevicePath]];
+        [self setMRL: [NSString stringWithFormat: @"cdda://%@", [self getBSDNodeFromMountPath: o_opticalDevicePath]]];
     }
     else if (diskType == kVLCMediaVCD)
     {
-        [o_disc_vcd_lbl setStringValue: [[NSFileManager defaultManager] displayNameAtPath: o_currentOpticalDevice]];
-        [self showOpticalMediaView: o_disc_vcd_view withIcon: [[NSWorkspace sharedWorkspace] iconForFile: o_currentOpticalDevice]];
-        [self setMRL: [NSString stringWithFormat: @"vcd://%@#%i:%i", [self getBSDNodeFromMountPath: o_currentOpticalDevice], [o_disc_vcd_title intValue], [o_disc_vcd_chapter intValue]]];
+        [o_disc_vcd_lbl setStringValue: [[NSFileManager defaultManager] displayNameAtPath: o_opticalDevicePath]];
+        [self showOpticalMediaView: o_disc_vcd_view withIcon: [[NSWorkspace sharedWorkspace] iconForFile: o_opticalDevicePath]];
+        [self setMRL: [NSString stringWithFormat: @"vcd://%@#%i:%i", [self getBSDNodeFromMountPath: o_opticalDevicePath], [o_disc_vcd_title intValue], [o_disc_vcd_chapter intValue]]];
     }
     else if (diskType == kVLCMediaSVCD)
     {
-        [o_disc_vcd_lbl setStringValue: [[NSFileManager defaultManager] displayNameAtPath: o_currentOpticalDevice]];
-        [self showOpticalMediaView: o_disc_vcd_view withIcon: [[NSWorkspace sharedWorkspace] iconForFile: o_currentOpticalDevice]];
-        [self setMRL: [NSString stringWithFormat: @"vcd://%@@%i:%i", [self getBSDNodeFromMountPath: o_currentOpticalDevice], [o_disc_vcd_title intValue], [o_disc_vcd_chapter intValue]]];
+        [o_disc_vcd_lbl setStringValue: [[NSFileManager defaultManager] displayNameAtPath: o_opticalDevicePath]];
+        [self showOpticalMediaView: o_disc_vcd_view withIcon: [[NSWorkspace sharedWorkspace] iconForFile: o_opticalDevicePath]];
+        [self setMRL: [NSString stringWithFormat: @"vcd://%@@%i:%i", [self getBSDNodeFromMountPath: o_opticalDevicePath], [o_disc_vcd_title intValue], [o_disc_vcd_chapter intValue]]];
     }
     else if (diskType == kVLCMediaBD || diskType == kVLCMediaBDMVFolder)
     {
-        [o_disc_bd_lbl setStringValue: [[NSFileManager defaultManager] displayNameAtPath: o_currentOpticalDevice]];
-        [self showOpticalMediaView: o_disc_bd_view withIcon: [[NSWorkspace sharedWorkspace] iconForFile: o_currentOpticalDevice]];
-        if (diskType == kVLCMediaBD)
-            [self setMRL: [NSString stringWithFormat: @"bluray://%@", [self getBSDNodeFromMountPath: o_currentOpticalDevice]]];
-        else
-            [self setMRL: [NSString stringWithFormat: @"bluray://%@", o_currentOpticalDevice]];
+        [o_disc_bd_lbl setStringValue: [[NSFileManager defaultManager] displayNameAtPath: o_opticalDevicePath]];
+        [self showOpticalMediaView: o_disc_bd_view withIcon: [[NSWorkspace sharedWorkspace] iconForFile: o_opticalDevicePath]];
+        [self setMRL: [NSString stringWithFormat: @"bluray://%@", o_opticalDevicePath]];
     }
     else
     {
@@ -865,13 +1028,18 @@ static VLCOpen *_o_sharedMainInstance = nil;
     [o_pool release];
 }
 
+- (void)showSelectedOpticalDisc
+{
+    NSString *o_opticalDevicePath = [o_opticalDevices objectAtIndex:[o_disc_selector_pop indexOfSelectedItem]];
+    [NSThread detachNewThreadSelector:@selector(showOpticalAtPath:) toTarget:self withObject:o_opticalDevicePath];
+}
+
 - (void)scanOpticalMedia:(NSNotification *)o_notification
 {
     [o_opticalDevices removeAllObjects];
     [o_disc_selector_pop removeAllItems];
     [o_opticalDevices addObjectsFromArray: [[NSWorkspace sharedWorkspace] mountedRemovableMedia]];
-    if ([o_specialMediaFolders count] > 0)
-        [o_opticalDevices addObjectsFromArray: o_specialMediaFolders];
+    [o_opticalDevices addObjectsFromArray: o_specialMediaFolders];
     if ([o_opticalDevices count] > 0) {
         NSUInteger deviceCount = [o_opticalDevices count];
         for (NSUInteger i = 0; i < deviceCount ; i++)
@@ -882,7 +1050,11 @@ static VLCOpen *_o_sharedMainInstance = nil;
         else
             [o_disc_selector_pop setHidden: NO];
 
-        [NSThread detachNewThreadSelector:@selector(showOpticalAtIndex:) toTarget:self withObject:[NSNumber numberWithInt:[o_disc_selector_pop indexOfSelectedItem]]];
+        // select newly added media folder
+        if (o_notification && [[o_notification name] isEqualToString:@"VLCNewMediaFolderNotification"])
+            [o_disc_selector_pop selectItemAtIndex: [[o_disc_selector_pop itemArray] count] - 1];
+
+        [self showSelectedOpticalDisc];
     }
     else
     {
@@ -894,7 +1066,7 @@ static VLCOpen *_o_sharedMainInstance = nil;
 
 - (IBAction)discSelectorChanged:(id)sender
 {
-    [NSThread detachNewThreadSelector:@selector(showOpticalAtIndex:) toTarget:self withObject:[NSNumber numberWithInt:[o_disc_selector_pop indexOfSelectedItem]]];
+    [self showSelectedOpticalDisc];
 }
 
 - (IBAction)openSpecialMediaFolder:(id)sender
@@ -913,22 +1085,26 @@ static VLCOpen *_o_sharedMainInstance = nil;
         NSString *o_path = [[[o_open_panel URLs] objectAtIndex: 0] path];
         if ([o_path length] > 0 )
         {
-            if ([o_path rangeOfString:@"VIDEO_TS"].location != NSNotFound || [o_path rangeOfString:@"BDMV"].location != NSNotFound)
-            {
-                [o_specialMediaFolders addObject: o_path];
-                [self scanOpticalMedia: nil];
-            }
-            else
-                msg_Dbg( VLCIntf, "chosen directory is no suitable special media folder" );
+            [o_specialMediaFolders addObject: o_path];
+            [self scanOpticalMedia: [NSNotification notificationWithName:@"VLCNewMediaFolderNotification" object:nil]];
         }
     }
 }
 
 - (IBAction)dvdreadOptionChanged:(id)sender
 {
+    NSString *o_device_path = [o_opticalDevices objectAtIndex: [o_disc_selector_pop indexOfSelectedItem]];
+    char *diskType = [self getVolumeTypeFromMountPath:o_device_path];
+
+    NSString *pathToOpen;
+    if (diskType == kVLCMediaVideoTSFolder)
+        pathToOpen = o_device_path;
+    else
+        pathToOpen = [self getBSDNodeFromMountPath: o_device_path];
+
     if (sender == o_disc_dvdwomenus_enablemenus_btn) {
         b_nodvdmenus = NO;
-        [self setMRL: [NSString stringWithFormat: @"dvdnav://%@", [self getBSDNodeFromMountPath:[o_opticalDevices objectAtIndex: [o_disc_selector_pop indexOfSelectedItem]]]]];
+        [self setMRL: [NSString stringWithFormat: @"dvdnav://%@", pathToOpen]];
         [self showOpticalMediaView: o_disc_dvd_view withIcon: [o_currentOpticalMediaIconView image]];
         return;
     }
@@ -946,7 +1122,7 @@ static VLCOpen *_o_sharedMainInstance = nil;
     if (sender == o_disc_dvdwomenus_chapter_stp)
         [o_disc_dvdwomenus_chapter setIntValue: [o_disc_dvdwomenus_chapter_stp intValue]];
 
-    [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]]];
+    [self setMRL: [NSString stringWithFormat: @"dvdread://%@#%i:%i-", pathToOpen, [o_disc_dvdwomenus_title intValue], [o_disc_dvdwomenus_chapter intValue]]];
 }
 
 - (IBAction)vcdOptionChanged:(id)sender
@@ -963,6 +1139,9 @@ static VLCOpen *_o_sharedMainInstance = nil;
     [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]]];
 }
 
+#pragma mark -
+#pragma mark Network Panel
+
 - (void)textFieldWasClicked:(NSNotification *)o_notification
 {
     if( [o_notification object] == o_net_udp_port )
@@ -1027,9 +1206,9 @@ static VLCOpen *_o_sharedMainInstance = nil;
             int i_port = [o_net_udp_port intValue];
 
             if( [[o_net_udp_protocol_mat selectedCell] tag] == 0 )
-                o_mrl_string = [NSString stringWithString: @"udp://"];
+                o_mrl_string = @"udp://";
             else
-                o_mrl_string = [NSString stringWithString: @"rtp://"];
+                o_mrl_string = @"rtp://";
 
             if( i_port != config_GetInt( p_intf, "server-port" ) )
             {
@@ -1083,11 +1262,11 @@ static VLCOpen *_o_sharedMainInstance = nil;
         if( [[[o_net_mode selectedCell] title] isEqualToString: _NS("Unicast")] )
         {
             int i_port = [o_net_udp_port intValue];
-            
+
             if( [[o_net_udp_protocol_mat selectedCell] tag] == 0 )
-                o_mrl_string = [NSString stringWithString: @"udp://"];
+                o_mrl_string = @"udp://";
             else
-                o_mrl_string = [NSString stringWithString: @"rtp://"];
+                o_mrl_string = @"rtp://";
 
             if( i_port != config_GetInt( p_intf, "server-port" ) )
             {
@@ -1099,7 +1278,7 @@ static VLCOpen *_o_sharedMainInstance = nil;
         {
             NSString *o_addr = [o_net_udpm_addr stringValue];
             int i_port = [o_net_udpm_port intValue];
-            
+
             if( [[o_net_udp_protocol_mat selectedCell] tag] == 0 )
                 o_mrl_string = [NSString stringWithFormat: @"udp://@%@", o_addr];
             else
@@ -1117,48 +1296,9 @@ static VLCOpen *_o_sharedMainInstance = nil;
         [NSApp endSheet: o_net_udp_panel];
     }
 }
-    
-- (void)openFile
-{
-    NSOpenPanel *o_open_panel = [NSOpenPanel openPanel];
-    b_autoplay = config_GetInt( VLCIntf, "macosx-autoplay" );
 
-    [o_open_panel setAllowsMultipleSelection: YES];
-    [o_open_panel setCanChooseDirectories: YES];
-    [o_open_panel setTitle: _NS("Open File")];
-    [o_open_panel setPrompt: _NS("Open")];
-    if( [o_open_panel runModal] == NSOKButton )
-    {
-        NSArray * o_urls = [o_open_panel URLs];
-        NSUInteger count = [o_urls count];
-        NSMutableArray *o_values = [NSMutableArray arrayWithCapacity:count];
-        NSMutableArray *o_array = [NSMutableArray arrayWithCapacity:count];
-        for( NSUInteger i = 0; i < count; i++ )
-        {
-            [o_values addObject: [[o_urls objectAtIndex: i] path]];
-        }
-        [o_values sortUsingSelector:@selector(caseInsensitiveCompare:)];
-
-        for( NSUInteger i = 0; i < count; i++ )
-        {
-            NSDictionary *o_dic;
-            char *psz_uri = make_URI([[o_values objectAtIndex:i] UTF8String], "file");
-            if( !psz_uri )
-                continue;
-
-            o_dic = [NSDictionary dictionaryWithObject:[NSString stringWithCString:psz_uri encoding:NSUTF8StringEncoding] forKey:@"ITEM_URL"];
-
-            free( psz_uri );
-
-            [o_array addObject: o_dic];
-        }
-        if( b_autoplay )
-            [[[VLCMain sharedInstance] playlist] appendArray: o_array atPos: -1 enqueue:NO];
-        else
-            [[[VLCMain sharedInstance] playlist] appendArray: o_array atPos: -1 enqueue:YES];
-    }
-}
+#pragma mark -
+#pragma mark Capture Panel
 
 - (void)showCaptureView: theView
 {
@@ -1172,7 +1312,9 @@ static VLCOpen *_o_sharedMainInstance = nil;
         [o_currentCaptureView release];
     }
     else
-         [[[[o_tabview tabViewItemAtIndex: 3] view] animator] addSubview: theView];
+    {
+        [[[[o_tabview tabViewItemAtIndex: 3] view] animator] addSubview: theView];
+    }
     o_currentCaptureView = theView;
     [o_currentCaptureView retain];
 }
@@ -1196,7 +1338,7 @@ static VLCOpen *_o_sharedMainInstance = nil;
         else
             [self showCaptureView: o_eyetv_notLaunched_view];
         [self setMRL: @""];
-    } 
+    }
     else if( [[[o_capture_mode_pop selectedItem] title] isEqualToString: _NS("Screen")] )
     {
         [self showCaptureView: o_screen_view];
@@ -1207,8 +1349,51 @@ static VLCOpen *_o_sharedMainInstance = nil;
         [o_screen_left_fld setIntValue: config_GetInt( p_intf, "screen-left" )];
         [o_screen_top_fld setIntValue: config_GetInt( p_intf, "screen-top" )];
         [o_screen_follow_mouse_ckb setIntValue: config_GetInt( p_intf, "screen-follow-mouse" )];
+
+        int screen_index = config_GetInt( p_intf, "screen-index" );
+        int display_id = config_GetInt( p_intf, "screen-display-id" );
+        unsigned int i, displayCount = 0;
+        CGLError returnedError;
+        struct display_info_t *item;
+        NSValue *v;
+
+        returnedError = CGGetOnlineDisplayList( 0, NULL, &displayCount );
+        if( !returnedError )
+        {
+            CGDirectDisplayID *ids;
+            ids = ( CGDirectDisplayID * )malloc( displayCount * sizeof( CGDirectDisplayID ) );
+            returnedError = CGGetOnlineDisplayList( displayCount, ids, &displayCount );
+            if( !returnedError )
+            {
+                for( i = 0; i < [o_displayInfos count]; i ++ )
+                {
+                    v = [o_displayInfos objectAtIndex:i];
+                    free( [v pointerValue] );
+                }
+                [o_displayInfos removeAllObjects];
+                [o_screen_screen_pop removeAllItems];
+                for( i = 0; i < displayCount; i ++ )
+                {
+                    item = ( struct display_info_t * )malloc( sizeof( struct display_info_t ) );
+                    item->id = ids[i];
+                    item->rect = CGDisplayBounds( item->id );
+                    [o_screen_screen_pop addItemWithTitle: [NSString stringWithFormat:@"Screen %d (%dx%d)", i + 1, (int)item->rect.size.width, (int)item->rect.size.height]];
+                    v = [NSValue valueWithPointer:item];
+                    [o_displayInfos addObject:v];
+                    if( i == 0 || display_id == item->id || screen_index - 1 == i )
+                    {
+                        [o_screen_screen_pop selectItemAtIndex: i];
+                        [o_screen_left_stp setMaxValue: item->rect.size.width];
+                        [o_screen_top_stp setMaxValue: item->rect.size.height];
+                        [o_screen_width_stp setMaxValue: item->rect.size.width];
+                        [o_screen_height_stp setMaxValue: item->rect.size.height];
+                    }
+                }
+            }
+            free( ids );
+        }
     }
-    else if( [[[o_capture_mode_pop selectedItem] title] isEqualToString: _NS("Capture Device")] )
+    else if( [[[o_capture_mode_pop selectedItem] title] isEqualToString: _NS("Video Device")] )
     {
         [self showCaptureView: o_qtk_view];
         if ([o_capture_width_fld intValue] <= 0)
@@ -1219,13 +1404,16 @@ static VLCOpen *_o_sharedMainInstance = nil;
         else
             [self setMRL:[NSString stringWithFormat:@"qtcapture://%@", qtk_currdevice_uid]];
     }
-}
+    else if( [[[o_capture_mode_pop selectedItem] title] isEqualToString: _NS("Audio Device")] )
+    {
+        [self showCaptureView: o_qtkaudio_view];
+        [self qtkAudioChanged:nil];
 
-- (IBAction)screenStepperChanged:(id)sender
-{
-    [o_screen_fps_fld setFloatValue: [o_screen_fps_stp floatValue]];
-    [o_panel makeFirstResponder: o_screen_fps_fld];
-    [self setMRL: @"screen://"];
+        if(!qtkaudio_currdevice_uid)
+            [self setMRL: @""];
+        else
+            [self setMRL:[NSString stringWithFormat:@"qtsound://%@", qtkaudio_currdevice_uid]];
+    }
 }
 
 - (void)screenFPSfieldChanged:(NSNotification *)o_notification
@@ -1297,7 +1485,7 @@ static VLCOpen *_o_sharedMainInstance = nil;
         msg_Dbg( VLCIntf, "eyetv was launched, no device yet" );
         setEyeTVUnconnected;
     }
-}    
+}
 
 /* little helper method, since this code needs to be run by multiple objects */
 - (void)setupChannelInfo
@@ -1308,7 +1496,7 @@ static VLCOpen *_o_sharedMainInstance = nil;
     [o_eyetv_chn_bgbar animate: self];
     [o_eyetv_chn_status_txt setStringValue: _NS("Retrieving Channel Info...")];
     [o_eyetv_chn_status_txt setHidden: NO];
+
     /* retrieve info */
     NSEnumerator *channels = [[[VLCMain sharedInstance] eyeTVController] allChannels];
     int x = -2;
@@ -1318,7 +1506,7 @@ static VLCOpen *_o_sharedMainInstance = nil;
     [[[o_eyetv_channels_pop menu] addItemWithTitle: _NS("S-Video input")
                                                action: nil
                                         keyEquivalent: @""] setTag:x++];
-    if( channels ) 
+    if( channels )
     {
         NSString *channel;
         [[o_eyetv_channels_pop menu] addItem: [NSMenuItem separatorItem]];
@@ -1333,12 +1521,15 @@ static VLCOpen *_o_sharedMainInstance = nil;
         /* make Tuner the default */
         [o_eyetv_channels_pop selectItemWithTag:[[[VLCMain sharedInstance] eyeTVController] currentChannel]];
     }
+
     /* clean up GUI */
     [o_eyetv_chn_bgbar setHidden: YES];
     [o_eyetv_chn_status_txt setHidden: YES];
 }
 
+#pragma mark -
+#pragma mark Subtitle Settings
+
 - (IBAction)subsChanged:(id)sender
 {
     if ([o_file_sub_ckbox state] == NSOnState)
@@ -1372,11 +1563,11 @@ static VLCOpen *_o_sharedMainInstance = nil;
     [o_file_sub_sheet orderOut:sender];
     [NSApp endSheet: o_file_sub_sheet];
 }
-    
+
 - (IBAction)subFileBrowse:(id)sender
 {
     NSOpenPanel *o_open_panel = [NSOpenPanel openPanel];
+
     [o_open_panel setAllowsMultipleSelection: NO];
     [o_open_panel setTitle: _NS("Open File")];
     [o_open_panel setPrompt: _NS("Open")];
@@ -1420,6 +1611,9 @@ static VLCOpen *_o_sharedMainInstance = nil;
     [o_file_sub_fps setFloatValue: [o_file_sub_fps_stp floatValue]];
 }
 
+#pragma mark -
+#pragma mark Miscellaneous
+
 - (IBAction)panelCancel:(id)sender
 {
     [NSApp stopModalWithCode: 0];
@@ -1435,17 +1629,30 @@ static VLCOpen *_o_sharedMainInstance = nil;
 
 - (NSArray *)qtkvideoDevices
 {
-    if (!qtkvideoDevices)
-        [self qtkrefreshDevices];
+    if ( !qtkvideoDevices )
+        [self qtkrefreshVideoDevices];
     return qtkvideoDevices;
 }
 
-- (void)qtkrefreshDevices
+- (void)qtkrefreshVideoDevices
 {
     [qtkvideoDevices release];
     qtkvideoDevices = [[[QTCaptureDevice inputDevicesWithMediaType:QTMediaTypeVideo] arrayByAddingObjectsFromArray:[QTCaptureDevice inputDevicesWithMediaType:QTMediaTypeMuxed]] retain];
 }
 
+- (NSArray *)qtkaudioDevices
+{
+    if ( !qtkaudioDevices )
+        [self qtkrefreshAudioDevices];
+    return qtkaudioDevices;
+}
+
+- (void)qtkrefreshAudioDevices
+{
+    [qtkaudioDevices release];
+    qtkaudioDevices = [[[QTCaptureDevice inputDevicesWithMediaType:QTMediaTypeSound] arrayByAddingObjectsFromArray:[QTCaptureDevice inputDevicesWithMediaType:QTMediaTypeMuxed]] retain];
+}
+
 @end
 
 @implementation VLCOpenTextField