/*****************************************************************************
* 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
*
* 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() */
{
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 ) );
/**
* 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
/**
* Deletes a view
*
+ * This function must be entered wit the playlist lock
+ *
* \param p_view the view to delete
* \return nothing
*/
int playlist_ViewDelete( playlist_t *p_playlist,playlist_view_t *p_view )
{
+ 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;
}
*/
int playlist_ViewDump( playlist_t *p_playlist, playlist_view_t *p_view )
{
+#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;
}
}
/* 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;
}
playlist_item_t *p_item = (playlist_item_t *)malloc(
sizeof( playlist_item_t ) );
vlc_value_t val;
- playlist_add_t *p_add = (playlist_add_t*)malloc( sizeof(playlist_add_t));
+ 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 )
{
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->p_node = p_parent;
- p_add->p_item = p_item;
+ 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 ?
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 )
{
* \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;
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;
+}
/**
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;
}
/**
- * 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 )
{
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 )
#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_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 )
}
else
{
+#ifdef PLAYLIST_DEBUG
+ msg_Dbg( p_playlist, "Not moving on to next node: you loose" );
+#endif
return NULL;
}
}
#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;
}
#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 );
}
}
-/* 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 )
{
}
return;
}
+#endif