+ if( p_next == p_cur )
+ p_playlist->i_current_index = p_playlist->current.i_size;
+ ARRAY_APPEND( p_playlist->current, p_next);
+ }
+ PL_DEBUG("rebuild done - %i items, index %i", p_playlist->current.i_size,
+ p_playlist->i_current_index);
+
+ if( var_GetBool( p_playlist, "random" ) )
+ {
+ /* Shuffle the array */
+ srand( (unsigned int)mdate() );
+ for( int j = p_playlist->current.i_size - 1; j > 0; j-- )
+ {
+ int i = rand() % (j+1); /* between 0 and j */
+ playlist_item_t *p_tmp;
+ /* swap the two items */
+ p_tmp = ARRAY_VAL(p_playlist->current, i);
+ ARRAY_VAL(p_playlist->current,i) = ARRAY_VAL(p_playlist->current,j);
+ ARRAY_VAL(p_playlist->current,j) = p_tmp;
+ }
+ }
+ p_sys->b_reset_currently_playing = false;
+ stats_TimerStop( p_playlist, STATS_TIMER_PLAYLIST_BUILD );
+}
+
+
+/**
+ * Start the input for an item
+ *
+ * \param p_playlist the playlist object
+ * \param p_item the item to play
+ * \return nothing
+ */
+static int PlayItem( playlist_t *p_playlist, playlist_item_t *p_item )
+{
+ playlist_private_t *p_sys = pl_priv(p_playlist);
+ input_item_t *p_input = p_item->p_input;
+
+ PL_ASSERT_LOCKED;
+
+ msg_Dbg( p_playlist, "creating new input thread" );
+
+ p_input->i_nb_played++;
+ set_current_status_item( p_playlist, p_item );
+
+ p_sys->status.i_status = PLAYLIST_RUNNING;
+
+ UpdateActivity( p_playlist, DEFAULT_INPUT_ACTIVITY );
+
+ assert( p_sys->p_input == NULL );
+
+ input_thread_t *p_input_thread =
+ input_CreateThreadExtended( p_playlist, p_input, NULL, p_sys->p_input_resource );
+
+ if( p_input_thread )
+ {
+ p_sys->p_input = p_input_thread;
+
+ var_AddCallback( p_input_thread, "intf-event", InputEvent, p_playlist );
+ }
+
+ p_sys->p_input_resource = NULL;
+
+ char *psz_uri = input_item_GetURI( p_item->p_input );
+ if( psz_uri && ( !strncmp( psz_uri, "directory:", 10 ) ||
+ !strncmp( psz_uri, "vlc:", 4 ) ) )
+ {
+ free( psz_uri );
+ return VLC_SUCCESS;
+ }
+ free( psz_uri );
+
+ /* TODO store art policy in playlist private data */
+ if( var_GetInteger( p_playlist, "album-art" ) == ALBUM_ART_WHEN_PLAYED )
+ {
+ bool b_has_art;
+
+ char *psz_arturl, *psz_name;
+ psz_arturl = input_item_GetArtURL( p_input );
+ psz_name = input_item_GetName( p_input );
+
+ /* p_input->p_meta should not be null after a successfull CreateThread */
+ b_has_art = !EMPTY_STR( psz_arturl );
+
+ if( !b_has_art || strncmp( psz_arturl, "attachment://", 13 ) )
+ {
+ PL_DEBUG( "requesting art for %s", psz_name );
+ playlist_AskForArtEnqueue( p_playlist, p_input, pl_Locked );
+ }
+ free( psz_arturl );
+ free( psz_name );
+ }
+
+ PL_UNLOCK;
+ var_SetInteger( p_playlist, "item-current", p_input->i_id );
+ PL_LOCK;
+
+ return VLC_SUCCESS;
+}
+
+/**
+ * Compute the next playlist item depending on
+ * the playlist course mode (forward, backward, random, view,...).
+ *
+ * \param p_playlist the playlist object
+ * \return nothing
+ */
+static playlist_item_t *NextItem( playlist_t *p_playlist )
+{
+ playlist_private_t *p_sys = pl_priv(p_playlist);
+ playlist_item_t *p_new = NULL;
+
+ /* Handle quickly a few special cases */
+ /* No items to play */
+ if( p_playlist->items.i_size == 0 )
+ {
+ msg_Info( p_playlist, "playlist is empty" );
+ return NULL;
+ }
+
+ /* Start the real work */
+ if( p_sys->request.b_request )
+ {
+ p_new = p_sys->request.p_item;
+ int i_skip = p_sys->request.i_skip;
+ PL_DEBUG( "processing request item %s node %s skip %i",
+ PLI_NAME( p_sys->request.p_item ),
+ PLI_NAME( p_sys->request.p_node ), i_skip );
+
+ if( p_sys->request.p_node &&
+ p_sys->request.p_node != get_current_status_node( p_playlist ) )