]> git.sesse.net Git - vlc/blobdiff - src/playlist/view.c
Get rid of --enable-shared-libvlc on non-Microsoft platforms
[vlc] / src / playlist / view.c
index b4618e61e048ff80f1683ee47d1f109fc78a5904..5d675e0888b44cfe5424f2f80b0eaff64f189518 100644 (file)
@@ -1,10 +1,10 @@
 /*****************************************************************************
  * view.c : Playlist views functions
  *****************************************************************************
- * Copyright (C) 1999-2004 VideoLAN
- * $Id: item.c 7997 2004-06-18 11:35:45Z sigmunau $
+ * Copyright (C) 1999-2004 the VideoLAN team
+ * $Id$
  *
- * Authors: Clément Stenac <zorglub@videolan.org>
+ * Authors: Clément Stenac <zorglub@videolan.org>
  *
  * 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
@@ -18,7 +18,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  *****************************************************************************/
 #include <stdlib.h>                                      /* free(), strtol() */
 #include <stdio.h>                                              /* sprintf() */
@@ -29,6 +29,8 @@
 
 #include "vlc_playlist.h"
 
+#undef PLAYLIST_DEBUG
+
 /************************************************************************
  * Local prototypes
  ************************************************************************/
@@ -68,8 +70,6 @@ playlist_view_t * playlist_ViewCreate( playlist_t *p_playlist, int i_id,
 {
     playlist_view_t * p_view;
 
-    msg_Dbg( p_playlist, "Creating view %i",i_id );
-
     p_view = malloc( sizeof( playlist_view_t ) );
 
     memset( p_view, 0, sizeof( playlist_view_t ) );
@@ -84,6 +84,8 @@ playlist_view_t * playlist_ViewCreate( playlist_t *p_playlist, int i_id,
 /**
  * Creates a new view and add it to the list
  *
+ * This function must be entered without the playlist lock
+ *
  * \param p_playlist a playlist object
  * \param i_id the view identifier
  * \return VLC_SUCCESS or an error
@@ -111,13 +113,16 @@ int playlist_ViewInsert( playlist_t *p_playlist, int i_id, char *psz_name )
 /**
  * Deletes a view
  *
+ * This function must be entered wit the playlist lock
+ *
  * \param p_view the view to delete
  * \return nothing
  */
-void playlist_ViewDelete( playlist_t *p_playlist,playlist_view_t *p_view )
+int playlist_ViewDelete( playlist_t *p_playlist,playlist_view_t *p_view )
 {
-    //playlist_Delete( p_view->p_root );
+    playlist_NodeDelete( p_playlist, p_view->p_root, VLC_TRUE, VLC_TRUE );
     REMOVE_ELEM( p_playlist->pp_views, p_playlist->i_views, 0 );
+    return VLC_SUCCESS;
 }
 
 
@@ -128,10 +133,13 @@ void playlist_ViewDelete( playlist_t *p_playlist,playlist_view_t *p_view )
  * \param p_view the view to dump
  * \return nothing
  */
-void playlist_ViewDump( playlist_t *p_playlist, playlist_view_t *p_view )
+int playlist_ViewDump( playlist_t *p_playlist, playlist_view_t *p_view )
 {
-    msg_Dbg( p_playlist, "Dumping view %i",p_view->i_id );
+#ifdef PLAYLIST_DEBUG
+    msg_Dbg( p_playlist, "dumping view %i",p_view->i_id );
     playlist_NodeDump( p_playlist,p_view->p_root, 1 );
+#endif
+    return VLC_SUCCESS;
 }
 
 /**
@@ -171,15 +179,24 @@ int playlist_ViewUpdate( playlist_t *p_playlist, int i_view)
     }
 
     /* Handle update of sorted views here */
-    if( i_view == VIEW_S_AUTHOR )
+    if( i_view >= VIEW_FIRST_SORTED )
     {
+        int i_sort_type;
         playlist_ViewEmpty( p_playlist, i_view, VLC_FALSE );
 
+        switch( i_view )
+        {
+            case VIEW_S_AUTHOR: i_sort_type = SORT_AUTHOR;break;
+            case VIEW_S_ALBUM: i_sort_type = SORT_ALBUM;break;
+            case VIEW_S_GENRE: i_sort_type = SORT_GENRE;break;
+            default: i_sort_type = SORT_AUTHOR;
+        }
         playlist_NodeGroup( p_playlist, i_view, p_view->p_root,
                             p_playlist->pp_items,p_playlist->i_size,
-                            SORT_AUTHOR, ORDER_NORMAL );
+                            i_sort_type, ORDER_NORMAL );
     }
 
+
     return VLC_SUCCESS;
 }
 
@@ -239,12 +256,20 @@ playlist_item_t * playlist_NodeCreate( playlist_t *p_playlist, int i_view,
     /* Create the item */
     playlist_item_t *p_item = (playlist_item_t *)malloc(
                                         sizeof( playlist_item_t ) );
+    vlc_value_t val;
+    playlist_add_t *p_add;
 
-    vlc_input_item_Init( VLC_OBJECT(p_playlist), &p_item->input );
     if( p_item == NULL )
     {
         return NULL;
     }
+    p_add = (playlist_add_t*)malloc( sizeof(playlist_add_t) );
+    if( p_add == NULL )
+    {
+        free( p_item );
+        return NULL;
+    }
+    vlc_input_item_Init( VLC_OBJECT(p_playlist), &p_item->input );
 
     if( psz_name != NULL )
     {
@@ -270,25 +295,44 @@ playlist_item_t * playlist_NodeCreate( playlist_t *p_playlist, int i_view,
     p_item->input.i_options = 0;
     p_item->input.i_categories = 0;
     p_item->input.pp_categories = NULL;
+    p_item->input.i_id = ++p_playlist->i_last_id;
+
+    p_item->input.i_type = ITEM_TYPE_NODE;
 
     p_item->pp_parents = NULL;
     p_item->i_parents = 0;
+    p_item->i_serial = 0;
 
     p_item->i_flags |= PLAYLIST_SKIP_FLAG; /* Default behaviour */
 
     vlc_mutex_init( p_playlist, &p_item->input.lock );
 
+    INSERT_ELEM( p_playlist->pp_all_items,
+                 p_playlist->i_all_size,
+                 p_playlist->i_all_size,
+                 p_item );
+
     if( p_parent != NULL )
     {
         playlist_NodeAppend( p_playlist, i_view, p_item, p_parent );
     }
 
+    p_add->i_node = p_parent ? p_parent->input.i_id : -1;
+    p_add->i_item = p_item->input.i_id;
+    p_add->i_view = i_view;
+    val.p_address = p_add;
+    var_Set( p_playlist, "item-append", val);
+
+    free( p_add );
+
     return p_item;
 }
 
 /**
  * Remove all the children of a node
  *
+ * This function must be entered with the playlist lock
+ *
  * \param p_playlist the playlist
  * \param p_root the node
  * \param b_delete_items do we have to delete the children items ?
@@ -309,11 +353,12 @@ int playlist_NodeEmpty( playlist_t *p_playlist, playlist_item_t *p_root,
         if( p_root->pp_children[i]->i_children > -1 )
         {
             playlist_NodeDelete( p_playlist, p_root->pp_children[i],
-                                b_delete_items );
+                                 b_delete_items , VLC_FALSE );
         }
         else if( b_delete_items )
         {
             /* Delete the item here */
+            playlist_Delete( p_playlist, p_root->pp_children[i]->input.i_id );
         }
     }
     return VLC_SUCCESS;
@@ -328,9 +373,9 @@ int playlist_NodeEmpty( playlist_t *p_playlist, playlist_item_t *p_root,
  * \return VLC_SUCCESS or an error
  */
 int playlist_NodeDelete( playlist_t *p_playlist, playlist_item_t *p_root,
-                        vlc_bool_t b_delete_items )
+                         vlc_bool_t b_delete_items, vlc_bool_t b_force )
 {
-    int i;
+    int i, i_top, i_bottom;
     if( p_root->i_children == -1 )
     {
         return VLC_EGENERIC;
@@ -342,23 +387,50 @@ int playlist_NodeDelete( playlist_t *p_playlist, playlist_item_t *p_root,
         if( p_root->pp_children[i]->i_children > -1 )
         {
             playlist_NodeDelete( p_playlist, p_root->pp_children[i],
-                                b_delete_items );
+                                b_delete_items , b_force );
         }
         else if( b_delete_items )
         {
             /* Delete the item here */
+            playlist_Delete( p_playlist, p_root->pp_children[i]->input.i_id );
         }
     }
     /* Delete the node */
-    for( i = 0 ; i< p_root->i_parents; i++ )
+    if( p_root->i_flags & PLAYLIST_RO_FLAG && !b_force )
     {
-        playlist_NodeRemoveItem( p_playlist, p_root,
-                                 p_root->pp_parents[i]->p_parent );
     }
-    playlist_ItemDelete( p_root );
-   return VLC_SUCCESS;
-}
+    else
+    {
+        for( i = 0 ; i< p_root->i_parents; i++ )
+        {
+            playlist_NodeRemoveItem( p_playlist, p_root,
+                                     p_root->pp_parents[i]->p_parent );
+        }
+        var_SetInteger( p_playlist, "item-deleted", p_root->input.i_id );
 
+        i_bottom = 0; i_top = p_playlist->i_all_size - 1;
+        i = i_top / 2;
+        while( p_playlist->pp_all_items[i]->input.i_id != p_root->input.i_id &&
+               i_top > i_bottom )
+        {
+            if( p_playlist->pp_all_items[i]->input.i_id < p_root->input.i_id )
+            {
+                i_bottom = i + 1;
+            }
+            else
+            {
+                i_top = i - 1;
+            }
+            i = i_bottom + ( i_top - i_bottom ) / 2;
+        }
+        if( p_playlist->pp_all_items[i]->input.i_id == p_root->input.i_id )
+        {
+            REMOVE_ELEM( p_playlist->pp_all_items, p_playlist->i_all_size, i );
+        }
+        playlist_ItemDelete( p_root );
+    }
+    return VLC_SUCCESS;
+}
 
 
 /**
@@ -389,6 +461,7 @@ int playlist_NodeInsert( playlist_t *p_playlist,
    if( !p_parent || p_parent->i_children == -1 )
    {
         msg_Err( p_playlist, "invalid node" );
+        return VLC_EGENERIC;
    }
 
    if( i_position == -1 ) i_position = p_parent->i_children ;
@@ -410,7 +483,7 @@ int playlist_NodeInsert( playlist_t *p_playlist,
    if( b_found == VLC_FALSE )
    {
         struct item_parent_t *p_ip = (struct item_parent_t *)
-                                malloc(sizeof(struct item_parent_t) );
+                                     malloc(sizeof(struct item_parent_t) );
         p_ip->i_view = i_view;
         p_ip->p_parent = p_parent;
 
@@ -425,14 +498,14 @@ int playlist_NodeInsert( playlist_t *p_playlist,
 }
 
 /**
- * Deletes an item from the children of a node
+ * Deletes a parent from the parent list of a node
  *
  * \param p_playlist the playlist
  * \param p_item the item to remove
  * \param p_parent the parent node
  * \return VLC_SUCCESS or an error
  */
-int playlist_NodeRemoveItem( playlist_t *p_playlist,
+int playlist_NodeRemoveParent( playlist_t *p_playlist,
                         playlist_item_t *p_item,
                         playlist_item_t *p_parent )
 {
@@ -442,6 +515,34 @@ int playlist_NodeRemoveItem( playlist_t *p_playlist,
         msg_Err( p_playlist, "invalid node" );
    }
 
+   for( i = 0; i < p_item->i_parents; i++ )
+   {
+       if( p_item->pp_parents[i]->p_parent == p_parent )
+       {
+           if( p_item->pp_parents[i] )
+           {
+               free( p_item->pp_parents[i] );
+           }
+           REMOVE_ELEM( p_item->pp_parents, p_item->i_parents, i );
+       }
+   }
+   p_item->i_serial++;
+   return VLC_SUCCESS;
+}
+
+/**
+ * Deletes an item from the children of a node
+ *
+ * \param p_playlist the playlist
+ * \param p_item the item to remove
+ * \param p_parent the parent node
+ * \return VLC_SUCCESS or an error
+ */
+int playlist_NodeRemoveItem( playlist_t *p_playlist,
+                        playlist_item_t *p_item,
+                        playlist_item_t *p_parent )
+{
+   int i;
    for( i= 0; i< p_parent->i_children ; i++ )
    {
        if( p_parent->pp_children[i] == p_item )
@@ -498,22 +599,20 @@ int playlist_NodeChildrenCount( playlist_t *p_playlist, playlist_item_t*p_node)
 playlist_item_t *playlist_ChildSearchName( playlist_item_t *p_node,
                                            const char *psz_search )
 {
-   int i;
-
-   if( p_node->i_children < 0 )
-   {
-        return NULL;
-   }
+    int i;
 
-   for( i = 0 ; i< p_node->i_children; i++ )
-   {
-        if( !strncmp( p_node->pp_children[i]->input.psz_name, psz_search,
-                      strlen( p_node->pp_children[i]->input.psz_name ) ) )
+    if( p_node->i_children < 0 )
+    {
+         return NULL;
+    }
+    for( i = 0 ; i< p_node->i_children; i++ )
+    {
+        if( !strcmp( p_node->pp_children[i]->input.psz_name, psz_search ) )
         {
             return p_node->pp_children[i];
         }
-   }
-   return NULL;
+    }
+    return NULL;
 }
 
 
@@ -539,17 +638,20 @@ playlist_item_t *playlist_FindNextFromParent( playlist_t *p_playlist,
 {
     playlist_item_t *p_search, *p_next;
 
+#ifdef PLAYLIST_DEBUG
     if( p_item != NULL )
     {
-        msg_Dbg( p_playlist, "Finding next of %s within %s",
-                        p_item->input.psz_name, p_node->input.psz_name );
+        msg_Dbg( p_playlist, "finding next of %s within %s - root %s",
+                        p_item->input.psz_name, p_node->input.psz_name,
+                        p_root->input.psz_name );
     }
     else
     {
-        msg_Dbg( p_playlist, "Finding something to play within %s",
-                                 p_node->input.psz_name );
+        msg_Dbg( p_playlist, "finding something to play within %s -root %s",
+                            p_node->input.psz_name, p_root->input.psz_name );
 
     }
+#endif
 
     if( !p_node  || p_node->i_children == -1 )
     {
@@ -581,6 +683,10 @@ playlist_item_t *playlist_FindNextFromParent( playlist_t *p_playlist,
     {
         if( p_playlist->b_go_next )
         {
+#ifdef PLAYLIST_DEBUG
+            msg_Dbg( p_playlist, "Moving on to next node: search from %s",
+                            p_root->input.psz_name );
+#endif
             p_next = playlist_RecursiveFindNext( p_playlist, i_view,
                                 p_root, p_item, p_search );
             if( p_next == NULL )
@@ -592,6 +698,9 @@ playlist_item_t *playlist_FindNextFromParent( playlist_t *p_playlist,
         }
         else
         {
+#ifdef PLAYLIST_DEBUG
+            msg_Dbg( p_playlist, "Not moving on to next node: you loose" );
+#endif
             return NULL;
         }
     }
@@ -616,6 +725,7 @@ playlist_item_t *playlist_FindPrevFromParent( playlist_t *p_playlist,
 {
     playlist_item_t *p_search, *p_next;
 
+#ifdef PLAYLIST_DEBUG
     if( p_item != NULL )
     {
         msg_Dbg( p_playlist, "Finding prev of %s within %s",
@@ -624,8 +734,8 @@ playlist_item_t *playlist_FindPrevFromParent( playlist_t *p_playlist,
     else
     {
         msg_Dbg( p_playlist, "Finding prev from %s",p_node->input.psz_name );
-
     }
+#endif
 
     if( !p_node  || p_node->i_children == -1 )
     {
@@ -696,16 +806,24 @@ playlist_item_t *playlist_RecursiveFindNext( playlist_t *p_playlist,
             {
                 i = -1;
             }
+#ifdef PLAYLIST_DEBUG
             msg_Dbg( p_playlist,"Current item found, child %i of %s",
                                 i , p_parent->input.psz_name );
+#endif
             /* We found our item */
             if( i+1 >= p_parent->i_children )
             {
                 /* Too far... */
+#ifdef PLAYLIST_DEBUG
                 msg_Dbg( p_playlist, "Going up the tree,at parent of %s",
                                 p_parent->input.psz_name );
+#endif
                 if( p_parent == p_root )
                 {
+#ifdef PLAYLIST_DEBUG
+                    msg_Dbg( p_playlist, "At root item (%s)",
+                                         p_root->input.psz_name );
+#endif
                     /* Hmm, seems it's the end for you, guy ! */
                     return NULL;
                 }
@@ -726,16 +844,20 @@ playlist_item_t *playlist_RecursiveFindNext( playlist_t *p_playlist,
                 if( p_parent->pp_children[i+1]->i_children == -1 )
                 {
                     /* Cool, we have found a real item to play */
+#ifdef PLAYLIST_DEBUG
                     msg_Dbg( p_playlist, "Playing child %i of %s",
                                      i+1 , p_parent->input.psz_name );
+#endif
                     return p_parent->pp_children[i+1];
                 }
                 else if( p_parent->pp_children[i+1]->i_children > 0 )
                 {
                     /* Select the first child of this node */
+#ifdef PLAYLIST_DEBUG
                     msg_Dbg( p_playlist, "%s is a node with children, "
                                  "playing the first",
                                   p_parent->pp_children[i+1]->input.psz_name);
+#endif
                     if( p_parent->pp_children[i+1]->pp_children[0]
                                     ->i_children >= 0 )
                     {
@@ -749,8 +871,10 @@ playlist_item_t *playlist_RecursiveFindNext( playlist_t *p_playlist,
                 else
                 {
                     /* This node has no child... We must continue */
+#ifdef PLAYLIST_DEBUG
                     msg_Dbg( p_playlist, "%s is a node with no children",
                                  p_parent->pp_children[i+1]->input.psz_name);
+#endif
                     p_item = p_parent->pp_children[i+1];
                 }
             }
@@ -778,22 +902,37 @@ playlist_item_t *playlist_RecursiveFindPrev( playlist_t *p_playlist,
             {
                 i = -1;
             }
+#ifdef PLAYLIST_DEBUG
             msg_Dbg( p_playlist,"Current item found, child %i of %s",
                              i , p_parent->input.psz_name );
+#endif
             /* We found our item */
             if( i < 1 )
             {
                 /* Too far... */
+#ifdef PLAYLIST_DEBUG
                 msg_Dbg( p_playlist, "Going up the tree,at parent of %s",
                                      p_parent->input.psz_name );
+#endif
                 if( p_parent == p_root )
                 {
+#ifdef PLAYLIST_DEBUG
+                    msg_Dbg( p_playlist, "At root item (%s)",
+                                         p_root->input.psz_name );
+#endif
                     /* Hmm, seems it's the end for you, guy ! */
                     return NULL;
                 }
                 /* Go up one level */
                 p_parent_parent = playlist_FindDirectParent( p_playlist,
                                             p_parent, i_view );
+                if( p_parent_parent == NULL )
+                {
+#ifdef PLAYLIST_DEBUG
+                    msg_Dbg( p_playlist, "Mmmh, couldn't find parent" );
+#endif
+                    return NULL;
+                }
                 return playlist_RecursiveFindPrev( p_playlist, i_view,p_root,
                                             p_parent, p_parent_parent );
             }
@@ -802,16 +941,20 @@ playlist_item_t *playlist_RecursiveFindPrev( playlist_t *p_playlist,
                 if( p_parent->pp_children[i-1]->i_children == -1 )
                 {
                     /* Cool, we have found a real item to play */
+#ifdef PLAYLIST_DEBUG
                     msg_Dbg( p_playlist, "Playing child %i of %s",
                                      i-1, p_parent->input.psz_name );
+#endif
                     return p_parent->pp_children[i-1];
                 }
                 else if( p_parent->pp_children[i-1]->i_children > 0 )
                 {
                     /* Select the last child of this node */
+#ifdef PLAYLIST_DEBUG
                     msg_Dbg( p_playlist, "%s is a node with children,"
                                    " playing the last",
                                    p_parent->pp_children[i-1]->input.psz_name);
+#endif
                     if( p_parent->pp_children[i-1]->pp_children[p_parent->
                             pp_children[i-1]->i_children-1]->i_children >= 0 )
                     {
@@ -827,8 +970,10 @@ playlist_item_t *playlist_RecursiveFindPrev( playlist_t *p_playlist,
                 else
                 {
                     /* This node has no child... We must continue */
+#ifdef PLAYLIST_DEBUG
                     msg_Dbg( p_playlist, "%s is a node with no children",
                                 p_parent->pp_children[i-1]->input.psz_name);
+#endif
                     p_item = p_parent->pp_children[i-1];
                 }
             }
@@ -854,7 +999,8 @@ playlist_item_t *playlist_FindDirectParent( playlist_t *p_playlist,
 }
 
 
-/* This function dumps a node */
+#ifdef PLAYLIST_DEBUG
+/* This function dumps a node : to be used only for debug*/
 void playlist_NodeDump( playlist_t *p_playlist, playlist_item_t *p_item,
                         int i_level )
 {
@@ -887,3 +1033,4 @@ void playlist_NodeDump( playlist_t *p_playlist, playlist_item_t *p_item,
     }
     return;
 }
+#endif