vlc | branch: master | Rémi Denis-Courmont <r...@remlab.net> | Fri Nov 18 21:40:54 2016 +0200| [92982fa78fce0bfd4e59b7519b0d78d8a48bfbc5] | committer: Rémi Denis-Courmont
wip > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=92982fa78fce0bfd4e59b7519b0d78d8a48bfbc5 --- src/playlist/engine.c | 4 ++ src/playlist/item.c | 85 ++++++++++++++++++++++++++++++++++------ src/playlist/playlist_internal.h | 6 ++- src/playlist/tree.c | 2 +- 4 files changed, 83 insertions(+), 14 deletions(-) diff --git a/src/playlist/engine.c b/src/playlist/engine.c index dbb2723..d86ac30 100644 --- a/src/playlist/engine.c +++ b/src/playlist/engine.c @@ -209,6 +209,10 @@ playlist_t *playlist_Create( vlc_object_t *p_parent ) assert( offsetof( playlist_private_t, public_data ) == 0 ); p_playlist = &p->public_data; + + p->input_tree = NULL; + p->id_tree = NULL; + TAB_INIT( pl_priv(p_playlist)->i_sds, pl_priv(p_playlist)->pp_sds ); VariablesInit( p_playlist ); diff --git a/src/playlist/item.c b/src/playlist/item.c index 4caaa34..5d56956 100644 --- a/src/playlist/item.c +++ b/src/playlist/item.c @@ -25,8 +25,13 @@ # include "config.h" #endif -#include <vlc_common.h> #include <assert.h> +#include <limits.h> +#ifdef HAVE_SEARCH_H +# include <search.h> +#endif + +#include <vlc_common.h> #include <vlc_playlist.h> #include <vlc_rand.h> #include "playlist_internal.h" @@ -263,23 +268,41 @@ static void uninstall_input_item_observer( playlist_item_t * p_item ) input_item_changed, p_item ); } +static int playlist_ItemCmpId( const void *a, const void *b ) +{ + const playlist_item_t *pa = a, *pb = b; + + /* ID are between 1 and INT_MAX, this cannot overflow. */ + return pa->i_id - pb->i_id; +} + +static int playlist_ItemCmpInput( const void *a, const void *b ) +{ + const playlist_item_t *pa = a, *pb = b; + + if( pa->p_input == pb->p_input ) + return 0; + return (((uintptr_t)pa->p_input) > ((uintptr_t)pb->p_input)) + ? +1 : -1; +} + /***************************************************************************** * Playlist item creation *****************************************************************************/ playlist_item_t *playlist_ItemNewFromInput( playlist_t *p_playlist, input_item_t *p_input ) { - playlist_item_t* p_item = malloc( sizeof( playlist_item_t ) ); - if( !p_item ) + playlist_private_t *p = pl_priv(p_playlist); + playlist_item_t **pp, *p_item; + + p_item = malloc( sizeof( playlist_item_t ) ); + if( unlikely(p_item == NULL) ) return NULL; assert( p_input ); p_item->p_input = p_input; - vlc_gc_incref( p_item->p_input ); - - p_item->i_id = ++pl_priv(p_playlist)->i_last_playlist_id; - + p_item->i_id = p->i_last_playlist_id; p_item->p_parent = NULL; p_item->i_children = -1; p_item->pp_children = NULL; @@ -287,9 +310,44 @@ playlist_item_t *playlist_ItemNewFromInput( playlist_t *p_playlist, p_item->i_flags = 0; p_item->p_playlist = p_playlist; - install_input_item_observer( p_item ); + PL_ASSERT_LOCKED; + do /* Find an unused ID for the item */ + { + if( unlikely(p_item->i_id == INT_MAX) ) + p_item->i_id = 0; + + p_item->i_id++; + + if( unlikely(p_item->i_id == p->i_last_playlist_id) ) + goto error; /* All IDs taken */ + + pp = tsearch( p_item, &p->id_tree, playlist_ItemCmpId ); + if( unlikely(pp == NULL) ) + goto error; + + assert( (*pp)->i_id == p_item->i_id ); + assert( (*pp) == p_item || (*pp)->p_input != p_input ); + } + while( p_item != *pp ); + + pp = tsearch( p_item, &p->input_tree, playlist_ItemCmpInput ); + if( unlikely(pp == NULL) ) + { + tdelete( p_item, &p->id_tree, playlist_ItemCmpId ); + goto error; + } + /* Same input item cannot be inserted twice. */ + assert( p_item == *pp ); + + p->i_last_playlist_id = p_item->i_id; + vlc_gc_incref( p_item->p_input ); + install_input_item_observer( p_item ); return p_item; + +error: + free( p_item ); + return NULL; } /*************************************************************************** @@ -301,15 +359,18 @@ playlist_item_t *playlist_ItemNewFromInput( playlist_t *p_playlist, * * \param p_item item to delete */ -void playlist_ItemRelease( playlist_item_t *p_item ) +void playlist_ItemRelease( playlist_t *p_playlist, playlist_item_t *p_item ) { - /* For the assert */ - playlist_t *p_playlist = p_item->p_playlist; + playlist_private_t *p = pl_priv(p_playlist); + PL_ASSERT_LOCKED; uninstall_input_item_observer( p_item ); - free( p_item->pp_children ); vlc_gc_decref( p_item->p_input ); + + tdelete( p_item, &p->input_tree, playlist_ItemCmpInput ); + tdelete( p_item, &p->id_tree, playlist_ItemCmpId ); + free( p_item->pp_children ); free( p_item ); } diff --git a/src/playlist/playlist_internal.h b/src/playlist/playlist_internal.h index efcd587..1113f26 100644 --- a/src/playlist/playlist_internal.h +++ b/src/playlist/playlist_internal.h @@ -49,6 +49,10 @@ typedef struct playlist_private_t playlist_t public_data; struct intf_thread_t *interface; /**< Linked-list of interfaces */ + void *input_tree; /**< Search tree for input item + to playlist item mapping */ + void *id_tree; /**< Search tree for item ID to item mapping */ + playlist_item_array_t all_items; /**< Array of items and nodes */ vlc_sd_internal_t **pp_sds; @@ -129,7 +133,7 @@ int playlist_NodeInsert(playlist_t *, playlist_item_t*, playlist_item_t *, playlist_item_t *playlist_ItemFindFromInputAndRoot( playlist_t *p_playlist, input_item_t *p_input, playlist_item_t *p_root ); -void playlist_ItemRelease( playlist_item_t * ); +void playlist_ItemRelease( playlist_t *, playlist_item_t * ); void ResetCurrentlyPlaying( playlist_t *p_playlist, playlist_item_t *p_cur ); void ResyncCurrentIndex( playlist_t *p_playlist, playlist_item_t *p_cur ); diff --git a/src/playlist/tree.c b/src/playlist/tree.c index b6bc9c3..2496c8f 100644 --- a/src/playlist/tree.c +++ b/src/playlist/tree.c @@ -151,7 +151,7 @@ void playlist_NodeDelete( playlist_t *p_playlist, playlist_item_t *p_root, } } - playlist_ItemRelease( p_root ); + playlist_ItemRelease( p_playlist, p_root ); } int playlist_NodeInsert( playlist_t *p_playlist, _______________________________________________ vlc-commits mailing list vlc-commits@videolan.org https://mailman.videolan.org/listinfo/vlc-commits