From 0900f11014557ea895a290d2c1518d739f97a8b6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Cl=C3=A9ment=20Stenac?= <zorglub@videolan.org>
Date: Sun, 19 Nov 2006 13:20:02 +0000
Subject: [PATCH] Finish the playlist API transition (hopefully)  - Remove a
 bunch of transition now-useless API.  - Remove all playlist_Lock* functions.
 Matching functions now accept a    b_locked parameter that should be set to
 VLC_TRUE if the playlist is    locked when calling the function. The
 advantages are that it reduces    the API bloat and that the b_locked flag
 can be propagated in the    call stack  - Remove useless playlist testsuite 
 - Remove broken daap plugin (unmaintained wrt VLC API changes, relies on   
 an unmaintained library, probably unable to read content from new itunes,   
 ...). Implementations exist in rhythmbox, xmms2 and    daap-sharp, we should
 see if a proper lib exists or if we could    make one  - Reduce verbosity a
 bit  - Documentation

---
 configure.ac                                  |  14 -
 include/vlc_playlist.h                        | 162 +++--
 include/vlc_symbols.h                         |  54 +-
 modules/access/cdda.c                         |   6 +-
 modules/access/cdda/info.c                    |  12 +-
 modules/access/directory.c                    |   6 +-
 modules/codec/cmml/intf.c                     |   2 +-
 modules/control/hotkeys.c                     |   4 +-
 modules/control/http/macro.c                  |  29 +-
 modules/control/http/rpn.c                    |  16 +-
 modules/control/rc.c                          |   4 +-
 modules/demux/mp4/mp4.c                       |   9 +-
 modules/demux/playlist/asx.c                  |   4 +-
 modules/demux/playlist/b4s.c                  |   2 +-
 modules/demux/playlist/dvb.c                  |   2 +-
 modules/demux/playlist/gvp.c                  |   2 +-
 modules/demux/playlist/m3u.c                  |   2 +-
 modules/demux/playlist/playlist.h             |   7 +-
 modules/demux/playlist/pls.c                  |   4 +-
 modules/demux/playlist/podcast.c              |   2 +-
 modules/demux/playlist/qtl.c                  |   8 +-
 modules/demux/playlist/sgimb.c                |   3 +-
 modules/demux/playlist/shoutcast.c            |   4 +-
 modules/demux/playlist/xspf.c                 |   2 +-
 modules/gui/beos/InterfaceWindow.cpp          |   2 +-
 modules/gui/macosx/intf.m                     |   2 +-
 modules/gui/macosx/playlist.m                 |  20 +-
 modules/gui/macosx/wizard.m                   |   2 +-
 modules/gui/ncurses.c                         |   6 +-
 modules/gui/pda/pda_callbacks.c               |   4 +-
 .../qt4/components/playlist/standardpanel.cpp |   3 +-
 modules/gui/qt4/playlist_model.cpp            |  74 +-
 modules/gui/skins2/src/skin_main.cpp          |   2 +-
 modules/gui/skins2/vars/playtree.cpp          |   8 +-
 modules/gui/wxwidgets/dialogs/playlist.cpp    |  50 +-
 modules/gui/wxwidgets/playlist_manager.cpp    |   2 +-
 modules/gui/wxwidgets/wxwidgets.cpp           |   2 +-
 modules/misc/testsuite/Modules.am             |   1 -
 modules/misc/testsuite/playlist.c             | 403 -----------
 modules/services_discovery/Modules.am         |   1 -
 modules/services_discovery/bonjour.c          |   4 +-
 modules/services_discovery/daap.c             | 651 ------------------
 modules/services_discovery/hal.c              |   3 +-
 modules/services_discovery/sap.c              |   6 +-
 modules/services_discovery/upnp_cc.cpp        |  66 +-
 modules/services_discovery/upnp_intel.cpp     | 112 ++-
 src/control/playlist.c                        |  28 +-
 src/input/meta.c                              |   3 +-
 src/libvlc.c                                  |   2 +-
 src/playlist/control.c                        |  37 +-
 src/playlist/engine.c                         |  34 +-
 src/playlist/item.c                           | 115 ++--
 src/playlist/playlist_internal.h              |  14 +-
 src/playlist/search.c                         |  18 +-
 src/playlist/tree.c                           |  52 +-
 55 files changed, 509 insertions(+), 1578 deletions(-)
 delete mode 100644 modules/misc/testsuite/playlist.c
 delete mode 100644 modules/services_discovery/daap.c

diff --git a/configure.ac b/configure.ac
index 78fcd495f96c..17f7a67eee09 100644
--- a/configure.ac
+++ b/configure.ac
@@ -5064,20 +5064,6 @@ then
   fi
 fi
 
-dnl
-dnl DAAP access plugin and services discovery 
-dnl
-AC_ARG_ENABLE(daap,
-  [  --enable-daap	          DAAP shares services discovery support (default enabled)])
-if test "$enable_daap" != "no"
-then
-   PKG_CHECK_MODULES(DAAP, opendaap >= 0.3.0,
-      [ VLC_ADD_PLUGINS([daap])
-       VLC_ADD_LDFLAGS([daap],[$DAAP_LIBS])
-       VLC_ADD_CFLAGS([daap],[$DAAP_CFLAGS])]:,
-      [AC_MSG_WARN(DAAP library not found)])
-fi
-
 dnl
 dnl  Bonjour services discovery
 dnl
diff --git a/include/vlc_playlist.h b/include/vlc_playlist.h
index cc2394821983..bab715301a18 100644
--- a/include/vlc_playlist.h
+++ b/include/vlc_playlist.h
@@ -37,12 +37,85 @@ TYPEDEF_ARRAY(input_item_t*, input_item_array_t);
  * to the playlist in vlc
  *
  * \defgroup vlc_playlist Playlist
+ *
+ * The VLC playlist system has a tree structure. This allows advanced
+ * categorization, like for SAP streams (which are grouped by "sap groups").
+ *
+ * The base structure for all playlist operations is the input_item_t. This
+ * contains all information needed to play a stream and get info, ie, mostly,
+ * mrl and metadata. This structure contains a unique i_id field. ids are
+ * not recycled when an item is destroyed.
+ *
+ * Input items are not used directly, but through playlist items.
+ * The playlist items are themselves in a tree structure. They only contain
+ * a link to the input item, a unique id and a few flags. the playlist
+ * item id is NOT the same as the input item id.
+ * Several playlist items can be attached to a single input item. The input
+ * item is refcounted and is automatically destroyed when it is not used
+ * anymore.
+ *
+ * In the playlist itself, there are two trees, that should always be kept
+ * in sync. The "category" tree contains the whole tree structure with
+ * several levels, while the onelevel tree contains only one level :), ie
+ * it only contains "real" items, not nodes
+ * For example, if you open a directory, you will have
+ *
+ * Category tree:               Onevelel tree:
+ * Playlist                     Playlist
+ *  - Dir                         - item1
+ *    - Subdir                    - item2
+ *      - item1
+ *      - item2
+ *
+ * The top-level items of both tree are the same, and they are reproduced
+ * in the left-part of the playlist GUIs, they are the "sources" from the
+ * source selectors. Top-level items include: playlist, media library, SAP,
+ * Shoutcast, devices, ...
+ *
+ * It is envisioned that a third tree will appear: VLM, but it's not done yet
+ *
+ * The playlist also stores, for utility purposes, an array of all input
+ * items, an array of all playlist items and an array of all playlist items
+ * and nodes (both are represented by the same structure).
+ *
+ * So, here is an example:
+ *
+ * Inputs array
+ *  - input 1 -> name = foo 1 uri = ...
+ *  - input 2 -> name = foo 2 uri = ...
+ *
+ * Category tree                        Onlevel tree
+ * - playlist (id 1)                    - playlist (id 3)
+ *    - category 1 (id 2)                - foo 2 (id 8 - input 2)
+ *      - foo 2 (id 6 - input 2)       - media library (id 4)
+ * - media library (id 2)                - foo 1 (id6 - input 1)
+ *    - foo 1 (id 5 - input 1)
+ *
+ * Sometimes, an item must be transformed to a node. This happens for the
+ * directory access for example. In that case, the item is removed from
+ * the onelevel tree, as it is not a real item anymore.
+ *
+ * For "standard" item addition, you can use playlist_Add, playlist_AddExt
+ * (more options) or playlist_AddInput if you already created your input
+ * item. This will add the item at the root of "Playlist" or of "Media library"
+ * in each of the two trees.
+ *
+ * If you want more control (like, adding the item as the child of a given
+ * node in the category tree, use playlist_BothAddInput. You'll have to provide
+ * the node in the category tree. The item will be added as a child of
+ * this node in the category tree, and as a child of the matching top-level
+ * node in the onelevel tree. (Nodes are created with playlist_NodeCreate)
+ *
+ * Generally speaking, playlist_NodeAddInput should not be used in newer code, it
+ * will maybe become useful again when we merge VLM;
+ *
+ * To delete an item, use playlist_DeleteFromInput( input_id ) which will
+ * remove all occurences of the input in both trees
+ *
  * @{
  */
 
-/**
- * playlist export helper structure
- */
+/** Helper structure to export to file part of the playlist */
 struct playlist_export_t
 {
     char *psz_filename;
@@ -50,10 +123,7 @@ struct playlist_export_t
     playlist_item_t *p_root;
 };
 
-/**
- * playlist item / node
- * \see playlist_t
- */
+/** playlist item / node */
 struct playlist_item_t
 {
     input_item_t           *p_input;    /**< input item descriptor */
@@ -105,19 +175,19 @@ struct playlist_t
 
     playlist_item_array_t current; /**< Items currently being played */
     int                   i_current_index; /**< Index in current array */
-    /** Reset current item ? */
+    /** Reset current item array */
     vlc_bool_t            b_reset_currently_playing;
     mtime_t               last_rebuild_date;
 
     int                   i_last_playlist_id; /**< Last id to an item */
     int                   i_last_input_id ; /**< Last id on an input */
 
-    services_discovery_t **pp_sds;
-    int                   i_sds;
+    services_discovery_t **pp_sds; /**< Loaded service discovery modules */
+    int                   i_sds;   /**< Number of service discovery modules */
 
     /* Predefined items */
-    playlist_item_t *     p_root_category;
-    playlist_item_t *     p_root_onelevel;
+    playlist_item_t *     p_root_category; /**< Root of category tree */
+    playlist_item_t *     p_root_onelevel; /**< Root of onelevel tree */
     playlist_item_t *     p_local_category; /** < "Playlist" in CATEGORY view */
     playlist_item_t *     p_ml_category; /** < "Library" in CATEGORY view */
     playlist_item_t *     p_local_onelevel; /** < "Playlist" in ONELEVEL view */
@@ -165,10 +235,9 @@ struct playlist_t
     } request;
 
     // Playlist-unrelated fields
-    interaction_t       *p_interaction;       /**< Interaction manager */
-    /** The input thread computing stats */
-    input_thread_t      *p_stats_computer;
-    global_stats_t      *p_stats;             /**< Global statistics */
+    interaction_t       *p_interaction;    /**< Interaction manager */
+    input_thread_t      *p_stats_computer; /**< Input thread computing stats */
+    global_stats_t      *p_stats;          /**< Global statistics */
 };
 
 /** Helper to add an item */
@@ -216,18 +285,16 @@ static inline playlist_t *__pl_Yield( vlc_object_t *p_this )
 #define pl_Release(a) vlc_object_release( a->p_libvlc->p_playlist );
 
 /* Playlist control */
-#define playlist_Play(p) playlist_LockControl(p,PLAYLIST_PLAY )
-#define playlist_Pause(p) playlist_LockControl(p,PLAYLIST_PAUSE )
-#define playlist_Stop(p) playlist_LockControl(p,PLAYLIST_STOP )
-#define playlist_Next(p) playlist_LockControl(p,PLAYLIST_SKIP, 1)
-#define playlist_Prev(p) playlist_LockControl(p,PLAYLIST_SKIP, -1)
-#define playlist_Skip(p,i) playlist_LockControl(p,PLAYLIST_SKIP, i)
+#define playlist_Play(p) playlist_Control(p,PLAYLIST_PLAY, VLC_FALSE )
+#define playlist_Pause(p) playlist_Control(p,PLAYLIST_PAUSE, VLC_FALSE )
+#define playlist_Stop(p) playlist_Control(p,PLAYLIST_STOP, VLC_FALSE )
+#define playlist_Next(p) playlist_Control(p,PLAYLIST_SKIP, VLC_FALSE, 1)
+#define playlist_Prev(p) playlist_Control(p,PLAYLIST_SKIP, VLC_FALSE, -1)
+#define playlist_Skip(p,i) playlist_Control(p,PLAYLIST_SKIP, VLC_FALSE,  i)
 
-VLC_EXPORT( int, playlist_Control, ( playlist_t *, int, ...  ) );
-VLC_EXPORT( int, playlist_LockControl, ( playlist_t *, int, ...  ) );
+VLC_EXPORT( int, playlist_Control, ( playlist_t *, int, vlc_bool_t, ...  ) );
 
-VLC_EXPORT( void,  playlist_Clear, ( playlist_t * ) );
-VLC_EXPORT( void,  playlist_LockClear, ( playlist_t * ) );
+VLC_EXPORT( void,  playlist_Clear, ( playlist_t *, vlc_bool_t ) );
 
 VLC_EXPORT( int, playlist_PreparseEnqueue, (playlist_t *, input_item_t *) );
 VLC_EXPORT( int, playlist_PreparseEnqueueItem, (playlist_t *, playlist_item_t *) );
@@ -245,7 +312,7 @@ VLC_EXPORT( int,  playlist_TreeMove, ( playlist_t *, playlist_item_t *, playlist
 VLC_EXPORT( int,  playlist_NodeSort, ( playlist_t *, playlist_item_t *,int, int ) );
 VLC_EXPORT( int,  playlist_RecursiveNodeSort, ( playlist_t *, playlist_item_t *,int, int ) );
 
-/* Load/Save */
+/* Save a playlist file */
 VLC_EXPORT( int,  playlist_Export, ( playlist_t *, const char *, playlist_item_t *, const char * ) );
 
 /********************************************************
@@ -275,11 +342,7 @@ VLC_EXPORT( playlist_item_t *, __playlist_ItemNewFromInput, ( vlc_object_t *p_ob
 
 /*************************** Item deletion **************************/
 VLC_EXPORT( int, playlist_ItemDelete, ( playlist_item_t * ) );
-VLC_EXPORT( int,  playlist_DeleteAllFromInput, ( playlist_t *, int ) );
-VLC_EXPORT( int,  playlist_DeleteFromInput, ( playlist_t *, int, playlist_item_t *, vlc_bool_t ) );
-VLC_EXPORT( int,  playlist_DeleteFromItemId, ( playlist_t *, int ) );
-VLC_EXPORT( int,  playlist_LockDelete, ( playlist_t *, int ) );
-VLC_EXPORT( int,  playlist_LockDeleteAllFromInput, ( playlist_t *, int ) );
+VLC_EXPORT( int,  playlist_DeleteFromInput, ( playlist_t *, int, vlc_bool_t ) );
 
 /*************************** Item fields accessors **************************/
 VLC_EXPORT( int, playlist_ItemSetName, (playlist_item_t *, const char * ) );
@@ -289,40 +352,18 @@ VLC_EXPORT( int,  playlist_Add,    ( playlist_t *, const char *, const char *, i
 VLC_EXPORT( int,  playlist_AddExt, ( playlist_t *, const char *, const char *, int, int, mtime_t, const char *const *,int, vlc_bool_t ) );
 VLC_EXPORT( int, playlist_AddInput, ( playlist_t *, input_item_t *,int , int, vlc_bool_t ) );
 VLC_EXPORT( playlist_item_t *, playlist_NodeAddInput, ( playlist_t *, input_item_t *,playlist_item_t *,int , int ) );
-VLC_EXPORT( void, playlist_NodeAddItem, ( playlist_t *, playlist_item_t *, playlist_item_t *,int , int ) );
-VLC_EXPORT( int, playlist_BothAddInput, ( playlist_t *, input_item_t *,playlist_item_t *,int , int ) );
+VLC_EXPORT( int, playlist_BothAddInput, ( playlist_t *, input_item_t *,playlist_item_t *,int , int, int*, int* ) );
 
 /********************** Misc item operations **********************/
-VLC_EXPORT( playlist_item_t*, playlist_ItemToNode, (playlist_t *,playlist_item_t *) );
-VLC_EXPORT( playlist_item_t*, playlist_LockItemToNode, (playlist_t *,playlist_item_t *) );
+VLC_EXPORT( playlist_item_t*, playlist_ItemToNode, (playlist_t *,playlist_item_t *, vlc_bool_t) );
 
 playlist_item_t *playlist_ItemFindFromInputAndRoot( playlist_t *p_playlist,
                                    int i_input_id, playlist_item_t *p_root,
                                    vlc_bool_t );
 
 /********************************** Item search *************************/
-VLC_EXPORT( playlist_item_t *, playlist_ItemGetById, (playlist_t *, int) );
-VLC_EXPORT( playlist_item_t *, playlist_ItemGetByInput, (playlist_t *,input_item_t * ) );
-
-static inline playlist_item_t *playlist_LockItemGetById( playlist_t *p_playlist,
-                                                         int i_id)
-{
-    playlist_item_t *p_ret;
-    vlc_mutex_lock( &p_playlist->object_lock );
-    p_ret = playlist_ItemGetById( p_playlist, i_id );
-    vlc_mutex_unlock( &p_playlist->object_lock );
-    return p_ret;
-}
-
-static inline playlist_item_t *playlist_LockItemGetByInput(
-                                playlist_t *p_playlist, input_item_t *p_item )
-{
-    playlist_item_t *p_ret;
-    vlc_mutex_lock( &p_playlist->object_lock );
-    p_ret = playlist_ItemGetByInput( p_playlist, p_item );
-    vlc_mutex_unlock( &p_playlist->object_lock );
-    return p_ret;
-}
+VLC_EXPORT( playlist_item_t *, playlist_ItemGetById, (playlist_t *, int, vlc_bool_t) );
+VLC_EXPORT( playlist_item_t *, playlist_ItemGetByInput, (playlist_t *,input_item_t *, vlc_bool_t ) );
 
 VLC_EXPORT( int, playlist_LiveSearchUpdate, (playlist_t *, playlist_item_t *, const char *) );
 
@@ -367,7 +408,6 @@ static inline int playlist_Import( playlist_t *p_playlist, const char *psz_file)
 /** Tell the number of items in the current playing context */
 #define playlist_CurrentSize( obj ) obj->p_libvlc->p_playlist->current.i_size
 
-
 /** Ask the playlist to do some work */
 static inline void playlist_Signal( playlist_t *p_playlist )
 {
@@ -376,8 +416,6 @@ static inline void playlist_Signal( playlist_t *p_playlist )
     PL_UNLOCK;
 }
 
-/**
- * @}
- */
+/** @} */
 
 #endif
diff --git a/include/vlc_symbols.h b/include/vlc_symbols.h
index bfe87f6484db..28730bfbfa94 100644
--- a/include/vlc_symbols.h
+++ b/include/vlc_symbols.h
@@ -256,10 +256,10 @@ struct module_symbols_t
     void (*__vlc_object_release_inner) (vlc_object_t *);
     vlc_list_t * (*__vlc_list_find_inner) (vlc_object_t *, int, int);
     void (*vlc_list_release_inner) (vlc_list_t *);
-    int (*playlist_Control_inner) (playlist_t *, int, ...);
-    int (*playlist_LockControl_inner) (playlist_t *, int, ...);
-    void (*playlist_Clear_inner) (playlist_t *);
-    void (*playlist_LockClear_inner) (playlist_t *);
+    int (*playlist_Control_inner) (playlist_t *, int, vlc_bool_t, ...);
+    void *playlist_LockControl_deprecated;
+    void (*playlist_Clear_inner) (playlist_t *, vlc_bool_t);
+    void *playlist_LockClear_deprecated;
     int (*playlist_PreparseEnqueue_inner) (playlist_t *, input_item_t *);
     int (*playlist_ServicesDiscoveryAdd_inner) (playlist_t *, const char *);
     int (*playlist_ServicesDiscoveryRemove_inner) (playlist_t *, const char *);
@@ -290,20 +290,20 @@ struct module_symbols_t
     int (*playlist_Add_inner) (playlist_t *, const char *, const char *, int, int, vlc_bool_t);
     int (*playlist_AddExt_inner) (playlist_t *, const char *, const char *, int, int, mtime_t, const char *const *,int, vlc_bool_t);
     void *playlist_ItemAdd_deprecated;
-    void (*playlist_NodeAddItem_inner) (playlist_t *, playlist_item_t *, playlist_item_t *,int , int);
+    void *playlist_NodeAddItem_deprecated;
     void *playlist_Delete_deprecated;
-    int (*playlist_LockDelete_inner) (playlist_t *, int);
+    void *playlist_LockDelete_deprecated;
     void *playlist_Disable_deprecated;
     void *playlist_Enable_deprecated;
-    playlist_item_t* (*playlist_ItemToNode_inner) (playlist_t *,playlist_item_t *);
-    playlist_item_t* (*playlist_LockItemToNode_inner) (playlist_t *,playlist_item_t *);
+    playlist_item_t* (*playlist_ItemToNode_inner) (playlist_t *,playlist_item_t *, vlc_bool_t);
+    void *playlist_LockItemToNode_deprecated;
     void *playlist_Replace_deprecated;
     void *playlist_LockReplace_deprecated;
-    playlist_item_t * (*playlist_ItemGetById_inner) (playlist_t *, int);
+    playlist_item_t * (*playlist_ItemGetById_inner) (playlist_t *, int, vlc_bool_t);
     void *playlist_LockItemGetById_deprecated;
     void *playlist_ItemGetByPos_deprecated;
     void *playlist_LockItemGetByPos_deprecated;
-    playlist_item_t * (*playlist_ItemGetByInput_inner) (playlist_t *,input_item_t *);
+    playlist_item_t * (*playlist_ItemGetByInput_inner) (playlist_t *,input_item_t *, vlc_bool_t);
     void *playlist_LockItemGetByInput_deprecated;
     void *playlist_GetPositionById_deprecated;
     void *playlist_ItemAddOption_deprecated;
@@ -498,16 +498,16 @@ struct module_symbols_t
     void *playlist_PlaylistAdd_deprecated;
     void *playlist_PlaylistAddExt_deprecated;
     void *playlist_PlaylistAddInput_deprecated;
-    int (*playlist_BothAddInput_inner) (playlist_t *, input_item_t *,playlist_item_t *,int , int);
+    int (*playlist_BothAddInput_inner) (playlist_t *, input_item_t *,playlist_item_t *,int , int, int*, int*);
     playlist_item_t * (*__playlist_ItemNewFromInput_inner) (vlc_object_t *p_obj,input_item_t *p_input);
     input_item_t * (*input_ItemGetById_inner) (playlist_t *, int);
     int (*playlist_LiveSearchUpdate_inner) (playlist_t *, playlist_item_t *, const char *);
     void *vlc_input_item_AddOption_deprecated;
-    int (*playlist_DeleteFromInput_inner) (playlist_t *, int, playlist_item_t *, vlc_bool_t);
-    int (*playlist_DeleteAllFromInput_inner) (playlist_t *, int);
-    int (*playlist_LockDeleteAllFromInput_inner) (playlist_t *, int);
+    int (*playlist_DeleteFromInput_inner) (playlist_t *, int, vlc_bool_t);
+    void *playlist_DeleteAllFromInput_deprecated;
+    void *playlist_LockDeleteAllFromInput_deprecated;
     void *playlist_AddWhereverNeeded_deprecated;
-    int (*playlist_DeleteFromItemId_inner) (playlist_t *, int);
+    void *playlist_DeleteFromItemId_deprecated;
     void (*playlist_NodeDump_inner) (playlist_t *p_playlist, playlist_item_t *p_item, int i_level);
     void *__intf_UserOkayCancel_deprecated;
     int (*__intf_UserStringInput_inner) (vlc_object_t*, const char*, const char*, char **);
@@ -793,9 +793,7 @@ struct module_symbols_t
 #  define __vlc_list_find (p_symbols)->__vlc_list_find_inner
 #  define vlc_list_release (p_symbols)->vlc_list_release_inner
 #  define playlist_Control (p_symbols)->playlist_Control_inner
-#  define playlist_LockControl (p_symbols)->playlist_LockControl_inner
 #  define playlist_Clear (p_symbols)->playlist_Clear_inner
-#  define playlist_LockClear (p_symbols)->playlist_LockClear_inner
 #  define playlist_PreparseEnqueue (p_symbols)->playlist_PreparseEnqueue_inner
 #  define playlist_ServicesDiscoveryAdd (p_symbols)->playlist_ServicesDiscoveryAdd_inner
 #  define playlist_ServicesDiscoveryRemove (p_symbols)->playlist_ServicesDiscoveryRemove_inner
@@ -814,10 +812,7 @@ struct module_symbols_t
 #  define playlist_NodeEmpty (p_symbols)->playlist_NodeEmpty_inner
 #  define playlist_Add (p_symbols)->playlist_Add_inner
 #  define playlist_AddExt (p_symbols)->playlist_AddExt_inner
-#  define playlist_NodeAddItem (p_symbols)->playlist_NodeAddItem_inner
-#  define playlist_LockDelete (p_symbols)->playlist_LockDelete_inner
 #  define playlist_ItemToNode (p_symbols)->playlist_ItemToNode_inner
-#  define playlist_LockItemToNode (p_symbols)->playlist_LockItemToNode_inner
 #  define playlist_ItemGetById (p_symbols)->playlist_ItemGetById_inner
 #  define playlist_ItemGetByInput (p_symbols)->playlist_ItemGetByInput_inner
 #  define playlist_NodeSort (p_symbols)->playlist_NodeSort_inner
@@ -994,9 +989,6 @@ struct module_symbols_t
 #  define input_ItemGetById (p_symbols)->input_ItemGetById_inner
 #  define playlist_LiveSearchUpdate (p_symbols)->playlist_LiveSearchUpdate_inner
 #  define playlist_DeleteFromInput (p_symbols)->playlist_DeleteFromInput_inner
-#  define playlist_DeleteAllFromInput (p_symbols)->playlist_DeleteAllFromInput_inner
-#  define playlist_LockDeleteAllFromInput (p_symbols)->playlist_LockDeleteAllFromInput_inner
-#  define playlist_DeleteFromItemId (p_symbols)->playlist_DeleteFromItemId_inner
 #  define playlist_NodeDump (p_symbols)->playlist_NodeDump_inner
 #  define __intf_UserStringInput (p_symbols)->__intf_UserStringInput_inner
 #  define input_AddSubtitles (p_symbols)->input_AddSubtitles_inner
@@ -1273,9 +1265,7 @@ struct module_symbols_t
     ((p_symbols)->__vlc_list_find_inner) = __vlc_list_find; \
     ((p_symbols)->vlc_list_release_inner) = vlc_list_release; \
     ((p_symbols)->playlist_Control_inner) = playlist_Control; \
-    ((p_symbols)->playlist_LockControl_inner) = playlist_LockControl; \
     ((p_symbols)->playlist_Clear_inner) = playlist_Clear; \
-    ((p_symbols)->playlist_LockClear_inner) = playlist_LockClear; \
     ((p_symbols)->playlist_PreparseEnqueue_inner) = playlist_PreparseEnqueue; \
     ((p_symbols)->playlist_ServicesDiscoveryAdd_inner) = playlist_ServicesDiscoveryAdd; \
     ((p_symbols)->playlist_ServicesDiscoveryRemove_inner) = playlist_ServicesDiscoveryRemove; \
@@ -1294,10 +1284,7 @@ struct module_symbols_t
     ((p_symbols)->playlist_NodeEmpty_inner) = playlist_NodeEmpty; \
     ((p_symbols)->playlist_Add_inner) = playlist_Add; \
     ((p_symbols)->playlist_AddExt_inner) = playlist_AddExt; \
-    ((p_symbols)->playlist_NodeAddItem_inner) = playlist_NodeAddItem; \
-    ((p_symbols)->playlist_LockDelete_inner) = playlist_LockDelete; \
     ((p_symbols)->playlist_ItemToNode_inner) = playlist_ItemToNode; \
-    ((p_symbols)->playlist_LockItemToNode_inner) = playlist_LockItemToNode; \
     ((p_symbols)->playlist_ItemGetById_inner) = playlist_ItemGetById; \
     ((p_symbols)->playlist_ItemGetByInput_inner) = playlist_ItemGetByInput; \
     ((p_symbols)->playlist_NodeSort_inner) = playlist_NodeSort; \
@@ -1474,9 +1461,6 @@ struct module_symbols_t
     ((p_symbols)->input_ItemGetById_inner) = input_ItemGetById; \
     ((p_symbols)->playlist_LiveSearchUpdate_inner) = playlist_LiveSearchUpdate; \
     ((p_symbols)->playlist_DeleteFromInput_inner) = playlist_DeleteFromInput; \
-    ((p_symbols)->playlist_DeleteAllFromInput_inner) = playlist_DeleteAllFromInput; \
-    ((p_symbols)->playlist_LockDeleteAllFromInput_inner) = playlist_LockDeleteAllFromInput; \
-    ((p_symbols)->playlist_DeleteFromItemId_inner) = playlist_DeleteFromItemId; \
     ((p_symbols)->playlist_NodeDump_inner) = playlist_NodeDump; \
     ((p_symbols)->__intf_UserStringInput_inner) = __intf_UserStringInput; \
     ((p_symbols)->input_AddSubtitles_inner) = input_AddSubtitles; \
@@ -1522,6 +1506,8 @@ struct module_symbols_t
     (p_symbols)->sout_CfgCreate_deprecated = NULL; \
     (p_symbols)->vlc_input_item_GetInfo_deprecated = NULL; \
     (p_symbols)->vlc_input_item_AddInfo_deprecated = NULL; \
+    (p_symbols)->playlist_LockControl_deprecated = NULL; \
+    (p_symbols)->playlist_LockClear_deprecated = NULL; \
     (p_symbols)->__playlist_ItemNew_deprecated = NULL; \
     (p_symbols)->__playlist_ItemCopy_deprecated = NULL; \
     (p_symbols)->playlist_ItemAddParent_deprecated = NULL; \
@@ -1534,9 +1520,12 @@ struct module_symbols_t
     (p_symbols)->playlist_ViewDump_deprecated = NULL; \
     (p_symbols)->playlist_ViewEmpty_deprecated = NULL; \
     (p_symbols)->playlist_ItemAdd_deprecated = NULL; \
+    (p_symbols)->playlist_NodeAddItem_deprecated = NULL; \
     (p_symbols)->playlist_Delete_deprecated = NULL; \
+    (p_symbols)->playlist_LockDelete_deprecated = NULL; \
     (p_symbols)->playlist_Disable_deprecated = NULL; \
     (p_symbols)->playlist_Enable_deprecated = NULL; \
+    (p_symbols)->playlist_LockItemToNode_deprecated = NULL; \
     (p_symbols)->playlist_Replace_deprecated = NULL; \
     (p_symbols)->playlist_LockReplace_deprecated = NULL; \
     (p_symbols)->playlist_LockItemGetById_deprecated = NULL; \
@@ -1568,7 +1557,10 @@ struct module_symbols_t
     (p_symbols)->playlist_PlaylistAddExt_deprecated = NULL; \
     (p_symbols)->playlist_PlaylistAddInput_deprecated = NULL; \
     (p_symbols)->vlc_input_item_AddOption_deprecated = NULL; \
+    (p_symbols)->playlist_DeleteAllFromInput_deprecated = NULL; \
+    (p_symbols)->playlist_LockDeleteAllFromInput_deprecated = NULL; \
     (p_symbols)->playlist_AddWhereverNeeded_deprecated = NULL; \
+    (p_symbols)->playlist_DeleteFromItemId_deprecated = NULL; \
     (p_symbols)->__intf_UserOkayCancel_deprecated = NULL; \
     (p_symbols)->playlist_NodesCreateForSD_deprecated = NULL; \
     (p_symbols)->stats_TimerClean_deprecated = NULL; \
diff --git a/modules/access/cdda.c b/modules/access/cdda.c
index dec483594b3b..1d5a11cdbc70 100644
--- a/modules/access/cdda.c
+++ b/modules/access/cdda.c
@@ -195,7 +195,7 @@ static int Open( vlc_object_t *p_this )
         {
             input_item_t *p_current = ( (input_thread_t*)p_access->p_parent)->
                                          input.p_item;
-            p_item = playlist_LockItemGetByInput( p_playlist, p_current );
+            p_item = playlist_ItemGetByInput( p_playlist, p_current, VLC_FALSE );
 
             if( !p_item )
             {
@@ -415,7 +415,7 @@ static int GetTracks( access_t *p_access,
         return VLC_EGENERIC;
     }
 
-    p_item_in_category = playlist_LockItemToNode( p_playlist, p_parent );
+    p_item_in_category = playlist_ItemToNode( p_playlist, p_parent, VLC_FALSE );
     psz_name = strdup( "Audio CD" );
     vlc_mutex_lock( &p_playlist->object_lock );
     playlist_ItemSetName( p_parent, psz_name );
@@ -502,7 +502,7 @@ static int GetTracks( access_t *p_access,
         }
 #endif
         playlist_BothAddInput( p_playlist, p_input_item, p_item_in_category,
-                               PLAYLIST_APPEND, PLAYLIST_END );
+                               PLAYLIST_APPEND, PLAYLIST_END, NULL, NULL );
         free( psz_uri ); free( psz_opt ); free( psz_name );
         free( psz_first ); free( psz_last );
     }
diff --git a/modules/access/cdda/info.c b/modules/access/cdda/info.c
index cc6e596c8f54..e2ef12268728 100644
--- a/modules/access/cdda/info.c
+++ b/modules/access/cdda/info.c
@@ -844,12 +844,6 @@ CDDACreatePlaylistItem( const access_t *p_access, cdda_data_t *p_cdda,
     free(psz_title);
 
     if( !p_child ) return NULL;
-#if 0
-    playlist_NodeAddItem( p_playlist, p_child,
-                          p_item->p_parent->i_view,
-                          p_item, PLAYLIST_APPEND, PLAYLIST_END );
-    playlist_CopyParents( p_item, p_child );
-#endif
     return p_child;
 }
 
@@ -945,8 +939,8 @@ CDDAFixupPlaylist( access_t *p_access, cdda_data_t *p_cdda,
 
     if (p_playlist) {
 
-      p_item = playlist_LockItemGetByInput( p_playlist,
-                        ((input_thread_t *)p_access->p_parent)->input.p_item );
+      p_item = playlist_ItemGetByInput( p_playlist,
+                        ((input_thread_t *)p_access->p_parent)->input.p_item, VLC_FALSE );
 
       if( p_item == p_playlist->status.p_item && !b_single_track )
 	{
@@ -1030,7 +1024,7 @@ CDDAFixupPlaylist( access_t *p_access, cdda_data_t *p_cdda,
 
     if( b_play )
     {
-        playlist_Control( p_playlist, PLAYLIST_VIEWPLAY,
+        playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, VLC_TRUE,
                           p_playlist->status.p_item, NULL );
     }
 
diff --git a/modules/access/directory.c b/modules/access/directory.c
index 40ec31878102..abc6f3a2f205 100644
--- a/modules/access/directory.c
+++ b/modules/access/directory.c
@@ -185,7 +185,7 @@ static int Read( access_t *p_access, uint8_t *p_buffer, int i_len)
     input_item_t       *p_current_input = ( (input_thread_t*)p_access->p_parent)
                                                        ->input.p_item;
     playlist_item_t    *p_current =
-                playlist_LockItemGetByInput( p_playlist, p_current_input );
+                    playlist_ItemGetByInput( p_playlist, p_current_input, VLC_FALSE );
     char               *psz_name = strdup (p_access->psz_path);
 
     if( psz_name == NULL )
@@ -221,7 +221,7 @@ static int Read( access_t *p_access, uint8_t *p_buffer, int i_len)
     msg_Dbg( p_access, "opening directory `%s'", p_access->psz_path );
 
     p_current->p_input->i_type = ITEM_TYPE_DIRECTORY;
-    p_item_in_category = playlist_LockItemToNode( p_playlist, p_current );
+    p_item_in_category = playlist_ItemToNode( p_playlist, p_current, VLC_FALSE );
 
     i_activity = var_GetInteger( p_playlist, "activity" );
     var_SetInteger( p_playlist, "activity", i_activity +
@@ -472,7 +472,7 @@ static int ReadDir( playlist_t *p_playlist, const char *psz_name,
                     playlist_BothAddInput( p_playlist, p_input,
                                            p_parent_category,
                                            PLAYLIST_APPEND|PLAYLIST_PREPARSE,
-                                           PLAYLIST_END );
+                                           PLAYLIST_END, NULL, NULL );
             }
         }
     }
diff --git a/modules/codec/cmml/intf.c b/modules/codec/cmml/intf.c
index 346c69020ef0..72e5c5a98849 100644
--- a/modules/codec/cmml/intf.c
+++ b/modules/codec/cmml/intf.c
@@ -533,7 +533,7 @@ static void FollowAnchor ( intf_thread_t *p_intf )
             msg_Dbg( p_intf, "calling browser_Open with \"%s\"", psz_url );
 #endif
             (void) browser_Open( psz_url );
-            playlist_Control( p_playlist, PLAYLIST_PAUSE, 0 );
+            playlist_Control( p_playlist, PLAYLIST_PAUSE, VLC_TRUE, 0 );
         }
 
         free( psz_uri_to_load );
diff --git a/modules/control/hotkeys.c b/modules/control/hotkeys.c
index 00134cfb24af..e066a69d23f0 100644
--- a/modules/control/hotkeys.c
+++ b/modules/control/hotkeys.c
@@ -800,10 +800,12 @@ static void PlayBookmark( intf_thread_t *p_intf, int i_num )
     FOREACH_ARRAY( playlist_item_t *p_item, p_playlist->items )
         if( !strcmp( psz_bookmark, p_item->p_input->psz_uri ) )
         {
-            playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, NULL, p_item );
+            playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, VLC_TRUE,
+                              NULL, p_item );
             break;
         }
     FOREACH_END();
+    PL_UNLOCK;
     vlc_object_release( p_playlist );
 }
 
diff --git a/modules/control/http/macro.c b/modules/control/http/macro.c
index 45e8e8654ed3..bc9706096213 100644
--- a/modules/control/http/macro.c
+++ b/modules/control/http/macro.c
@@ -197,26 +197,30 @@ void E_(MacroDo)( httpd_file_sys_t *p_args,
                         break;
                     }
                     playlist_Control( p_sys->p_playlist, PLAYLIST_VIEWPLAY,
-                                      NULL,
+                                      VLC_TRUE, NULL,
                                       playlist_ItemGetById( p_sys->p_playlist,
-                                      i_item ) );
+                                      i_item, VLC_TRUE ) );
                     msg_Dbg( p_intf, "requested playlist item: %i", i_item );
                     break;
                 }
                 case MVLC_STOP:
-                    playlist_Control( p_sys->p_playlist, PLAYLIST_STOP );
+                    playlist_Control( p_sys->p_playlist, PLAYLIST_STOP,
+                                      VLC_TRUE );
                     msg_Dbg( p_intf, "requested playlist stop" );
                     break;
                 case MVLC_PAUSE:
-                    playlist_Control( p_sys->p_playlist, PLAYLIST_PAUSE );
+                    playlist_Control( p_sys->p_playlist, PLAYLIST_PAUSE,
+                                      VLC_TRUE );
                     msg_Dbg( p_intf, "requested playlist pause" );
                     break;
                 case MVLC_NEXT:
-                    playlist_Control( p_sys->p_playlist, PLAYLIST_SKIP, 1 );
+                    playlist_Control( p_sys->p_playlist, PLAYLIST_SKIP,
+                                      VLC_TRUE, 1 );
                     msg_Dbg( p_intf, "requested playlist next" );
                     break;
                 case MVLC_PREVIOUS:
-                    playlist_Control( p_sys->p_playlist, PLAYLIST_SKIP, -1 );
+                    playlist_Control( p_sys->p_playlist, PLAYLIST_SKIP,
+                                      VLC_TRUE, -1 );
                     msg_Dbg( p_intf, "requested playlist previous" );
                     break;
                 case MVLC_FULLSCREEN:
@@ -368,8 +372,8 @@ void E_(MacroDo)( httpd_file_sys_t *p_args,
                         int i;
                         for( i = 0; i < i_nb_items; i++ )
                         {
-                            playlist_LockDeleteAllFromInput( p_sys->p_playlist,
-                                                             p_items[i] );
+                            playlist_DeleteFromInput( p_sys->p_playlist,
+                                                      p_items[i], VLC_FALSE );
                             msg_Dbg( p_intf, "requested playlist delete: %d",
                                      p_items[i] );
                             p_items[i] = -1;
@@ -410,8 +414,9 @@ void E_(MacroDo)( httpd_file_sys_t *p_args,
                         }
                         if( j == i_nb_items )
                         {
-                            playlist_LockDeleteAllFromInput( p_sys->p_playlist,
-                           p_sys->p_playlist->items.p_elems[i]->p_input->i_id );
+                            playlist_DeleteFromInput( p_sys->p_playlist,
+                                     p_sys->p_playlist->items.p_elems[i]->p_input->i_id,
+                                                      VLC_FALSE );
                             msg_Dbg( p_intf, "requested playlist delete: %d",
                                      i );
                         }
@@ -422,7 +427,7 @@ void E_(MacroDo)( httpd_file_sys_t *p_args,
                 }
                 case MVLC_EMPTY:
                 {
-                    playlist_LockClear( p_sys->p_playlist );
+                    playlist_Clear( p_sys->p_playlist, VLC_FALSE );
                     msg_Dbg( p_intf, "requested playlist empty" );
                     break;
                 }
@@ -444,7 +449,7 @@ void E_(MacroDo)( httpd_file_sys_t *p_args,
 
                     if( !strcmp( type , "title" ) )
                     {
-                        playlist_RecursiveNodeSort( p_sys->p_playlist, /*playlist_ItemGetById( p_sys->p_playlist, i_item ),*/
+                        playlist_RecursiveNodeSort( p_sys->p_playlist,
                                                     /* Ugly hack,but not worse than before ... */
                                                     p_sys->p_playlist->p_root_onelevel,
                                                     SORT_TITLE_NODES_FIRST,
diff --git a/modules/control/http/rpn.c b/modules/control/http/rpn.c
index 1da4491eb6dc..c1ba23ca79d4 100644
--- a/modules/control/http/rpn.c
+++ b/modules/control/http/rpn.c
@@ -489,31 +489,31 @@ void E_(EvaluateRPN)( intf_thread_t *p_intf, mvar_t  *vars,
             int i_id = E_(SSPopN)( st, vars );
             int i_ret;
 
-            i_ret = playlist_Control( p_sys->p_playlist, PLAYLIST_VIEWPLAY,
+            i_ret = playlist_Control( p_sys->p_playlist, PLAYLIST_VIEWPLAY, VLC_TRUE,
                                       NULL,
                                       playlist_ItemGetById( p_sys->p_playlist,
-                                      i_id ) );
+                                      i_id, VLC_TRUE ) );
             msg_Dbg( p_intf, "requested playlist item: %i", i_id );
             E_(SSPushN)( st, i_ret );
         }
         else if( !strcmp( s, "vlc_stop" ) )
         {
-            playlist_Control( p_sys->p_playlist, PLAYLIST_STOP );
+            playlist_Control( p_sys->p_playlist, VLC_TRUE, PLAYLIST_STOP );
             msg_Dbg( p_intf, "requested playlist stop" );
         }
         else if( !strcmp( s, "vlc_pause" ) )
         {
-            playlist_Control( p_sys->p_playlist, PLAYLIST_PAUSE );
+            playlist_Control( p_sys->p_playlist, VLC_TRUE, PLAYLIST_PAUSE );
             msg_Dbg( p_intf, "requested playlist pause" );
         }
         else if( !strcmp( s, "vlc_next" ) )
         {
-            playlist_Control( p_sys->p_playlist, PLAYLIST_SKIP, 1 );
+            playlist_Control( p_sys->p_playlist, VLC_TRUE, PLAYLIST_SKIP, 1 );
             msg_Dbg( p_intf, "requested playlist next" );
         }
         else if( !strcmp( s, "vlc_previous" ) )
         {
-            playlist_Control( p_sys->p_playlist, PLAYLIST_SKIP, -1 );
+            playlist_Control( p_sys->p_playlist, VLC_TRUE, PLAYLIST_SKIP, -1 );
             msg_Dbg( p_intf, "requested playlist previous" );
         }
         else if( !strcmp( s, "vlc_seek" ) )
@@ -861,13 +861,13 @@ void E_(EvaluateRPN)( intf_thread_t *p_intf, mvar_t  *vars,
         }
         else if( !strcmp( s, "playlist_empty" ) )
         {
-            playlist_LockClear( p_sys->p_playlist );
+            playlist_Clear( p_sys->p_playlist, VLC_FALSE );
             msg_Dbg( p_intf, "requested playlist empty" );
         }
         else if( !strcmp( s, "playlist_delete" ) )
         {
             int i_id = E_(SSPopN)( st, vars );
-            playlist_LockDeleteAllFromInput( p_sys->p_playlist, i_id );
+            playlist_DeleteFromInput( p_sys->p_playlist, i_id, VLC_FALSE );
             msg_Dbg( p_intf, "requested playlist delete: %d", i_id );
         }
         else if( !strcmp( s, "playlist_move" ) )
diff --git a/modules/control/rc.c b/modules/control/rc.c
index 0a1e297d7504..acc4fbdc6e6d 100644
--- a/modules/control/rc.c
+++ b/modules/control/rc.c
@@ -1404,9 +1404,7 @@ static int Playlist( vlc_object_t *p_this, char const *psz_cmd,
     else if( !strcmp( psz_cmd, "clear" ) )
     {
         playlist_Stop( p_playlist );
-        vlc_mutex_lock( &p_playlist->object_lock );
-        playlist_Clear( p_playlist );
-        vlc_mutex_unlock( &p_playlist->object_lock );
+        playlist_Clear( p_playlist, VLC_FALSE );
     }
     else if( !strcmp( psz_cmd, "add" ) &&
              newval.psz_string && *newval.psz_string )
diff --git a/modules/demux/mp4/mp4.c b/modules/demux/mp4/mp4.c
index a430c7fa3893..1e0ee95e89ea 100644
--- a/modules/demux/mp4/mp4.c
+++ b/modules/demux/mp4/mp4.c
@@ -364,7 +364,7 @@ static int Open( vlc_object_t * p_this )
         if( p_playlist )
         {
             b_play = FindItem( p_demux, p_playlist, &p_current );
-            p_item_in_category = playlist_ItemToNode( p_playlist, p_current );
+            p_item_in_category = playlist_ItemToNode( p_playlist, p_current, VLC_TRUE );
             p_current->p_input->i_type = ITEM_TYPE_PLAYLIST;
 
             for( i = 0; i < i_count; i++ )
@@ -417,7 +417,8 @@ static int Open( vlc_object_t * p_this )
                         input_ItemCopyOptions( p_current->p_input, p_input );
                         playlist_BothAddInput( p_playlist, p_input,
                                                p_item_in_category,
-                                               PLAYLIST_APPEND, PLAYLIST_END );
+                                               PLAYLIST_APPEND, PLAYLIST_END,
+                                               NULL, NULL);
                     }
                 }
                 else
@@ -430,7 +431,7 @@ static int Open( vlc_object_t * p_this )
             if( b_play && p_playlist->status.p_item &&
                   p_playlist->status.p_item->i_children > 0)
             {
-                playlist_Control( p_playlist, PLAYLIST_VIEWPLAY,
+                playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, VLC_TRUE,
                                   p_playlist->status.p_item, NULL );
             }
             vlc_object_release( p_playlist );
@@ -2225,7 +2226,7 @@ static vlc_bool_t FindItem( demux_t *p_demux, playlist_t *p_playlist,
      {
          input_item_t *p_current = ( (input_thread_t*)p_demux->p_parent)->
                                                         input.p_item;
-         *pp_item = playlist_LockItemGetByInput( p_playlist, p_current );
+         *pp_item = playlist_ItemGetByInput( p_playlist, p_current, VLC_FALSE );
          if( !*pp_item )
          {
              msg_Dbg( p_playlist, "unable to find item in playlist");
diff --git a/modules/demux/playlist/asx.c b/modules/demux/playlist/asx.c
index a3d44aeaa4ad..a6c3fa0d91f9 100644
--- a/modules/demux/playlist/asx.c
+++ b/modules/demux/playlist/asx.c
@@ -371,7 +371,7 @@ static int Demux( demux_t *p_demux )
                             playlist_BothAddInput( p_playlist, p_input,
                                                    p_item_in_category,
                                             PLAYLIST_APPEND|PLAYLIST_SPREPARSE,
-                                            PLAYLIST_END );
+                                            PLAYLIST_END, NULL, NULL );
                             free( psz_string );
                         }
                         else continue;
@@ -451,7 +451,7 @@ static int Demux( demux_t *p_demux )
                             playlist_BothAddInput( p_playlist, p_entry,
                                                  p_item_in_category,
                                                  PLAYLIST_APPEND | PLAYLIST_SPREPARSE
-                                                 , PLAYLIST_END);
+                                                 , PLAYLIST_END, NULL, NULL);
                             free( psz_string );
                         }
                         else continue;
diff --git a/modules/demux/playlist/b4s.c b/modules/demux/playlist/b4s.c
index baa52f911334..6f4eca3379c6 100644
--- a/modules/demux/playlist/b4s.c
+++ b/modules/demux/playlist/b4s.c
@@ -269,7 +269,7 @@ static int Demux( demux_t *p_demux )
                     playlist_BothAddInput( p_playlist, p_input,
                                            p_item_in_category,
                                            PLAYLIST_APPEND | PLAYLIST_SPREPARSE,
-                                           PLAYLIST_END );
+                                           PLAYLIST_END, NULL, NULL );
                     FREENULL( psz_name );
                     FREENULL( psz_mrl );
                     FREENULL( psz_genre );
diff --git a/modules/demux/playlist/dvb.c b/modules/demux/playlist/dvb.c
index 0c0eeb11164d..2ea17e11ab9d 100644
--- a/modules/demux/playlist/dvb.c
+++ b/modules/demux/playlist/dvb.c
@@ -120,7 +120,7 @@ static int Demux( demux_t *p_demux )
         }
         playlist_BothAddInput( p_playlist, p_input, p_item_in_category,
                                PLAYLIST_APPEND | PLAYLIST_SPREPARSE,
-                               PLAYLIST_END );
+                               PLAYLIST_END, NULL, NULL );
 
         while( i_options-- ) free( ppsz_options[i_options] );
         if( ppsz_options ) free( ppsz_options );
diff --git a/modules/demux/playlist/gvp.c b/modules/demux/playlist/gvp.c
index 23ecc4d748ed..5ccac509dbfb 100644
--- a/modules/demux/playlist/gvp.c
+++ b/modules/demux/playlist/gvp.c
@@ -216,7 +216,7 @@ static int Demux( demux_t *p_demux )
         playlist_BothAddInput( p_sys->p_playlist, p_input,
                                p_sys->p_item_in_category,
                                PLAYLIST_APPEND | PLAYLIST_SPREPARSE,
-                               PLAYLIST_END );
+                               PLAYLIST_END, NULL, NULL );
     }
 
     HANDLE_PLAY_AND_RELEASE;
diff --git a/modules/demux/playlist/m3u.c b/modules/demux/playlist/m3u.c
index 25e259454df0..6f44392a5b73 100644
--- a/modules/demux/playlist/m3u.c
+++ b/modules/demux/playlist/m3u.c
@@ -170,7 +170,7 @@ static int Demux( demux_t *p_demux )
                                         _(VLC_META_ARTIST), "%s", psz_artist );
             playlist_BothAddInput( p_playlist, p_input, p_item_in_category,
                                    PLAYLIST_APPEND | PLAYLIST_SPREPARSE,
-                                   PLAYLIST_END );
+                                   PLAYLIST_END, NULL, NULL );
             free( psz_mrl );
         }
 
diff --git a/modules/demux/playlist/playlist.h b/modules/demux/playlist/playlist.h
index 49c1612556d5..98cd832ea349 100644
--- a/modules/demux/playlist/playlist.h
+++ b/modules/demux/playlist/playlist.h
@@ -73,9 +73,10 @@ void E_(Close_GVP) ( vlc_object_t * );
     input_item_t *p_current_input = ( (input_thread_t*)p_demux->p_parent)-> \
                                                          input.p_item; \
     playlist_item_t *p_current = \
-                 playlist_LockItemGetByInput( p_playlist, p_current_input ); \
+                 playlist_ItemGetByInput( p_playlist, p_current_input, VLC_FALSE ); \
     playlist_item_t *p_item_in_category = \
-                            playlist_ItemToNode( p_playlist, p_current ); \
+                            playlist_ItemToNode( p_playlist, p_current, \
+                                                 VLC_TRUE ); \
     b_play = b_play && p_current == p_playlist->status.p_item; \
     if( p_item_in_category ) \
         p_item_in_category->p_input->i_type = ITEM_TYPE_PLAYLIST;
@@ -83,6 +84,6 @@ void E_(Close_GVP) ( vlc_object_t * );
 #define HANDLE_PLAY_AND_RELEASE \
     /* Go back and play the playlist */ \
     if( b_play && p_item_in_category && p_item_in_category->i_children > 0 ) \
-        playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, p_item_in_category, \
+        playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, VLC_TRUE, p_item_in_category, \
                           NULL ); \
     vlc_object_release( p_playlist );
diff --git a/modules/demux/playlist/pls.c b/modules/demux/playlist/pls.c
index 816cdbb2aa94..164b351f1be3 100644
--- a/modules/demux/playlist/pls.c
+++ b/modules/demux/playlist/pls.c
@@ -158,7 +158,7 @@ static int Demux( demux_t *p_demux )
                 input_ItemCopyOptions( p_current->p_input, p_input );
                 playlist_BothAddInput( p_playlist, p_input, p_item_in_category,
                                        PLAYLIST_APPEND | PLAYLIST_SPREPARSE,
-                                       PLAYLIST_END );
+                                       PLAYLIST_END, NULL, NULL );
             }
             else
             {
@@ -215,7 +215,7 @@ static int Demux( demux_t *p_demux )
         input_ItemCopyOptions( p_current->p_input, p_input );
         playlist_BothAddInput( p_playlist, p_input, p_item_in_category,
                                PLAYLIST_APPEND | PLAYLIST_SPREPARSE,
-                               PLAYLIST_END );
+                               PLAYLIST_END, NULL, NULL );
         free( psz_mrl_orig );
         psz_mrl = NULL;
     }
diff --git a/modules/demux/playlist/podcast.c b/modules/demux/playlist/podcast.c
index 78976e817392..9bb23f6830db 100644
--- a/modules/demux/playlist/podcast.c
+++ b/modules/demux/playlist/podcast.c
@@ -294,7 +294,7 @@ static int Demux( demux_t *p_demux )
                     playlist_BothAddInput( p_playlist, p_input,
                                            p_item_in_category,
                                            PLAYLIST_APPEND | PLAYLIST_SPREPARSE
-                                           , PLAYLIST_END );
+                                           , PLAYLIST_END, NULL, NULL );
                     FREENULL( psz_item_name );
                     FREENULL( psz_item_mrl );
                     FREENULL( psz_item_size );
diff --git a/modules/demux/playlist/qtl.c b/modules/demux/playlist/qtl.c
index cae957baf51b..e4177395a298 100644
--- a/modules/demux/playlist/qtl.c
+++ b/modules/demux/playlist/qtl.c
@@ -71,11 +71,11 @@ typedef enum { FULLSCREEN_NORMAL,
                FULLSCREEN_HALF,
                FULLSCREEN_CURRENT,
                FULLSCREEN_FULL } qtl_fullscreen_t;
-char* ppsz_fullscreen[] = { "normal", "double", "half", "current", "full" };
+const char* ppsz_fullscreen[] = { "normal", "double", "half", "current", "full" };
 typedef enum { LOOP_TRUE,
                LOOP_FALSE,
                LOOP_PALINDROME } qtl_loop_t;
-char* ppsz_loop[] = { "true", "false", "palindrome" };
+const char* ppsz_loop[] = { "true", "false", "palindrome" };
 
 /*****************************************************************************
  * Local prototypes
@@ -363,7 +363,7 @@ static int Demux( demux_t *p_demux )
         playlist_BothAddInput( p_sys->p_playlist, p_input,
                                p_sys->p_item_in_category,
                                PLAYLIST_APPEND | PLAYLIST_SPREPARSE,
-                               PLAYLIST_END );
+                               PLAYLIST_END, NULL, NULL );
         if( psz_qtnext )
         {
             p_input = input_ItemNewExt( p_sys->p_playlist,
@@ -371,7 +371,7 @@ static int Demux( demux_t *p_demux )
             playlist_BothAddInput( p_sys->p_playlist, p_input,
                                    p_sys->p_item_in_category,
                                    PLAYLIST_APPEND | PLAYLIST_SPREPARSE,
-                                   PLAYLIST_END );
+                                   PLAYLIST_END, NULL, NULL );
         }
     }
 
diff --git a/modules/demux/playlist/sgimb.c b/modules/demux/playlist/sgimb.c
index cc3da442f913..f244f9727e78 100644
--- a/modules/demux/playlist/sgimb.c
+++ b/modules/demux/playlist/sgimb.c
@@ -407,7 +407,8 @@ static int Demux ( demux_t *p_demux )
     }
 
     playlist_BothAddInput( p_playlist, p_child, p_item_in_category,
-                           PLAYLIST_APPEND | PLAYLIST_SPREPARSE, PLAYLIST_END );
+                           PLAYLIST_APPEND | PLAYLIST_SPREPARSE, PLAYLIST_END,
+                           NULL, NULL);
     HANDLE_PLAY_AND_RELEASE
     return -1; /* Needed for correct operation of go back */
 }
diff --git a/modules/demux/playlist/shoutcast.c b/modules/demux/playlist/shoutcast.c
index 2bad421f0790..04b25ff8e050 100644
--- a/modules/demux/playlist/shoutcast.c
+++ b/modules/demux/playlist/shoutcast.c
@@ -243,7 +243,7 @@ static int DemuxGenre( demux_t *p_demux )
                     playlist_BothAddInput( p_sys->p_playlist, p_input,
                                            p_sys->p_item_in_category,
                                            PLAYLIST_APPEND | PLAYLIST_SPREPARSE,
-                                           PLAYLIST_END );
+                                           PLAYLIST_END, NULL, NULL );
                     FREENULL( psz_name );
                 }
                 FREENULL( psz_eltname );
@@ -435,7 +435,7 @@ static int DemuxStation( demux_t *p_demux )
                     playlist_BothAddInput( p_sys->p_playlist, p_input,
                                            p_sys->p_item_in_category,
                                            PLAYLIST_APPEND | PLAYLIST_SPREPARSE,
-                                           PLAYLIST_END );
+                                           PLAYLIST_END, NULL, NULL );
 
                     FREENULL( psz_name );
                     FREENULL( psz_mt )
diff --git a/modules/demux/playlist/xspf.c b/modules/demux/playlist/xspf.c
index 7be83eb4614d..2e0d69458b26 100644
--- a/modules/demux/playlist/xspf.c
+++ b/modules/demux/playlist/xspf.c
@@ -482,7 +482,7 @@ static vlc_bool_t parse_track_node COMPLEX_INTERFACE
                     playlist_BothAddInput( p_playlist, p_new_input,
                                            p_demux->p_sys->p_item_in_category,
                                            PLAYLIST_APPEND | PLAYLIST_SPREPARSE,
-                                           PLAYLIST_END );
+                                           PLAYLIST_END, NULL, NULL );
                     if( p_demux->p_sys->i_identifier <
                         p_demux->p_sys->i_tracklist_entries )
                     {
diff --git a/modules/gui/beos/InterfaceWindow.cpp b/modules/gui/beos/InterfaceWindow.cpp
index 74db1a5b7b43..4e62d657a296 100644
--- a/modules/gui/beos/InterfaceWindow.cpp
+++ b/modules/gui/beos/InterfaceWindow.cpp
@@ -737,7 +737,7 @@ void InterfaceWindow::MessageReceived( BMessage * p_message )
 
             if( b_remove && p_playlist )
             {
-                playlist_Clear( p_playlist );
+                playlist_Clear( p_playlist, VLC_TRUE );
             }
 
             entry_ref ref;
diff --git a/modules/gui/macosx/intf.m b/modules/gui/macosx/intf.m
index c163ae7e7d0e..87d5dd1199da 100644
--- a/modules/gui/macosx/intf.m
+++ b/modules/gui/macosx/intf.m
@@ -461,7 +461,7 @@ static VLCMain *_o_sharedMainInstance = nil;
     /* Check if we need to start playing */
     if( p_intf->b_play )
     {
-        playlist_LockControl( p_playlist, PLAYLIST_AUTOPLAY );
+        playlist_Control( p_playlist, PLAYLIST_AUTOPLAY, VLC_FALSE );
     }
     var_Create( p_playlist, "fullscreen", VLC_VAR_BOOL | VLC_VAR_DOINHERIT);
     val.b_bool = VLC_FALSE;
diff --git a/modules/gui/macosx/playlist.m b/modules/gui/macosx/playlist.m
index 545c80a2159f..0a03cafd5649 100644
--- a/modules/gui/macosx/playlist.m
+++ b/modules/gui/macosx/playlist.m
@@ -747,7 +747,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 +855,7 @@ NSLog( @"expandable" );
         }
         else
         {
-            playlist_LockDelete( p_playlist, p_item->i_id );
+            playlist_DeleteFromInput( p_playlist, p_item->p_input->i_id );
         }
     }
     [self playlistUpdated];
@@ -1017,14 +1017,14 @@ NSLog( @"expandable" );
         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];
@@ -1059,14 +1059,14 @@ NSLog( @"expandable" );
         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];
diff --git a/modules/gui/macosx/wizard.m b/modules/gui/macosx/wizard.m
index 9d950b35ade6..e01f615f12de 100644
--- a/modules/gui/macosx/wizard.m
+++ b/modules/gui/macosx/wizard.m
@@ -1320,7 +1320,7 @@ static VLCWizard *_o_sharedInstance = nil;
             if( x == 0 )
             {
                 /* play the first item and add the others afterwards */
-                playlist_item_t *p_item = playlist_ItemGetByInput( p_playlist, p_input );
+                playlist_item_t *p_item = playlist_ItemGetByInput( p_playlist, p_input, VLC_TRUE );
                 playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, NULL,
                           p_item );
             }
diff --git a/modules/gui/ncurses.c b/modules/gui/ncurses.c
index b5576dac9d43..d14f0a8f9988 100644
--- a/modules/gui/ncurses.c
+++ b/modules/gui/ncurses.c
@@ -548,7 +548,8 @@ static int HandleKey( intf_thread_t *p_intf, int i_key )
                 p_item = p_sys->pp_plist[p_sys->i_box_plidx]->p_item;
                 if( p_item->i_children == -1 )
                 {
-                    playlist_DeleteFromItemId( p_playlist, p_item->i_id );
+                    playlist_DeleteFromInput( p_playlist,
+                                              p_item->p_input->i_id );
                 }
                 else
                 {
@@ -567,12 +568,13 @@ static int HandleKey( intf_thread_t *p_intf, int i_key )
                         == -1 )
                 {
                     playlist_Control( p_sys->p_playlist, PLAYLIST_VIEWPLAY,
-                        NULL,
+                                      VLC_TRUE, NULL,
                         p_sys->pp_plist[p_sys->i_box_plidx]->p_item );
                 }
                 else
                 {
                     playlist_Control( p_sys->p_playlist, PLAYLIST_VIEWPLAY,
+                        VLC_TRUE,
                         p_sys->pp_plist[p_sys->i_box_plidx]->p_item,
                         NULL );
                 }
diff --git a/modules/gui/pda/pda_callbacks.c b/modules/gui/pda/pda_callbacks.c
index 73d8b38facc9..9883af11bfcb 100644
--- a/modules/gui/pda/pda_callbacks.c
+++ b/modules/gui/pda/pda_callbacks.c
@@ -881,7 +881,7 @@ void onDeletePlaylist(GtkButton *button, gpointer user_data)
                         gint item;
 
                         gtk_tree_model_get(p_model, &iter, 2, &item, -1);
-                        playlist_LockDelete(p_playlist, item);
+                        msg_Err( p_playlist, "PDA delete broken");
                     }
                 }
             }
@@ -923,7 +923,7 @@ void onClearPlaylist(GtkButton *button, gpointer user_data)
 
     for(item = p_playlist->i_size - 1; item >= 0 ;item-- )
     {
-        playlist_LockDelete( p_playlist, item);
+        msg_Err( p_playlist "fix pda delete");
     }
     vlc_object_release( p_playlist );
 
diff --git a/modules/gui/qt4/components/playlist/standardpanel.cpp b/modules/gui/qt4/components/playlist/standardpanel.cpp
index c4f9acc009bd..9942c29cf64e 100644
--- a/modules/gui/qt4/components/playlist/standardpanel.cpp
+++ b/modules/gui/qt4/components/playlist/standardpanel.cpp
@@ -210,7 +210,8 @@ void StandardPLPanel::doPopup( QModelIndex index, QPoint point )
 
 void StandardPLPanel::setRoot( int i_root_id )
 {
-    playlist_item_t *p_item = playlist_ItemGetById( THEPL, i_root_id );
+    playlist_item_t *p_item = playlist_ItemGetById( THEPL, i_root_id,
+                                                    VLC_TRUE );
     assert( p_item );
     p_item = playlist_GetPreferredNode( THEPL, p_item );
     assert( p_item );
diff --git a/modules/gui/qt4/playlist_model.cpp b/modules/gui/qt4/playlist_model.cpp
index b0bbdbabdd99..13b2a7c6c3e0 100644
--- a/modules/gui/qt4/playlist_model.cpp
+++ b/modules/gui/qt4/playlist_model.cpp
@@ -243,8 +243,10 @@ bool PLModel::dropMimeData(const QMimeData *data, Qt::DropAction action,
 
             PL_LOCK;
             playlist_item_t *p_target =
-                        playlist_ItemGetById( p_playlist, targetItem->i_id );
-            playlist_item_t *p_src = playlist_ItemGetById( p_playlist, srcId );
+                        playlist_ItemGetById( p_playlist, targetItem->i_id,
+                                              VLC_TRUE );
+            playlist_item_t *p_src = playlist_ItemGetById( p_playlist, srcId,
+                                                           VLC_TRUE );
 
             if( !p_target || !p_src )
             {
@@ -256,7 +258,8 @@ bool PLModel::dropMimeData(const QMimeData *data, Qt::DropAction action,
                 PLItem *parentItem = targetItem->parent();
                 assert( parentItem );
                 playlist_item_t *p_parent =
-                         playlist_ItemGetById( p_playlist, parentItem->i_id );
+                         playlist_ItemGetById( p_playlist, parentItem->i_id,
+                                               VLC_TRUE );
                 if( !p_parent )
                 {
                     PL_UNLOCK;
@@ -330,7 +333,8 @@ void PLModel::activateItem( const QModelIndex &index )
     PLItem *item = static_cast<PLItem*>(index.internalPointer());
     assert( item );
     PL_LOCK;
-    playlist_item_t *p_item = playlist_ItemGetById( p_playlist, item->i_id );
+    playlist_item_t *p_item = playlist_ItemGetById( p_playlist, item->i_id,
+                                                    VLC_TRUE);
     activateItem( p_item );
     PL_UNLOCK;
 }
@@ -345,7 +349,7 @@ void PLModel::activateItem( playlist_item_t *p_item )
         p_parent = p_parent->p_parent;
     }
     if( p_parent )
-        playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, p_parent, p_item );
+        playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, VLC_TRUE, p_parent, p_item );
 }
 
 /****************** Base model mandatory implementations *****************/
@@ -610,7 +614,7 @@ void PLModel::ProcessItemAppend( playlist_add_t *p_add )
     PL_LOCK;
     if( !nodeItem ) goto end;
 
-    p_item = playlist_ItemGetById( p_playlist, p_add->i_item );
+    p_item = playlist_ItemGetById( p_playlist, p_add->i_item, VLC_TRUE );
     if( !p_item || p_item->i_flags & PLAYLIST_DBL_FLAG ) goto end;
     if( i_depth == 1 && p_item->p_parent &&
                         p_item->p_parent->i_id != rootItem->i_id )
@@ -678,7 +682,8 @@ void PLModel::rebuild( playlist_item_t *p_root )
 /* This function must be entered WITH the playlist lock */
 void PLModel::UpdateNodeChildren( PLItem *root )
 {
-    playlist_item_t *p_node = playlist_ItemGetById( p_playlist, root->i_id );
+    playlist_item_t *p_node = playlist_ItemGetById( p_playlist, root->i_id,
+                                                    VLC_TRUE );
     UpdateNodeChildren( p_node, root );
 }
 
@@ -699,7 +704,8 @@ void PLModel::UpdateNodeChildren( playlist_item_t *p_node, PLItem *root )
 /* This function must be entered WITH the playlist lock */
 void PLModel::UpdateTreeItem( PLItem *item, bool signal, bool force )
 {
-    playlist_item_t *p_item = playlist_ItemGetById( p_playlist, item->i_id );
+    playlist_item_t *p_item = playlist_ItemGetById( p_playlist, item->i_id,
+                                                    VLC_TRUE );
     UpdateTreeItem( p_item, item, signal, force );
 }
 
@@ -762,13 +768,14 @@ void PLModel::doDeleteItem( PLItem *item, QModelIndexList *fullList )
     fullList->removeAll( deleteIndex );
 
     PL_LOCK;
-    playlist_item_t *p_item = playlist_ItemGetById( p_playlist, item->i_id );
+    playlist_item_t *p_item = playlist_ItemGetById( p_playlist, item->i_id,
+                                                    VLC_TRUE );
     if( !p_item )
     {
         PL_UNLOCK; return;
     }
     if( p_item->i_children == -1 )
-        playlist_DeleteAllFromInput( p_playlist, item->i_input_id );
+        playlist_DeleteFromInput( p_playlist, item->i_input_id, VLC_TRUE );
     else
         playlist_NodeDelete( p_playlist, p_item, VLC_TRUE, VLC_FALSE );
     /* And finally, remove it from the tree */
@@ -780,19 +787,23 @@ void PLModel::doDeleteItem( PLItem *item, QModelIndexList *fullList )
 void PLModel::sort( int column, Qt::SortOrder order )
 {
     PL_LOCK;
-    playlist_item_t *p_root = playlist_ItemGetById( p_playlist, rootItem->i_id );
-    int i_mode;
-    switch( column )
     {
-    case 0: i_mode = SORT_TITLE_NODES_FIRST;break;
-    case 1: i_mode = SORT_ARTIST;break;
-    case 2: i_mode = SORT_DURATION; break;
-    default: i_mode = SORT_TITLE_NODES_FIRST; break;
+        playlist_item_t *p_root = playlist_ItemGetById( p_playlist,
+                                                        rootItem->i_id,
+                                                        VLC_TRUE );
+        int i_mode;
+        switch( column )
+        {
+        case 0: i_mode = SORT_TITLE_NODES_FIRST;break;
+        case 1: i_mode = SORT_ARTIST;break;
+        case 2: i_mode = SORT_DURATION; break;
+        default: i_mode = SORT_TITLE_NODES_FIRST; break;
+        }
+        if( p_root )
+            playlist_RecursiveNodeSort( p_playlist, p_root, i_mode,
+                                        order == Qt::AscendingOrder ?
+                                            ORDER_NORMAL : ORDER_REVERSE );
     }
-    if( p_root )
-        playlist_RecursiveNodeSort( p_playlist, p_root, i_mode,
-                                    order == Qt::AscendingOrder ? ORDER_NORMAL :
-                                                            ORDER_REVERSE );
     PL_UNLOCK
     rebuild();
 }
@@ -801,10 +812,14 @@ void PLModel::search( QString search_text )
 {
     /** \todo Fire the search with a small delay ? */
     PL_LOCK;
-    playlist_item_t *p_root = playlist_ItemGetById( p_playlist,rootItem->i_id );
-    assert( p_root );
-    char *psz_name = search_text.toUtf8().data();
-    playlist_LiveSearchUpdate( p_playlist , p_root, psz_name );
+    {
+        playlist_item_t *p_root = playlist_ItemGetById( p_playlist,
+                                                        rootItem->i_id,
+                                                        VLC_TRUE );
+        assert( p_root );
+        char *psz_name = search_text.toUtf8().data();
+        playlist_LiveSearchUpdate( p_playlist , p_root, psz_name );
+    }
     PL_UNLOCK;
     rebuild();
 }
@@ -815,7 +830,7 @@ void PLModel::popup( QModelIndex & index, QPoint &point, QModelIndexList list )
     assert( index.isValid() );
     PL_LOCK;
     playlist_item_t *p_item = playlist_ItemGetById( p_playlist,
-                                                    itemId( index ) );
+                                                    itemId( index ), VLC_TRUE );
     if( p_item )
     {
         i_popup_item = p_item->i_id;
@@ -849,8 +864,11 @@ void PLModel::popupDel()
 void PLModel::popupPlay()
 {
     PL_LOCK;
-    playlist_item_t *p_item = playlist_ItemGetById( p_playlist, i_popup_item );
-    activateItem( p_item );
+    {
+        playlist_item_t *p_item = playlist_ItemGetById( p_playlist,
+                                                        i_popup_item,VLC_TRUE );
+        activateItem( p_item );
+    }
     PL_UNLOCK;
 }
 
diff --git a/modules/gui/skins2/src/skin_main.cpp b/modules/gui/skins2/src/skin_main.cpp
index 0d31f70165f2..6d050c7b797f 100644
--- a/modules/gui/skins2/src/skin_main.cpp
+++ b/modules/gui/skins2/src/skin_main.cpp
@@ -256,7 +256,7 @@ static void Run( intf_thread_t *p_intf )
                                            FIND_ANYWHERE );
         if( p_playlist )
         {
-            playlist_LockControl( p_playlist, PLAYLIST_AUTOPLAY );
+            playlist_Control( p_playlist, PLAYLIST_AUTOPLAY, VLC_FALSE );
             vlc_object_release( p_playlist );
         }
     }
diff --git a/modules/gui/skins2/vars/playtree.cpp b/modules/gui/skins2/vars/playtree.cpp
index ca1bc3748c12..fbe77bf37f0c 100644
--- a/modules/gui/skins2/vars/playtree.cpp
+++ b/modules/gui/skins2/vars/playtree.cpp
@@ -68,8 +68,8 @@ void Playtree::delSelected()
             playlist_item_t *p_item = (playlist_item_t *)(it->m_pData);
             if( p_item->i_children == -1 )
             {
-                playlist_DeleteFromItemId( getIntf()->p_sys->p_playlist,
-                                           p_item->i_id );
+                playlist_DeleteFromInput( getIntf()->p_sys->p_playlist,
+                                          p_item->p_input->i_id, VLC_TRUE );
                 it2 = getNextVisibleItem( it ) ;
                 it->parent()->removeChild( it );
                 it = it2;
@@ -107,7 +107,7 @@ void Playtree::action( VarTree *pItem )
 
     if( p_parent )
     {
-        playlist_Control( m_pPlaylist, PLAYLIST_VIEWPLAY, p_parent, p_item );
+        playlist_Control( m_pPlaylist, PLAYLIST_VIEWPLAY, VLC_TRUE, p_parent, p_item );
     }
     vlc_mutex_unlock( &m_pPlaylist->object_lock );
 }
@@ -170,7 +170,7 @@ void Playtree::onAppend( playlist_add_t *p_add )
         if( item == end() )
         {
             playlist_item_t *p_item = playlist_ItemGetById(
-                                        m_pPlaylist, p_add->i_item );
+                                        m_pPlaylist, p_add->i_item, VLC_TRUE );
             if( !p_item ) return;
             UString *pName = new UString( getIntf(),
                                           p_item->p_input->psz_name );
diff --git a/modules/gui/wxwidgets/dialogs/playlist.cpp b/modules/gui/wxwidgets/dialogs/playlist.cpp
index d33886077cb0..ebcd71cfbdae 100644
--- a/modules/gui/wxwidgets/dialogs/playlist.cpp
+++ b/modules/gui/wxwidgets/dialogs/playlist.cpp
@@ -505,7 +505,7 @@ void Playlist::UpdateTreeItem( wxTreeItemId item )
     if( !p_data ) return;
 
     playlist_item_t *p_item = playlist_ItemGetById( p_playlist,
-                                          ((PlaylistItem *)p_data)->i_id );
+                                    ((PlaylistItem *)p_data)->i_id, VLC_TRUE );
     if( !p_item )
     {
         UnlockPlaylist( p_intf->p_sys, p_playlist );
@@ -581,7 +581,7 @@ void Playlist::AppendItem( wxCommandEvent& event )
     node = FindItem( treectrl->GetRootItem(), p_add->i_node );
     if( !node.IsOk() ) goto update;
 
-    p_item = playlist_ItemGetById( p_playlist, p_add->i_item );
+    p_item = playlist_ItemGetById( p_playlist, p_add->i_item, VLC_TRUE );
     if( !p_item ) goto update;
     if( (p_item->i_flags & PLAYLIST_DBL_FLAG ) ) goto update;
 
@@ -744,7 +744,7 @@ int Playlist::CountItems( wxTreeItemId root )
         {
             playlist_item_t *p_item;
             LockPlaylist( p_intf->p_sys, p_playlist );
-            p_item = playlist_ItemGetById( p_playlist, ((PlaylistItem *)treectrl->GetItemData( item ))->i_id );
+            p_item = playlist_ItemGetById( p_playlist, ((PlaylistItem *)treectrl->GetItemData( item ))->i_id, VLC_TRUE );
             if( p_item && p_item->i_children == -1 )
                 count++;
             UnlockPlaylist( p_intf->p_sys, p_playlist );
@@ -890,7 +890,7 @@ void Playlist::DeleteTreeItem( wxTreeItemId item )
    p_wxitem = (PlaylistItem *)treectrl->GetItemData( item );
 
    LockPlaylist( p_intf->p_sys, p_playlist );
-   p_item = playlist_ItemGetById( p_playlist, p_wxitem->i_id );
+   p_item = playlist_ItemGetById( p_playlist, p_wxitem->i_id, VLC_TRUE );
 
    if( !p_item )
    {
@@ -1013,12 +1013,14 @@ void Playlist::OnSort( wxCommandEvent& event )
     {
         case SortTitle_Event:
             playlist_RecursiveNodeSort( p_playlist,
-                            playlist_ItemGetById( p_playlist, p_wxitem->i_id ),
+                            playlist_ItemGetById( p_playlist, p_wxitem->i_id,
+                                                  VLC_TRUE ),
                             SORT_TITLE_NODES_FIRST, ORDER_NORMAL );
             break;
         case RSortTitle_Event:
             playlist_RecursiveNodeSort( p_playlist,
-                            playlist_ItemGetById( p_playlist, p_wxitem->i_id ),
+                            playlist_ItemGetById( p_playlist, p_wxitem->i_id,
+                                                  VLC_TRUE ),
                             SORT_TITLE_NODES_FIRST, ORDER_REVERSE );
     }
     UnlockPlaylist( p_intf->p_sys, p_playlist );
@@ -1039,7 +1041,8 @@ void Playlist::OnSearch( wxCommandEvent& WXUNUSED(event) )
     wxString search_string = search_text->GetValue();
     PlaylistItem *p_wxroot;
     p_wxroot = (PlaylistItem *)treectrl->GetItemData( treectrl->GetRootItem() );
-    playlist_item_t *p_root = playlist_ItemGetById( p_playlist, p_wxroot->i_id );
+    playlist_item_t *p_root = playlist_ItemGetById( p_playlist, p_wxroot->i_id,
+                                                    VLC_TRUE );
 
     assert( p_root );
     char *psz_name = wxFromLocale( search_string );
@@ -1115,7 +1118,7 @@ void Playlist::OnActivateItem( wxTreeEvent& event )
         UnlockPlaylist( p_intf->p_sys, p_playlist );
         return;
     }
-    p_item = playlist_ItemGetById( p_playlist, p_wxitem->i_id );
+    p_item = playlist_ItemGetById( p_playlist, p_wxitem->i_id, VLC_TRUE );
 
     p_parent = p_item;
     while( p_parent )
@@ -1127,7 +1130,7 @@ void Playlist::OnActivateItem( wxTreeEvent& event )
 
     if( p_parent )
     {
-        playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, p_parent, p_item );
+        playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, VLC_TRUE, p_parent, p_item );
     }
     UnlockPlaylist( p_intf->p_sys, p_playlist );
 }
@@ -1191,9 +1194,9 @@ void Playlist::OnDragItemEnd( wxTreeEvent& event )
     }
 
     playlist_item_t *p_drageditem =
-        playlist_ItemGetById(p_playlist, p_wxdrageditem->i_id );
+        playlist_ItemGetById(p_playlist, p_wxdrageditem->i_id, VLC_TRUE );
     playlist_item_t *p_destitem =
-        playlist_ItemGetById(p_playlist, p_wxdestitem->i_id );
+        playlist_ItemGetById(p_playlist, p_wxdestitem->i_id, VLC_TRUE );
     if( !p_drageditem || !p_destitem )
     {
         UnlockPlaylist( p_intf->p_sys, p_playlist );
@@ -1212,7 +1215,7 @@ void Playlist::OnDragItemEnd( wxTreeEvent& event )
             return;
         }
         playlist_item_t *p_destitem2 =
-            playlist_ItemGetById( p_playlist, p_parent->i_id );
+            playlist_ItemGetById( p_playlist, p_parent->i_id, VLC_TRUE );
         if( !p_destitem2 )
         {
             UnlockPlaylist( p_intf->p_sys, p_playlist );
@@ -1267,7 +1270,7 @@ bool PlaylistFileDropTarget::OnDropFiles( wxCoord x, wxCoord y,
     {
         PlaylistItem *p_plitem =
             (PlaylistItem *)p->treectrl->GetItemData( item );
-        p_dest = playlist_ItemGetById( p->p_playlist, p_plitem->i_id );
+        p_dest = playlist_ItemGetById( p->p_playlist, p_plitem->i_id, VLC_TRUE );
 
         if( p_dest->i_children == -1 )
         {
@@ -1283,7 +1286,7 @@ bool PlaylistFileDropTarget::OnDropFiles( wxCoord x, wxCoord y,
                 return FALSE;
             }
             playlist_item_t *p_node =
-                playlist_ItemGetById( p->p_playlist, p_parent->i_id );
+                playlist_ItemGetById( p->p_playlist, p_parent->i_id, VLC_TRUE );
             if( !p_node )
             {
                 UnlockPlaylist( p->p_intf->p_sys, p->p_playlist );
@@ -1486,7 +1489,7 @@ void Playlist::OnPopup( wxContextMenuEvent& event )
         treectrl->SelectItem( i_wx_popup_item );
 
         LockPlaylist( p_intf->p_sys, p_playlist );
-        p_item = playlist_ItemGetById( p_playlist, i_popup_item );
+        p_item = playlist_ItemGetById( p_playlist, i_popup_item, VLC_TRUE );
 
         if( !p_item )
         {
@@ -1512,7 +1515,7 @@ void Playlist::OnPopupPlay( wxCommandEvent& event )
 {
     playlist_item_t *p_popup_item, *p_popup_parent;
     LockPlaylist( p_intf->p_sys, p_playlist );
-    p_popup_item = playlist_ItemGetById( p_playlist, i_popup_item );
+    p_popup_item = playlist_ItemGetById( p_playlist, i_popup_item, VLC_TRUE );
 
     p_popup_parent = p_popup_item;
     while( p_popup_parent )
@@ -1524,7 +1527,7 @@ void Playlist::OnPopupPlay( wxCommandEvent& event )
 
     if( p_popup_parent )
     {
-        playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, p_popup_parent,
+        playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, VLC_TRUE, p_popup_parent,
                           p_popup_item );
     }
     UnlockPlaylist( p_intf->p_sys, p_playlist );
@@ -1539,7 +1542,7 @@ void Playlist::Preparse()
 {
     playlist_item_t *p_popup_item;
     LockPlaylist( p_intf->p_sys, p_playlist );
-    p_popup_item = playlist_ItemGetById( p_playlist, i_popup_item );
+    p_popup_item = playlist_ItemGetById( p_playlist, i_popup_item, VLC_TRUE );
 
     if( p_popup_item != NULL )
     {
@@ -1577,7 +1580,7 @@ void Playlist::OnPopupSort( wxCommandEvent& event )
     p_wxitem = (PlaylistItem *)treectrl->GetItemData( i_wx_popup_item );
     LockPlaylist( p_intf->p_sys, p_playlist );
 
-    p_item = playlist_ItemGetById( p_playlist, p_wxitem->i_id );
+    p_item = playlist_ItemGetById( p_playlist, p_wxitem->i_id, VLC_TRUE );
     if( p_item->i_children >= 0 )
     {
         playlist_RecursiveNodeSort( p_playlist, p_item,
@@ -1594,7 +1597,9 @@ void Playlist::OnPopupSort( wxCommandEvent& event )
 void Playlist::OnPopupInfo( wxCommandEvent& event )
 {
     LockPlaylist( p_intf->p_sys, p_playlist );
-    playlist_item_t *p_popup_item = playlist_ItemGetById( p_playlist, i_popup_item );
+    playlist_item_t *p_popup_item = playlist_ItemGetById( p_playlist,
+                                                          i_popup_item,
+                                                          VLC_TRUE );
     if( p_popup_item )
     {
         iteminfo_dialog = new ItemInfoDialog( p_intf, p_popup_item, this );
@@ -1622,7 +1627,7 @@ void Playlist::OnPopupAddNode( wxCommandEvent& event )
 
     p_wxitem = (PlaylistItem *)treectrl->GetItemData( i_wx_popup_item );
 
-    p_item = playlist_ItemGetById( p_playlist, p_wxitem->i_id );
+    p_item = playlist_ItemGetById( p_playlist, p_wxitem->i_id, VLC_TRUE );
 
     playlist_NodeCreate( p_playlist, psz_name, p_item );
 
@@ -1638,7 +1643,8 @@ void Playlist::OnSourceSelected( wxListEvent &event )
 
    if( p_current_treeroot && i_id != p_current_treeroot->i_id )
    {
-       playlist_item_t *p_item = playlist_ItemGetById( p_playlist, i_id );
+       playlist_item_t *p_item = playlist_ItemGetById( p_playlist, i_id,
+                                                       VLC_TRUE );
        if( p_item ) p_current_treeroot = p_item;
        Rebuild( VLC_TRUE );
    }
diff --git a/modules/gui/wxwidgets/playlist_manager.cpp b/modules/gui/wxwidgets/playlist_manager.cpp
index d9e4c28f4a9c..b6ddce5729b9 100644
--- a/modules/gui/wxwidgets/playlist_manager.cpp
+++ b/modules/gui/wxwidgets/playlist_manager.cpp
@@ -502,7 +502,7 @@ void PlaylistManager::OnActivateItem( wxTreeEvent& event )
         p_node = p_item;
         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 );
     UnlockPlaylist( p_intf->p_sys, p_playlist );
 }
 
diff --git a/modules/gui/wxwidgets/wxwidgets.cpp b/modules/gui/wxwidgets/wxwidgets.cpp
index fc22a5807ec1..400365f7d178 100644
--- a/modules/gui/wxwidgets/wxwidgets.cpp
+++ b/modules/gui/wxwidgets/wxwidgets.cpp
@@ -398,7 +398,7 @@ bool Instance::OnInit()
                                            FIND_ANYWHERE );
         if( p_playlist )
         {
-            playlist_LockControl( p_playlist, PLAYLIST_AUTOPLAY );
+            playlist_Control( p_playlist, PLAYLIST_AUTOPLAY, VLC_FALSE );
             vlc_object_release( p_playlist );
         }
     }
diff --git a/modules/misc/testsuite/Modules.am b/modules/misc/testsuite/Modules.am
index 8754a73afd50..4f6e6000c870 100644
--- a/modules/misc/testsuite/Modules.am
+++ b/modules/misc/testsuite/Modules.am
@@ -2,4 +2,3 @@ SOURCES_test1 = test1.c
 SOURCES_test2 = test2.cpp
 SOURCES_test3 = test3.m
 SOURCES_test4 = test4.c
-SOURCES_test_playlist = playlist.c
diff --git a/modules/misc/testsuite/playlist.c b/modules/misc/testsuite/playlist.c
deleted file mode 100644
index 8296b5e02203..000000000000
--- a/modules/misc/testsuite/playlist.c
+++ /dev/null
@@ -1,403 +0,0 @@
-/*****************************************************************************
- * playlist.c : Playlist testsuite
- *****************************************************************************
- * Copyright (C) 2004 the VideoLAN team
- * $Id$
- *
- * 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
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
- *****************************************************************************/
-
-/* To run these tests, run vlc with
- *  --playlist-test --quiet --no-plugins-cache -I dummy */
-
-/* greek tree used for tests, borrowed from the SubVersion project 
- *
-
-                                   A                       iota
-          _______________________//|\
-         /         ______________/ | \_____________
-        mu        /                |               \
-                 /                 |                \
-                B                  C                 D
-          _____/|\_____                _____________/|\
-         /      |      \              /              | \
-        /       |       \            /              /   \___
-     lambda     |        F          /              /        \
-                E                gamma            /          \
-               / \                               /            |
-              /   \                     ________/             |
-          alpha   beta                 /                      H
-                                      /               _______/|\______
-                                     /               /        |       \
-                                    G               /         |        \
-                           ________/|\_______     chi        psi      omega
-                          /         |        \
-                         /          |         \
-                        /           |          \
-                       pi          rho         tau
-
- */
- 
-/*****************************************************************************
- * Preamble
- *****************************************************************************/
-#include <vlc/vlc.h>
-
-#include <vlc_input.h>
-#include <vlc_playlist.h>
-
-#include <stdlib.h>
-
-/*****************************************************************************
- * Local prototypes.
- *****************************************************************************/
-int    PlaylistTest    ( vlc_object_t *, char const *,
-                          vlc_value_t, vlc_value_t, void * );
-
-static int Callback( vlc_object_t *, char *, vlc_value_t, vlc_value_t,void*);
-
-static void Assert( intf_sys_t *p_sys,const char* psz_text, int condition );
-
-static void StressTest (vlc_object_t *);
-
-#define MAX_ITEMS 100
-
-#define CREATE_GT 1000
-
-struct intf_sys_t
-{
-    char *ppsz_names[MAX_ITEMS];
-    playlist_t *p_playlist;
-    int i_names;
-    int i_current;
-    vlc_bool_t b_error;
-};
-
-/*****************************************************************************
- * Module descriptor.
- *****************************************************************************/
-vlc_module_begin();
-    set_description( _("Playlist stress tests") );
-    add_bool( "playlist-test" , VLC_FALSE , PlaylistTest , "" , "" ,
-  	      VLC_TRUE );
-vlc_module_end();
-
-/*****************************************************************************
- * PlaylistTest: callback function, spawns the tester thread
- *****************************************************************************/
-int PlaylistTest( vlc_object_t *p_this, char const *psz_cmd,
-                   vlc_value_t oldval, vlc_value_t newval, void *p_data )
-{
-    if( newval.b_bool == VLC_FALSE ) return VLC_SUCCESS;
-
-    if( vlc_thread_create( p_this, "playlist tester", StressTest,
-                    VLC_THREAD_PRIORITY_LOW, VLC_FALSE ) )
-    {
-        msg_Err( p_this, "unable to spawn playlist test thread" );
-        return VLC_EGENERIC;
-    }
-    return VLC_SUCCESS;
-}
-
-/*****************************************************************************
- * Tester thread 
- *****************************************************************************/
-static void StressTest( vlc_object_t *p_this )
-{
-    playlist_t *p_playlist = NULL;
-    playlist_view_t *p_view;
-    int i;
-    mtime_t i_start;
-    playlist_item_t *p_item,*p_a,*p_b,*p_c,*p_d,*p_e,*p_f,*p_g,*p_h, *p_gamma;
-
-    intf_sys_t *p_sys = (intf_sys_t *)malloc( sizeof( intf_sys_t ) );
-    p_sys->b_error = VLC_FALSE;
-
-    fprintf( stderr, "beginning playlist test\n" );
-    while( p_playlist == NULL )
-    {
-        msleep( INTF_IDLE_SLEEP );
-        p_playlist = vlc_object_find( p_this, VLC_OBJECT_PLAYLIST,
-                                        FIND_ANYWHERE );
-    }
-    fprintf( stderr, "Attached to playlist\n");
-
-    p_sys->p_playlist = p_playlist;
-
-    /* let time for vlc initialization */
-    sleep( 3 );
-
-    var_AddCallback( p_playlist, "playlist-current", Callback, p_sys );
-
-
-    /* Test 1 : Create a greek tree */
-    fprintf(stderr,"1/ Creating greek tree pattern (except H)\n");
-
-    p_view = playlist_ViewFind( p_playlist, VIEW_CATEGORY );
-    i_start = mdate();
-
-    playlist_Stop( p_playlist );
-    Assert( p_sys, "Checking playlist status STOPPED ...",
-            p_playlist->status.i_status == PLAYLIST_STOPPED );
-
-    p_a = playlist_NodeCreate( p_playlist, VIEW_CATEGORY, "A", p_view->p_root );
-    p_item = playlist_ItemNew(p_playlist, "mu","mu" );
-    playlist_NodeAddItem( p_playlist, p_item, VIEW_CATEGORY,
-                          p_a, PLAYLIST_APPEND, PLAYLIST_END );
-    p_b = playlist_NodeCreate( p_playlist, VIEW_CATEGORY, "B", p_a );
-    p_c = playlist_NodeCreate( p_playlist, VIEW_CATEGORY, "C", p_a );
-    p_d = playlist_NodeCreate( p_playlist, VIEW_CATEGORY, "D", p_a );
-    p_item = playlist_ItemNew(p_playlist, "lambda","lambda" );
-    playlist_NodeAddItem( p_playlist, p_item, VIEW_CATEGORY,
-                          p_b, PLAYLIST_APPEND, PLAYLIST_END );
-    p_e = playlist_NodeCreate( p_playlist, VIEW_CATEGORY, "E", p_b );
-    p_f = playlist_NodeCreate( p_playlist, VIEW_CATEGORY, "F", p_b );
-    p_gamma = p_item = playlist_ItemNew(p_playlist, "gamma","gamma" );
-    playlist_NodeAddItem( p_playlist, p_item, VIEW_CATEGORY,
-                          p_d, PLAYLIST_APPEND, PLAYLIST_END );
-    p_g = playlist_NodeCreate( p_playlist, VIEW_CATEGORY, "G", p_d );
-    p_item = playlist_ItemNew(p_playlist, "beta","beta" );
-    playlist_NodeAddItem( p_playlist, p_item, VIEW_CATEGORY,
-                          p_e, PLAYLIST_INSERT, 0 );
-    p_item = playlist_ItemNew(p_playlist, "alpha","alpha" );
-    playlist_NodeAddItem( p_playlist, p_item, VIEW_CATEGORY,
-                          p_e, PLAYLIST_INSERT, 0 );
-    p_item = playlist_ItemNew(p_playlist, "pi","pi" );
-    playlist_NodeAddItem( p_playlist, p_item, VIEW_CATEGORY,
-                          p_g, PLAYLIST_APPEND, PLAYLIST_END );
-    p_item = playlist_ItemNew(p_playlist, "tau","tau" );
-    playlist_NodeAddItem( p_playlist, p_item, VIEW_CATEGORY,
-                          p_g, PLAYLIST_APPEND, PLAYLIST_END );
-    p_item = playlist_ItemNew(p_playlist, "rho","rho" );
-    playlist_NodeAddItem( p_playlist, p_item, VIEW_CATEGORY,
-                          p_g, PLAYLIST_INSERT, 1 );
-    /* Create H as an item, we'll expand it later */
-    p_item = playlist_ItemNew(p_playlist, "H","H" );
-    playlist_NodeAddItem( p_playlist, p_item, VIEW_CATEGORY,
-                          p_d, PLAYLIST_INSERT, 1 );
-
-    fprintf( stderr, "Created in "I64Fi " us\n", mdate() - i_start );
-
-    fprintf(stderr,"Dumping category view\n" );
-    playlist_ViewDump( p_playlist, p_view );
-
-    Assert( p_sys, "Checking playlist status STOPPED ...",
-            p_playlist->status.i_status == PLAYLIST_STOPPED );
-
-//    Assert( p_sys, "Checking 0 items in VIEW_SIMPLE ...",
-  //          playlist_ViewItemsCount( p_playlist, VIEW_SIMPLE ) == 0 );
- //   Assert( p_sys, "Checking 9 items in VIEW_ALL ...",
-   //         playlist_ViewItemsCount( p_playlist, VIEW_ALL ) == 9 );
-
-
-    p_sys->ppsz_names[0] = strdup("mu");
-    p_sys->ppsz_names[1]= strdup("lambda");
-    p_sys->ppsz_names[2] = strdup("beta");
-    p_sys->ppsz_names[3] = strdup("alpha");
-    p_sys->ppsz_names[4] = strdup("gamma");
-    p_sys->ppsz_names[5] = strdup("pi");
-    p_sys->ppsz_names[6] = strdup("tau");
-    p_sys->ppsz_names[7] = strdup("rho");
-    p_sys->ppsz_names[8] = strdup("H");
-    p_sys->i_names = 9;
-    p_sys->i_current = 0;
-
-    fprintf( stderr, "Starting playlist\n");
-
-    playlist_Play( p_playlist );
-
-    sleep( 1 );
-
-    Assert( p_sys, "Checking nothing was played ...",
-                    (p_sys->i_current == 0) );
-    fprintf(stderr,"played : %i\n",p_sys->i_current );
-
-    playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, VIEW_CATEGORY,
-                      p_view->p_root, NULL );
-
-    Assert( p_sys, "Checking playlist RUNNING ...",
-                     p_playlist->status.i_status == 1 );
-
-    /* Wait for everything to have played */
-#if 0
-     while( p_sys->i_current != 8 );// && p_sys->b_error == VLC_FALSE )
-     {
-         msleep( INTF_IDLE_SLEEP );
-     }
-     fprintf(stderr,"finished\n" );
-#endif
-
-    /* Let some more time */
-    sleep( 5 );
-    Assert( p_sys, "Checking playlist status STOPPED ...",
-            (p_playlist->status.i_status == PLAYLIST_STOPPED) );
-
-    p_sys->i_names = -1;
-
-    /* Test 2 : Repeat */
-    fprintf( stderr, "2/ Checking repeat\n" );
-    var_SetBool( p_playlist, "repeat", VLC_TRUE );
-    playlist_Goto( p_playlist, 4 );
-    msleep( 100 );
-    Assert( p_sys, "Checking playing of gamma ...",
-            p_playlist->status.p_item == p_gamma );
-    sleep( 2 );
-    Assert( p_sys, "Checking still playing gamma ...", 
-	    p_playlist->status.p_item == p_gamma );
-    Assert( p_sys, "Checking playlist still running ...",
-            p_playlist->status.i_status == PLAYLIST_RUNNING );
-
-    /* Test 3: Play and stop */
-    fprintf( stderr, "3/ Checking play and stop\n" );
-    playlist_Stop( p_playlist );
-    var_SetBool( p_playlist, "repeat", VLC_FALSE );
-    var_SetBool( p_playlist, "play-and-stop", VLC_TRUE );
-    playlist_Skip( p_playlist, 1 );
-    Assert( p_sys, "Checking playlist status RUNNING ...",
-            p_playlist->status.i_status == PLAYLIST_RUNNING );
-    sleep( 2 );
-    Assert( p_sys, "Checking playlist stopped  ...",
-            p_playlist->status.i_status == PLAYLIST_STOPPED );
-
-    /* Test 4 : Simple adding of iota */
-    fprintf( stderr, "4/ Checking simple add\n" );
-    p_item = playlist_ItemNew( p_playlist, "iota","iota" );
-    playlist_AddItem( p_playlist, p_item, PLAYLIST_APPEND, PLAYLIST_END ); 
-
-    /* Check items counts */
-//    Assert( p_sys, "Checking 1 item in VIEW_SIMPLE ...",
-  //          playlist_ViewItemsCount( p_playlist, VIEW_SIMPLE ) == 1 );
-//    Assert( p_sys, "Checking 10 items in VIEW_CATEGORY ...",
-  //          playlist_ViewItemsCount( p_playlist, VIEW_CATEGORY ) == 10 );
-
-    /* Test 5:Expand H : it was added only to view_category so the children 
-     * should not appear in VIEW_SIMPLE */
-    fprintf( stderr, "5/ ItemToNode - Parent inheritance\n" );
-
-    
-    /* Test 6 : Add many items */
-    fprintf( stderr, "6/ Adding %i items", 12*CREATE_GT );
-
-    i_start = mdate();
-
-    for( i = CREATE_GT ; i >= 0 ; i-- )
-    {
-	GreekTree( p_playlist, p_view->p_root );
-    }
-    
-    fprintf( stderr, "Created in "I64Fi " us\n", mdate() - i_start );
-
-    vlc_object_release( p_playlist );
-
-    if( p_sys->b_error == VLC_FALSE )
-    {
-        p_this->p_libvlc->b_die = VLC_TRUE;
-    }
-    else
-    {
-	exit( 1 );
-    }
-    return;
-}
-
-static inline void GreekTree( playlist_t *p_playlist, playlist_item_t *p_node )
-{
-    playlist_item_t *p_item,*p_a,*p_b,*p_c,*p_d,*p_e,*p_f,*p_g,*p_h;	
-    p_a = playlist_NodeCreate( p_playlist, VIEW_CATEGORY, "A", p_node );
-    p_item = playlist_ItemNew(p_playlist, "mu","mu" );
-    playlist_NodeAddItem( p_playlist, p_item, VIEW_CATEGORY,
-                          p_a, PLAYLIST_APPEND, PLAYLIST_END );
-    p_b = playlist_NodeCreate( p_playlist, VIEW_CATEGORY, "B", p_a );
-    p_c = playlist_NodeCreate( p_playlist, VIEW_CATEGORY, "C", p_a );
-    p_d = playlist_NodeCreate( p_playlist, VIEW_CATEGORY, "D", p_a );
-    p_item = playlist_ItemNew(p_playlist, "lambda","lambda" );
-    playlist_NodeAddItem( p_playlist, p_item, VIEW_CATEGORY,
-                          p_b, PLAYLIST_APPEND, PLAYLIST_END );
-    p_e = playlist_NodeCreate( p_playlist, VIEW_CATEGORY, "E", p_b );
-    p_f = playlist_NodeCreate( p_playlist, VIEW_CATEGORY, "F", p_b );
-    p_item = playlist_ItemNew(p_playlist, "gamma","gamma" );
-    playlist_NodeAddItem( p_playlist, p_item, VIEW_CATEGORY,
-                          p_d, PLAYLIST_APPEND, PLAYLIST_END );
-    p_g = playlist_NodeCreate( p_playlist, VIEW_CATEGORY, "G", p_d );
-    p_item = playlist_ItemNew(p_playlist, "beta","beta" );
-    playlist_NodeAddItem( p_playlist, p_item, VIEW_CATEGORY,
-                          p_e, PLAYLIST_INSERT, 0 );
-    p_item = playlist_ItemNew(p_playlist, "alpha","alpha" );
-    playlist_NodeAddItem( p_playlist, p_item, VIEW_CATEGORY,
-                          p_e, PLAYLIST_INSERT, 0 );
-    p_item = playlist_ItemNew(p_playlist, "pi","pi" );
-    playlist_NodeAddItem( p_playlist, p_item, VIEW_CATEGORY,
-                          p_g, PLAYLIST_APPEND, PLAYLIST_END );
-    p_item = playlist_ItemNew(p_playlist, "tau","tau" );
-    playlist_NodeAddItem( p_playlist, p_item, VIEW_CATEGORY,
-                          p_g, PLAYLIST_APPEND, PLAYLIST_END );
-    p_item = playlist_ItemNew(p_playlist, "rho","rho" );
-    playlist_NodeAddItem( p_playlist, p_item, VIEW_CATEGORY,
-                          p_g, PLAYLIST_INSERT, 1 );
-    p_g = playlist_NodeCreate( p_playlist, VIEW_CATEGORY, "H", p_d );
-}
-
-static void Assert( intf_sys_t *p_sys,const char* psz_text, int condition )
-{
-    fprintf( stderr, "%s", psz_text );
-    if( condition == 0 )
-    {
-        fprintf( stderr, "Fail\n" );
-        p_sys->b_error = VLC_TRUE;
-    }
-    else
-    {
-        fprintf(stderr,"Pass\n" );
-    }
-    return;
-}
-
-
-static int Callback( vlc_object_t *p_this, char *psz_cmd,
-                vlc_value_t ov, vlc_value_t nv,void *param)
-{
-    intf_sys_t *p_sys = (intf_sys_t*) param;
-    playlist_t *p_playlist = (playlist_t*)p_this;
-    char *psz_name;
-    playlist_item_t *p_item;
-    
-    if( p_sys->i_names == -1 ) return;
-    
-    p_item= playlist_ItemGetById( p_sys->p_playlist,nv.i_int );
-    psz_name = strdup (p_item->input.psz_name );
-
-    if( p_sys->i_current >= p_sys->i_names )
-    {
-        fprintf( stderr,"Error, we read too many items\n" );
-        p_sys->b_error = VLC_TRUE;
-	return;
-    }
-
-    if( !strcmp( p_sys->ppsz_names[p_sys->i_current], psz_name ) )
-    {
-        p_sys->i_current++;
-        fprintf(stderr,"playing %s\n",p_sys->ppsz_names[p_sys->i_current-1]);
-    }
-    else
-    {
-        fprintf( stderr, "Error, we read %s, %s expected",
-                 psz_name ,  p_sys->ppsz_names[p_sys->i_current] );
-        p_sys->b_error = VLC_TRUE;
-    }
-
-    return VLC_SUCCESS;
-}
diff --git a/modules/services_discovery/Modules.am b/modules/services_discovery/Modules.am
index b5f76ffcd3cf..c489b913dae4 100644
--- a/modules/services_discovery/Modules.am
+++ b/modules/services_discovery/Modules.am
@@ -1,6 +1,5 @@
 SOURCES_sap = sap.c
 SOURCES_hal = hal.c
-SOURCES_daap = daap.c
 SOURCES_shout = shout.c
 SOURCES_upnp_cc = upnp_cc.cpp
 SOURCES_upnp_intel = upnp_intel.cpp
diff --git a/modules/services_discovery/bonjour.c b/modules/services_discovery/bonjour.c
index 8fc7293cc4bc..ff24a493b9ca 100644
--- a/modules/services_discovery/bonjour.c
+++ b/modules/services_discovery/bonjour.c
@@ -239,8 +239,8 @@ static void browse_callback(
             msg_Err( p_sd, "failed to find service '%s' in playlist", name );
         else
         {
-            playlist_LockDeleteAllFromInput( p_sys->p_playlist,
-                                              p_item->p_input->i_id );
+            playlist_DeleteFromInput( p_sys->p_playlist, p_item->p_input->i_id,
+                                      VLC_FALSE );
         }
     }
 }
diff --git a/modules/services_discovery/daap.c b/modules/services_discovery/daap.c
deleted file mode 100644
index fbb2a85a4b9e..000000000000
--- a/modules/services_discovery/daap.c
+++ /dev/null
@@ -1,651 +0,0 @@
-/*****************************************************************************
- * daap.c :  Apple DAAP discovery module
- *****************************************************************************
- * Copyright (C) 2004 the VideoLAN team
- * $Id$
- *
- * 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
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
- *****************************************************************************/
-
-/*****************************************************************************
- * Includes
- *****************************************************************************/
-#include <stdlib.h>                                      /* malloc(), free() */
-
-#include <vlc/vlc.h>
-#include <vlc/intf.h>
-
-#include "vlc_url.h"
-
-#include <vlc/input.h>
-
-#include <daap/client.h>
-
-/************************************************************************
- * Macros and definitions
- ************************************************************************/
-
-/*****************************************************************************
- * Module descriptor
- *****************************************************************************/
-
-/* Callbacks */
-    static int  Open ( vlc_object_t * );
-    static void Close( vlc_object_t * );
-    static int  OpenAccess ( vlc_object_t * );
-    static void CloseAccess( vlc_object_t * );
-
-vlc_module_begin();
-    set_description( _("DAAP shares") );
-    set_category( CAT_PLAYLIST );
-    set_subcategory( SUBCAT_PLAYLIST_SD );
-
-    set_capability( "services_discovery", 0 );
-    set_callbacks( Open, Close );
-
-    add_submodule();
-        set_description( _( "DAAP access") );
-        set_capability( "access2", 0 );
-        set_callbacks( OpenAccess, CloseAccess );
-vlc_module_end();
-
-
-/*****************************************************************************
- * Local structures
- *****************************************************************************/
-
-typedef struct dhost_s {
-    char *psz_name;
-    int i_id;
-
-    DAAP_SClientHost *p_host;
-    vlc_bool_t b_updated;
-    vlc_bool_t b_new;
-    int i_database_id;
-
-    playlist_item_t *p_node;
-
-    DAAP_ClientHost_DatabaseItem *p_songs;
-    int i_songs;
-} dhost_t;
-
-typedef struct daap_db_s {
-    dhost_t **pp_hosts;
-    int       i_hosts;
-
-    int i_last_id;
-
-    vlc_mutex_t search_lock;
-} daap_db_t;
-
-struct services_discovery_sys_t {
-    playlist_item_t *p_node;
-
-    DAAP_SClient *p_client;
-    DAAP_SClientHost *p_host;
-
-    daap_db_t *p_db;
-};
-
-struct access_sys_t {
-    vlc_url_t url;
-
-    dhost_t *p_host;
-    int i_host;
-    int i_song;
-
-    daap_db_t *p_db;
-
-    DAAP_ClientHost_Song song;
-    DAAP_ClientHost_DatabaseItem songdata;
-    int i_orig_size;
-    void *p_orig_buffer;
-};
-
-/*****************************************************************************
- * Local prototypes
- *****************************************************************************/
-
-/* Main functions */
-    static void Run    ( services_discovery_t *p_sd );
-    static void Callback( DAAP_SClient *p_client, DAAP_Status status,
-                          int i_pos, void *p_context );
-    static int EnumerateCallback( DAAP_SClient *p_client,
-                                  DAAP_SClientHost *p_host,
-                                  void *p_context );
-    static void OnHostsUpdate( services_discovery_t *p_sd );
-    static void ProcessHost( services_discovery_t *p_sd, dhost_t *p_host );
-    static void FreeHost( services_discovery_t *p_sd, dhost_t *p_host );
-
-    static int Control( access_t *p_access, int i_query, va_list args );
-    static int Read( access_t *, uint8_t *, int );
-    static int Seek( access_t *, int64_t );
-
-/*****************************************************************************
- * Open: initialize and create stuff
- *****************************************************************************/
-static int Open( vlc_object_t *p_this )
-{
-    services_discovery_t *p_sd = ( services_discovery_t* )p_this;
-    services_discovery_sys_t *p_sys  = (services_discovery_sys_t *)
-                                malloc( sizeof( services_discovery_sys_t ) );
-
-    playlist_t          *p_playlist;
-    playlist_view_t     *p_view;
-    vlc_value_t         val;
-
-    p_sd->pf_run = Run;
-    p_sd->p_sys  = p_sys;
-
-    p_sys->p_db = (daap_db_t *)malloc( sizeof( daap_db_t ) );
-    if( !p_sys->p_db )
-    {
-        return VLC_EGENERIC;
-    }
-    p_sys->p_db->pp_hosts = NULL;
-    p_sys->p_db->i_hosts = 0;
-
-    var_Create( p_sd->p_libvlc, "daap-db", VLC_VAR_ADDRESS );
-    val.p_address = p_sys->p_db;
-    var_Set( p_sd->p_libvlc, "daap-db", val );
-
-    vlc_mutex_init( p_sd, &p_sys->p_db->search_lock );
-
-    /* Init DAAP */
-    p_sys->p_client = DAAP_Client_Create( Callback, p_sd );
-    p_sys->p_db->i_last_id = 0;
-
-    /* TODO: Set debugging correctly */
-//    DAAP_Client_SetDebug( p_sys->p_client, "+trace" );
-
-
-    /* Create our playlist node */
-    p_playlist = (playlist_t *)vlc_object_find( p_sd, VLC_OBJECT_PLAYLIST,
-                                                FIND_ANYWHERE );
-    if( !p_playlist )
-    {
-        msg_Warn( p_sd, "unable to find playlist, cancelling DAAP" );
-        return VLC_EGENERIC;
-    }
-    msg_Err( p_sd, "DAAP IS BROKEN !! Fix it if you want it !" );
-    return VLC_EGENERIC;
-
-#if 0
-    p_sys->p_node = playlist_NodeCreate( p_playlist, VIEW_CATEGORY,
-                                         _("DAAP shares"), p_view->p_root );
-    p_sys->p_node->i_flags |= PLAYLIST_RO_FLAG;
-
-    val.b_bool = VLC_TRUE;
-    var_Set( p_playlist, "intf-change", val );
-    vlc_object_release( p_playlist );
-
-    return VLC_SUCCESS;
-#endif
-}
-
-static int OpenAccess( vlc_object_t *p_this )
-{
-#if 0
-    access_t     *p_access = (access_t*)p_this;
-    access_sys_t *p_sys;
-    vlc_value_t val;
-    vlc_bool_t b_found = VLC_FALSE;
-    int i, i_ret;
-
-    p_access->pf_read = Read;
-    p_access->pf_block = NULL;
-    p_access->pf_control = Control;
-    p_access->pf_seek = Seek;
-    p_access->info.i_update = 0;
-    p_access->info.i_size = 0;
-    p_access->info.i_pos = 0;
-    p_access->info.b_eof = VLC_FALSE;
-    p_access->info.i_title = 0;
-    p_access->info.i_seekpoint = 0;
-    p_access->p_sys = p_sys = malloc( sizeof( access_sys_t ) );
-    memset( p_sys, 0, sizeof( access_sys_t ) );
-
-    i_ret = var_Get( p_access->p_libvlc , "daap-db", &val );
-    p_sys->p_db = val.p_address;
-
-    if( p_sys->p_db == NULL || i_ret )
-    {
-        msg_Err( p_access, "the DAAP services_discovery module must be enabled" );
-        return VLC_EGENERIC;
-    }
-
-    vlc_UrlParse( &p_sys->url, p_access->psz_path, 0 );
-
-    p_sys->p_host = NULL;
-    p_sys->i_host = atoi( p_sys->url.psz_host ) ;
-    p_sys->i_song = p_sys->url.i_port;
-
-    if( !p_sys->i_host || !p_sys->i_song )
-    {
-        msg_Err( p_access, "invalid host or song" );
-        return VLC_EGENERIC;
-    }
-
-    /* Search the host */
-    vlc_mutex_lock( &p_sys->p_db->search_lock );
-    for( i = 0 ; i < p_sys->p_db->i_hosts ; i++ )
-    {
-        if( p_sys->p_db->pp_hosts[i]->i_id == p_sys->i_host )
-        {
-            p_sys->p_host = p_sys->p_db->pp_hosts[i];
-            break;
-        }
-    }
-    if( p_sys->p_host )
-    {
-       for( i = 0 ; i < p_sys->p_host->i_songs ; i++ )
-       {
-           if( p_sys->p_host->p_songs[i].id == p_sys->i_song )
-           {
-               p_sys->songdata = p_sys->p_host->p_songs[i];
-               b_found = VLC_TRUE;
-               break;
-           }
-       }
-       if( !b_found )
-       {
-           msg_Err( p_access, "invalid song (not found in %i)",
-                             p_sys->p_host->i_songs );
-       }
-    }
-    else
-    {
-        msg_Warn( p_access, "invalid host (not found in %i)",
-                             p_sys->p_db->i_hosts );
-    }
-    vlc_mutex_unlock( &p_sys->p_db->search_lock );
-
-    if( !p_sys->p_host || !b_found )
-    {
-        return VLC_EGENERIC;
-    }
-
-
-    msg_Dbg( p_access, "downloading %s song %i (db %i)",
-                           p_sys->songdata.songformat,
-                           p_sys->i_song, p_sys->p_host->i_database_id );
-
-    /* FIXME: wait for better method by upstream */
-    i_ret = DAAP_ClientHost_GetAudioFile( p_sys->p_host->p_host,
-                                          p_sys->p_host->i_database_id,
-                                          p_sys->i_song,
-                                          p_sys->songdata.songformat,
-                                          &(p_sys->song) );
-
-    msg_Dbg( p_access, "finished downloading, read %i bytes (ret %i)",
-                                          p_sys->song.size, i_ret );
-
-    p_access->info.i_size = p_sys->song.size;
-
-    if( i_ret != 0 )
-        return VLC_EGENERIC;
-#endif
-    return VLC_SUCCESS;
-}
-
-/*****************************************************************************
- * Close:
- *****************************************************************************/
-static void Close( vlc_object_t *p_this )
-{
-#if 0
-    services_discovery_t *p_sd = ( services_discovery_t* )p_this;
-    services_discovery_sys_t    *p_sys  = p_sd->p_sys;
-
-    playlist_t *p_playlist;
-    int i;
-
-    p_playlist = (playlist_t *) vlc_object_find( p_sd, VLC_OBJECT_PLAYLIST,
-                                                 FIND_ANYWHERE );
-
-    for( i = 0 ; i< p_sys->p_db->i_hosts ; i++ )
-    {
-        FreeHost( p_sd, p_sys->p_db->pp_hosts[i] );
-    }
-
-    var_Destroy( p_sd->p_libvlc, "daap-db" );
-
-    if( p_playlist )
-    {
-        playlist_NodeDelete( p_playlist, p_sys->p_node, VLC_TRUE, VLC_TRUE );
-        vlc_object_release( p_playlist );
-    }
-
-    free( p_sys );
-#endif
-}
-
-static void CloseAccess( vlc_object_t *p_this )
-{
-    access_t *p_access = (access_t*) p_this;
-    access_sys_t *p_sys = p_access->p_sys;
-
-    if( p_sys )
-    {
-        if( p_sys->p_host )
-        {
-            p_sys->song.data = p_sys->p_orig_buffer;
-            p_sys->song.size = p_sys->i_orig_size;
-            DAAP_ClientHost_FreeAudioFile( p_sys->p_host->p_host, &p_sys->song );
-        }
-        free( p_sys );
-    }
-}
-
-/*****************************************************************************
- * Run: main DAAP thread
- *****************************************************************************/
-static void Run( services_discovery_t *p_sd )
-{
-    while( !p_sd->b_die )
-    {
-        msleep( 100000 );
-    }
-}
-
-/*****************************************************************************
- * Access functions
- *****************************************************************************/
-static int Control( access_t *p_access, int i_query, va_list args )
-{
-    vlc_bool_t *pb_bool;
-    int64_t *pi_64;
-    switch( i_query )
-    {
-        case ACCESS_CAN_SEEK:
-        case ACCESS_CAN_FASTSEEK:
-            pb_bool = (vlc_bool_t *)va_arg( args, vlc_bool_t *);
-            *pb_bool = VLC_TRUE;
-            break;
-        case ACCESS_CAN_PAUSE:
-        case ACCESS_CAN_CONTROL_PACE:
-            pb_bool = (vlc_bool_t *)va_arg( args, vlc_bool_t *);
-            *pb_bool = VLC_TRUE;
-            break;
-
-        case ACCESS_GET_PTS_DELAY:
-            pi_64 = (int64_t *)va_arg( args, int64_t *);
-            *pi_64 = (int64_t)300000;
-            break;
-
-        case ACCESS_SET_PAUSE_STATE:
-            break;
-
-        case ACCESS_GET_TITLE_INFO:
-        case ACCESS_SET_TITLE:
-        case ACCESS_SET_SEEKPOINT:
-        case ACCESS_SET_PRIVATE_ID_STATE:
-            return VLC_EGENERIC;
-
-        default:
-            msg_Warn( p_access, "unimplemented query control %i", i_query );
-            return VLC_EGENERIC;
-    }
-    return VLC_SUCCESS;
-}
-
-static int Read( access_t *p_access, uint8_t *p_buffer, int i_size )
-{
-    access_sys_t *p_sys = (access_sys_t *)p_access->p_sys;
-    int i_send;
-
-    if( i_size < p_sys->song.size && p_sys->song.size > 0 )
-    {
-        i_send = i_size;
-    }
-    else if( p_sys->song.size == 0 )
-    {
-        return 0;
-    }
-    else
-    {
-        i_send = p_sys->song.size;
-    }
-
-    memcpy( p_buffer, p_sys->song.data, i_send );
-    p_sys->song.size -= i_send;
-    p_sys->song.data += i_send;
-
-    return i_send;
-}
-
-static int Seek( access_t *p_access, int64_t i_pos )
-{
-    if( i_pos > p_access->p_sys->i_orig_size )
-    {
-        return VLC_EGENERIC;
-    }
-    p_access->p_sys->song.size = p_access->p_sys->i_orig_size - i_pos;
-    p_access->p_sys->song.data = p_access->p_sys->p_orig_buffer + i_pos;
-    return VLC_SUCCESS;
-}
-
-/**************************************************************
- * Local functions
- **************************************************************/
-static void Callback( DAAP_SClient *p_client, DAAP_Status status,
-                      int i_pos, void *p_context )
-{
-    services_discovery_t *p_sd = (services_discovery_t *)p_context;
-
-    if( status == DAAP_STATUS_hostschanged )
-    {
-        OnHostsUpdate( p_sd );
-    }
-    else if( status == DAAP_STATUS_downloading )
-    {
-    }
-}
-
-static void OnHostsUpdate( services_discovery_t *p_sd )
-{
-    int i;
-
-    for( i = 0 ; i< p_sd->p_sys->p_db->i_hosts ; i ++ )
-    {
-        p_sd->p_sys->p_db->pp_hosts[i]->b_updated = VLC_FALSE;
-        p_sd->p_sys->p_db->pp_hosts[i]->b_new     = VLC_FALSE;
-    }
-
-    vlc_mutex_lock( &p_sd->p_sys->p_db->search_lock );
-    DAAP_Client_EnumerateHosts( p_sd->p_sys->p_client, EnumerateCallback, p_sd);
-
-    for( i = 0 ; i< p_sd->p_sys->p_db->i_hosts ; i ++ )
-    {
-        if( p_sd->p_sys->p_db->pp_hosts[i]->b_updated == VLC_FALSE )
-        {
-            dhost_t *p_host = p_sd->p_sys->p_db->pp_hosts[i];
-            FreeHost( p_sd, p_host );
-            REMOVE_ELEM( p_sd->p_sys->p_db->pp_hosts,
-                         p_sd->p_sys->p_db->i_hosts, i );
-        }
-    }
-    vlc_mutex_unlock( &p_sd->p_sys->p_db->search_lock );
-
-    for( i = 0 ; i< p_sd->p_sys->p_db->i_hosts ; i ++ )
-    {
-        if( p_sd->p_sys->p_db->pp_hosts[i]->b_new )
-            ProcessHost( p_sd, p_sd->p_sys->p_db->pp_hosts[i] );
-    }
-}
-
-static int EnumerateCallback( DAAP_SClient *p_client,
-                              DAAP_SClientHost *p_host,
-                              void *p_context )
-{
-    int i;
-    int i_size = DAAP_ClientHost_GetSharename( p_host, NULL, 0 );
-    vlc_bool_t b_found = VLC_FALSE;
-    char *psz_buffer = (char *)malloc( i_size );
-    DAAP_ClientHost_GetSharename( p_host, psz_buffer, i_size );
-
-    services_discovery_t *p_sd = (services_discovery_t *)p_context;
-    services_discovery_sys_t *p_sys = p_sd->p_sys;
-
-    for( i = 0 ; i< p_sys->p_db->i_hosts; i++ )
-    {
-        if( !strcmp( p_sys->p_db->pp_hosts[i]->psz_name, psz_buffer ) )
-        {
-            p_sys->p_db->pp_hosts[i]->b_updated = VLC_TRUE;
-            b_found = VLC_TRUE;
-            break;
-        }
-    }
-
-    if( !b_found )
-    {
-        dhost_t *p_vlchost = (dhost_t *)malloc( sizeof( dhost_t ) );
-        p_vlchost->p_node = NULL;
-        p_vlchost->p_host = p_host;
-        p_vlchost->psz_name = psz_buffer;
-        p_vlchost->b_new = VLC_TRUE;
-        p_vlchost->b_updated = VLC_TRUE;
-        INSERT_ELEM( p_sys->p_db->pp_hosts, p_sys->p_db->i_hosts,
-                     p_sys->p_db->i_hosts, p_vlchost );
-    }
-
-    return VLC_SUCCESS;
-}
-
-static void ProcessHost( services_discovery_t *p_sd, dhost_t *p_host )
-{
-#if 0
-    int i_dbsize, i_db, i, i_songsize, i_ret;
-    int i_size = DAAP_ClientHost_GetSharename( p_host->p_host, NULL, 0 );
-
-    playlist_t *p_playlist;
-
-    p_playlist = (playlist_t *) vlc_object_find( p_sd, VLC_OBJECT_PLAYLIST,
-                                                       FIND_ANYWHERE );
-
-    if( !p_playlist )
-    {
-        return;
-    }
-
-    /* Connect to host */
-    if( p_host->b_new )
-    {
-        p_host->psz_name = (char *)malloc( i_size );
-        p_host->b_new = VLC_FALSE;
-        DAAP_ClientHost_GetSharename( p_host->p_host, p_host->psz_name ,
-                                      i_size );
-
-        msg_Dbg( p_sd, "new share %s", p_host->psz_name );
-        DAAP_ClientHost_AddRef( p_host->p_host );
-        i_ret = DAAP_ClientHost_Connect( p_host->p_host );
-        if( i_ret )
-        {
-            msg_Warn( p_sd, "unable to connect to DAAP host %s",
-                             p_host->psz_name );
-//            DAAP_ClientHost_Release( p_host->p_host );
-            vlc_object_release( p_playlist );
-            return;
-        }
-
-        p_host->p_node = playlist_NodeCreate( p_playlist, VIEW_CATEGORY,
-                                              p_host->psz_name,
-                                              p_sd->p_sys->p_node );
-        p_host->i_id = ++p_sd->p_sys->p_db->i_last_id;
-    }
-
-    /* Get DB */
-    i_dbsize = DAAP_ClientHost_GetDatabases( p_host->p_host, NULL, NULL, 0 );
-
-    DAAP_ClientHost_Database *p_database = malloc( i_dbsize );
-    DAAP_ClientHost_GetDatabases( p_host->p_host, p_database, &i_db, i_dbsize );
-
-
-    if( !i_db || !p_database )
-    {
-        msg_Warn( p_sd, "no database on DAAP host %s", p_host->psz_name );
-        vlc_object_release( p_playlist );
-        return;
-    }
-
-    /* We only use the first database */
-    p_host->i_database_id = p_database[0].id;
-
-    /* Get songs */
-    i_songsize = DAAP_ClientHost_GetDatabaseItems( p_host->p_host,
-                                                   p_host->i_database_id,
-                                                   NULL, NULL, 0 );
-    if( !i_songsize )
-    {
-        vlc_object_release( p_playlist );
-        return;
-    }
-    p_host->p_songs = malloc( i_songsize );
-
-    DAAP_ClientHost_GetDatabaseItems( p_host->p_host ,
-                                      p_host->i_database_id,
-                                      p_host->p_songs,
-                                      &p_host->i_songs, i_songsize );
-
-    for( i = 0; i< p_host->i_songs; i++ )
-    {
-        playlist_item_t *p_item;
-        int i_len = 7 + 10 + 1 + 10 ;    /* "daap://" + host + ":" + song */
-        char *psz_buff = (char *)malloc( i_len );
-
-        snprintf( psz_buff, i_len, "daap://%i:%i", p_host->i_id,
-                                                   p_host->p_songs[i].id );
-        p_item = playlist_ItemNew( p_sd, psz_buff,
-                                         p_host->p_songs[i].itemname );
-        input_ItemAddInfo( &p_item->input, _(VLC_META_INFO_CAT),
-                                _(VLC_META_ARTIST), p_host->p_songs[i].songartist );
-        input_ItemAddInfo( &p_item->input, _(VLC_META_INFO_CAT),
-                                _(VLC_META_COLLECTION), p_host->p_songs[i].songalbum );
-
-        playlist_NodeAddItem( p_playlist, p_item, VIEW_CATEGORY,
-                              p_host->p_node, PLAYLIST_APPEND, PLAYLIST_END );
-
-    }
-
-    DAAP_ClientHost_AsyncWaitUpdate( p_host->p_host );
-
-    vlc_object_release( p_playlist );
-#endif
-}
-
-static void FreeHost( services_discovery_t *p_sd, dhost_t *p_host )
-{
-    playlist_t *p_playlist;
-
-    if( p_host->p_host )
-    {
-        DAAP_ClientHost_Disconnect( p_host->p_host );
-        DAAP_ClientHost_Release( p_host->p_host );
-    }
-
-    p_playlist = (playlist_t *) vlc_object_find( p_sd, VLC_OBJECT_PLAYLIST,
-                                                 FIND_ANYWHERE );
-    if( p_playlist )
-    {
-        if( p_host->p_node )
-            playlist_NodeDelete( p_playlist, p_host->p_node, VLC_TRUE ,
-                                                             VLC_TRUE);
-        vlc_object_release( p_playlist );
-    }
-
-    if( p_host->p_songs ) free( p_host->p_songs );
-}
diff --git a/modules/services_discovery/hal.c b/modules/services_discovery/hal.c
index 1657089c2599..bb6224fd7682 100644
--- a/modules/services_discovery/hal.c
+++ b/modules/services_discovery/hal.c
@@ -297,7 +297,8 @@ static void DelItem( services_discovery_t *p_sd, char* psz_udi )
     {
         if( strcmp( psz_udi, p_sys->pp_devices[i]->psz_udi ) == 0 )
         {
-            playlist_DeleteFromItemId( p_playlist, p_sys->pp_devices[i]->i_id );
+            msg_Err(p_sd, "HAL delete must be fixed");
+/*      playlist_DeleteFromItemId( p_playlist, p_sys->pp_devices[i]->i_id );*/
             TAB_REMOVE( p_sys->i_devices_number, p_sys->pp_devices,
                     p_sys->pp_devices[i] );
         }
diff --git a/modules/services_discovery/sap.c b/modules/services_discovery/sap.c
index 1c05f29f4a96..f4775b1c35a6 100644
--- a/modules/services_discovery/sap.c
+++ b/modules/services_discovery/sap.c
@@ -304,7 +304,7 @@ static int Open( vlc_object_t *p_this )
     playlist_NodesPairCreate( pl_Get( p_sd ), _("SAP sessions"),
                               &p_sys->p_node_cat, &p_sys->p_node_one,
                               VLC_TRUE );
-
+    p_sys->p_node_cat->p_input->b_prefers_tree = VLC_TRUE;
     p_sys->i_announces = 0;
     p_sys->pp_announces = NULL;
 
@@ -577,7 +577,7 @@ static int Demux( demux_t *p_demux )
     if( p_playlist->status.p_item &&
              p_playlist->status.p_item->p_input == p_parent_input )
     {
-        playlist_Control( p_playlist, PLAYLIST_VIEWPLAY,
+        playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, VLC_TRUE,
                           p_playlist->status.p_node, p_playlist->status.p_item );
     }
 
@@ -1290,7 +1290,7 @@ static int RemoveAnnounce( services_discovery_t *p_sd,
     }
 
     if( p_announce->i_input_id > -1 )
-        playlist_LockDeleteAllFromInput( pl_Get(p_sd), p_announce->i_input_id );
+        playlist_DeleteFromInput( pl_Get(p_sd), p_announce->i_input_id, VLC_FALSE );
 
     for( i = 0; i< p_sd->p_sys->i_announces; i++)
     {
diff --git a/modules/services_discovery/upnp_cc.cpp b/modules/services_discovery/upnp_cc.cpp
index d2817ea23c58..925fb5e177c6 100644
--- a/modules/services_discovery/upnp_cc.cpp
+++ b/modules/services_discovery/upnp_cc.cpp
@@ -5,7 +5,7 @@
  * $Id$
  *
  * Authors: Rémi Denis-Courmont <rem # videolan.org>
- * 
+ *
  * Based on original wxWindows patch for VLC, and dependant on CyberLink
  * UPnP library from :
  *          Satoshi Konno <skonno@cybergarage.org>
@@ -71,10 +71,8 @@ vlc_module_end();
 
 struct services_discovery_sys_t
 {
-    /* playlist node */
-    playlist_item_t *p_node;
+    playlist_item_t *p_node_one;
     playlist_item_t *p_node_cat;
-    playlist_t *p_playlist;
 };
 
 /*****************************************************************************
@@ -96,18 +94,8 @@ static int Open( vlc_object_t *p_this )
     p_sd->pf_run = Run;
     p_sd->p_sys  = p_sys;
 
-    /* Create our playlist node */
-    p_sys->p_playlist = (playlist_t *)vlc_object_find( p_sd,
-                                                       VLC_OBJECT_PLAYLIST,
-                                                       FIND_ANYWHERE );
-    if( !p_sys->p_playlist )
-    {
-        msg_Warn( p_sd, "unable to find playlist, cancelling UPnP listening");
-        return VLC_EGENERIC;
-    }
-
-    playlist_NodesPairCreate( p_sys->p_playlist, _("Devices"),
-                              &p_sys->p_node_cat, &p_sys->p_node,
+    playlist_NodesPairCreate( pl_Get( p_sd ), _("Devices"),
+                              &p_sys->p_node_cat, &p_sys->p_node_one,
                               VLC_TRUE );
     return VLC_SUCCESS;
 }
@@ -120,16 +108,12 @@ static void Close( vlc_object_t *p_this )
 {
     services_discovery_t *p_sd = ( services_discovery_t* )p_this;
     services_discovery_sys_t    *p_sys  = p_sd->p_sys;
-
-    if( p_sys->p_playlist )
-    {
-        playlist_NodeDelete( p_sys->p_playlist, p_sys->p_node, VLC_TRUE,
-                             VLC_TRUE );
-        playlist_NodeDelete( p_sys->p_playlist, p_sys->p_node_cat, VLC_TRUE,
-                             VLC_TRUE );
-        vlc_object_release( p_sys->p_playlist );
-    }
-
+    playlist_t *p_playlist = pl_Yield( p_sd );
+    playlist_NodeDelete( p_playlist, p_sys->p_node_one, VLC_TRUE,
+                         VLC_TRUE );
+    playlist_NodeDelete( p_playlist, p_sys->p_node_cat, VLC_TRUE,
+                         VLC_TRUE );
+    pl_Release();
     free( p_sys );
 }
 
@@ -222,7 +206,7 @@ playlist_item_t *UPnPHandler::AddDevice( Device *dev )
      */
     char *str = strdup( dev->getFriendlyName( ) );
 
-    p_item = playlist_NodeCreate( p_sys->p_playlist, str, p_sys->p_node );
+    p_item = playlist_NodeCreate( p_sys->p_playlist, str, p_sys->p_node_cat );
     p_item->i_flags &= ~PLAYLIST_SKIP_FLAG;
     msg_Dbg( p_sd, "device %s added", str );
     free( str );
@@ -251,29 +235,25 @@ void UPnPHandler::AddContent( playlist_item_t *p_parent, ContentNode *node )
 
     msg_Dbg( p_sd, "title = %s", title );
 
-    if ( node->isItemNode() ) 
+    if ( node->isItemNode() )
     {
         ItemNode *iNode = (ItemNode *)node;
-
-	playlist_item_t *p_item;
-	p_item = playlist_ItemNew( p_sd, iNode->getResource(), title );
-    
-	playlist_NodeAddItem( p_sys->p_playlist, p_item,
-			      p_parent, PLAYLIST_APPEND, PLAYLIST_END );
-
-    } else if ( node->isContainerNode() ) 
+        input_item_t *p_input = input_ItemNew( p_sd, iNode->getResource(), title );
+        playlist_BothAddInput( p_sys->p_playlist, p_input, p_parent,
+                               PLAYLIST_APPEND, PLAYLIST_END, NULL, NULL );
+    } else if ( node->isContainerNode() )
     {
         ContainerNode *conNode = (ContainerNode *)node;
 
-	char* p_name = strdup(title); /* See other comment on strdup */
-	playlist_item_t* p_node = playlist_NodeCreate( p_sys->p_playlist,
-						       p_name, p_parent );
-	free(p_name);
+        char* p_name = strdup(title); /* See other comment on strdup */
+        playlist_item_t* p_node = playlist_NodeCreate( p_sys->p_playlist,
+                                                       p_name, p_parent );
+        free(p_name);
 
-	unsigned nContentNodes = conNode->getNContentNodes();
+        unsigned nContentNodes = conNode->getNContentNodes();
 
-	for( unsigned n = 0; n < nContentNodes; n++ )
-	    AddContent( p_node, conNode->getContentNode( n ) );
+        for( unsigned n = 0; n < nContentNodes; n++ )
+           AddContent( p_node, conNode->getContentNode( n ) );
     }
 }
 
diff --git a/modules/services_discovery/upnp_intel.cpp b/modules/services_discovery/upnp_intel.cpp
index c300ee8e7800..2d194182bb3f 100644
--- a/modules/services_discovery/upnp_intel.cpp
+++ b/modules/services_discovery/upnp_intel.cpp
@@ -49,8 +49,7 @@
 struct services_discovery_sys_t
 {
     playlist_item_t *p_node_cat;
-    playlist_item_t *p_node;
-    playlist_t *p_playlist;
+    playlist_item_t *p_node_one;
 };
 
 
@@ -287,17 +286,8 @@ static int Open( vlc_object_t *p_this )
     p_sd->p_sys = p_sys;
 
     /* Create our playlist node */
-    p_sys->p_playlist = ( playlist_t * )vlc_object_find( p_sd,
-                             VLC_OBJECT_PLAYLIST,
-                             FIND_ANYWHERE );
-    if( !p_sys->p_playlist )
-    {
-        msg_Warn( p_sd, "unable to find playlist, cancelling UPnP listening" );
-        return VLC_EGENERIC;
-    }
-
-    playlist_NodesPairCreate( p_sys->p_playlist, _("Devices"),
-                              &p_sys->p_node_cat, &p_sys->p_node,
+    playlist_NodesPairCreate( pl_Get( p_sd ), _("Devices"),
+                              &p_sys->p_node_cat, &p_sys->p_node_one,
                               VLC_TRUE );
 
     return VLC_SUCCESS;
@@ -308,14 +298,10 @@ static void Close( vlc_object_t *p_this )
     services_discovery_t *p_sd = ( services_discovery_t* )p_this;
     services_discovery_sys_t *p_sys = p_sd->p_sys;
 
-    if( p_sys->p_playlist )
-    {
-        playlist_NodeDelete( p_sys->p_playlist, p_sys->p_node, VLC_TRUE,
-                             VLC_TRUE );
-        playlist_NodeDelete( p_sys->p_playlist, p_sys->p_node_cat, VLC_TRUE,
-                             VLC_TRUE );
-        vlc_object_release( p_sys->p_playlist );
-    }
+    playlist_NodeDelete( pl_Get( p_sd ), p_sys->p_node_one, VLC_TRUE,
+                         VLC_TRUE );
+    playlist_NodeDelete( pl_Get( p_sd ), p_sys->p_node_cat, VLC_TRUE,
+                         VLC_TRUE );
 
     free( p_sys );
 }
@@ -327,8 +313,8 @@ static void Run( services_discovery_t* p_sd )
     res = UpnpInit( 0, 0 );
     if( res != UPNP_E_SUCCESS )
     {
-    msg_Err( p_sd, "%s", UpnpGetErrorMessage( res ) );
-    return;
+        msg_Err( p_sd, "%s", UpnpGetErrorMessage( res ) );
+        return;
     }
 
     Cookie cookie;
@@ -340,21 +326,21 @@ static void Run( services_discovery_t* p_sd )
     res = UpnpRegisterClient( Callback, &cookie, &cookie.clientHandle );
     if( res != UPNP_E_SUCCESS )
     {
-    msg_Err( p_sd, "%s", UpnpGetErrorMessage( res ) );
-    goto shutDown;
+        msg_Err( p_sd, "%s", UpnpGetErrorMessage( res ) );
+        goto shutDown;
     }
 
     res = UpnpSearchAsync( cookie.clientHandle, 5, MEDIA_SERVER_DEVICE_TYPE, &cookie );
     if( res != UPNP_E_SUCCESS )
     {
-    msg_Err( p_sd, "%s", UpnpGetErrorMessage( res ) );
-    goto shutDown;
+        msg_Err( p_sd, "%s", UpnpGetErrorMessage( res ) );
+        goto shutDown;
     }
 
     msg_Dbg( p_sd, "UPnP discovery started" );
     while( !p_sd->b_die )
     {
-    msleep( 500 );
+        msleep( 500 );
     }
 
     msg_Dbg( p_sd, "UPnP discovery stopped" );
@@ -408,7 +394,7 @@ IXML_Document* parseBrowseResult( IXML_Document* doc )
 
     const char* resultString = ixmlNode_getNodeValue( textNode );
     char* resultXML = strdup( resultString );
-    
+
     resolve_xml_special_chars( resultXML );
 
     IXML_Document* browseDoc = ixmlParseBuffer( resultXML );
@@ -634,10 +620,8 @@ MediaServer::~MediaServer()
 {
     if ( _contents )
     {
-    playlist_NodeDelete( _cookie->serviceDiscovery->p_sys->p_playlist,
-                _playlistNode,
-                true,
-                true );
+        playlist_NodeDelete( pl_Get( _cookie->serviceDiscovery ) ,
+                             _playlistNode, VLC_TRUE, VLC_TRUE );
     }
 
     delete _contents;
@@ -770,19 +754,15 @@ IXML_Document* MediaServer::_browseAction( const char* pObjectID, const char* pB
 void MediaServer::fetchContents()
 {
     Container* root = new Container( 0, "0", getFriendlyName() );
+    playlist_t * p_playlist = pl_Get( _cookie->serviceDiscovery );
     _fetchContents( root );
 
     if ( _contents )
     {
-    vlc_mutex_lock( &_cookie->serviceDiscovery->p_sys->p_playlist->object_lock );
-
-    playlist_NodeEmpty( _cookie->serviceDiscovery->p_sys->p_playlist,
-               _playlistNode,
-               true );
-
-    vlc_mutex_unlock( &_cookie->serviceDiscovery->p_sys->p_playlist->object_lock );
-
-    delete _contents;
+        PL_LOCK;
+        playlist_NodeEmpty( p_playlist, _playlistNode, VLC_TRUE );
+        PL_UNLOCK;
+        delete _contents;
     }
 
     _contents = root;
@@ -868,35 +848,35 @@ bool MediaServer::_fetchContents( Container* parent )
 
 void MediaServer::_buildPlaylist( Container* parent )
 {
+    playlist_t *p_playlist = pl_Get( _cookie->serviceDiscovery );
     for ( unsigned int i = 0; i < parent->getNumContainers(); i++ )
     {
-    Container* container = parent->getContainer( i );
-    playlist_item_t* parentNode = parent->getPlaylistNode();
+        Container* container = parent->getContainer( i );
+        playlist_item_t* parentNode = parent->getPlaylistNode();
 
-    char* title = strdup( container->getTitle() );
-    playlist_item_t* node = playlist_NodeCreate( _cookie->serviceDiscovery->p_sys->p_playlist,
-                             title,
-                             parentNode );
-    free( title );
+        char* title = strdup( container->getTitle() );
+        playlist_item_t* node = playlist_NodeCreate( p_playlist, title, parentNode );
+        free( title );
 
-    container->setPlaylistNode( node );
-    _buildPlaylist( container );
+        container->setPlaylistNode( node );
+        _buildPlaylist( container );
     }
 
     for ( unsigned int i = 0; i < parent->getNumItems(); i++ )
     {
-    Item* item = parent->getItem( i );
-    playlist_item_t* parentNode = parent->getPlaylistNode();
-
-    playlist_item_t* node = playlist_ItemNew( _cookie->serviceDiscovery,
-                         item->getResource(),
-                         item->getTitle() );
-
-    playlist_NodeAddItem( _cookie->serviceDiscovery->p_sys->p_playlist,
-                 node,
-                 parentNode, PLAYLIST_APPEND, PLAYLIST_END );
-
-    item->setPlaylistNode( node );
+        Item* item = parent->getItem( i );
+        playlist_item_t* parentNode = parent->getPlaylistNode();
+
+        input_item_t* p_input = input_ItemNew( _cookie->serviceDiscovery,
+                                               item->getResource(),
+                                               item->getTitle() );
+        int i_cat;
+        playlist_BothAddInput( p_playlist, p_input, parentNode,
+                               PLAYLIST_APPEND, PLAYLIST_END, &i_cat, NULL );
+        /* TODO: do this better by storing ids */
+        playlist_item_t *p_node = playlist_ItemGetById( p_playlist, i_cat, VLC_FALSE );
+        assert( p_node );
+        item->setPlaylistNode( p_node );
     }
 }
 
@@ -935,9 +915,9 @@ bool MediaServerList::addServer( MediaServer* s )
     _list.push_back( s );
 
     char* name = strdup( s->getFriendlyName() );
-    playlist_item_t* node = playlist_NodeCreate( _cookie->serviceDiscovery->p_sys->p_playlist,
-                        name,
-                        _cookie->serviceDiscovery->p_sys->p_node );
+    playlist_item_t* node = playlist_NodeCreate( pl_Get( _cookie->serviceDiscovery ),
+                                                 name,
+                                          _cookie->serviceDiscovery->p_sys->p_node_cat );
     free( name );
     s->setPlaylistNode( node );
 
diff --git a/src/control/playlist.c b/src/control/playlist.c
index 5b03177a31f6..a1f4fac45786 100644
--- a/src/control/playlist.c
+++ b/src/control/playlist.c
@@ -47,12 +47,11 @@ void libvlc_playlist_play( libvlc_instance_t *p_instance, int i_id,
     if( PL->items.i_size == 0 ) RAISEVOID( "Empty playlist" );
     if( i_id > 0 )
     {
-        playlist_item_t *p_item = playlist_ItemGetById( PL,
-                                                        i_id );
+        playlist_item_t *p_item = playlist_ItemGetById( PL, i_id, VLC_TRUE );
         if( !p_item ) RAISEVOID( "Unable to find item" );
 
-        playlist_LockControl( PL, PLAYLIST_VIEWPLAY,
-                              PL->status.p_node, p_item );
+        playlist_Control( PL, PLAYLIST_VIEWPLAY, VLC_FALSE,
+                          PL->status.p_node, p_item );
     }
     else
     {
@@ -81,7 +80,7 @@ void libvlc_playlist_clear( libvlc_instance_t *p_instance,
                            libvlc_exception_t *p_e )
 {
     assert( PL );
-    playlist_LockClear( PL );
+    playlist_Clear( PL, VLC_FALSE );
 }
 
 void libvlc_playlist_next( libvlc_instance_t *p_instance,
@@ -120,8 +119,25 @@ int libvlc_playlist_add_extended( libvlc_instance_t *p_instance,
 int libvlc_playlist_delete_item( libvlc_instance_t *p_instance, int i_id,
                                  libvlc_exception_t *p_e )
 {
+    playlist_item_t *p_item;
     assert( PL );
-    return playlist_DeleteFromItemId( PL, i_id );
+    vlc_mutex_lock( &PL->object_lock );
+    p_item = playlist_ItemGetById( PL, i_id, VLC_TRUE );
+    if( p_item && p_item->p_input ) {
+        int i_ret = playlist_DeleteFromInput( PL, p_item->p_input->i_id, VLC_TRUE );
+        if( i_ret ) {
+            libvlc_exception_raise( p_e, "delete failed" );
+            vlc_mutex_unlock( &PL->object_lock );
+            return VLC_EGENERIC;
+        }
+        else {
+            vlc_mutex_unlock( &PL->object_lock );
+            return VLC_SUCCESS;
+        }
+    }
+    libvlc_exception_raise( p_e, "item not found" );
+    vlc_mutex_unlokc( &PL->object_lock );
+    return VLC_EGENERIC;
 }
 
 
diff --git a/src/input/meta.c b/src/input/meta.c
index 577cdbe57a26..00673013394e 100644
--- a/src/input/meta.c
+++ b/src/input/meta.c
@@ -39,6 +39,7 @@ vlc_bool_t input_MetaSatisfied( playlist_t *p_playlist, input_item_t *p_item,
                                 uint32_t *pi_mandatory, uint32_t *pi_optional )
 {
     *pi_mandatory = VLC_META_ENGINE_TITLE | VLC_META_ENGINE_ARTIST;
+    assert( p_item->p_meta );
 
     uint32_t i_meta = input_CurrentMetaFlags( p_item->p_meta );
     *pi_mandatory &= ~i_meta;
@@ -51,7 +52,7 @@ int input_MetaFetch( playlist_t *p_playlist, input_item_t *p_item )
     struct meta_engine_t *p_me;
     uint32_t i_mandatory, i_optional;
 
-    if( !p_item->p_meta ) return VLC_EGENERIC;
+    assert( p_item->p_meta );
 
     input_MetaSatisfied( p_playlist, p_item, &i_mandatory, &i_optional );
     // Meta shouldn't magically appear
diff --git a/src/libvlc.c b/src/libvlc.c
index 89f04d2133b1..ad4883f489cf 100644
--- a/src/libvlc.c
+++ b/src/libvlc.c
@@ -708,7 +708,7 @@ int VLC_PlaylistPrev( int i_object )
 int VLC_PlaylistClear( int i_object )
 {
     LIBVLC_PLAYLIST_FUNC;
-    playlist_Clear( p_libvlc->p_playlist );
+    playlist_Clear( p_libvlc->p_playlist, VLC_TRUE );
     LIBVLC_PLAYLIST_FUNC_END;
     return VLC_SUCCESS;
 }
diff --git a/src/playlist/control.c b/src/playlist/control.c
index 6fa949576dba..2b518c6b1b11 100644
--- a/src/playlist/control.c
+++ b/src/playlist/control.c
@@ -30,33 +30,14 @@
 /*****************************************************************************
  * Local prototypes
  *****************************************************************************/
-int PlaylistVAControl( playlist_t * p_playlist, int i_query, va_list args );
+static int PlaylistVAControl( playlist_t * p_playlist, int i_query, va_list args );
 
-void PreparseEnqueueItemSub( playlist_t *, playlist_item_t * );
-
-playlist_item_t *playlist_RecursiveFindLast(playlist_t *p_playlist,
-                                            playlist_item_t *p_node );
+static void PreparseEnqueueItemSub( playlist_t *, playlist_item_t * );
 
 /*****************************************************************************
  * Playlist control
  *****************************************************************************/
 
-/**
- * Do a playlist action. Should be entered without playlist lock
- * \see playlist_Control
- */
-int playlist_LockControl( playlist_t * p_playlist, int i_query, ... )
-{
-    va_list args;
-    int i_result;
-    va_start( args, i_query );
-    vlc_mutex_lock( &p_playlist->object_lock );
-    i_result = PlaylistVAControl( p_playlist, i_query, args );
-    va_end( args );
-    vlc_mutex_unlock( &p_playlist->object_lock );
-    return i_result;
-}
-
 /**
  * Do a playlist action.
  * If there is something in the playlist then you can do playlist actions.
@@ -68,23 +49,25 @@ int playlist_LockControl( playlist_t * p_playlist, int i_query, ... )
  * \param variable number of arguments
  * \return VLC_SUCCESS or an error
  */
-int playlist_Control( playlist_t * p_playlist, int i_query, ... )
+int playlist_Control( playlist_t * p_playlist, int i_query, vlc_bool_t b_locked, ... )
 {
     va_list args;
     int i_result;
-    va_start( args, i_query );
+    va_start( args, b_locked );
+    if( !b_locked ) PL_LOCK;
     i_result = PlaylistVAControl( p_playlist, i_query, args );
     va_end( args );
+    if( !b_locked ) PL_UNLOCK;
 
     return i_result;
 }
 
-int PlaylistVAControl( playlist_t * p_playlist, int i_query, va_list args )
+static int PlaylistVAControl( playlist_t * p_playlist, int i_query, va_list args )
 {
     playlist_item_t *p_item, *p_node;
     vlc_value_t val;
 
-    if( p_playlist->items.i_size <= 0 )
+    if( playlist_IsEmpty( p_playlist ) )
         return VLC_EGENERIC;
 
     switch( i_query )
@@ -236,8 +219,8 @@ int playlist_AskForArtEnqueue( playlist_t *p_playlist,
     return VLC_SUCCESS;
 }
 
-void PreparseEnqueueItemSub( playlist_t *p_playlist,
-                             playlist_item_t *p_item )
+static void PreparseEnqueueItemSub( playlist_t *p_playlist,
+                                    playlist_item_t *p_item )
 {
     int i;
     if( p_item->i_children == -1 )
diff --git a/src/playlist/engine.c b/src/playlist/engine.c
index 9840a3f61c6c..4e510eb9186c 100644
--- a/src/playlist/engine.c
+++ b/src/playlist/engine.c
@@ -97,6 +97,9 @@ playlist_t * playlist_Create( vlc_object_t *p_parent )
     p_playlist->p_root_category = playlist_NodeCreate( p_playlist, NULL, NULL);
     p_playlist->p_root_onelevel = playlist_NodeCreate( p_playlist, NULL, NULL);
 
+    if( !p_playlist->p_root_category || !p_playlist->p_root_onelevel )
+        return NULL;
+
     /* Create playlist and media library */
     p_playlist->p_local_category = playlist_NodeCreate( p_playlist,
                                  _( "Playlist" ),p_playlist->p_root_category );
@@ -105,6 +108,11 @@ playlist_t * playlist_Create( vlc_object_t *p_parent )
     p_playlist->p_local_category->i_flags |= PLAYLIST_RO_FLAG;
     p_playlist->p_local_onelevel->i_flags |= PLAYLIST_RO_FLAG;
 
+    if( !p_playlist->p_local_category || !p_playlist->p_local_onelevel ||
+        !p_playlist->p_local_category->p_input ||
+        !p_playlist->p_local_onelevel->p_input )
+        return NULL;
+
     /* Link the nodes together. Todo: actually create them from the same input*/
     p_playlist->p_local_onelevel->p_input->i_id =
         p_playlist->p_local_category->p_input->i_id;
@@ -115,6 +123,10 @@ playlist_t * playlist_Create( vlc_object_t *p_parent )
                            _( "Media Library" ), p_playlist->p_root_category );
         p_playlist->p_ml_onelevel =  playlist_NodeCreate( p_playlist,
                            _( "Media Library" ), p_playlist->p_root_onelevel );
+
+        if(!p_playlist->p_ml_category || !p_playlist->p_ml_onelevel)
+            return NULL;
+
         p_playlist->p_ml_category->i_flags |= PLAYLIST_RO_FLAG;
         p_playlist->p_ml_onelevel->i_flags |= PLAYLIST_RO_FLAG;
         p_playlist->p_ml_onelevel->p_input->i_id =
@@ -201,7 +213,6 @@ void playlist_Destroy( playlist_t *p_playlist )
     vlc_object_destroy( p_playlist->p_fetcher );
     vlc_object_detach( p_playlist );
     vlc_object_destroy( p_playlist );
-
 }
 
 /* Destroy remaining objects */
@@ -522,7 +533,8 @@ void playlist_PreparseLoop( playlist_preparse_t *p_obj )
              * This only checks for meta, not for art
              * \todo don't do this for things we won't get meta for, like vids
              */
-            if( !input_MetaSatisfied( p_playlist, p_current, &i_m, &i_o ) )
+            if( p_current->p_meta &&
+                !input_MetaSatisfied( p_playlist, p_current, &i_m, &i_o ) )
             {
                 preparse_item_t p;
                 PL_DEBUG("need to fetch meta for %s", p_current->psz_name );
@@ -531,13 +543,13 @@ void playlist_PreparseLoop( playlist_preparse_t *p_obj )
                 vlc_mutex_lock( &p_playlist->p_fetcher->object_lock );
                 INSERT_ELEM( p_playlist->p_fetcher->p_waiting,
                              p_playlist->p_fetcher->i_waiting,
-                             p_playlist->p_fetcher->i_waiting,
-                             p );
+                             p_playlist->p_fetcher->i_waiting, p);
                 vlc_mutex_unlock( &p_playlist->p_fetcher->object_lock );
                 vlc_cond_signal( &p_playlist->p_fetcher->object_wait );
             }
             /* We already have all needed meta, but we need art right now */
-            else if( p_playlist->p_fetcher->i_art_policy == ALBUM_ART_ALL &&
+            else if( p_current->p_meta &&
+                     p_playlist->p_fetcher->i_art_policy == ALBUM_ART_ALL &&
                      EMPTY_STR( p_current->p_meta->psz_arturl ) )
             {
                 preparse_item_t p;
@@ -546,17 +558,18 @@ void playlist_PreparseLoop( playlist_preparse_t *p_obj )
                 p.p_item = p_current;
                 p.b_fetch_art = VLC_TRUE;
                 vlc_mutex_lock( &p_playlist->p_fetcher->object_lock );
-                INSERT_ELEM( p_playlist->p_fetcher->p_waiting,
-                             p_playlist->p_fetcher->i_waiting,
-                             p_playlist->p_fetcher->i_waiting,
-                             p );
+                TAB_APPEND( p_playlist->p_fetcher->i_waiting,
+                            p_playlist->p_fetcher->p_waiting,
+                            p );
                 vlc_mutex_unlock( &p_playlist->p_fetcher->object_lock );
                 vlc_cond_signal( &p_playlist->p_fetcher->object_wait );
             }
             else
             {
                 PL_DEBUG( "no fetch required for %s (art currently %s)",
-                          p_current->psz_name, p_current->p_meta->psz_arturl );
+                          p_current->psz_name,
+                          p_current->p_meta ? p_current->p_meta->psz_arturl:
+                                              "null" );
                 vlc_gc_decref( p_current );
             }
             PL_UNLOCK;
@@ -600,6 +613,7 @@ void playlist_FetcherLoop( playlist_fetcher_t *p_obj )
         vlc_mutex_unlock( &p_obj->object_lock );
         if( p_item )
         {
+            assert( p_item->p_meta );
             if( !b_fetch_art )
             {
                 input_MetaFetch( p_playlist, p_item );
diff --git a/src/playlist/item.c b/src/playlist/item.c
index 64a9887b73ec..720bcbced303 100644
--- a/src/playlist/item.c
+++ b/src/playlist/item.c
@@ -87,30 +87,9 @@ int playlist_ItemDelete( playlist_item_t *p_item )
     return VLC_SUCCESS;
 }
 
-/** Remove an input item from ONELEVEL and CATEGORY */
-int playlist_DeleteAllFromInput( playlist_t *p_playlist, int i_input_id )
-{
-    playlist_DeleteFromInput( p_playlist, i_input_id,
-                              p_playlist->p_root_category, VLC_TRUE );
-    playlist_DeleteFromInput( p_playlist, i_input_id,
-                              p_playlist->p_root_onelevel, VLC_TRUE );
-    return VLC_SUCCESS;
-}
-
-/** Remove an input item from ONELEVEL and CATEGORY.
- * This function must be entered without the playlist lock */
-int playlist_LockDeleteAllFromInput( playlist_t * p_playlist, int i_id )
-{
-    int i_ret;
-    vlc_mutex_lock( &p_playlist->object_lock );
-    i_ret = playlist_DeleteAllFromInput( p_playlist, i_id );
-    vlc_mutex_unlock( &p_playlist->object_lock );
-    return i_ret;
-}
-
 /** Remove an input item when it appears from a root playlist item */
-int playlist_DeleteFromInput( playlist_t *p_playlist, int i_input_id,
-                              playlist_item_t *p_root, vlc_bool_t b_do_stop )
+static int DeleteFromInput( playlist_t *p_playlist, int i_input_id,
+                            playlist_item_t *p_root, vlc_bool_t b_do_stop )
 {
     int i;
     for( i = 0 ; i< p_root->i_children ; i++ )
@@ -123,45 +102,43 @@ int playlist_DeleteFromInput( playlist_t *p_playlist, int i_input_id,
         }
         else if( p_root->pp_children[i]->i_children >= 0 )
         {
-            int i_ret = playlist_DeleteFromInput( p_playlist, i_input_id,
-                                        p_root->pp_children[i], b_do_stop );
+            int i_ret = DeleteFromInput( p_playlist, i_input_id,
+                                         p_root->pp_children[i], b_do_stop );
             if( i_ret == VLC_SUCCESS ) return VLC_SUCCESS;
         }
     }
     return VLC_EGENERIC;
 }
 
-/** Remove a playlist item from the playlist, given its id */
-int playlist_DeleteFromItemId( playlist_t *p_playlist, int i_id )
-{
-    playlist_item_t *p_item = playlist_ItemGetById( p_playlist, i_id );
-    if( !p_item ) return VLC_EGENERIC;
-    return DeleteInner( p_playlist, p_item, VLC_TRUE );
-}
-
-/** Remove a playlist item from the playlist, given its id
- * This function should be entered without the playlist lock */
-int playlist_LockDelete( playlist_t * p_playlist, int i_id )
+/** Remove an input item from ONELEVEL and CATEGORY */
+int playlist_DeleteFromInput( playlist_t *p_playlist, int i_input_id,
+                              vlc_bool_t b_locked )
 {
-    int i_ret;
-    vlc_mutex_lock( &p_playlist->object_lock );
-    i_ret = playlist_DeleteFromItemId( p_playlist, i_id );
-    vlc_mutex_unlock( &p_playlist->object_lock );
-    return i_ret;
+    if( !b_locked ) PL_LOCK;
+    DeleteFromInput( p_playlist, i_input_id,
+                     p_playlist->p_root_category, VLC_TRUE );
+    DeleteFromInput( p_playlist, i_input_id,
+                     p_playlist->p_root_onelevel, VLC_TRUE );
+    if( !b_locked ) PL_UNLOCK;
+    return VLC_SUCCESS;
 }
 
 /** Clear the playlist */
-void playlist_Clear( playlist_t * p_playlist )
+void playlist_Clear( playlist_t * p_playlist, vlc_bool_t b_locked )
 {
+    if( !b_locked ) PL_LOCK;
     playlist_NodeEmpty( p_playlist, p_playlist->p_root_category, VLC_TRUE );
     playlist_NodeEmpty( p_playlist, p_playlist->p_root_onelevel, VLC_TRUE );
+    if( !b_locked ) PL_UNLOCK;
 }
-/** Clear the playlist. This function must be entered without the lock */
-void playlist_LockClear( playlist_t *p_playlist )
+
+/** Remove a playlist item from the playlist, given its id
+ * This function is to be used only by the playlist */
+int playlist_DeleteFromItemId( playlist_t *p_playlist, int i_id )
 {
-    vlc_mutex_lock( &p_playlist->object_lock );
-    playlist_Clear( p_playlist );
-    vlc_mutex_unlock( &p_playlist->object_lock );
+    playlist_item_t *p_item = playlist_ItemGetById( p_playlist, i_id,  VLC_TRUE );
+    if( !p_item ) return VLC_EGENERIC;
+    return DeleteInner( p_playlist, p_item, VLC_TRUE );
 }
 
 /***************************************************************************
@@ -251,7 +228,8 @@ int playlist_AddInput( playlist_t* p_playlist, input_item_t *p_input,
 int playlist_BothAddInput( playlist_t *p_playlist,
                            input_item_t *p_input,
                            playlist_item_t *p_direct_parent,
-                           int i_mode, int i_pos )
+                           int i_mode, int i_pos,
+                           int *i_cat, int *i_one )
 {
     playlist_item_t *p_item_cat, *p_item_one, *p_up;
     int i_top;
@@ -285,6 +263,9 @@ int playlist_BothAddInput( playlist_t *p_playlist,
     }
     GoAndPreparse( p_playlist, i_mode, p_item_cat, p_item_one );
 
+    if( i_cat ) *i_cat = p_item_cat->i_id;
+    if( i_one ) *i_one = p_item_one->i_id;
+
     vlc_mutex_unlock( &p_playlist->object_lock );
     return VLC_SUCCESS;
 }
@@ -310,15 +291,6 @@ playlist_item_t * playlist_NodeAddInput( playlist_t *p_playlist,
     return p_item;
 }
 
-/** Add a playlist item to a given node */
-void playlist_NodeAddItem( playlist_t *p_playlist, playlist_item_t *p_item,
-                           playlist_item_t *p_parent, int i_mode, int i_pos )
-{
-    vlc_mutex_lock( &p_playlist->object_lock );
-    AddItem( p_playlist, p_item, p_parent, i_pos );
-    vlc_mutex_unlock( &p_playlist->object_lock );
-}
-
 /*****************************************************************************
  * Playlist item misc operations
  *****************************************************************************/
@@ -329,7 +301,8 @@ void playlist_NodeAddItem( playlist_t *p_playlist, playlist_item_t *p_item,
  * This function must be entered without the playlist lock
  */
 playlist_item_t *playlist_ItemToNode( playlist_t *p_playlist,
-                                      playlist_item_t *p_item )
+                                      playlist_item_t *p_item,
+                                      vlc_bool_t b_locked )
 {
 
     playlist_item_t *p_item_in_category;
@@ -347,9 +320,13 @@ playlist_item_t *playlist_ItemToNode( playlist_t *p_playlist,
      * useful for later BothAddInput )
      */
 
+    if( !b_locked ) PL_LOCK;
+
     /* Fast track the media library, no time to loose */
-    if( p_item == p_playlist->p_ml_category )
+    if( p_item == p_playlist->p_ml_category ) {
+        if( !b_locked ) PL_UNLOCK;
         return p_item;
+    }
 
     /** \todo First look if we don't already have it */
     p_item_in_category = playlist_ItemFindFromInputAndRoot(
@@ -370,36 +347,24 @@ playlist_item_t *playlist_ItemToNode( playlist_t *p_playlist,
             ChangeToNode( p_playlist, p_item_in_one );
         else
         {
-            playlist_DeleteFromInput( p_playlist, p_item_in_one->p_input->i_id,
-                                      p_playlist->p_root_onelevel, VLC_FALSE );
+            DeleteFromInput( p_playlist, p_item_in_one->p_input->i_id,
+                             p_playlist->p_root_onelevel, VLC_FALSE );
         }
         p_playlist->b_reset_currently_playing = VLC_TRUE;
         vlc_cond_signal( &p_playlist->object_wait );
         var_SetInteger( p_playlist, "item-change", p_item_in_category->
                                                         p_input->i_id );
+        if( !b_locked ) PL_UNLOCK;
         return p_item_in_category;
     }
     else
     {
         ChangeToNode( p_playlist, p_item );
+        if( !b_locked ) PL_UNLOCK;
         return NULL;
     }
 }
 
-/** Transform an item to a node
- *  This function must be entered without the playlist lock
- *  \see playlist_ItemToNode
- */
-playlist_item_t * playlist_LockItemToNode( playlist_t *p_playlist,
-                                           playlist_item_t *p_item )
-{
-    playlist_item_t *p_ret;
-    vlc_mutex_lock( &p_playlist->object_lock );
-    p_ret = playlist_ItemToNode( p_playlist, p_item );
-    vlc_mutex_unlock( &p_playlist->object_lock );
-    return p_ret;
-}
-
 /** Find an item within a root, given its input id.
  * \return the first found item, or NULL if not found
  */
diff --git a/src/playlist/playlist_internal.h b/src/playlist/playlist_internal.h
index 979200fb834b..03f61c63482f 100644
--- a/src/playlist/playlist_internal.h
+++ b/src/playlist/playlist_internal.h
@@ -99,6 +99,8 @@ playlist_item_t *playlist_GetPrevLeaf( playlist_t *p_playlist,
 playlist_item_t *playlist_GetLastLeaf( playlist_t *p_playlist,
                                     playlist_item_t *p_root );
 
+int playlist_DeleteFromItemId( playlist_t*, int );
+
 /**
  * @}
  */
@@ -107,9 +109,15 @@ playlist_item_t *playlist_GetLastLeaf( playlist_t *p_playlist,
 //#undef PLAYLIST_DEBUG
 
 #ifdef PLAYLIST_DEBUG
-#define PL_DEBUG( msg, args... ) msg_Dbg( p_playlist, msg, ## args )
+ #define PL_DEBUG( msg, args... ) msg_Dbg( p_playlist, msg, ## args )
+ #ifdef PLAYLIST_DEBUG2
+  #define PL_DEBUG2( msg, args... ) msg_Dbg( p_playlist, msg, ## args )
+ #else
+  #define PL_DEBUG2( msg, args... ) {}
+ #endif
 #else
-#define PL_DEBUG( msg, args ... ) {}
+ #define PL_DEBUG( msg, args ... ) {}
+ #define PL_DEBUG2( msg, args... ) {}
 #endif
 
-#define PLI_NAME( p ) p ? p->p_input->psz_name : "null"
+#define PLI_NAME( p ) p && p->p_input ? p->p_input->psz_name : "null"
diff --git a/src/playlist/search.c b/src/playlist/search.c
index ba7a52c6818a..e5e63e46ac9c 100644
--- a/src/playlist/search.c
+++ b/src/playlist/search.c
@@ -36,12 +36,17 @@
  * \param i_id the id to find
  * \return the item or NULL on failure
  */
-playlist_item_t * playlist_ItemGetById( playlist_t * p_playlist , int i_id )
+playlist_item_t * playlist_ItemGetById( playlist_t * p_playlist , int i_id,
+                                        vlc_bool_t b_locked )
 {
     int i;
+    if( !b_locked ) PL_LOCK;
     ARRAY_BSEARCH( p_playlist->all_items,->i_id, int, i_id, i );
-    if( i != -1 )
+    if( i != -1 ) {
+        if( !b_locked ) PL_UNLOCK;
         return ARRAY_VAL( p_playlist->all_items, i );
+    }
+    if( !b_locked ) PL_UNLOCK;
     return NULL;
 }
 
@@ -53,20 +58,27 @@ playlist_item_t * playlist_ItemGetById( playlist_t * p_playlist , int i_id )
  * \return the item, or NULL on failure
  */
 playlist_item_t * playlist_ItemGetByInput( playlist_t * p_playlist ,
-                                           input_item_t *p_item )
+                                           input_item_t *p_item,
+                                           vlc_bool_t b_locked )
 {
     int i;
+    if( !b_locked ) PL_LOCK;
     if( p_playlist->status.p_item &&
         p_playlist->status.p_item->p_input == p_item )
     {
+        if( !b_locked ) PL_UNLOCK;
         return p_playlist->status.p_item;
     }
     /** \todo Check if this is always incremental and whether we can bsearch */
     for( i =  0 ; i < p_playlist->all_items.i_size; i++ )
     {
         if( ARRAY_VAL(p_playlist->all_items, i)->p_input->i_id == p_item->i_id )
+        {
+            if( !b_locked ) PL_UNLOCK;
             return ARRAY_VAL(p_playlist->all_items, i);
+        }
     }
+    if( !b_locked ) PL_UNLOCK;
     return NULL;
 }
 
diff --git a/src/playlist/tree.c b/src/playlist/tree.c
index 552f3e5def87..fe4f70abe7ec 100644
--- a/src/playlist/tree.c
+++ b/src/playlist/tree.c
@@ -401,14 +401,8 @@ playlist_item_t *playlist_GetNextLeaf( playlist_t *p_playlist,
 
     assert( p_root && p_root->i_children != -1 );
 
-#ifdef PLAYLIST_DEBUG
-    if( p_item != NULL )
-        msg_Dbg( p_playlist, "finding next of %s within %s",
-                        p_item->p_input->psz_name,  p_root->p_input->psz_name );
-    else
-        msg_Dbg( p_playlist, "finding something to play within %s",
-                         p_root->p_input->psz_name );
-#endif
+    PL_DEBUG2( "finding next of %s within %s",
+               PLI_NAME( p_item ), PLI_NAME( p_root ) );
 
     /* Now, walk the tree until we find a suitable next item */
     p_next = p_item;
@@ -427,10 +421,7 @@ playlist_item_t *playlist_GetNextLeaf( playlist_t *p_playlist,
             if( b_ena_ok && b_unplayed_ok ) break;
         }
     }
-#ifdef PLAYLIST_DEBUG
-    if( p_next == NULL )
-        msg_Dbg( p_playlist, "At end of node" );
-#endif
+    if( p_next == NULL ) PL_DEBUG2( "at end of node" );
     return p_next;
 }
 
@@ -449,14 +440,8 @@ playlist_item_t *playlist_GetPrevLeaf( playlist_t *p_playlist,
 {
     playlist_item_t *p_prev;
 
-#ifdef PLAYLIST_DEBUG
-    if( p_item != NULL )
-        msg_Dbg( p_playlist, "finding previous of %s within %s",
-                        p_item->p_input->psz_name,  p_root->p_input->psz_name );
-    else
-        msg_Dbg( p_playlist, "finding previous to play within %s",
-                         p_root->p_input->psz_name );
-#endif
+    PL_DEBUG2( "finding previous os %s within %s", PLI_NAME( p_item ),
+                                                   PLI_NAME( p_root ) );
     assert( p_root && p_root->i_children != -1 );
 
     /* Now, walk the tree until we find a suitable previous item */
@@ -476,10 +461,7 @@ playlist_item_t *playlist_GetPrevLeaf( playlist_t *p_playlist,
             if( b_ena_ok && b_unplayed_ok ) break;
         }
     }
-#ifdef PLAYLIST_DEBUG
-    if( p_prev == NULL )
-        msg_Dbg( p_playlist, "At beginning of node" );
-#endif
+    if( p_prev == NULL ) PL_DEBUG2( "at beginning of node" );
     return p_prev;
 }
 
@@ -516,13 +498,13 @@ playlist_item_t *GetNextItem( playlist_t *p_playlist,
             if( i+1 >= p_parent->i_children )
             {
                 /* Was already the last sibling. Look for uncles */
-                PL_DEBUG( "Current item is the last of the node,"
-                          "looking for uncle from %s",
-                           p_parent->p_input->psz_name );
+                PL_DEBUG2( "Current item is the last of the node,"
+                           "looking for uncle from %s",
+                            p_parent->p_input->psz_name );
 
                 if( p_parent == p_root )
                 {
-                    PL_DEBUG( "already at root" );
+                    PL_DEBUG2( "already at root" );
                     return NULL;
                 }
                 return GetNextUncle( p_playlist, p_item, p_root );
@@ -553,9 +535,9 @@ playlist_item_t *GetNextUncle( playlist_t *p_playlist, playlist_item_t *p_item,
             {
                 if( p_parent == p_grandparent->pp_children[i] )
                 {
-                    PL_DEBUG( "parent %s found as child %i of grandparent %s",
-                              p_parent->p_input->psz_name, i,
-                              p_grandparent->p_input->psz_name );
+                    PL_DEBUG2( "parent %s found as child %i of grandparent %s",
+                               p_parent->p_input->psz_name, i,
+                               p_grandparent->p_input->psz_name );
                     b_found = VLC_TRUE;
                     break;
                 }
@@ -650,12 +632,12 @@ playlist_item_t *GetPrevItem( playlist_t *p_playlist,
             if( i-1 < 0 )
             {
                /* Was already the first sibling. Look for uncles */
-                PL_DEBUG( "current item is the first of its node,"
-                          "looking for uncle from %s",
-                          p_parent->p_input->psz_name );
+                PL_DEBUG2( "current item is the first of its node,"
+                           "looking for uncle from %s",
+                           p_parent->p_input->psz_name );
                 if( p_parent == p_root )
                 {
-                    PL_DEBUG( "already at root" );
+                    PL_DEBUG2( "already at root" );
                     return NULL;
                 }
                 return GetPrevUncle( p_playlist, p_item, p_root );
-- 
GitLab