[vlc-commits] wip
Rémi Denis-Courmont
git at videolan.org
Fri Nov 18 21:40:16 CET 2016
vlc | branch: master | Rémi Denis-Courmont <remi at 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,
More information about the vlc-commits
mailing list