]> git.sesse.net Git - vlc/blobdiff - modules/gui/macosx/playlist.m
Mac OS X gui: Prevent a crash when dropping item on the playlist.
[vlc] / modules / gui / macosx / playlist.m
index c3aba6cb691781a84a9f775c6ac8e462d43ba30f..f2562128469fea7e46b35ac4411680d6844b0c18 100644 (file)
@@ -50,7 +50,7 @@
 #import "controls.h"
 #import "vlc_osd.h"
 #import "misc.h"
-#import <vlc_interaction.h>
+#import <vlc_interface.h>
 
 /*****************************************************************************
  * VLCPlaylistView implementation 
 
     if( i_return <= 0 )
         i_return = 0;
-NSLog( @"%d children for %s", i_return, p_item->p_input->psz_name ); 
+
     return i_return;
 }
 
@@ -198,9 +198,7 @@ NSLog( @"%d children for %s", i_return, p_item->p_input->psz_name );
     vlc_object_release( p_playlist );
 
     o_value = [o_outline_dict objectForKey:[NSString stringWithFormat: @"%p", p_return]];
-    #if 0
-    NSLog( @"%s", p_return->p_input->psz_name);
-    #endif
+
     if( o_value == nil )
     {
         o_value = [[NSValue valueWithPointer: p_return] retain];
@@ -231,36 +229,56 @@ NSLog( @"%d children for %s", i_return, p_item->p_input->psz_name );
     }
     vlc_object_release( p_playlist );
 
-NSLog( @"expandable" ); 
-    if( i_return <= 0 )
-        return NO;
-    else
-        return YES;
+    return (i_return > 0);
 }
 
 /* retrieve the string values for the cells */
 - (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)o_tc byItem:(id)item
 {
     id o_value = nil;
-    intf_thread_t *p_intf = VLCIntf;
     playlist_item_t *p_item;
-    
-    if( item == nil || ![item isKindOfClass: [NSValue class]] ) return( @"error" );
+
+    /* For error handling */
+    static BOOL attempted_reload = NO;
+
+    if( item == nil || ![item isKindOfClass: [NSValue class]] )
+    {
+        /* Attempt to fix the error by asking for a data redisplay
+         * This might cause infinite loop, so add a small check */
+        if( !attempted_reload )
+        {
+            attempted_reload = YES;
+            [outlineView reloadData];
+        }
+        return @"error" ;
+    }
     
     p_item = (playlist_item_t *)[item pointerValue];
-    if( p_item == NULL )
+    if( !p_item || !p_item->p_input )
     {
-        return( @"error");
+        /* Attempt to fix the error by asking for a data redisplay
+         * This might cause infinite loop, so add a small check */
+        if( !attempted_reload )
+        {
+            attempted_reload = YES;
+            [outlineView reloadData];
+        }
+        return @"error";
     }
-//NSLog( @"values for %p", p_item ); 
     
+    attempted_reload = NO;
+
     if( [[o_tc identifier] isEqualToString:@"1"] )
     {
-        o_value = [NSString stringWithUTF8String:
-            p_item->p_input->psz_name];
-        if( o_value == NULL )
-            o_value = [NSString stringWithCString:
+        /* sanity check to prevent the NSString class from crashing */
+        if( p_item->p_input->psz_name != NULL )
+        {
+            o_value = [NSString stringWithUTF8String:
                 p_item->p_input->psz_name];
+            if( o_value == NULL )
+                o_value = [NSString stringWithCString:
+                    p_item->p_input->psz_name];
+        }
     }
     else if( [[o_tc identifier] isEqualToString:@"2"] && p_item->p_input->p_meta &&
         p_item->p_input->p_meta->psz_artist && *p_item->p_input->p_meta->psz_artist )
@@ -376,7 +394,7 @@ NSLog( @"expandable" );
             while( p_parser->pp_shortcuts[++i] != NULL ); i--;
 
             /* Check whether to enable these menuitems */
-            objectname = i>=0 ? p_parser->pp_shortcuts[i] : p_parser->psz_object_name;
+            objectname = i>=0 ? (char *)p_parser->pp_shortcuts[i] : (char *)p_parser->psz_object_name;
             b_enabled = playlist_IsServicesDiscoveryLoaded( p_playlist, objectname );
             
             /* Create the menu entries used in the playlist menu */
@@ -464,22 +482,18 @@ NSLog( @"expandable" );
 
     playlist_t *p_playlist = pl_Yield( VLCIntf );
 
-    /** \todo fix i_size use */
-    if( p_playlist->items.i_size >= 2 )
+    if( playlist_CurrentSize( p_playlist ) >= 2 )
     {
         [o_status_field setStringValue: [NSString stringWithFormat:
-                    _NS("%i items in the playlist"), p_playlist->items.i_size]];
+                    _NS("%i items in the playlist"),
+                               playlist_CurrentSize( p_playlist )]];
     }
     else
     {
         if( playlist_IsEmpty( p_playlist ) )
-        {
             [o_status_field setStringValue: _NS("No items in the playlist")];
-        }
         else
-        {
             [o_status_field setStringValue: _NS("1 item in the playlist")];
-        }
     }
     vlc_object_release( p_playlist );
 }
@@ -598,10 +612,10 @@ NSLog( @"expandable" );
         /* Since outlineView: willDisplayCell:... may call this function with
            p_items that don't exist anymore, first check if the item is still
            in the playlist. Any cleaner solution welcomed. */
-            for( i = 0; i < p_playlist->i_all_size; i++ )
+            for( i = 0; i < p_playlist->all_items.i_size; i++ )
             {
-                if( p_playlist->pp_all_items[i] == p_item ) break;
-                else if ( i == p_playlist->i_all_size - 1 )
+                if( ARRAY_VAL( p_playlist->all_items, i) == p_item ) break;
+                else if ( i == p_playlist->all_items.i_size - 1 )
                 {
                     vlc_object_release( p_playlist );
                     vlc_mutex_unlock( &p_playlist->object_lock );
@@ -747,7 +761,7 @@ NSLog( @"expandable" );
                 p_item = NULL;
             }
         }
-        playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, p_node, p_item );
+        playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, VLC_TRUE, p_node, p_item );
     }
     vlc_object_release( p_playlist );
 }
@@ -855,7 +869,7 @@ NSLog( @"expandable" );
         }
         else
         {
-            playlist_LockDelete( p_playlist, p_item->i_id );
+            playlist_DeleteFromInput( p_playlist, p_item->p_input->i_id, VLC_FALSE );
         }
     }
     [self playlistUpdated];
@@ -1011,20 +1025,21 @@ NSLog( @"expandable" );
         }
 
         /* Add the item */
-        playlist_PlaylistAddInput( p_playlist, p_input, PLAYLIST_INSERT,
-                        i_position == -1 ? PLAYLIST_END : i_position + i_item );
+        playlist_AddInput( p_playlist, p_input, PLAYLIST_INSERT,
+             i_position == -1 ? PLAYLIST_END : i_position + i_item, VLC_TRUE,
+            VLC_FALSE );
 
         if( i_item == 0 && !b_enqueue )
         {
             playlist_item_t *p_item;
-            p_item = playlist_ItemGetByInput( p_playlist, p_input );
-            playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, NULL, p_item );
+            p_item = playlist_ItemGetByInput( p_playlist, p_input, VLC_TRUE );
+            playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, VLC_TRUE, NULL, p_item );
         }
         else
         {
             playlist_item_t *p_item;
-            p_item = playlist_ItemGetByInput( p_playlist, p_input );
-            playlist_Control( p_playlist, PLAYLIST_PREPARSE, p_item );
+            p_item = playlist_ItemGetByInput( p_playlist, p_input, VLC_TRUE );
+            playlist_Control( p_playlist, PLAYLIST_PREPARSE, VLC_TRUE, p_item );
         }
     }
     [self playlistUpdated];
@@ -1053,20 +1068,20 @@ NSLog( @"expandable" );
        playlist_NodeAddInput( p_playlist, p_input, p_node,
                                       PLAYLIST_INSERT,
                                       i_position == -1 ?
-                                      PLAYLIST_END : i_position + i_item );
+                                      PLAYLIST_END : i_position + i_item, VLC_FALSE );
 
 
         if( i_item == 0 && !b_enqueue )
         {
             playlist_item_t *p_item;
-            p_item = playlist_ItemGetByInput( p_playlist, p_input );
-            playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, NULL, p_item );
+            p_item = playlist_ItemGetByInput( p_playlist, p_input, VLC_TRUE );
+            playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, VLC_TRUE, NULL, p_item );
         }
         else
         {
             playlist_item_t *p_item;
-            p_item = playlist_ItemGetByInput( p_playlist, p_input );
-            playlist_Control( p_playlist, PLAYLIST_PREPARSE, p_item );
+            p_item = playlist_ItemGetByInput( p_playlist, p_input, VLC_TRUE );
+            playlist_Control( p_playlist, PLAYLIST_PREPARSE, VLC_TRUE, p_item );
         }
     }
     [self playlistUpdated];
@@ -1342,15 +1357,19 @@ NSLog( @"expandable" );
     playlist_item_t * p_item;
     ret_v = intf_UserStringInput( p_playlist, _("New Node"), 
         _("Please enter a name for the new node."), &psz_name );
+
     if( psz_name != NULL && psz_name != "" )
         p_item = playlist_NodeCreate( p_playlist, psz_name, 
-                                            p_playlist->p_local_category );
-    else
+                                            p_playlist->p_local_category, 0 );
+    else if(! config_GetInt( p_playlist, "interact" ) )
+    {
+        /* in case that the interaction is disabled, just give it a bogus name */
         p_item = playlist_NodeCreate( p_playlist, _("Empty Folder"), 
-                                            p_playlist->p_local_category );
+                                            p_playlist->p_local_category, 0 );
+    }
 
     if(! p_item )
-        msg_Warn( VLCIntf, "node creation failed" );
+        msg_Warn( VLCIntf, "node creation failed or cancelled by user" );
 
     vlc_object_release( p_playlist );
     [ourPool release];
@@ -1365,13 +1384,11 @@ NSLog( @"expandable" );
     id o_value = [super outlineView: outlineView child: index ofItem: item];
     playlist_t *p_playlist = pl_Yield( VLCIntf );
 
-    /* FIXME: playlist->i_size doesn't provide the correct number of items anymore
-     * check the playlist API for the fixed function, once zorglub implemented it -- fpk, 9/17/06 */
-    /** \todo fix i_size use */
-    if( p_playlist->items.i_size >= 2 )
+    if( playlist_CurrentSize( p_playlist )  >= 2 )
     {
         [o_status_field setStringValue: [NSString stringWithFormat:
-                    _NS("%i items in the playlist"), p_playlist->items.i_size]];
+                    _NS("%i items in the playlist"),
+                       playlist_CurrentSize( p_playlist )]];
     }
     else
     {
@@ -1457,6 +1474,13 @@ NSLog( @"expandable" );
         }
     }
 
+    /* Don't allow on drop on playlist root element's child */
+    if( !item && index != NSOutlineViewDropOnItemIndex)
+    {
+        vlc_object_release( p_playlist );
+        return NSDragOperationNone;
+    }
+
     /* We refuse to drop an item in anything else than a child of the General
        Node. We still accept items that would be root nodes of the outlineview
        however, to allow drop in an empty playlist. */