📄 item.c
字号:
PL_UNLOCK_IF( !b_locked ); return p_item_in_category; } else { ChangeToNode( p_playlist, p_item ); PL_UNLOCK_IF( !b_locked ); return p_item; }}/** * Find an item within a root, given its input id. * * \param p_playlist the playlist object * \param i_input_id id of the input * \param p_root root playlist item * \param b_items_only TRUE if we want the item himself * \return the first found item, or NULL if not found */playlist_item_t *playlist_ItemFindFromInputAndRoot( playlist_t *p_playlist, int i_input_id, playlist_item_t *p_root, bool b_items_only ){ int i; for( i = 0 ; i< p_root->i_children ; i++ ) { if( ( b_items_only ? p_root->pp_children[i]->i_children == -1 : 1 ) && p_root->pp_children[i]->p_input->i_id == i_input_id ) { return p_root->pp_children[i]; } else if( p_root->pp_children[i]->i_children >= 0 ) { playlist_item_t *p_search = playlist_ItemFindFromInputAndRoot( p_playlist, i_input_id, p_root->pp_children[i], b_items_only ); if( p_search ) return p_search; } } return NULL;}static int TreeMove( playlist_t *p_playlist, playlist_item_t *p_item, playlist_item_t *p_node, int i_newpos ){ int j; playlist_item_t *p_detach = p_item->p_parent; (void)p_playlist; if( p_node->i_children == -1 ) return VLC_EGENERIC; for( j = 0; j < p_detach->i_children; j++ ) { if( p_detach->pp_children[j] == p_item ) break; } REMOVE_ELEM( p_detach->pp_children, p_detach->i_children, j ); /* If j < i_newpos, we are moving the element from the top to the * down of the playlist. So when removing the element we change have * to change the position as we loose one element */ if( j < i_newpos ) i_newpos--; /* Attach to new parent */ INSERT_ELEM( p_node->pp_children, p_node->i_children, i_newpos, p_item ); p_item->p_parent = p_node; return VLC_SUCCESS;}/** * Moves an item * * This function must be entered with the playlist lock * * \param p_playlist the playlist * \param p_item the item to move * \param p_node the new parent of the item * \param i_newpos the new position under this new parent * \return VLC_SUCCESS or an error */int playlist_TreeMove( playlist_t * p_playlist, playlist_item_t *p_item, playlist_item_t *p_node, int i_newpos ){ int i_ret; PL_ASSERT_LOCKED; /* Drop on a top level node. Move in the two trees */ if( p_node->p_parent == p_playlist->p_root_category || p_node->p_parent == p_playlist->p_root_onelevel ) { /* Fixme: avoid useless lookups but we need some clean helpers */ { /* Fixme: if we try to move a node on a top-level node, it will * fail because the node doesn't exist in onelevel and we will * do some shit in onelevel. We should recursively move all items * within the node */ playlist_item_t *p_node_onelevel; playlist_item_t *p_item_onelevel; p_node_onelevel = playlist_ItemFindFromInputAndRoot( p_playlist, p_node->p_input->i_id, p_playlist->p_root_onelevel, false ); p_item_onelevel = playlist_ItemFindFromInputAndRoot( p_playlist, p_item->p_input->i_id, p_playlist->p_root_onelevel, false ); if( p_node_onelevel && p_item_onelevel ) TreeMove( p_playlist, p_item_onelevel, p_node_onelevel, i_newpos ); } { playlist_item_t *p_node_category; playlist_item_t *p_item_category; p_node_category = playlist_ItemFindFromInputAndRoot( p_playlist, p_node->p_input->i_id, p_playlist->p_root_category, false ); p_item_category = playlist_ItemFindFromInputAndRoot( p_playlist, p_item->p_input->i_id, p_playlist->p_root_category, false ); if( p_node_category && p_item_category ) TreeMove( p_playlist, p_item_category, p_node_category, 0 ); } i_ret = VLC_SUCCESS; } else i_ret = TreeMove( p_playlist, p_item, p_node, i_newpos ); p_playlist->b_reset_currently_playing = true; vlc_object_signal_unlocked( p_playlist ); return i_ret;}/** * Send a notification that an item has been added to a node * * \param p_playlist the playlist object * \param i_item_id id of the item added * \param i_node_id id of the node in wich the item was added * \param b_signal TRUE if the function must send a signal * \return nothing */void playlist_SendAddNotify( playlist_t *p_playlist, int i_item_id, int i_node_id, bool b_signal ){ vlc_value_t val; PL_ASSERT_LOCKED; playlist_add_t *p_add = (playlist_add_t *)malloc( sizeof( playlist_add_t) ); if( !p_add ) return; p_add->i_item = i_item_id; p_add->i_node = i_node_id; val.p_address = p_add; p_playlist->b_reset_currently_playing = true; if( b_signal ) vlc_object_signal_unlocked( p_playlist ); var_Set( p_playlist, "item-append", val ); free( p_add );}/***************************************************************************** * Playlist item accessors *****************************************************************************//** * Set the name of a playlist item * * \param p_item the item * \param psz_name the name * \return VLC_SUCCESS or VLC_EGENERIC */int playlist_ItemSetName( playlist_item_t *p_item, const char *psz_name ){ if( psz_name && p_item ) { input_item_SetName( p_item->p_input, psz_name ); return VLC_SUCCESS; } return VLC_EGENERIC;}/*************************************************************************** * The following functions are local ***************************************************************************//* Enqueue an item for preparsing, and play it, if needed */static void GoAndPreparse( playlist_t *p_playlist, int i_mode, playlist_item_t *p_item_cat, playlist_item_t *p_item_one ){ PL_ASSERT_LOCKED; if( (i_mode & PLAYLIST_GO ) ) { playlist_item_t *p_parent = p_item_one; playlist_item_t *p_toplay = NULL; while( p_parent ) { if( p_parent == p_playlist->p_root_category ) { p_toplay = p_item_cat; break; } else if( p_parent == p_playlist->p_root_onelevel ) { p_toplay = p_item_one; break; } p_parent = p_parent->p_parent; } assert( p_toplay ); p_playlist->request.b_request = true; p_playlist->request.i_skip = 0; p_playlist->request.p_item = p_toplay; if( p_playlist->p_input ) input_StopThread( p_playlist->p_input ); p_playlist->request.i_status = PLAYLIST_RUNNING; vlc_object_signal_unlocked( p_playlist ); } /* Preparse if PREPARSE or SPREPARSE & not enough meta */ char *psz_artist = input_item_GetArtist( p_item_cat->p_input ); char *psz_album = input_item_GetAlbum( p_item_cat->p_input ); if( p_playlist->b_auto_preparse && (i_mode & PLAYLIST_PREPARSE || ( i_mode & PLAYLIST_SPREPARSE && ( EMPTY_STR( psz_artist ) || ( EMPTY_STR( psz_album ) ) ) ) ) ) playlist_PreparseEnqueue( p_playlist, p_item_cat->p_input ); /* If we already have it, signal it */ else if( !EMPTY_STR( psz_artist ) && !EMPTY_STR( psz_album ) ) input_item_SetPreparsed( p_item_cat->p_input, true ); free( psz_artist ); free( psz_album );}/* Add the playlist item to the requested node and fire a notification */static void AddItem( playlist_t *p_playlist, playlist_item_t *p_item, playlist_item_t *p_node, int i_mode, int i_pos ){ PL_ASSERT_LOCKED; ARRAY_APPEND(p_playlist->items, p_item); ARRAY_APPEND(p_playlist->all_items, p_item); if( i_pos == PLAYLIST_END ) playlist_NodeAppend( p_playlist, p_item, p_node ); else playlist_NodeInsert( p_playlist, p_item, p_node, i_pos ); if( !p_playlist->b_doing_ml ) playlist_SendAddNotify( p_playlist, p_item->i_id, p_node->i_id, !( i_mode & PLAYLIST_NO_REBUILD ) );}/* Actually convert an item to a node */static void ChangeToNode( playlist_t *p_playlist, playlist_item_t *p_item ){ int i; if( p_item->i_children == -1 ) p_item->i_children = 0; /* Remove it from the array of available items */ ARRAY_BSEARCH( p_playlist->items,->i_id, int, p_item->i_id, i ); if( i != -1 ) ARRAY_REMOVE( p_playlist->items, i );}/* Do the actual removal */static int DeleteInner( playlist_t * p_playlist, playlist_item_t *p_item, bool b_stop ){ int i; int i_id = p_item->i_id; PL_ASSERT_LOCKED; if( p_item->i_children > -1 ) { return playlist_NodeDelete( p_playlist, p_item, true, false ); } p_playlist->b_reset_currently_playing = true; var_SetInteger( p_playlist, "item-deleted", i_id ); /* Remove the item from the bank */ ARRAY_BSEARCH( p_playlist->all_items,->i_id, int, i_id, i ); if( i != -1 ) ARRAY_REMOVE( p_playlist->all_items, i ); ARRAY_BSEARCH( p_playlist->items,->i_id, int, i_id, i ); if( i != -1 ) ARRAY_REMOVE( p_playlist->items, i ); /* Check if it is the current item */ if( get_current_status_item( p_playlist ) == p_item ) { /* Hack we don't call playlist_Control for lock reasons */ if( b_stop ) { p_playlist->request.i_status = PLAYLIST_STOPPED; p_playlist->request.b_request = true; p_playlist->request.p_item = NULL; msg_Info( p_playlist, "stopping playback" ); vlc_object_signal_unlocked( VLC_OBJECT(p_playlist) ); } } PL_DEBUG( "deleting item `%s'", p_item->p_input->psz_name ); /* Remove the item from its parent */ playlist_NodeRemoveItem( p_playlist, p_item, p_item->p_parent ); playlist_ItemRelease( p_item ); return VLC_SUCCESS;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -