📄 view.c
字号:
/***************************************************************************** * view.c : Playlist views functions ***************************************************************************** * Copyright (C) 1999-2004 VideoLAN * $Id: item.c 7997 2004-06-18 11:35:45Z sigmunau $ * * Authors: Cl閙ent 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA. *****************************************************************************/#include <stdlib.h> /* free(), strtol() */#include <stdio.h> /* sprintf() */#include <string.h> /* strerror() */#include <vlc/vlc.h>#include <vlc/input.h>#include "vlc_playlist.h"#undef PLAYLIST_DEBUG/************************************************************************ * Local prototypes ************************************************************************//* TODO: inline */playlist_item_t *playlist_FindDirectParent( playlist_t *p_playlist, playlist_item_t *, int );playlist_item_t *playlist_RecursiveFindNext( playlist_t *p_playlist, int i_view, playlist_item_t *p_root, playlist_item_t *p_item, playlist_item_t *p_parent );playlist_item_t *playlist_RecursiveFindPrev( playlist_t *p_playlist, int i_view, playlist_item_t *p_root, playlist_item_t *p_item, playlist_item_t *p_parent );void playlist_NodeDump( playlist_t *p_playlist, playlist_item_t *p_item, int i_level );/********************************************************************** * Exported View management functions **********************************************************************//** * Create a new view * * \param p_playlist a playlist object * \param i_id the view identifier * \return the new view or NULL on failure */playlist_view_t * playlist_ViewCreate( playlist_t *p_playlist, int i_id, char *psz_name ){ playlist_view_t * p_view; p_view = malloc( sizeof( playlist_view_t ) ); memset( p_view, 0, sizeof( playlist_view_t ) ); p_view->p_root = playlist_NodeCreate( p_playlist, i_id, NULL, NULL ); p_view->i_id = i_id; p_view->psz_name = psz_name ? strdup( psz_name ) : strdup(_("Undefined") ); return p_view;}/** * Creates a new view and add it to the list * * This function must be entered without the playlist lock * * \param p_playlist a playlist object * \param i_id the view identifier * \return VLC_SUCCESS or an error */int playlist_ViewInsert( playlist_t *p_playlist, int i_id, char *psz_name ){ playlist_view_t *p_view = playlist_ViewCreate( p_playlist, i_id , psz_name ); if( !p_view ) { msg_Err( p_playlist, "Creation failed" ); return VLC_EGENERIC; } vlc_mutex_lock( &p_playlist->object_lock ); INSERT_ELEM( p_playlist->pp_views, p_playlist->i_views, p_playlist->i_views, p_view ); vlc_mutex_unlock( &p_playlist->object_lock ); return VLC_SUCCESS;}/** * Deletes a view * * This function must be entered wit the playlist lock * * \param p_view the view to delete * \return nothing */int playlist_ViewDelete( playlist_t *p_playlist,playlist_view_t *p_view ){ playlist_NodeDelete( p_playlist, p_view->p_root, VLC_TRUE, VLC_TRUE ); REMOVE_ELEM( p_playlist->pp_views, p_playlist->i_views, 0 ); return VLC_SUCCESS;}/** * Dumps the content of a view * * \param p_playlist the playlist * \param p_view the view to dump * \return nothing */int playlist_ViewDump( playlist_t *p_playlist, playlist_view_t *p_view ){#ifdef PLAYLIST_DEBUG msg_Dbg( p_playlist, "dumping view %i",p_view->i_id ); playlist_NodeDump( p_playlist,p_view->p_root, 1 );#endif return VLC_SUCCESS;}/** * Counts the items of a view * * \param p_playlist the playlist * \param p_view the view to count * \return the number of items */int playlist_ViewItemCount( playlist_t *p_playlist, playlist_view_t *p_view ){ return playlist_NodeChildrenCount( p_playlist, p_view->p_root );}/** * Updates a view. Only make sense for "sorted" and "ALL" views * * \param p_playlist the playlist * \param i_view the view to update * \return nothing */int playlist_ViewUpdate( playlist_t *p_playlist, int i_view){ playlist_view_t *p_view = playlist_ViewFind( p_playlist, i_view ); if( p_view == NULL ) { return VLC_EGENERIC; } if( i_view == VIEW_ALL ) { p_view->p_root->i_children = p_playlist->i_size; p_view->p_root->pp_children = p_playlist->pp_items; } /* Handle update of sorted views here */ if( i_view >= VIEW_FIRST_SORTED ) { int i_sort_type; playlist_ViewEmpty( p_playlist, i_view, VLC_FALSE ); switch( i_view ) { case VIEW_S_AUTHOR: i_sort_type = SORT_AUTHOR;break; case VIEW_S_GENRE: i_sort_type = SORT_GENRE;break; default: i_sort_type = SORT_AUTHOR; } playlist_NodeGroup( p_playlist, i_view, p_view->p_root, p_playlist->pp_items,p_playlist->i_size, i_sort_type, ORDER_NORMAL ); } return VLC_SUCCESS;}/** * Find a view * * \param p_playlist the playlist * \param i_id the id to find * \return the found view or NULL if not found */playlist_view_t *playlist_ViewFind( playlist_t *p_playlist, int i_id ){ int i; for( i=0 ; i< p_playlist->i_views ; i++ ) { if( p_playlist->pp_views[i]->i_id == i_id ) { return p_playlist->pp_views[i]; } } return NULL;}int playlist_ViewEmpty( playlist_t *p_playlist, int i_view, vlc_bool_t b_delete_items ){ playlist_view_t *p_view = playlist_ViewFind( p_playlist, i_view ); if( p_view == NULL ) { return VLC_EGENERIC; } return playlist_NodeEmpty( p_playlist, p_view->p_root, b_delete_items );}/********************************************************************** * Exported Nodes management functions **********************************************************************//** * Create a playlist node * * \param p_playlist the playlist * \paam psz_name the name of the node * \param p_parent the parent node to attach to or NULL if no attach * \return the new node */playlist_item_t * playlist_NodeCreate( playlist_t *p_playlist, int i_view, char *psz_name, playlist_item_t *p_parent ){ /* Create the item */ playlist_item_t *p_item = (playlist_item_t *)malloc( sizeof( playlist_item_t ) ); vlc_value_t val; playlist_add_t *p_add; if( p_item == NULL ) { return NULL; } p_add = (playlist_add_t*)malloc( sizeof(playlist_add_t) ); if( p_add == NULL ) { free( p_item ); return NULL; } vlc_input_item_Init( VLC_OBJECT(p_playlist), &p_item->input ); if( psz_name != NULL ) { p_item->input.psz_name = strdup( psz_name ); } else { p_item->input.psz_name = strdup( _("Undefined") ); } p_item->input.psz_uri = NULL; p_item->b_enabled = VLC_TRUE; p_item->i_nb_played = 0; p_item->i_flags = 0; p_item->i_children = 0; p_item->pp_children = NULL; p_item->input.i_duration = -1; p_item->input.ppsz_options = NULL; p_item->input.i_options = 0; p_item->input.i_categories = 0; p_item->input.pp_categories = NULL; p_item->input.i_id = ++p_playlist->i_last_id; p_item->input.i_type = ITEM_TYPE_NODE; p_item->pp_parents = NULL; p_item->i_parents = 0; p_item->i_flags |= PLAYLIST_SKIP_FLAG; /* Default behaviour */ vlc_mutex_init( p_playlist, &p_item->input.lock ); INSERT_ELEM( p_playlist->pp_all_items, p_playlist->i_all_size, p_playlist->i_all_size, p_item ); if( p_parent != NULL ) { playlist_NodeAppend( p_playlist, i_view, p_item, p_parent ); } p_add->i_node = p_parent ? p_parent->input.i_id : -1; p_add->i_item = p_item->input.i_id; p_add->i_view = i_view; val.p_address = p_add; var_Set( p_playlist, "item-append", val); free( p_add ); return p_item;}/** * Remove all the children of a node * * This function must be entered with the playlist lock * * \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_NodeEmpty( playlist_t *p_playlist, playlist_item_t *p_root, vlc_bool_t b_delete_items ){ 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 , VLC_FALSE ); } else if( b_delete_items ) { /* Delete the item here */ playlist_Delete( p_playlist, p_root->pp_children[i]->input.i_id ); } } return VLC_SUCCESS;}/** * 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, vlc_bool_t b_delete_items, vlc_bool_t b_force ){ int i, i_top, i_bottom; 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 ) { /* Delete the item here */ playlist_Delete( p_playlist, p_root->pp_children[i]->input.i_id ); } } /* Delete the node */ if( p_root->i_flags & PLAYLIST_RO_FLAG && !b_force ) { } else { for( i = 0 ; i< p_root->i_parents; i++ ) { playlist_NodeRemoveItem( p_playlist, p_root, p_root->pp_parents[i]->p_parent ); } var_SetInteger( p_playlist, "item-deleted", p_root->input.i_id ); i_bottom = 0; i_top = p_playlist->i_all_size - 1; i = i_top / 2; while( p_playlist->pp_all_items[i]->input.i_id != p_root->input.i_id && i_top > i_bottom ) { if( p_playlist->pp_all_items[i]->input.i_id < p_root->input.i_id ) { i_bottom = i + 1; } else { i_top = i - 1; } i = i_bottom + ( i_top - i_bottom ) / 2; } if( p_playlist->pp_all_items[i]->input.i_id == p_root->input.i_id ) { REMOVE_ELEM( p_playlist->pp_all_items, p_playlist->i_all_size, i ); } playlist_ItemDelete( p_root ); } return VLC_SUCCESS;}/** * Adds an item to the childs of a node * * \param p_playlist the playlist * \param i_view the view of the node ( needed for parent search ) * \param p_item the item to append * \param p_parent the parent node * \return VLC_SUCCESS or an error */int playlist_NodeAppend( playlist_t *p_playlist, int i_view, playlist_item_t *p_item, playlist_item_t *p_parent ){ return playlist_NodeInsert( p_playlist, i_view, p_item, p_parent, -1 );}int playlist_NodeInsert( playlist_t *p_playlist, int i_view, playlist_item_t *p_item, playlist_item_t *p_parent, int i_position ){ int i; vlc_bool_t b_found = VLC_FALSE; if( !p_parent || p_parent->i_children == -1 ) { msg_Err( p_playlist, "invalid node" ); return VLC_EGENERIC; } if( i_position == -1 ) i_position = p_parent->i_children ; INSERT_ELEM( p_parent->pp_children, p_parent->i_children, i_position, p_item ); /* Add the parent to the array */ for( i= 0; i< p_item->i_parents ; i++ ) { if( p_item->pp_parents[i]->i_view == i_view ) { b_found = VLC_TRUE; break; } } if( b_found == VLC_FALSE ) { struct item_parent_t *p_ip = (struct item_parent_t *) malloc(sizeof(struct item_parent_t) ); p_ip->i_view = i_view; p_ip->p_parent = p_parent; INSERT_ELEM( p_item->pp_parents, p_item->i_parents, p_item->i_parents, p_ip ); } /* Let the interface know this has been updated */ p_parent->i_serial++; return VLC_SUCCESS;}/** * Deletes an item from the children of a node * * \param p_playlist the playlist * \param p_item the item to remove * \param p_parent the parent node * \return VLC_SUCCESS or an error */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -