📄 item.c
字号:
/***************************************************************************** * item.c : Playlist item creation/deletion/add/removal functions ***************************************************************************** * Copyright (C) 1999-2007 the VideoLAN team * $Id$ * * Authors: Samuel Hocevar <sam@zoy.org> * 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. *****************************************************************************/#ifdef HAVE_CONFIG_H# include "config.h"#endif#include <vlc_common.h>#include <assert.h>#include <vlc_playlist.h>#include "playlist_internal.h"static void AddItem( playlist_t *p_playlist, playlist_item_t *p_item, playlist_item_t *p_node, int i_mode, int i_pos );static void GoAndPreparse( playlist_t *p_playlist, int i_mode, playlist_item_t *, playlist_item_t * );static void ChangeToNode( playlist_t *p_playlist, playlist_item_t *p_item );static int DeleteInner( playlist_t * p_playlist, playlist_item_t *p_item, bool b_stop );/***************************************************************************** * An input item has gained a subitem (Event Callback) *****************************************************************************/static void input_item_subitem_added( const vlc_event_t * p_event, void * user_data ){ playlist_item_t *p_parent_playlist_item = user_data; playlist_t * p_playlist = p_parent_playlist_item->p_playlist; input_item_t * p_parent, * p_child; playlist_item_t * p_child_in_category; playlist_item_t * p_item_in_category; bool b_play; p_parent = p_event->p_obj; p_child = p_event->u.input_item_subitem_added.p_new_child; PL_LOCK; b_play = var_CreateGetBool( p_playlist, "playlist-autostart" ); /* This part is really hakish, but this playlist system isn't simple */ /* First check if we haven't already added the item as we are * listening using the onelevel and the category representent * (Because of the playlist design) */ p_child_in_category = playlist_ItemFindFromInputAndRoot( p_playlist, p_child->i_id, p_playlist->p_root_category, false /* Only non-node */ ); if( !p_child_in_category ) { /* Then, transform to a node if needed */ p_item_in_category = playlist_ItemFindFromInputAndRoot( p_playlist, p_parent->i_id, p_playlist->p_root_category, false /* Only non-node */ ); if( !p_item_in_category ) { /* Item may have been removed */ PL_UNLOCK; return; } b_play = b_play && p_item_in_category == get_current_status_item( p_playlist ); /* If this item is already a node don't transform it */ if( p_item_in_category->i_children == -1 ) { p_item_in_category = playlist_ItemToNode( p_playlist, p_item_in_category, pl_Locked ); p_item_in_category->p_input->i_type = ITEM_TYPE_PLAYLIST; } int i_ret = playlist_BothAddInput( p_playlist, p_child, p_item_in_category, PLAYLIST_APPEND | PLAYLIST_SPREPARSE , PLAYLIST_END, NULL, NULL, pl_Locked ); if( i_ret == VLC_SUCCESS && b_play ) { playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, pl_Locked, p_item_in_category, NULL ); } } PL_UNLOCK;}/***************************************************************************** * An input item's meta or duration has changed (Event Callback) *****************************************************************************/static void input_item_changed( const vlc_event_t * p_event, void * user_data ){ (void)p_event; playlist_item_t * p_item = user_data; var_SetInteger( p_item->p_playlist, "item-change", p_item->i_id );}/***************************************************************************** * Listen to vlc_InputItemAddSubItem event *****************************************************************************/static void install_input_item_observer( playlist_item_t * p_item ){ vlc_event_manager_t * p_em = &p_item->p_input->event_manager; vlc_event_attach( p_em, vlc_InputItemSubItemAdded, input_item_subitem_added, p_item ); vlc_event_attach( p_em, vlc_InputItemDurationChanged, input_item_changed, p_item ); vlc_event_attach( p_em, vlc_InputItemMetaChanged, input_item_changed, p_item ); vlc_event_attach( p_em, vlc_InputItemNameChanged, input_item_changed, p_item ); vlc_event_attach( p_em, vlc_InputItemInfoChanged, input_item_changed, p_item ); vlc_event_attach( p_em, vlc_InputItemErrorWhenReadingChanged, input_item_changed, p_item );}static void uninstall_input_item_observer( playlist_item_t * p_item ){ vlc_event_manager_t * p_em = &p_item->p_input->event_manager; vlc_event_detach( p_em, vlc_InputItemSubItemAdded, input_item_subitem_added, p_item ); vlc_event_detach( p_em, vlc_InputItemMetaChanged, input_item_changed, p_item ); vlc_event_detach( p_em, vlc_InputItemDurationChanged, input_item_changed, p_item ); vlc_event_detach( p_em, vlc_InputItemNameChanged, input_item_changed, p_item ); vlc_event_detach( p_em, vlc_InputItemInfoChanged, input_item_changed, p_item ); vlc_event_detach( p_em, vlc_InputItemErrorWhenReadingChanged, input_item_changed, p_item );}/***************************************************************************** * Playlist item creation *****************************************************************************/playlist_item_t *playlist_ItemNewFromInput( playlist_t *p_playlist, input_item_t *p_input ){ DECMALLOC_NULL( p_item, playlist_item_t ); assert( p_input ); p_item->p_input = p_input; vlc_gc_incref( p_item->p_input ); p_item->i_id = ++p_playlist->i_last_playlist_id; p_item->p_parent = NULL; p_item->i_children = -1; p_item->pp_children = NULL; p_item->i_flags = 0; p_item->p_playlist = p_playlist; install_input_item_observer( p_item ); return p_item;}playlist_item_t * playlist_ItemNewWithType( playlist_t *p_playlist, const char *psz_uri, const char *psz_name, int i_options, const char *const *ppsz_options, int i_duration, int i_type ){ input_item_t *p_input; if( psz_uri == NULL ) return NULL; p_input = input_item_NewWithType( VLC_OBJECT(p_playlist), psz_uri, psz_name, i_options, ppsz_options, i_duration, i_type ); return playlist_ItemNewFromInput( p_playlist, p_input );}/*************************************************************************** * Playlist item destruction ***************************************************************************//** * Release an item * * \param p_item item to delete * \return VLC_SUCCESS*/int playlist_ItemRelease( playlist_item_t *p_item ){ /* For the assert */ playlist_t *p_playlist = p_item->p_playlist; PL_ASSERT_LOCKED; /* Surprise, we can't actually do more because we * don't do refcounting, or eauivalent. * Because item are not only accessed by their id * using playlist_item outside the PL_LOCK isn't safe. * Most of the modules does that. * * Who wants to add proper memory management? */ uninstall_input_item_observer( p_item ); ARRAY_APPEND( p_item->p_playlist->items_to_delete, p_item); return VLC_SUCCESS;}/** * Delete input item * * Remove an input item when it appears from a root playlist item * \param p_playlist playlist object * \param i_input_id id of 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, int i_input_id, playlist_item_t *p_root, bool b_do_stop ){ int i; PL_ASSERT_LOCKED; for( i = 0 ; i< p_root->i_children ; i++ ) { if( p_root->pp_children[i]->i_children == -1 && p_root->pp_children[i]->p_input->i_id == i_input_id ) { DeleteInner( p_playlist, p_root->pp_children[i], b_do_stop ); return VLC_SUCCESS; } else if( p_root->pp_children[i]->i_children >= 0 ) { 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;}/** * Delete input item * * Remove an input item when it appears from a root playlist item * \param p_playlist playlist object * \param i_input_id id of the input to delete * \param p_root root playlist item * \param b_locked TRUE if the playlist is locked * \return VLC_SUCCESS or VLC_EGENERIC */int playlist_DeleteFromInputInParent( playlist_t *p_playlist, int i_input_id, playlist_item_t *p_root, bool b_locked ){ int i_ret; PL_LOCK_IF( !b_locked ); i_ret = DeleteFromInput( p_playlist, i_input_id, p_root, true ); PL_UNLOCK_IF( !b_locked ); return i_ret;}/** * Delete from input * * Remove an input item from ONELEVEL and CATEGORY * \param p_playlist playlist object * \param i_input_id id of the input to delete * \param b_locked TRUE if the playlist is locked * \return VLC_SUCCESS or VLC_ENOITEM */int playlist_DeleteFromInput( playlist_t *p_playlist, int i_input_id, bool b_locked ){ int i_ret1, i_ret2; PL_LOCK_IF( !b_locked ); i_ret1 = DeleteFromInput( p_playlist, i_input_id, p_playlist->p_root_category, true ); i_ret2 = DeleteFromInput( p_playlist, i_input_id, p_playlist->p_root_onelevel, true ); PL_UNLOCK_IF( !b_locked ); return ( i_ret1 == VLC_SUCCESS || i_ret2 == VLC_SUCCESS ) ? VLC_SUCCESS : VLC_ENOITEM;}/** * Clear the playlist * * \param p_playlist playlist object * \param b_locked TRUE if the playlist is locked * \return nothing */void playlist_Clear( playlist_t * p_playlist, bool b_locked ){ PL_LOCK_IF( !b_locked ); playlist_NodeEmpty( p_playlist, p_playlist->p_local_category, true ); playlist_NodeEmpty( p_playlist, p_playlist->p_local_onelevel, true ); PL_UNLOCK_IF( !b_locked );}/**
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -