📄 playlist.c
字号:
/***************************************************************************** * playlist.c : Playlist management functions ***************************************************************************** * Copyright (C) 1999-2004 VideoLAN * $Id: playlist.c 11476 2005-06-20 18:58:27Z zorglub $ * * Authors: Samuel Hocevar <sam@zoy.org> * 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/vout.h>#include <vlc/sout.h>#include <vlc/input.h>#include "vlc_playlist.h"#define TITLE_CATEGORY N_( "By category" )#define TITLE_SIMPLE N_( "Manually added" )#define TITLE_ALL N_( "All items, unsorted" )#undef PLAYLIST_PROFILE#undef PLAYLIST_DEBUG/***************************************************************************** * Local prototypes *****************************************************************************/static void RunThread ( playlist_t * );static void RunPreparse( playlist_preparse_t * );static playlist_item_t * NextItem ( playlist_t * );static int PlayItem ( playlist_t *, playlist_item_t * );static int ItemChange( vlc_object_t *, const char *, vlc_value_t, vlc_value_t, void * );int playlist_vaControl( playlist_t * p_playlist, int i_query, va_list args );/** * Create playlist * * Create a playlist structure. * \param p_parent the vlc object that is to be the parent of this playlist * \return a pointer to the created playlist, or NULL on error */playlist_t * __playlist_Create ( vlc_object_t *p_parent ){ playlist_t *p_playlist; playlist_view_t *p_view; vlc_value_t val; /* Allocate structure */ p_playlist = vlc_object_create( p_parent, VLC_OBJECT_PLAYLIST ); if( !p_playlist ) { msg_Err( p_parent, "out of memory" ); return NULL; } /* These variables control updates */ var_Create( p_playlist, "intf-change", VLC_VAR_BOOL ); val.b_bool = VLC_TRUE; var_Set( p_playlist, "intf-change", val ); var_Create( p_playlist, "item-change", VLC_VAR_INTEGER ); val.i_int = -1; var_Set( p_playlist, "item-change", val ); var_Create( p_playlist, "item-deleted", VLC_VAR_INTEGER ); val.i_int = -1; var_Set( p_playlist, "item-deleted", val ); var_Create( p_playlist, "item-append", VLC_VAR_ADDRESS ); var_Create( p_playlist, "playlist-current", VLC_VAR_INTEGER ); val.i_int = -1; var_Set( p_playlist, "playlist-current", val ); var_Create( p_playlist, "intf-popupmenu", VLC_VAR_BOOL ); var_Create( p_playlist, "intf-show", VLC_VAR_BOOL ); val.b_bool = VLC_TRUE; var_Set( p_playlist, "intf-show", val ); /* Variables to control playback */ var_CreateGetBool( p_playlist, "play-and-stop" ); var_CreateGetBool( p_playlist, "random" ); var_CreateGetBool( p_playlist, "repeat" ); var_CreateGetBool( p_playlist, "loop" ); /* Initialise data structures */ vlc_mutex_init( p_playlist, &p_playlist->gc_lock ); p_playlist->i_last_id = 0; p_playlist->b_go_next = VLC_TRUE; p_playlist->p_input = NULL; p_playlist->request_date = 0; p_playlist->i_views = 0; p_playlist->pp_views = NULL; p_playlist->i_index = -1; p_playlist->i_size = 0; p_playlist->pp_items = NULL; p_playlist->i_all_size = 0; p_playlist->pp_all_items = 0; playlist_ViewInsert( p_playlist, VIEW_CATEGORY, TITLE_CATEGORY ); playlist_ViewInsert( p_playlist, VIEW_ALL, TITLE_ALL ); p_view = playlist_ViewFind( p_playlist, VIEW_CATEGORY ); p_playlist->p_general = playlist_NodeCreate( p_playlist, VIEW_CATEGORY, _( "General" ), p_view->p_root ); p_playlist->p_general->i_flags |= PLAYLIST_RO_FLAG; /* Set startup status * We set to simple view on startup for interfaces that don't do * anything */ p_view = playlist_ViewFind( p_playlist, VIEW_CATEGORY ); p_playlist->status.i_view = VIEW_CATEGORY; p_playlist->status.p_item = NULL; p_playlist->status.p_node = p_view->p_root; p_playlist->request.b_request = VLC_FALSE; p_playlist->status.i_status = PLAYLIST_STOPPED; p_playlist->i_sort = SORT_ID; p_playlist->i_order = ORDER_NORMAL; /* Finally, launch the thread ! */ if( vlc_thread_create( p_playlist, "playlist", RunThread, VLC_THREAD_PRIORITY_LOW, VLC_TRUE ) ) { msg_Err( p_playlist, "cannot spawn playlist thread" ); vlc_object_destroy( p_playlist ); return NULL; } /* Preparsing stuff */ p_playlist->p_preparse = vlc_object_create( p_playlist, sizeof( playlist_preparse_t ) ); if( !p_playlist->p_preparse ) { msg_Err( p_playlist, "unable to create preparser" ); vlc_object_destroy( p_playlist ); return NULL; } p_playlist->p_preparse->i_waiting = 0; p_playlist->p_preparse->pp_waiting = NULL; vlc_object_attach( p_playlist->p_preparse, p_playlist ); if( vlc_thread_create( p_playlist->p_preparse, "preparser", RunPreparse, VLC_THREAD_PRIORITY_LOW, VLC_TRUE ) ) { msg_Err( p_playlist, "cannot spawn preparse thread" ); vlc_object_detach( p_playlist->p_preparse ); vlc_object_destroy( p_playlist->p_preparse ); return NULL; } /* The object has been initialized, now attach it */ vlc_object_attach( p_playlist, p_parent ); return p_playlist;}/** * Destroy the playlist. * * Delete all items in the playlist and free the playlist structure. * \param p_playlist the playlist structure to destroy * \return VLC_SUCCESS or an error */int playlist_Destroy( playlist_t * p_playlist ){ int i; p_playlist->b_die = 1; while( p_playlist->i_sds ) { playlist_ServicesDiscoveryRemove( p_playlist, p_playlist->pp_sds[0]->psz_module ); } vlc_thread_join( p_playlist->p_preparse ); vlc_thread_join( p_playlist ); vlc_object_detach( p_playlist->p_preparse ); var_Destroy( p_playlist, "intf-change" ); var_Destroy( p_playlist, "item-change" ); var_Destroy( p_playlist, "playlist-current" ); var_Destroy( p_playlist, "intf-popmenu" ); var_Destroy( p_playlist, "intf-show" ); var_Destroy( p_playlist, "play-and-stop" ); var_Destroy( p_playlist, "random" ); var_Destroy( p_playlist, "repeat" ); var_Destroy( p_playlist, "loop" ); playlist_Clear( p_playlist ); for( i = p_playlist->i_views - 1; i >= 0 ; i-- ) { playlist_view_t *p_view = p_playlist->pp_views[i]; if( p_view->psz_name ) free( p_view->psz_name ); playlist_ItemDelete( p_view->p_root ); REMOVE_ELEM( p_playlist->pp_views, p_playlist->i_views, i ); free( p_view ); } vlc_mutex_destroy( &p_playlist->gc_lock ); vlc_object_destroy( p_playlist->p_preparse ); vlc_object_destroy( p_playlist ); return VLC_SUCCESS;}/** * Do a playlist action. * * If there is something in the playlist then you can do playlist actions. * * Playlist lock must not be taken when calling this function * * \param p_playlist the playlist to do the command on * \param i_query the command to do * \param variable number of arguments * \return VLC_SUCCESS or an error */int playlist_LockControl( playlist_t * p_playlist, int i_query, ... ){ va_list args; int i_result; va_start( args, i_query ); vlc_mutex_lock( &p_playlist->object_lock ); i_result = playlist_vaControl( p_playlist, i_query, args ); va_end( args ); vlc_mutex_unlock( &p_playlist->object_lock ); return i_result;}/** * Do a playlist action. * * If there is something in the playlist then you can do playlist actions. * * Playlist lock must be taken when calling this function * * \param p_playlist the playlist to do the command on * \param i_query the command to do * \param variable number of arguments * \return VLC_SUCCESS or an error */int playlist_Control( playlist_t * p_playlist, int i_query, ... ){ va_list args; int i_result; va_start( args, i_query ); i_result = playlist_vaControl( p_playlist, i_query, args ); va_end( args ); return i_result;}int playlist_vaControl( playlist_t * p_playlist, int i_query, va_list args ){ playlist_view_t *p_view; playlist_item_t *p_item, *p_node; int i_view; vlc_value_t val;#ifdef PLAYLIST_PROFILE p_playlist->request_date = mdate();#endif if( p_playlist->i_size <= 0 ) { return VLC_EGENERIC; } switch( i_query ) { case PLAYLIST_STOP: p_playlist->status.i_status = PLAYLIST_STOPPED; p_playlist->request.b_request = VLC_TRUE; break; case PLAYLIST_ITEMPLAY: p_item = (playlist_item_t *)va_arg( args, playlist_item_t * ); if ( p_item == NULL || p_item->input.psz_uri == NULL ) return VLC_EGENERIC; p_playlist->status.i_status = PLAYLIST_RUNNING; p_playlist->request.i_skip = 0; p_playlist->request.b_request = VLC_TRUE; p_playlist->request.p_item = p_item; p_playlist->request.i_view = p_playlist->status.i_view; p_view = playlist_ViewFind( p_playlist, p_playlist->status.i_view ); if( p_view ) { p_playlist->request.p_node = p_view->p_root; } else { p_playlist->request.p_node = NULL; } break; case PLAYLIST_VIEWPLAY: i_view = (int)va_arg( args,int ); p_node = (playlist_item_t *)va_arg( args, playlist_item_t * ); p_item = (playlist_item_t *)va_arg( args, playlist_item_t * ); if ( p_node == NULL || (p_item != NULL && p_item->input.psz_uri == NULL )) { p_playlist->status.i_status = PLAYLIST_STOPPED; p_playlist->request.b_request = VLC_TRUE; return VLC_SUCCESS; } p_playlist->status.i_status = PLAYLIST_RUNNING; p_playlist->request.i_skip = 0; p_playlist->request.b_request = VLC_TRUE; p_playlist->request.i_view = i_view; p_playlist->request.p_node = p_node; p_playlist->request.p_item = p_item; /* If we select a node, play only it. * If we select an item, continue */ if( p_playlist->request.p_item == NULL || ! p_playlist->request.p_node->i_flags & PLAYLIST_SKIP_FLAG ) { p_playlist->b_go_next = VLC_FALSE; } else { p_playlist->b_go_next = VLC_TRUE; } break; case PLAYLIST_PLAY: p_playlist->status.i_status = PLAYLIST_RUNNING; if( p_playlist->p_input ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -