/** * Delete playlist item * * Remove a playlist item from the playlist, given its id * This function is to be used only by the playlist * \param p_playlist playlist object * \param i_id id of the item do delete * \return VLC_SUCCESS or an error */ int playlist_DeleteFromItemId( playlist_t *p_playlist, int i_id ) { PL_ASSERT_LOCKED; playlist_item_t *p_item = playlist_ItemGetById( p_playlist, i_id ); if( !p_item ) return VLC_EGENERIC; return playlist_DeleteItem( p_playlist, p_item, true ); }
/** * Delete input item * * Remove an input item when it appears from a root playlist item * \param p_playlist playlist object * \param p_input the input to delete * \param p_root root playlist item * \param b_do_stop must stop or not the playlist * \return VLC_SUCCESS or VLC_EGENERIC */ static int DeleteFromInput( playlist_t *p_playlist, input_item_t *p_input, playlist_item_t *p_root, bool b_do_stop ) { PL_ASSERT_LOCKED; playlist_item_t *p_item = playlist_ItemFindFromInputAndRoot( p_playlist, p_input, p_root, false ); if( !p_item ) return VLC_EGENERIC; return playlist_DeleteItem( p_playlist, p_item, b_do_stop ); }
/** * Remove all the children of a node and removes the node * * \param p_playlist the playlist * \param p_root the node * \param b_delete_items do we have to delete the children items ? * \return VLC_SUCCESS or an error */ int playlist_NodeDelete( playlist_t *p_playlist, playlist_item_t *p_root, bool b_delete_items, bool b_force ) { PL_ASSERT_LOCKED; int i; if( p_root->i_children == -1 ) { return VLC_EGENERIC; } /* Delete the children */ for( i = p_root->i_children - 1 ; i >= 0; i-- ) { if( p_root->pp_children[i]->i_children > -1 ) { playlist_NodeDelete( p_playlist, p_root->pp_children[i], b_delete_items , b_force ); } else if( b_delete_items ) { playlist_DeleteItem( p_playlist, p_root->pp_children[i], true ); } } /* Delete the node */ if( p_root->i_flags & PLAYLIST_RO_FLAG && !b_force ) { } else { int i; var_SetInteger( p_playlist, "playlist-item-deleted", p_root->i_id ); ARRAY_BSEARCH( p_playlist->all_items, ->i_id, int, p_root->i_id, i ); if( i != -1 ) ARRAY_REMOVE( p_playlist->all_items, i ); /* Remove the item from its parent */ if( p_root->p_parent ) playlist_NodeRemoveItem( p_playlist, p_root, p_root->p_parent ); playlist_ItemRelease( p_root ); } return VLC_SUCCESS; }
static void input_item_add_subitem_tree ( const vlc_event_t * p_event, void * user_data ) { input_item_t *p_input = p_event->p_obj; playlist_t *p_playlist = (( playlist_item_t* ) user_data)->p_playlist; input_item_node_t *p_new_root = p_event->u.input_item_subitem_tree_added.p_root; PL_LOCK; playlist_item_t *p_item = playlist_ItemGetByInput( p_playlist, p_input ); assert( p_item != NULL ); bool b_current = get_current_status_item( p_playlist ) == p_item; bool b_autostart = var_GetBool( p_playlist, "playlist-autostart" ); bool b_stop = p_item->i_flags & PLAYLIST_SUBITEM_STOP_FLAG; bool b_flat = false; p_item->i_flags &= ~PLAYLIST_SUBITEM_STOP_FLAG; /* We will have to flatten the tree out if we are in "the playlist" node and the user setting demands flat playlist */ if( !pl_priv(p_playlist)->b_tree ) { playlist_item_t *p_up = p_item; while( p_up->p_parent ) { if( p_up->p_parent == p_playlist->p_playing ) { b_flat = true; break; } p_up = p_up->p_parent; } } int pos = 0; /* If we have to flatten out, then take the item's position in the parent as insertion point and delete the item */ if( b_flat ) { playlist_item_t *p_parent = p_item->p_parent; assert( p_parent != NULL ); int i; for( i = 0; i < p_parent->i_children; i++ ) { if( p_parent->pp_children[i] == p_item ) { pos = i; break; } } assert( i < p_parent->i_children ); playlist_DeleteItem( p_playlist, p_item, true ); p_item = p_parent; } else { pos = p_item->i_children >= 0 ? p_item->i_children : 0; } /* At this point: "p_item" is the node where sub-items should be inserted, "pos" is the insertion position in that node */ int last_pos = playlist_InsertInputItemTree( p_playlist, p_item, p_new_root, pos, b_flat ); if( !b_flat ) var_SetInteger( p_playlist, "leaf-to-parent", p_item->i_id ); //control playback only if it was the current playing item that got subitems if( b_current ) { if( last_pos == pos || ( b_stop && !b_flat ) || !b_autostart ) { /* We stop, either because no sub-item was actually created, or some flags/settings want us to do so at this point */ PL_UNLOCK; playlist_Stop( p_playlist ); return; } else { /* Continue to play, either random or the first new item */ playlist_item_t *p_play_item; if( var_GetBool( p_playlist, "random" ) ) { p_play_item = NULL; } else { /* Don't Play a directory if it can loop into a parent */ if( p_new_root->b_can_loop ) { /* Play the first regular file */ for( ; pos < last_pos; pos++ ) { if( p_item->pp_children[pos]->p_input->i_type != ITEM_TYPE_DIRECTORY ) break; } if( last_pos == pos ) { PL_UNLOCK; playlist_Stop( p_playlist ); return; } } p_play_item = p_item->pp_children[pos]; /* NOTE: this is a work around the general bug: if node-to-be-played contains sub-nodes, then second instead of first leaf starts playing (only in case the leafs have just been instered and playlist has not yet been rebuilt.) */ while( p_play_item->i_children > 0 ) p_play_item = p_play_item->pp_children[0]; } playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, pl_Locked, get_current_status_node( p_playlist ), p_play_item ); } } PL_UNLOCK; }