]> git.sesse.net Git - vlc/blobdiff - modules/gui/macosx/playlist.m
* First set config variable, then add the files (and therefore potentially
[vlc] / modules / gui / macosx / playlist.m
index d290a41d90f5604fcc8d7b4b020e47e2c362c7d0..071990eefb3f113fcac8d4d2feaac4e8f684b622 100644 (file)
@@ -1,10 +1,11 @@
 /*****************************************************************************
  * playlist.m: MacOS X interface plugin
  *****************************************************************************
- * Copyright (C) 2002 VideoLAN
- * $Id: playlist.m,v 1.1 2002/08/04 17:23:43 sam Exp $
+ * Copyright (C) 2002-2003 VideoLAN
+ * $Id: playlist.m,v 1.22 2003/05/12 01:17:10 hartman Exp $
  *
  * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
+ *          Derk-Jan Hartman <thedj@users.sourceforge.net>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 #include <sys/param.h>                                    /* for MAXPATHLEN */
 #include <string.h>
 
-#include <vlc/vlc.h>
-#include <vlc/intf.h>
-
-#include <Cocoa/Cocoa.h> 
-
 #include "intf.h"
 #include "playlist.h"
 
  *****************************************************************************/
 @implementation VLCPlaylistView
 
+- (void)dealloc
+{
+    if( o_striped_row_color != nil )
+    {
+        [o_striped_row_color release];
+    }
+    [super dealloc];
+}
+
 - (NSMenu *)menuForEvent:(NSEvent *)o_event
 {
-    /* TODO */
+    return( [[self delegate] menuForEvent: o_event] );
+}
+
+- (void)keyDown:(NSEvent *)o_event
+{
+    unichar key = 0;
+    int i_row;
+    playlist_t * p_playlist;
+    intf_thread_t * p_intf = [NSApp getIntf];
+
+    if( [[o_event characters] length] )
+    {
+        key = [[o_event characters] characterAtIndex: 0];
+    }
 
-    return( nil );
+    p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+                                          FIND_ANYWHERE );
+    
+    if ( p_playlist == NULL )
+    {
+        return;
+    }
+    
+    switch( key )
+    {
+        case ' ':
+            vlc_mutex_lock( &p_playlist->object_lock );
+            if( p_playlist->p_input != NULL )
+            {
+                input_SetStatus( p_playlist->p_input, INPUT_STATUS_PAUSE );
+            }
+            vlc_mutex_unlock( &p_playlist->object_lock );
+            break;
+
+        case NSDeleteCharacter:
+        case NSDeleteFunctionKey:
+        case NSDeleteCharFunctionKey:
+        case NSBackspaceCharacter:
+            while( ( i_row = [self selectedRow] ) != -1 )
+            {
+                if( p_playlist->i_index == i_row && p_playlist->i_status )
+                {
+                    playlist_Stop( p_playlist );
+                }
+        
+                playlist_Delete( p_playlist, i_row ); 
+        
+                [self deselectRow: i_row];
+            }
+            [self reloadData];
+            break;
+            
+        default:
+            [super keyDown: o_event];
+            break;
+    }
+
+    if( p_playlist != NULL )
+    {
+        vlc_object_release( p_playlist );
+    }
+}
+
+- (void) highlightSelectionInClipRect:(NSRect)o_rect {
+    NSRect o_new_rect;
+    float f_height = [self rowHeight] + [self intercellSpacing].height;
+    float f_origin_y = NSMaxY( o_rect );
+    int i_row = o_rect.origin.y / f_height;
+    
+    if ( i_row % 2 == 0 )
+    {
+        i_row++;
+    }
+    
+    o_new_rect.size.width = o_rect.size.width;
+    o_new_rect.size.height = f_height;
+    o_new_rect.origin.x = o_rect.origin.x;
+    o_new_rect.origin.y = i_row * f_height;
+    
+    if ( o_striped_row_color == nil )
+    {
+        o_striped_row_color = [[[NSColor alternateSelectedControlColor]
+                                highlightWithLevel: 0.90] retain];
+    }
+    [o_striped_row_color set];
+    
+    while ( o_new_rect.origin.y < f_origin_y ) {
+        NSRectFill( o_new_rect );
+        o_new_rect.origin.y += f_height * 2.0;
+    }
+    [super highlightSelectionInClipRect:o_rect];
 }
 
 @end
  *****************************************************************************/
 @implementation VLCPlaylist
 
+- (id)init
+{
+    self = [super init];
+    if ( self !=nil )
+    {
+        i_moveRow = -1;
+    }
+    return self;
+}
+
 - (void)awakeFromNib
 {
     [o_table_view setTarget: self];
     [o_table_view setDelegate: self];
     [o_table_view setDataSource: self];
 
-    [o_table_view setDoubleAction: @selector(doubleClick:)];
+    [o_table_view setDoubleAction: @selector(playItem:)];
 
     [o_table_view registerForDraggedTypes: 
         [NSArray arrayWithObjects: NSFilenamesPboardType, nil]];
 
-    [o_panel setTitle: _NS("Playlist")];
-    [o_btn_close setTitle: _NS("Close")];
+    [o_mi_play setTitle: _NS("Play")];
+    [o_mi_delete setTitle: _NS("Delete")];
+    [o_mi_selectall setTitle: _NS("Select All")];
+    
+    [o_btn_add setToolTip: _NS("Add")];
+    [o_btn_remove setToolTip: _NS("Delete")];
 }
 
 - (BOOL)tableView:(NSTableView *)o_tv 
     return( NO );
 }
 
-- (NSDragOperation)tableView:(NSTableView*)o_tv 
-                   validateDrop:(id <NSDraggingInfo>)info 
-                   proposedRow:(int)i_row 
-                   proposedDropOperation:(NSTableViewDropOperation)operation
-{
-    return( NSDragOperationPrivate );
-}
-
-- (BOOL)tableView:(NSTableView*)o_tv 
-                  acceptDrop:(id <NSDraggingInfo>)info 
-                  row:(int)i_row 
-                  dropOperation:(NSTableViewDropOperation)operation
+- (NSMenu *)menuForEvent:(NSEvent *)o_event
 {
-    NSArray * o_values;
-    NSPasteboard * o_pasteboard;
-
-    o_pasteboard = [info draggingPasteboard];
+    NSPoint pt;
+    vlc_bool_t b_rows;
+    vlc_bool_t b_item_sel;
 
-    if( [[o_pasteboard types] containsObject: NSFilenamesPboardType] )
-    {
-        o_values = [o_pasteboard propertyListForType: NSFilenamesPboardType];
+    pt = [o_table_view convertPoint: [o_event locationInWindow] 
+                                                 fromView: nil];
+    b_item_sel = ( [o_table_view rowAtPoint: pt] != -1 &&
+                   [o_table_view selectedRow] != -1 );
+    b_rows = [o_table_view numberOfRows] != 0;
 
-        [self appendArray: o_values atPos: i_row];
+    [o_mi_play setEnabled: b_item_sel];
+    [o_mi_delete setEnabled: b_item_sel];
+    [o_mi_selectall setEnabled: b_rows];
 
-        if( i_row != -1 )
-        {
-            [o_table_view reloadData];
-        }
-        
-        return( YES );
-    }
-
-    return( NO ); 
+    return( o_ctx_menu );
 }
 
-- (void)tableView:(NSTableView *)o_tv willDisplayCell:(id)o_cell
-                  forTableColumn:(NSTableColumn *)o_tc row:(int)i_row
+- (IBAction)playItem:(id)sender
 {
-    [o_cell setDrawsBackground: YES];
+    intf_thread_t * p_intf = [NSApp getIntf];
+    playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+                                                       FIND_ANYWHERE );
 
-    if( i_row % 2 )
-    {
-        [o_cell setBackgroundColor: 
-            [NSColor colorWithDeviceRed: 0.937255 
-                                  green: 0.968627
-                                   blue: 1.0
-                                  alpha: 1.0]];
-    }
-    else
+    if( p_playlist == NULL )
     {
-        [o_cell setBackgroundColor: [NSColor whiteColor]];
+        return;
     }
+
+    playlist_Goto( p_playlist, [o_table_view selectedRow] );
+
+    vlc_object_release( p_playlist );
 }
 
-- (IBAction)doubleClick:(id)sender
+- (IBAction)deleteItems:(id)sender
 {
-    NSTableView * o_tv = sender;
+    int i_row;
+
     intf_thread_t * p_intf = [NSApp getIntf];
     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
                                                        FIND_ANYWHERE );
         return;
     }
 
-    playlist_Goto( p_playlist, [o_tv clickedRow] );
+    while( ( i_row = [o_table_view selectedRow] ) != -1 )
+    {
+        if( p_playlist->i_index == i_row && p_playlist->i_status )
+        {
+            playlist_Stop( p_playlist );
+        }
+
+        playlist_Delete( p_playlist, i_row ); 
+
+        [o_table_view deselectRow: i_row];
+    }
 
     vlc_object_release( p_playlist );
+
+    /* this is actually duplicity, because the intf.m manage also updates the view
+     * when the playlist changes. we do this on purpose, because else there is a 
+     * delay of .5 sec or so when we delete an item */
+    [self playlistUpdated];
+    [self updateRowSelection];
+}
+
+- (IBAction)selectAll:(id)sender
+{
+    [o_table_view selectAll: nil];
 }
 
-- (void)appendArray:(NSArray*)o_array atPos:(int)i_pos
+- (void)appendArray:(NSArray*)o_array atPos:(int)i_pos enqueue:(BOOL)b_enqueue
 {
     int i_items;
     NSString * o_value;
         return;
     }
 
-    if( p_intf->p_sys->b_loop )
-    {
-        playlist_Delete( p_playlist, p_playlist->i_size - 1 );
-    }
-
     i_items = 0;
     o_enum = [o_array objectEnumerator];
     while( ( o_value = [o_enum nextObject] ) )
     {
         NSURL * o_url;
 
-        int i_mode = i_items == 0 ? PLAYLIST_INSERT | PLAYLIST_GO :
-                                                   PLAYLIST_INSERT;
+        int i_mode = PLAYLIST_INSERT;
+        
+        if (i_items == 0 && !b_enqueue)
+            i_mode |= PLAYLIST_GO;
 
         playlist_Add( p_playlist, [o_value fileSystemRepresentation],
             i_mode, i_pos == -1 ? PLAYLIST_END : i_pos + i_items );
         i_items++;
     }
 
-    if( p_intf->p_sys->b_loop )
+    vlc_object_release( p_playlist );
+}
+
+- (void)playlistUpdated
+{
+    [o_table_view reloadData];
+}
+
+- (void)updateRowSelection
+{
+    int i_row;
+
+    intf_thread_t * p_intf = [NSApp getIntf];
+    playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+                                                       FIND_ANYWHERE );
+
+    if( p_playlist == NULL )
     {
-        playlist_Add( p_playlist, "vlc:loop",
-                      PLAYLIST_APPEND, PLAYLIST_END );
+        return;
     }
 
+    vlc_mutex_lock( &p_playlist->object_lock );    
+    i_row = p_playlist->i_index;
+    vlc_mutex_unlock( &p_playlist->object_lock );
     vlc_object_release( p_playlist );
+
+    [o_table_view selectRow: i_row byExtendingSelection: NO];
+    [o_table_view scrollRowToVisible: i_row];
 }
 
 @end
     int i_count = 0;
     intf_thread_t * p_intf = [NSApp getIntf];
     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
-                                               FIND_ANYWHERE );
+                                                       FIND_ANYWHERE );
 
     if( p_playlist != NULL )
     {
+        vlc_mutex_lock( &p_playlist->object_lock );
         i_count = p_playlist->i_size;
+        vlc_mutex_unlock( &p_playlist->object_lock );
         vlc_object_release( p_playlist );
     }
 
     }
 
     vlc_mutex_lock( &p_playlist->object_lock );
-    o_value = [NSString stringWithCString: 
-        p_playlist->pp_items[i_row]->psz_name]; 
+    o_value = [[NSString stringWithUTF8String: 
+        p_playlist->pp_items[i_row]->psz_name] lastPathComponent]
     vlc_mutex_unlock( &p_playlist->object_lock ); 
 
     vlc_object_release( p_playlist );
     return( o_value );
 }
 
+- (BOOL)tableView:(NSTableView *)o_tv
+                    writeRows:(NSArray*)o_rows
+                    toPasteboard:(NSPasteboard*)o_pasteboard 
+{
+    int i_rows = [o_rows count];
+    NSArray *o_filenames = [NSArray array];
+    
+    [o_pasteboard declareTypes:[NSArray arrayWithObject:NSFilenamesPboardType] owner:self];
+    [o_pasteboard setPropertyList:o_filenames forType:NSFilenamesPboardType];
+    if ( i_rows == 1 )
+    {
+        i_moveRow = [[o_rows objectAtIndex:0]intValue];
+        return YES;
+    }
+    return NO;
+}
+
+- (NSDragOperation)tableView:(NSTableView*)o_tv
+                    validateDrop:(id <NSDraggingInfo>)o_info
+                    proposedRow:(int)i_row
+                    proposedDropOperation:(NSTableViewDropOperation)o_operation 
+{
+    if ( o_operation == NSTableViewDropAbove )
+    {
+        if ( i_moveRow >= 0 )
+        {
+            if ( i_row != i_moveRow )
+            {
+                return NSDragOperationMove;
+            }
+            /* what if in the previous run, the row wasn't actually moved? 
+               then we can't drop new files on this location */
+            return NSDragOperationNone;
+        }
+        return NSDragOperationGeneric;
+    }
+    return NSDragOperationNone;
+}
+
+- (BOOL)tableView:(NSTableView*)o_tv
+                    acceptDrop:(id <NSDraggingInfo>)o_info
+                    row:(int)i_proposed_row
+                    dropOperation:(NSTableViewDropOperation)o_operation 
+{
+    if (  i_moveRow >= 0 )
+    {
+        if (i_moveRow != -1 && i_proposed_row != -1)
+        {
+            intf_thread_t * p_intf = [NSApp getIntf];
+            playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+                                                            FIND_ANYWHERE );
+        
+            if( p_playlist == NULL )
+            {
+                i_moveRow = -1;
+                return NO;
+            }
+    
+            playlist_Move( p_playlist, i_moveRow, i_proposed_row ); 
+        
+            vlc_object_release( p_playlist );
+        }
+        [self playlistUpdated];
+        i_moveRow = -1;
+        return YES;
+    }
+    else
+    {
+        NSArray * o_values;
+        NSPasteboard * o_pasteboard;
+        
+        intf_thread_t * p_intf = [NSApp getIntf];
+        o_pasteboard = [o_info draggingPasteboard];
+        
+        if( [[o_pasteboard types] containsObject: NSFilenamesPboardType] )
+        {
+            o_values = [[o_pasteboard propertyListForType: NSFilenamesPboardType]
+                        sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
+
+            config_PutPsz( p_intf, "sub-file", "" );
+            config_PutInt( p_intf, "sub-delay", 0 );
+            config_PutFloat( p_intf, "sub-fps", 0.0 );
+            config_PutPsz( p_intf, "sout", "" );
+
+            [self appendArray: o_values atPos: i_proposed_row enqueue:YES];
+
+            return( YES );
+        }
+        
+        return( NO );
+    }
+    [self updateRowSelection];
+}
+
 @end