From: Clément Stenac Date: Sun, 14 May 2006 18:29:00 +0000 (+0000) Subject: Merge back branch 0.8.6-playlist-vlm to trunk. X-Git-Tag: 0.9.0-test0~11247 X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=ed0b72e3714ad87cb4e10b9a7239e19b9ef0724e;p=vlc Merge back branch 0.8.6-playlist-vlm to trunk. What is currently broken: * Some playlist demuxers (shout, dvb and pls) * DAAP * BeOS playlist * GPE playlist, I suppose What has some trouble: * Meta handling in several demuxers (most notably TS) * Skins2 playlist (doesn't refresh correctly) * OS X playlist (see bigben's latest commits) --- diff --git a/configure.ac b/configure.ac index abbc0c5de3..5086009ddb 100644 --- a/configure.ac +++ b/configure.ac @@ -1121,7 +1121,7 @@ VLC_ADD_PLUGINS([deinterlace invert adjust transform distort motionblur rv32]) VLC_ADD_PLUGINS([fixed32tos16 s16tofixed32 u8tofixed32]) VLC_ADD_PLUGINS([trivial_resampler ugly_resampler]) VLC_ADD_PLUGINS([trivial_channel_mixer trivial_mixer]) -VLC_ADD_PLUGINS([playlist export sgimb m3u nsc xtag]) +VLC_ADD_PLUGINS([playlist export sgimb nsc xtag]) VLC_ADD_PLUGINS([i420_rgb rawvideo blend scale image logo magnify]) VLC_ADD_PLUGINS([wav araw subtitle vobsub adpcm a52sys dtssys au ty voc xa nuv]) VLC_ADD_PLUGINS([access_directory access_file access_udp access_tcp]) diff --git a/include/vlc/vlc.h b/include/vlc/vlc.h index a6afd1d4b9..f85164b0d6 100644 --- a/include/vlc/vlc.h +++ b/include/vlc/vlc.h @@ -138,11 +138,9 @@ struct vlc_list_t /* Used by VLC_AddTarget() */ #define PLAYLIST_INSERT 0x0001 -#define PLAYLIST_REPLACE 0x0002 -#define PLAYLIST_APPEND 0x0004 -#define PLAYLIST_GO 0x0008 -#define PLAYLIST_CHECK_INSERT 0x0010 -#define PLAYLIST_PREPARSE 0x0020 +#define PLAYLIST_APPEND 0x0002 +#define PLAYLIST_GO 0x0004 +#define PLAYLIST_PREPARSE 0x0008 #define PLAYLIST_END -666 diff --git a/include/vlc_common.h b/include/vlc_common.h index 75bafe91ae..7c8dbb259d 100644 --- a/include/vlc_common.h +++ b/include/vlc_common.h @@ -24,6 +24,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ + /** * \file * This file is a collection of common definitions and types @@ -203,6 +204,7 @@ typedef struct vlc_t vlc_t; typedef struct variable_t variable_t; typedef struct date_t date_t; typedef struct hashtable_entry_t hashtable_entry_t; +typedef struct gc_object_t gc_object_t ; /* Messages */ typedef struct msg_bank_t msg_bank_t; @@ -525,6 +527,44 @@ typedef int ( * vlc_callback_t ) ( vlc_object_t *, /* variable's object */ #define VLC_OBJECT( x ) \ ((vlc_object_t *)(x))+0*(x)->be_sure_to_add_VLC_COMMON_MEMBERS_to_struct +#define VLC_GC_MEMBERS \ +/** \name VLC_GC_MEMBERS \ + * these members are common to all objects that wish to be garbage-collected \ + */ \ +/**@{*/ \ + int i_gc_refcount; \ + void (*pf_destructor) ( gc_object_t * ); \ + void *p_destructor_arg; \ +/**@}*/ + +struct gc_object_t +{ + VLC_GC_MEMBERS +}; + +static inline void __vlc_gc_incref( gc_object_t * p_gc ) +{ + p_gc->i_gc_refcount ++; +}; + +static inline void __vlc_gc_decref( gc_object_t *p_gc ) +{ + p_gc->i_gc_refcount -- ; + + if( p_gc->i_gc_refcount == 0 ) + { + p_gc->pf_destructor( p_gc ); + /* Do not use the p_gc pointer from now on ! */ + } +} + +#define vlc_gc_incref( a ) __vlc_gc_incref( (gc_object_t *)a ) +#define vlc_gc_decref( a ) __vlc_gc_decref( (gc_object_t *)a ) +#define vlc_gc_init( a,b,c ) { ((gc_object_t *)a)->i_gc_refcount = 0; \ + ((gc_object_t *)a)->pf_destructor = b; \ + ((gc_object_t *)a)->p_destructor_arg = c; } + + /***************************************************************************** * Macros and inline functions *****************************************************************************/ diff --git a/include/vlc_config.h b/include/vlc_config.h index 966b1517bd..5c17718f3b 100644 --- a/include/vlc_config.h +++ b/include/vlc_config.h @@ -72,6 +72,10 @@ * Input thread configuration *****************************************************************************/ +#define DEFAULT_INPUT_ACTIVITY 1 +#define DIRECTORY_ACTIVITY 100 +#define TRANSCODE_ACTIVITY 10 + /* Used in ErrorThread */ #define INPUT_IDLE_SLEEP ((mtime_t)(0.100*CLOCK_FREQ)) diff --git a/include/vlc_input.h b/include/vlc_input.h index fed26101c7..9b9dc6a431 100644 --- a/include/vlc_input.h +++ b/include/vlc_input.h @@ -26,6 +26,11 @@ #ifndef _VLC__INPUT_H #define _VLC__INPUT_H 1 +#include +#include + +struct vlc_meta_t; + /***************************************************************************** * input_item_t: Describes an input and is used to spawn input_thread_t objects *****************************************************************************/ @@ -44,29 +49,32 @@ struct info_category_t struct input_item_t { + VLC_GC_MEMBERS + int i_id; /**< Identifier of the item */ + char *psz_name; /**< text describing this item */ char *psz_uri; /**< mrl of this item */ + vlc_bool_t b_fixed_name; /**< Can the interface change the name ?*/ int i_options; /**< Number of input options */ char **ppsz_options; /**< Array of input options */ - mtime_t i_duration; /**< A hint about the duration of this - * item, in milliseconds*/ + mtime_t i_duration; /**< Duration in milliseconds*/ - int i_id; /**< Identifier of the item */ uint8_t i_type; /**< Type (file, disc, ...) */ int i_categories; /**< Number of info categories */ info_category_t **pp_categories; /**< Pointer to the first info category */ int i_es; /**< Number of es format descriptions */ - es_format_t **es; /**< Pointer to an array of es formats */ - - vlc_bool_t b_fixed_name; /**< Can the interface change the name ?*/ + es_format_t **es; /**< Es formats */ input_stats_t *p_stats; /**< Statistics */ + int i_nb_played; /**< Number of times played */ + + vlc_meta_t *p_meta; - vlc_mutex_t lock; /**< Item cannot be changed without this lock */ + vlc_mutex_t lock; /**< Lock for the item */ }; #define ITEM_TYPE_UNKNOWN 0 @@ -83,18 +91,19 @@ struct input_item_t static inline void vlc_input_item_Init( vlc_object_t *p_o, input_item_t *p_i ) { memset( p_i, 0, sizeof(input_item_t) ); - p_i->i_options = 0; - p_i->i_es = 0; - p_i->i_categories = 0 ; p_i->psz_name = 0; p_i->psz_uri = 0; + p_i->i_es = 0; + p_i->es = 0; + p_i->i_options = 0; p_i->ppsz_options = 0; + p_i->i_categories = 0 ; p_i->pp_categories = 0; - p_i->es = 0; p_i->i_type = ITEM_TYPE_UNKNOWN; p_i->b_fixed_name = VLC_TRUE; p_i->p_stats = (input_stats_t*) malloc( sizeof( input_stats_t ) ); + p_i->p_meta = NULL; vlc_mutex_init( p_o, &p_i->p_stats->lock ); vlc_mutex_init( p_o, &p_i->lock ); @@ -115,6 +124,8 @@ static inline void vlc_input_item_CopyOptions( input_item_t *p_parent, } } +VLC_EXPORT( void, vlc_input_item_AddOption, ( input_item_t *p_input, const char *psz_option ) ); + static inline void vlc_input_item_Clean( input_item_t *p_i ) { if( p_i->psz_name ) free( p_i->psz_name ); @@ -123,6 +134,8 @@ static inline void vlc_input_item_Clean( input_item_t *p_i ) p_i->psz_name = 0; p_i->psz_uri = 0; + if( p_i->p_meta ) vlc_meta_Delete( p_i->p_meta ); + while( p_i->i_options ) { p_i->i_options--; @@ -168,6 +181,14 @@ static inline void vlc_input_item_Clean( input_item_t *p_i ) VLC_EXPORT( char *, vlc_input_item_GetInfo, ( input_item_t *p_i, const char *psz_cat,const char *psz_name ) ); VLC_EXPORT(int, vlc_input_item_AddInfo, ( input_item_t *p_i, const char *psz_cat, const char *psz_name, const char *psz_format, ... ) ); +#define input_ItemNew( a,b,c ) input_ItemNewExt( a, b, c, 0, NULL, -1 ) +#define input_ItemNewExt(a,b,c,d,e,f) __input_ItemNewExt( VLC_OBJECT(a),b,c,d,e,f) +VLC_EXPORT( input_item_t *, __input_ItemNewExt, (vlc_object_t *, const char *, const char*, int, const char **, int) ); +VLC_EXPORT( input_item_t *, input_ItemNewWithType, ( vlc_object_t *, const char *, const char *e, int, const char **, int, int ) ); + +VLC_EXPORT( input_item_t *, input_ItemGetById, (playlist_t *, int ) ); + + /***************************************************************************** * Seek point: (generalisation of chapters) *****************************************************************************/ diff --git a/include/vlc_messages.h b/include/vlc_messages.h index f3b46a075a..578f4cb1ec 100644 --- a/include/vlc_messages.h +++ b/include/vlc_messages.h @@ -301,9 +301,8 @@ static inline int __stats_GetInteger( vlc_object_t *p_obj, int i_id, static inline int __stats_GetFloat( vlc_object_t *p_obj, int i_id, unsigned int i_counter, float *value ) { - int i_ret; vlc_value_t val;val.f_float = 0.0; - i_ret = __stats_Get( p_obj, i_id, i_counter, &val ); + int i_ret = __stats_Get( p_obj, i_id, i_counter, &val ); *value = val.f_float; return i_ret; } diff --git a/include/vlc_meta.h b/include/vlc_meta.h index 5041fbfb92..2b427be97e 100644 --- a/include/vlc_meta.h +++ b/include/vlc_meta.h @@ -42,140 +42,120 @@ #define VLC_META_NOW_PLAYING N_("Now Playing") #define VLC_META_PUBLISHER N_("Publisher") -#define VLC_META_CDDB_ARTIST N_("CDDB Artist") -#define VLC_META_CDDB_CATEGORY N_("CDDB Category") -#define VLC_META_CDDB_DISCID N_("CDDB Disc ID") -#define VLC_META_CDDB_EXT_DATA N_("CDDB Extended Data") -#define VLC_META_CDDB_GENRE N_("CDDB Genre") -#define VLC_META_CDDB_YEAR N_("CDDB Year") -#define VLC_META_CDDB_TITLE N_("CDDB Title") - -#define VLC_META_CDTEXT_ARRANGER N_("CD-Text Arranger") -#define VLC_META_CDTEXT_COMPOSER N_("CD-Text Composer") -#define VLC_META_CDTEXT_DISCID N_("CD-Text Disc ID") -#define VLC_META_CDTEXT_GENRE N_("CD-Text Genre") -#define VLC_META_CDTEXT_MESSAGE N_("CD-Text Message") -#define VLC_META_CDTEXT_SONGWRITER N_("CD-Text Songwriter") -#define VLC_META_CDTEXT_PERFORMER N_("CD-Text Performer") -#define VLC_META_CDTEXT_TITLE N_("CD-Text Title") - -#define VLC_META_ISO_APPLICATION_ID N_("ISO-9660 Application ID") -#define VLC_META_ISO_PREPARER N_("ISO-9660 Preparer") -#define VLC_META_ISO_PUBLISHER N_("ISO-9660 Publisher") -#define VLC_META_ISO_VOLUME N_("ISO-9660 Volume") -#define VLC_META_ISO_VOLUMESET N_("ISO-9660 Volume Set") - #define VLC_META_CODEC_NAME N_("Codec Name") #define VLC_META_CODEC_DESCRIPTION N_("Codec Description") struct vlc_meta_t { - /* meta name/value pairs */ - int i_meta; - char **name; - char **value; - + char *psz_title; + char *psz_author; + char *psz_artist; + char *psz_genre; + char *psz_copyright; + char *psz_album; + char *psz_tracknum; + char *psz_description; + char *psz_rating; + char *psz_date; + char *psz_setting; + char *psz_url; + char *psz_language; + char *psz_nowplaying; + char *psz_publisher; +#if 0 /* track meta information */ int i_track; vlc_meta_t **track; +#endif }; +#define vlc_meta_Set( meta,var,val ) { \ + if( meta->psz_##var ) free( meta->psz_##var ); \ + meta->psz_##var = strdup( val ); } + +#define vlc_meta_SetTitle( meta, b ) vlc_meta_Set( meta, title, b ); +#define vlc_meta_SetArtist( meta, b ) vlc_meta_Set( meta, artist, b ); +#define vlc_meta_SetAuthor( meta, b ) vlc_meta_Set( meta, author, b ); +#define vlc_meta_SetGenre( meta, b ) vlc_meta_Set( meta, genre, b ); +#define vlc_meta_SetCopyright( meta, b ) vlc_meta_Set( meta, copyright, b ); +#define vlc_meta_SetAlbum( meta, b ) vlc_meta_Set( meta, album, b ); +#define vlc_meta_SetTracknum( meta, b ) vlc_meta_Set( meta, tracknum, b ); +#define vlc_meta_SetDescription( meta, b ) vlc_meta_Set( meta, description, b ); +#define vlc_meta_SetRating( meta, b ) vlc_meta_Set( meta, rating, b ); +#define vlc_meta_SetDate( meta, b ) vlc_meta_Set( meta, date, b ); +#define vlc_meta_SetSetting( meta, b ) vlc_meta_Set( meta, setting, b ); +#define vlc_meta_SetURL( meta, b ) vlc_meta_Set( meta, url, b ); +#define vlc_meta_SetLanguage( meta, b ) vlc_meta_Set( meta, language, b ); +#define vlc_meta_SetNowPlaying( meta, b ) vlc_meta_Set( meta, nowplaying, b ); +#define vlc_meta_SetPublisher( meta, b ) vlc_meta_Set( meta, publisher, b ); + static inline vlc_meta_t *vlc_meta_New( void ) { vlc_meta_t *m = (vlc_meta_t*)malloc( sizeof( vlc_meta_t ) ); - - m->i_meta = 0; - m->name = NULL; - m->value = NULL; - - m->i_track= 0; - m->track = NULL; - + if( !m ) return NULL; + m->psz_title = NULL; + m->psz_author = NULL; + m->psz_artist = NULL; + m->psz_genre = NULL; + m->psz_copyright = NULL; + m->psz_album = NULL; + m->psz_tracknum = NULL; + m->psz_description = NULL; + m->psz_rating = NULL; + m->psz_date = NULL; + m->psz_setting = NULL; + m->psz_url = NULL; + m->psz_language = NULL; + m->psz_nowplaying = NULL; + m->psz_publisher = NULL; return m; } static inline void vlc_meta_Delete( vlc_meta_t *m ) { - int i; - for( i = 0; i < m->i_meta; i++ ) - { - free( m->name[i] ); - free( m->value[i] ); - } - if( m->name ) free( m->name ); - if( m->value ) free( m->value ); + free( m->psz_title ); + free( m->psz_author ); + free( m->psz_artist ); + free( m->psz_genre ); + free( m->psz_copyright ); + free( m->psz_album ); + free( m->psz_tracknum ); + free( m->psz_description ); + free( m->psz_rating ); + free( m->psz_date ); + free( m->psz_setting ); + free( m->psz_url ); + free( m->psz_language ); + free( m->psz_nowplaying ); + free( m->psz_publisher ); - for( i = 0; i < m->i_track; i++ ) - { - vlc_meta_Delete( m->track[i] ); - } - if( m->track ) free( m->track ); free( m ); } -static inline void vlc_meta_Add( vlc_meta_t *m, - const char *name, const char *value ) -{ - m->name = (char**)realloc( m->name, sizeof(char*) * ( m->i_meta + 1 ) ); - m->name[m->i_meta] = strdup( name ); - - m->value = (char**)realloc( m->value, sizeof(char*) * ( m->i_meta + 1 ) ); - m->value[m->i_meta] = strdup( value ); - - m->i_meta++; -} - -static inline vlc_meta_t *vlc_meta_Duplicate( vlc_meta_t *src ) -{ - vlc_meta_t *dst = vlc_meta_New(); - int i; - for( i = 0; i < src->i_meta; i++ ) - { - vlc_meta_Add( dst, src->name[i], src->value[i] ); - } - for( i = 0; i < src->i_track; i++ ) - { - vlc_meta_t *tk = vlc_meta_Duplicate( src->track[i] ); - - dst->track = (vlc_meta_t**)realloc( dst->track, sizeof( vlc_meta_t* ) * (dst->i_track+1) ); - dst->track[dst->i_track++] = tk; - } - return dst; -} - static inline void vlc_meta_Merge( vlc_meta_t *dst, vlc_meta_t *src ) { - int i, j; - for( i = 0; i < src->i_meta; i++ ) - { - /* Check if dst contains the entry */ - for( j = 0; j < dst->i_meta; j++ ) - { - if( !strcmp( src->name[i], dst->name[j] ) ) break; - } - if( j < dst->i_meta ) - { - if( dst->value[j] ) free( dst->value[j] ); - dst->value[j] = strdup( src->value[i] ); - } - else vlc_meta_Add( dst, src->name[i], src->value[i] ); - } -} - -static inline char *vlc_meta_GetValue( vlc_meta_t *m, const char *name ) -{ - int i; - - for( i = 0; i < m->i_meta; i++ ) - { - if( !strcmp( m->name[i], name ) ) - { - char *value = NULL; - if( m->value[i] ) value = strdup( m->value[i] ); - return value; - } + if( !dst || !src ) return; +#define COPY_FIELD( a ) \ + if( src->psz_ ## a ) { \ + if( dst->psz_ ## a ) free( dst->psz_## a ); \ + dst->psz_##a = strdup( src->psz_##a ); \ } - return NULL; + COPY_FIELD( title ); + COPY_FIELD( author ); + COPY_FIELD( artist ); + COPY_FIELD( genre ); + COPY_FIELD( copyright ); + COPY_FIELD( album ); + COPY_FIELD( tracknum ); + COPY_FIELD( description ); + COPY_FIELD( rating ); + COPY_FIELD( date ); + COPY_FIELD( setting ); + COPY_FIELD( url ); + COPY_FIELD( language ); + COPY_FIELD( nowplaying ); + COPY_FIELD( publisher ); } + /** \todo Track meta */ #endif diff --git a/include/vlc_objects.h b/include/vlc_objects.h index 009b9f5488..6f8af17141 100644 --- a/include/vlc_objects.h +++ b/include/vlc_objects.h @@ -23,7 +23,7 @@ /** * \file - * This file defines the vlc_object_t structure and object types + * This file defines the vlc_object_t structure and object types. */ /** @@ -100,6 +100,7 @@ VLC_EXPORT( void, __vlc_object_release, ( vlc_object_t * ) ); VLC_EXPORT( vlc_list_t *, __vlc_list_find, ( vlc_object_t *, int, int ) ); VLC_EXPORT( void, vlc_list_release, ( vlc_list_t * ) ); VLC_EXPORT( vlc_t *, vlc_current_object, ( int ) ); + /*}@*/ #define vlc_object_create(a,b) \ @@ -129,4 +130,3 @@ VLC_EXPORT( vlc_t *, vlc_current_object, ( int ) ); #define vlc_list_find(a,b,c) \ __vlc_list_find( VLC_OBJECT(a),b,c) - diff --git a/include/vlc_playlist.h b/include/vlc_playlist.h index bb458706aa..d701fbd474 100644 --- a/include/vlc_playlist.h +++ b/include/vlc_playlist.h @@ -21,6 +21,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ +#ifndef _VLC_PLAYLIST_H_ +#define _VLC_PLAYLIST_H_ + /** * \file * This file contain structures and function prototypes related @@ -40,12 +43,7 @@ struct playlist_export_t { char *psz_filename; FILE *p_file; -}; - -struct item_parent_t -{ - int i_view; - playlist_item_t *p_parent; + playlist_item_t *p_root; }; /** @@ -54,70 +52,31 @@ struct item_parent_t */ struct playlist_item_t { - input_item_t input; /**< input item descriptor */ + input_item_t *p_input; /**< input item descriptor */ /* Tree specific fields */ int i_children; /**< Number of children -1 if not a node */ playlist_item_t **pp_children; /**< Children nodes/items */ - int i_parents; /**< Number of parents */ - struct item_parent_t **pp_parents; /**< Parents */ - int i_serial; /**< Has this node been updated ? */ - - uint8_t i_flags; /**< Flags */ - + playlist_item_t *p_parent; /**< Item parent */ - int i_nb_played; /**< How many times was this item played ? */ + int i_id; /**< Playlist item specific id */ - /* LEGACY FIELDS */ - vlc_bool_t b_autodeletion; /**< Indicates whther this item is to - * be deleted after playback. True mean - * that this item is to be deleted - * after playback, false otherwise */ - vlc_bool_t b_enabled; /**< Indicates whether this item is to be - * played or skipped */ - /* END LEGACY FIELDS */ + uint8_t i_flags; /**< Flags */ }; -#define PLAYLIST_SAVE_FLAG 0x01 /**< Must it be saved */ -#define PLAYLIST_SKIP_FLAG 0x02 /**< Must playlist skip after it ? */ -#define PLAYLIST_ENA_FLAG 0x04 /**< Is it enabled ? */ -#define PLAYLIST_DEL_FLAG 0x08 /**< Autodelete ? */ +#define PLAYLIST_SAVE_FLAG 0x01 /**< Must it be saved */ +#define PLAYLIST_SKIP_FLAG 0x02 /**< Must playlist skip after it ? */ +#define PLAYLIST_DBL_FLAG 0x04 /**< Is it disabled ? */ #define PLAYLIST_RO_FLAG 0x10 /**< Write-enabled ? */ #define PLAYLIST_REMOVE_FLAG 0x20 /**< Remove this item at the end */ - -/** - * playlist view - * \see playlist_t -*/ -struct playlist_view_t -{ - char * psz_name; /**< View name */ - int i_id; /**< Identifier for the view */ - playlist_item_t * p_root; /**< Root node */ -}; - - -/** - * predefined views - * - */ -#define VIEW_CATEGORY 1 -#define VIEW_SIMPLE 2 -#define VIEW_ALL 3 -#define VIEW_FIRST_SORTED 4 -#define VIEW_S_AUTHOR 4 -#define VIEW_S_GENRE 5 -#define VIEW_S_ALBUM 6 - -#define VIEW_LAST_SORTED 10 - -#define VIEW_FIRST_CUSTOM 100 +#define PLAYLIST_EXPANDED_FLAG 0x40 /**< Expanded node */ /** * Playlist status */ -typedef enum { PLAYLIST_STOPPED,PLAYLIST_RUNNING,PLAYLIST_PAUSED } playlist_status_t; +typedef enum +{ PLAYLIST_STOPPED,PLAYLIST_RUNNING,PLAYLIST_PAUSED } playlist_status_t; struct services_discovery_t @@ -136,7 +95,7 @@ struct playlist_preparse_t VLC_COMMON_MEMBERS vlc_mutex_t lock; int i_waiting; - int *pi_waiting; + input_item_t **pp_waiting; }; @@ -151,7 +110,6 @@ struct playlist_t These members are uniq to playlist_t */ /*@{*/ - int i_index; /**< current index into the playlist */ int i_enabled; /**< How many items are enabled ? */ int i_size; /**< total size of the list */ @@ -160,65 +118,59 @@ struct playlist_t int i_all_size; /**< size of list of items and nodes */ playlist_item_t ** pp_all_items; /**< array of pointers to the * playlist items and nodes */ + int i_last_playlist_id; /**< Last id to an item */ - int i_views; /**< Number of views */ - playlist_view_t ** pp_views; /**< array of pointers to the - * playlist views */ + int i_input_items; + input_item_t ** pp_input_items; - input_thread_t * p_input; /**< the input thread ascosiated - * with the current item */ + int i_last_input_id ; - mtime_t request_date; /**< Used for profiling */ + input_thread_t * p_input; /**< the input thread associated + * with the current item */ - int i_last_id; /**< Last id to an item */ int i_sort; /**< Last sorting applied to the playlist */ int i_order; /**< Last ordering applied to the playlist */ - playlist_item_t * p_general; /**< Keep a pointer on the "general" - category */ + playlist_item_t * p_root_category; + playlist_item_t * p_root_onelevel; + + playlist_item_t * p_local_category; /** < "Playlist" in CATEGORY view */ + playlist_item_t * p_ml_category; /** < "Library" in CATEGORY view */ + playlist_item_t * p_local_onelevel; /** < "Playlist" in ONELEVEL view */ + playlist_item_t * p_ml_onelevel; /** < "Library" in ONELEVEL iew */ services_discovery_t **pp_sds; int i_sds; - vlc_bool_t b_go_next; /*< Go further than the parent node ? */ - struct { - /* Current status */ + /* Current status. These fields are readonly, only the playlist + * main loop can touch it*/ playlist_status_t i_status; /**< Current status of playlist */ - - /* R/O fields, don't touch if you aren't the playlist thread */ - /* Use a request */ playlist_item_t * p_item; /**< Currently playing/active item */ - playlist_item_t * p_node; /**< Current node to play from */ - int i_view; /**< Current view */ + playlist_item_t * p_node; /**< Current node to play from */ } status; struct { - /* Request */ - /* Playlist thread uses this info to calculate the next position */ - int i_view; /**< requested view id */ + /* Request. Use this to give orders to the playlist main loop */ + int i_status; /**< requested playlist status */ playlist_item_t * p_node; /**< requested node to play from */ playlist_item_t * p_item; /**< requested item to play in the node */ int i_skip; /**< Number of items to skip */ - int i_goto; /**< Direct index to go to (non-view)*/ - vlc_bool_t b_request; /**< Set to true by the requester - The playlist sets it back to false - when processing the request */ - vlc_mutex_t lock; /**< Lock to protect request */ + vlc_bool_t b_request;/**< Set to true by the requester + The playlist sets it back to false + when processing the request */ + vlc_mutex_t lock; /**< Lock to protect request */ } request; - playlist_preparse_t *p_preparse; + playlist_preparse_t *p_preparse; /**< Preparser object */ vlc_mutex_t gc_lock; /**< Lock to protect the garbage collection */ - // The following members are about user interaction - // The playlist manages the user interaction to avoid creating another - // thread - interaction_t *p_interaction; - - global_stats_t *p_stats; + // Playlist-unrelated fields + interaction_t *p_interaction; /**< Interaction manager */ + global_stats_t *p_stats; /**< Global statistics */ /*@}*/ }; @@ -249,10 +201,27 @@ struct playlist_add_t * Prototypes *****************************************************************************/ +/* Global thread */ +#define playlist_ThreadCreate(a) __playlist_ThreadCreate(VLC_OBJECT(a)) +playlist_t *__playlist_ThreadCreate ( vlc_object_t * ); +int playlist_ThreadDestroy ( playlist_t * ); + +/* Helpers */ +#define PL_LOCK vlc_mutex_lock( &p_playlist->object_lock ); +#define PL_UNLOCK vlc_mutex_unlock( &p_playlist->object_lock ); + /* Creation/Deletion */ -#define playlist_Create(a) __playlist_Create(VLC_OBJECT(a)) -playlist_t * __playlist_Create ( vlc_object_t * ); -int playlist_Destroy ( playlist_t * ); +playlist_t *playlist_Create ( vlc_object_t * ); +void playlist_Destroy ( playlist_t * ); + +/* Engine */ +void playlist_MainLoop( playlist_t * ); +void playlist_LastLoop( playlist_t * ); +void playlist_PreparseLoop( playlist_preparse_t * ); + +/* Control */ +playlist_item_t * playlist_NextItem ( playlist_t * ); +int playlist_PlayItem ( playlist_t *, playlist_item_t * ); /* Playlist control */ #define playlist_Play(p) playlist_LockControl(p,PLAYLIST_PLAY ) @@ -261,13 +230,12 @@ int playlist_Destroy ( playlist_t * ); #define playlist_Next(p) playlist_LockControl(p,PLAYLIST_SKIP, 1) #define playlist_Prev(p) playlist_LockControl(p,PLAYLIST_SKIP, -1) #define playlist_Skip(p,i) playlist_LockControl(p,PLAYLIST_SKIP, i) -#define playlist_Goto(p,i) playlist_LockControl(p,PLAYLIST_GOTO, i) VLC_EXPORT( int, playlist_Control, ( playlist_t *, int, ... ) ); VLC_EXPORT( int, playlist_LockControl, ( playlist_t *, int, ... ) ); -VLC_EXPORT( int, playlist_Clear, ( playlist_t * ) ); -VLC_EXPORT( int, playlist_LockClear, ( playlist_t * ) ); +VLC_EXPORT( void, playlist_Clear, ( playlist_t * ) ); +VLC_EXPORT( void, playlist_LockClear, ( playlist_t * ) ); VLC_EXPORT( int, playlist_PreparseEnqueue, (playlist_t *, input_item_t *) ); VLC_EXPORT( int, playlist_PreparseEnqueueItem, (playlist_t *, playlist_item_t *) ); @@ -281,80 +249,99 @@ VLC_EXPORT( vlc_bool_t, playlist_IsServicesDiscoveryLoaded, ( playlist_t *,const /* Item management functions (act on items) */ -#define playlist_AddItem(p,pi,i1,i2) playlist_ItemAdd(p,pi,i1,i2) #define playlist_ItemNew( a , b, c ) __playlist_ItemNew(VLC_OBJECT(a) , b , c ) #define playlist_ItemCopy( a, b ) __playlist_ItemCopy(VLC_OBJECT(a), b ) VLC_EXPORT( playlist_item_t* , __playlist_ItemNew, ( vlc_object_t *,const char *,const char * ) ); VLC_EXPORT( playlist_item_t* , __playlist_ItemCopy, ( vlc_object_t *,playlist_item_t* ) ); -VLC_EXPORT( playlist_item_t* , playlist_ItemNewWithType, ( vlc_object_t *,const char *,const char *, int ) ); +VLC_EXPORT( playlist_item_t* , playlist_ItemNewWithType, ( vlc_object_t *,const char *,const char *, int , const char **, int, int) ); +#define playlist_ItemNewFromInput(a,b) __playlist_ItemNewFromInput(VLC_OBJECT(a),b) +VLC_EXPORT( playlist_item_t *, __playlist_ItemNewFromInput, ( vlc_object_t *p_obj,input_item_t *p_input ) ); + + VLC_EXPORT( int, playlist_ItemDelete, ( playlist_item_t * ) ); -VLC_EXPORT( int, playlist_ItemAddParent, ( playlist_item_t *, int,playlist_item_t *) ); -VLC_EXPORT( int, playlist_CopyParents, ( playlist_item_t *,playlist_item_t *) ); + /* Item informations accessors */ VLC_EXPORT( int, playlist_ItemSetName, (playlist_item_t *, char * ) ); VLC_EXPORT( int, playlist_ItemSetDuration, (playlist_item_t *, mtime_t ) ); +VLC_EXPORT( void, playlist_ItemAddOption, (playlist_item_t *, const char *) ); -/* View management functions */ -VLC_EXPORT( int, playlist_ViewInsert, (playlist_t *, int, char * ) ); -VLC_EXPORT( int, playlist_ViewDelete, (playlist_t *,playlist_view_t* ) ); -VLC_EXPORT( playlist_view_t *, playlist_ViewFind, (playlist_t *, int ) ); -VLC_EXPORT( int, playlist_ViewUpdate, (playlist_t *, int ) ); -VLC_EXPORT( int, playlist_ViewDump, (playlist_t *, playlist_view_t * ) ); -VLC_EXPORT( int, playlist_ViewEmpty, (playlist_t *, int, vlc_bool_t ) ); +VLC_EXPORT(void, playlist_NodeDump, ( playlist_t *p_playlist, playlist_item_t *p_item, int i_level ) ); + +/** Counts the items of a view */ +VLC_EXPORT( int, playlist_NodeChildrenCount, (playlist_t *,playlist_item_t* ) ); /* Node management */ -VLC_EXPORT( playlist_item_t *, playlist_NodeCreate, ( playlist_t *,int,char *, playlist_item_t * p_parent ) ); -VLC_EXPORT( int, playlist_NodeAppend, (playlist_t *,int,playlist_item_t*,playlist_item_t *) ); -VLC_EXPORT( int, playlist_NodeInsert, (playlist_t *,int,playlist_item_t*,playlist_item_t *, int) ); +VLC_EXPORT( playlist_item_t *, playlist_NodeCreate, ( playlist_t *, char *, playlist_item_t * p_parent ) ); +VLC_EXPORT( int, playlist_NodeAppend, (playlist_t *,playlist_item_t*,playlist_item_t *) ); +VLC_EXPORT( int, playlist_NodeInsert, (playlist_t *,playlist_item_t*,playlist_item_t *, int) ); VLC_EXPORT( int, playlist_NodeRemoveItem, (playlist_t *,playlist_item_t*,playlist_item_t *) ); -VLC_EXPORT( int, playlist_NodeRemoveParent, (playlist_t *,playlist_item_t*,playlist_item_t *) ); -VLC_EXPORT( int, playlist_NodeChildrenCount, (playlist_t *,playlist_item_t* ) ); VLC_EXPORT( playlist_item_t *, playlist_ChildSearchName, (playlist_item_t*, const char* ) ); VLC_EXPORT( int, playlist_NodeDelete, ( playlist_t *, playlist_item_t *, vlc_bool_t , vlc_bool_t ) ); VLC_EXPORT( int, playlist_NodeEmpty, ( playlist_t *, playlist_item_t *, vlc_bool_t ) ); -/* Tree walking */ -playlist_item_t *playlist_FindNextFromParent( playlist_t *p_playlist, - int i_view, - playlist_item_t *p_root, - playlist_item_t *p_node, - playlist_item_t *p_item ); -playlist_item_t *playlist_FindPrevFromParent( playlist_t *p_playlist, - int i_view, - playlist_item_t *p_root, - playlist_item_t *p_node, - playlist_item_t *p_item ); +/* Tree walking - These functions are only for playlist, not plugins */ +playlist_item_t *playlist_GetNextLeaf( playlist_t *p_playlist, + playlist_item_t *p_root, + playlist_item_t *p_item ); +playlist_item_t *playlist_GetNextEnabledLeaf( playlist_t *p_playlist, + playlist_item_t *p_root, + playlist_item_t *p_item ); +playlist_item_t *playlist_GetPrevLeaf( playlist_t *p_playlist, + playlist_item_t *p_root, + playlist_item_t *p_item ); +playlist_item_t *playlist_GetLastLeaf( playlist_t *p_playlist, + playlist_item_t *p_root ); /* Simple add/remove functions */ -/* These functions add the item to the "simple" view (+all & category )*/ -VLC_EXPORT( int, playlist_Add, ( playlist_t *, const char *, const char *, int, int ) ); -VLC_EXPORT( int, playlist_AddExt, ( playlist_t *, const char *, const char *, int, int, mtime_t, const char **,int ) ); -VLC_EXPORT( int, playlist_ItemAdd, ( playlist_t *, playlist_item_t *, int, int ) ); -VLC_EXPORT(int, playlist_NodeAddItem, ( playlist_t *, playlist_item_t *,int,playlist_item_t *,int , int ) ); +VLC_EXPORT( int, playlist_PlaylistAdd, ( playlist_t *, const char *, const char *, int, int ) ); +VLC_EXPORT( int, playlist_PlaylistAddExt, ( playlist_t *, const char *, const char *, int, int, mtime_t, const char **,int ) ); +VLC_EXPORT( int, playlist_PlaylistAddInput, ( playlist_t *, input_item_t *,int , int ) ); +VLC_EXPORT( playlist_item_t *, playlist_NodeAddInput, ( playlist_t *, input_item_t *,playlist_item_t *,int , int ) ); +VLC_EXPORT( void, playlist_NodeAddItem, ( playlist_t *, playlist_item_t *, playlist_item_t *,int , int ) ); +VLC_EXPORT( int, playlist_BothAddInput, ( playlist_t *, input_item_t *,playlist_item_t *,int , int ) ); +VLC_EXPORT( void, playlist_AddWhereverNeeded, (playlist_t* , input_item_t*, playlist_item_t*,playlist_item_t*,vlc_bool_t, int ) ); + +void playlist_SendAddNotify( playlist_t *p_playlist, int i_item_id, int i_node_id ); /* Misc item operations (act on item+playlist) */ -VLC_EXPORT( int, playlist_Delete, ( playlist_t *, int ) ); +VLC_EXPORT( int, playlist_DeleteAllFromInput, ( playlist_t *, int ) ); +VLC_EXPORT( int, playlist_DeleteFromInput, ( playlist_t *, int, playlist_item_t *, vlc_bool_t ) ); +VLC_EXPORT( int, playlist_DeleteFromItemId, ( playlist_t *, int ) ); VLC_EXPORT( int, playlist_LockDelete, ( playlist_t *, int ) ); -VLC_EXPORT( int, playlist_Disable, ( playlist_t *, playlist_item_t * ) ); -VLC_EXPORT( int, playlist_Enable, ( playlist_t *, playlist_item_t * ) ); -VLC_EXPORT( int, playlist_ItemToNode, (playlist_t *,playlist_item_t *) ); -VLC_EXPORT( int, playlist_LockItemToNode, (playlist_t *,playlist_item_t *) ); -VLC_EXPORT( int, playlist_Replace, (playlist_t *,playlist_item_t *, input_item_t*) ); -VLC_EXPORT( int, playlist_LockReplace, (playlist_t *,playlist_item_t *, input_item_t*) ); +VLC_EXPORT( int, playlist_LockDeleteAllFromInput, ( playlist_t *, int ) ); +VLC_EXPORT( playlist_item_t*, playlist_ItemToNode, (playlist_t *,playlist_item_t *) ); +VLC_EXPORT( playlist_item_t*, playlist_LockItemToNode, (playlist_t *,playlist_item_t *) ); +playlist_item_t *playlist_ItemFindFromInputAndRoot( playlist_t *p_playlist, + int i_input_id, playlist_item_t *p_root ); /* Item search functions */ VLC_EXPORT( playlist_item_t *, playlist_ItemGetById, (playlist_t *, int) ); -VLC_EXPORT( playlist_item_t *, playlist_LockItemGetById, (playlist_t *, int) ); -VLC_EXPORT( playlist_item_t *, playlist_ItemGetByPos, (playlist_t *, int) ); -VLC_EXPORT( playlist_item_t *, playlist_LockItemGetByPos, (playlist_t *, int) ); VLC_EXPORT( playlist_item_t *, playlist_ItemGetByInput, (playlist_t *,input_item_t * ) ); -VLC_EXPORT( playlist_item_t *, playlist_LockItemGetByInput, (playlist_t *,input_item_t * ) ); -VLC_EXPORT( int, playlist_GetPositionById, (playlist_t *,int ) ); -VLC_EXPORT( int, playlist_ItemAddOption, (playlist_item_t *, const char *) ); +static inline playlist_item_t *playlist_LockItemGetById( playlist_t *p_playlist, + int i_id) +{ + playlist_item_t *p_ret; + vlc_mutex_lock( &p_playlist->object_lock ); + p_ret = playlist_ItemGetById( p_playlist, i_id ); + vlc_mutex_unlock( &p_playlist->object_lock ); + return p_ret; +} + +static inline playlist_item_t *playlist_LockItemGetByInput( + playlist_t *p_playlist, input_item_t *p_item ) +{ + playlist_item_t *p_ret; + vlc_mutex_lock( &p_playlist->object_lock ); + p_ret = playlist_ItemGetByInput( p_playlist, p_item ); + vlc_mutex_unlock( &p_playlist->object_lock ); + return p_ret; +} + +VLC_EXPORT( int, playlist_LiveSearchUpdate, (playlist_t *, playlist_item_t *, const char *) ); /* Playlist sorting */ #define playlist_SortID(p, i) playlist_Sort( p, SORT_ID, i) @@ -362,56 +349,41 @@ VLC_EXPORT( int, playlist_ItemAddOption, (playlist_item_t *, const char *) ); #define playlist_SortAuthor(p, i) playlist_Sort( p, SORT_AUTHOR, i) #define playlist_SortAlbum(p, i) playlist_Sort( p, SORT_ALBUM, i) #define playlist_SortGroup(p, i) playlist_Sort( p, SORT_GROUP, i) -VLC_EXPORT( int, playlist_Sort, ( playlist_t *, int, int) ); -VLC_EXPORT( int, playlist_Move, ( playlist_t *, int, int ) ); -VLC_EXPORT( int, playlist_TreeMove, ( playlist_t *, playlist_item_t *, playlist_item_t *, int, int ) ); -VLC_EXPORT( int, playlist_NodeGroup, ( playlist_t *, int,playlist_item_t *,playlist_item_t **,int, int, int ) ); +VLC_EXPORT( int, playlist_TreeMove, ( playlist_t *, playlist_item_t *, playlist_item_t *, int ) ); +VLC_EXPORT( int, playlist_NodeGroup, ( playlist_t *, playlist_item_t *,playlist_item_t **,int, int, int ) ); VLC_EXPORT( int, playlist_NodeSort, ( playlist_t *, playlist_item_t *,int, int ) ); VLC_EXPORT( int, playlist_RecursiveNodeSort, ( playlist_t *, playlist_item_t *,int, int ) ); /* Load/Save */ VLC_EXPORT( int, playlist_Import, ( playlist_t *, const char * ) ); -VLC_EXPORT( int, playlist_Export, ( playlist_t *, const char *, const char * ) ); +VLC_EXPORT( int, playlist_Export, ( playlist_t *, const char *, playlist_item_t *, const char * ) ); /*********************************************************************** * Inline functions ***********************************************************************/ - -/** - * tell if a playlist is currently playing. - * \param p_playlist the playlist to check - * \return true if playlist is playing, false otherwise - */ +/** Tell if the playlist is currently running */ static inline vlc_bool_t playlist_IsPlaying( playlist_t * p_playlist ) { vlc_bool_t b_playing; - vlc_mutex_lock( &p_playlist->object_lock ); b_playing = p_playlist->status.i_status == PLAYLIST_RUNNING; vlc_mutex_unlock( &p_playlist->object_lock ); - return( b_playing ); } -/** - * tell if a playlist is currently empty - * \param p_playlist the playlist to check - * \return true if the playlist is empty, false otherwise - */ +/** Tell if the playlist is empty */ static inline vlc_bool_t playlist_IsEmpty( playlist_t * p_playlist ) { vlc_bool_t b_empty; - vlc_mutex_lock( &p_playlist->object_lock ); b_empty = p_playlist->i_size == 0; vlc_mutex_unlock( &p_playlist->object_lock ); - return( b_empty ); } - - /** * @} */ + +#endif diff --git a/include/vlc_symbols.h b/include/vlc_symbols.h index 5bff63cbcc..52622d837d 100644 --- a/include/vlc_symbols.h +++ b/include/vlc_symbols.h @@ -258,8 +258,8 @@ struct module_symbols_t void (*vlc_list_release_inner) (vlc_list_t *); int (*playlist_Control_inner) (playlist_t *, int, ...); int (*playlist_LockControl_inner) (playlist_t *, int, ...); - int (*playlist_Clear_inner) (playlist_t *); - int (*playlist_LockClear_inner) (playlist_t *); + void (*playlist_Clear_inner) (playlist_t *); + void (*playlist_LockClear_inner) (playlist_t *); int (*playlist_PreparseEnqueue_inner) (playlist_t *, input_item_t *); int (*playlist_ServicesDiscoveryAdd_inner) (playlist_t *, const char *); int (*playlist_ServicesDiscoveryRemove_inner) (playlist_t *, const char *); @@ -267,53 +267,53 @@ struct module_symbols_t vlc_bool_t (*playlist_IsServicesDiscoveryLoaded_inner) (playlist_t *,const char *); playlist_item_t* (*__playlist_ItemNew_inner) (vlc_object_t *,const char *,const char *); playlist_item_t* (*__playlist_ItemCopy_inner) (vlc_object_t *,playlist_item_t*); - playlist_item_t* (*playlist_ItemNewWithType_inner) (vlc_object_t *,const char *,const char *, int); + playlist_item_t* (*playlist_ItemNewWithType_inner) (vlc_object_t *,const char *,const char *, int , const char **, int, int); int (*playlist_ItemDelete_inner) (playlist_item_t *); - int (*playlist_ItemAddParent_inner) (playlist_item_t *, int,playlist_item_t *); - int (*playlist_CopyParents_inner) (playlist_item_t *,playlist_item_t *); + void *playlist_ItemAddParent_deprecated; + void *playlist_CopyParents_deprecated; int (*playlist_ItemSetName_inner) (playlist_item_t *, char *); int (*playlist_ItemSetDuration_inner) (playlist_item_t *, mtime_t); - int (*playlist_ViewInsert_inner) (playlist_t *, int, char *); - int (*playlist_ViewDelete_inner) (playlist_t *,playlist_view_t*); - playlist_view_t * (*playlist_ViewFind_inner) (playlist_t *, int); - int (*playlist_ViewUpdate_inner) (playlist_t *, int); - int (*playlist_ViewDump_inner) (playlist_t *, playlist_view_t *); - int (*playlist_ViewEmpty_inner) (playlist_t *, int, vlc_bool_t); - playlist_item_t * (*playlist_NodeCreate_inner) (playlist_t *,int,char *, playlist_item_t * p_parent); - int (*playlist_NodeAppend_inner) (playlist_t *,int,playlist_item_t*,playlist_item_t *); - int (*playlist_NodeInsert_inner) (playlist_t *,int,playlist_item_t*,playlist_item_t *, int); + void *playlist_ViewInsert_deprecated; + void *playlist_ViewDelete_deprecated; + void *playlist_ViewFind_deprecated; + void *playlist_ViewUpdate_deprecated; + void *playlist_ViewDump_deprecated; + void *playlist_ViewEmpty_deprecated; + playlist_item_t * (*playlist_NodeCreate_inner) (playlist_t *, char *, playlist_item_t * p_parent); + int (*playlist_NodeAppend_inner) (playlist_t *,playlist_item_t*,playlist_item_t *); + int (*playlist_NodeInsert_inner) (playlist_t *,playlist_item_t*,playlist_item_t *, int); int (*playlist_NodeRemoveItem_inner) (playlist_t *,playlist_item_t*,playlist_item_t *); int (*playlist_NodeChildrenCount_inner) (playlist_t *,playlist_item_t*); playlist_item_t * (*playlist_ChildSearchName_inner) (playlist_item_t*, const char*); int (*playlist_NodeDelete_inner) (playlist_t *, playlist_item_t *, vlc_bool_t , vlc_bool_t); int (*playlist_NodeEmpty_inner) (playlist_t *, playlist_item_t *, vlc_bool_t); - int (*playlist_Add_inner) (playlist_t *, const char *, const char *, int, int); - int (*playlist_AddExt_inner) (playlist_t *, const char *, const char *, int, int, mtime_t, const char **,int); - int (*playlist_ItemAdd_inner) (playlist_t *, playlist_item_t *, int, int); - int (*playlist_NodeAddItem_inner) (playlist_t *, playlist_item_t *,int,playlist_item_t *,int , int); - int (*playlist_Delete_inner) (playlist_t *, int); + void *playlist_Add_deprecated; + void *playlist_AddExt_deprecated; + void *playlist_ItemAdd_deprecated; + void (*playlist_NodeAddItem_inner) (playlist_t *, playlist_item_t *, playlist_item_t *,int , int); + void *playlist_Delete_deprecated; int (*playlist_LockDelete_inner) (playlist_t *, int); - int (*playlist_Disable_inner) (playlist_t *, playlist_item_t *); - int (*playlist_Enable_inner) (playlist_t *, playlist_item_t *); - int (*playlist_ItemToNode_inner) (playlist_t *,playlist_item_t *); - int (*playlist_LockItemToNode_inner) (playlist_t *,playlist_item_t *); - int (*playlist_Replace_inner) (playlist_t *,playlist_item_t *, input_item_t*); - int (*playlist_LockReplace_inner) (playlist_t *,playlist_item_t *, input_item_t*); + void *playlist_Disable_deprecated; + void *playlist_Enable_deprecated; + playlist_item_t* (*playlist_ItemToNode_inner) (playlist_t *,playlist_item_t *); + playlist_item_t* (*playlist_LockItemToNode_inner) (playlist_t *,playlist_item_t *); + void *playlist_Replace_deprecated; + void *playlist_LockReplace_deprecated; playlist_item_t * (*playlist_ItemGetById_inner) (playlist_t *, int); - playlist_item_t * (*playlist_LockItemGetById_inner) (playlist_t *, int); - playlist_item_t * (*playlist_ItemGetByPos_inner) (playlist_t *, int); - playlist_item_t * (*playlist_LockItemGetByPos_inner) (playlist_t *, int); + void *playlist_LockItemGetById_deprecated; + void *playlist_ItemGetByPos_deprecated; + void *playlist_LockItemGetByPos_deprecated; playlist_item_t * (*playlist_ItemGetByInput_inner) (playlist_t *,input_item_t *); - playlist_item_t * (*playlist_LockItemGetByInput_inner) (playlist_t *,input_item_t *); - int (*playlist_GetPositionById_inner) (playlist_t *,int); - int (*playlist_ItemAddOption_inner) (playlist_item_t *, const char *); - int (*playlist_Sort_inner) (playlist_t *, int, int); - int (*playlist_Move_inner) (playlist_t *, int, int); - int (*playlist_NodeGroup_inner) (playlist_t *, int,playlist_item_t *,playlist_item_t **,int, int, int); + void *playlist_LockItemGetByInput_deprecated; + void *playlist_GetPositionById_deprecated; + void (*playlist_ItemAddOption_inner) (playlist_item_t *, const char *); + void *playlist_Sort_deprecated; + void *playlist_Move_deprecated; + int (*playlist_NodeGroup_inner) (playlist_t *, playlist_item_t *,playlist_item_t **,int, int, int); int (*playlist_NodeSort_inner) (playlist_t *, playlist_item_t *,int, int); int (*playlist_RecursiveNodeSort_inner) (playlist_t *, playlist_item_t *,int, int); int (*playlist_Import_inner) (playlist_t *, const char *); - int (*playlist_Export_inner) (playlist_t *, const char *, const char *); + int (*playlist_Export_inner) (playlist_t *, const char *, playlist_item_t *, const char *); spu_t * (*__spu_Create_inner) (vlc_object_t *); int (*spu_Init_inner) (spu_t *); void (*spu_Destroy_inner) (spu_t *); @@ -379,7 +379,7 @@ struct module_symbols_t void (*net_ListenClose_inner) (int *fd); void (*DigestMD5_inner) (struct md5_s *, uint32_t *); int (*ACL_Check_inner) (vlc_acl_t *p_acl, const char *psz_ip); - int (*playlist_NodeRemoveParent_inner) (playlist_t *,playlist_item_t*,playlist_item_t *); + void *playlist_NodeRemoveParent_deprecated; vlc_acl_t * (*__ACL_Duplicate_inner) (vlc_object_t *p_this, const vlc_acl_t *p_acl); vlc_acl_t * (*__ACL_Create_inner) (vlc_object_t *p_this, vlc_bool_t b_allow); int (*ACL_LoadFile_inner) (vlc_acl_t *p_acl, const char *path); @@ -475,7 +475,7 @@ struct module_symbols_t char * (*FromLocaleDup_inner) (const char *); int (*utf8_mkdir_inner) (const char *filename); vlm_media_t* (*vlm_MediaSearch_inner) (vlm_t *, const char *); - int (*playlist_TreeMove_inner) (playlist_t *, playlist_item_t *, playlist_item_t *, int, int); + int (*playlist_TreeMove_inner) (playlist_t *, playlist_item_t *, playlist_item_t *, int); const char * (*config_GetDataDir_inner) (const vlc_object_t *); double (*us_atof_inner) (const char *); double (*us_strtod_inner) (const char *, char **); @@ -492,6 +492,26 @@ struct module_symbols_t void (*decode_URI_inner) (char *psz); char * (*encode_URI_component_inner) (const char *psz); size_t (*vlc_strlcpy_inner) (char *, const char *, size_t); + void *playlist_ItemNewFromInput_deprecated; + input_item_t * (*__input_ItemNewExt_inner) (vlc_object_t *, const char *, const char*, int, const char **, int); + input_item_t * (*input_ItemNewWithType_inner) (vlc_object_t *, const char *, const char *e, int, const char **, int, int); + playlist_item_t * (*playlist_NodeAddInput_inner) (playlist_t *, input_item_t *,playlist_item_t *,int , int); + int (*playlist_PlaylistAdd_inner) (playlist_t *, const char *, const char *, int, int); + int (*playlist_PlaylistAddExt_inner) (playlist_t *, const char *, const char *, int, int, mtime_t, const char **,int); + int (*playlist_PlaylistAddInput_inner) (playlist_t *, input_item_t *,int , int); + int (*playlist_BothAddInput_inner) (playlist_t *, input_item_t *,playlist_item_t *,int , int); + playlist_item_t * (*__playlist_ItemNewFromInput_inner) (vlc_object_t *p_obj,input_item_t *p_input); + input_item_t * (*input_ItemGetById_inner) (playlist_t *, int); + int (*playlist_LiveSearchUpdate_inner) (playlist_t *, playlist_item_t *, const char *); + void (*vlc_input_item_AddOption_inner) (input_item_t *p_input, const char *psz_option); + int (*playlist_DeleteFromInput_inner) (playlist_t *, int, playlist_item_t *, vlc_bool_t); + int (*playlist_DeleteAllFromInput_inner) (playlist_t *, int); + int (*playlist_LockDeleteAllFromInput_inner) (playlist_t *, int); + void (*playlist_AddWhereverNeeded_inner) (playlist_t* , input_item_t*, playlist_item_t*,playlist_item_t*,vlc_bool_t, int); + int (*playlist_DeleteFromItemId_inner) (playlist_t *, int); + void (*playlist_NodeDump_inner) (playlist_t *p_playlist, playlist_item_t *p_item, int i_level); + int (*__intf_UserOkayCancel_inner) (vlc_object_t*, const char*, const char*); + int (*__intf_UserStringInput_inner) (vlc_object_t*, const char*, const char*, char **); }; # if defined (__PLUGIN__) # define aout_FiltersCreatePipeline (p_symbols)->aout_FiltersCreatePipeline_inner @@ -743,16 +763,8 @@ struct module_symbols_t # define __playlist_ItemCopy (p_symbols)->__playlist_ItemCopy_inner # define playlist_ItemNewWithType (p_symbols)->playlist_ItemNewWithType_inner # define playlist_ItemDelete (p_symbols)->playlist_ItemDelete_inner -# define playlist_ItemAddParent (p_symbols)->playlist_ItemAddParent_inner -# define playlist_CopyParents (p_symbols)->playlist_CopyParents_inner # define playlist_ItemSetName (p_symbols)->playlist_ItemSetName_inner # define playlist_ItemSetDuration (p_symbols)->playlist_ItemSetDuration_inner -# define playlist_ViewInsert (p_symbols)->playlist_ViewInsert_inner -# define playlist_ViewDelete (p_symbols)->playlist_ViewDelete_inner -# define playlist_ViewFind (p_symbols)->playlist_ViewFind_inner -# define playlist_ViewUpdate (p_symbols)->playlist_ViewUpdate_inner -# define playlist_ViewDump (p_symbols)->playlist_ViewDump_inner -# define playlist_ViewEmpty (p_symbols)->playlist_ViewEmpty_inner # define playlist_NodeCreate (p_symbols)->playlist_NodeCreate_inner # define playlist_NodeAppend (p_symbols)->playlist_NodeAppend_inner # define playlist_NodeInsert (p_symbols)->playlist_NodeInsert_inner @@ -761,28 +773,13 @@ struct module_symbols_t # define playlist_ChildSearchName (p_symbols)->playlist_ChildSearchName_inner # define playlist_NodeDelete (p_symbols)->playlist_NodeDelete_inner # define playlist_NodeEmpty (p_symbols)->playlist_NodeEmpty_inner -# define playlist_Add (p_symbols)->playlist_Add_inner -# define playlist_AddExt (p_symbols)->playlist_AddExt_inner -# define playlist_ItemAdd (p_symbols)->playlist_ItemAdd_inner # define playlist_NodeAddItem (p_symbols)->playlist_NodeAddItem_inner -# define playlist_Delete (p_symbols)->playlist_Delete_inner # define playlist_LockDelete (p_symbols)->playlist_LockDelete_inner -# define playlist_Disable (p_symbols)->playlist_Disable_inner -# define playlist_Enable (p_symbols)->playlist_Enable_inner # define playlist_ItemToNode (p_symbols)->playlist_ItemToNode_inner # define playlist_LockItemToNode (p_symbols)->playlist_LockItemToNode_inner -# define playlist_Replace (p_symbols)->playlist_Replace_inner -# define playlist_LockReplace (p_symbols)->playlist_LockReplace_inner # define playlist_ItemGetById (p_symbols)->playlist_ItemGetById_inner -# define playlist_LockItemGetById (p_symbols)->playlist_LockItemGetById_inner -# define playlist_ItemGetByPos (p_symbols)->playlist_ItemGetByPos_inner -# define playlist_LockItemGetByPos (p_symbols)->playlist_LockItemGetByPos_inner # define playlist_ItemGetByInput (p_symbols)->playlist_ItemGetByInput_inner -# define playlist_LockItemGetByInput (p_symbols)->playlist_LockItemGetByInput_inner -# define playlist_GetPositionById (p_symbols)->playlist_GetPositionById_inner # define playlist_ItemAddOption (p_symbols)->playlist_ItemAddOption_inner -# define playlist_Sort (p_symbols)->playlist_Sort_inner -# define playlist_Move (p_symbols)->playlist_Move_inner # define playlist_NodeGroup (p_symbols)->playlist_NodeGroup_inner # define playlist_NodeSort (p_symbols)->playlist_NodeSort_inner # define playlist_RecursiveNodeSort (p_symbols)->playlist_RecursiveNodeSort_inner @@ -853,7 +850,6 @@ struct module_symbols_t # define net_ListenClose (p_symbols)->net_ListenClose_inner # define DigestMD5 (p_symbols)->DigestMD5_inner # define ACL_Check (p_symbols)->ACL_Check_inner -# define playlist_NodeRemoveParent (p_symbols)->playlist_NodeRemoveParent_inner # define __ACL_Duplicate (p_symbols)->__ACL_Duplicate_inner # define __ACL_Create (p_symbols)->__ACL_Create_inner # define ACL_LoadFile (p_symbols)->ACL_LoadFile_inner @@ -964,6 +960,25 @@ struct module_symbols_t # define decode_URI (p_symbols)->decode_URI_inner # define encode_URI_component (p_symbols)->encode_URI_component_inner # define vlc_strlcpy (p_symbols)->vlc_strlcpy_inner +# define __input_ItemNewExt (p_symbols)->__input_ItemNewExt_inner +# define input_ItemNewWithType (p_symbols)->input_ItemNewWithType_inner +# define playlist_NodeAddInput (p_symbols)->playlist_NodeAddInput_inner +# define playlist_PlaylistAdd (p_symbols)->playlist_PlaylistAdd_inner +# define playlist_PlaylistAddExt (p_symbols)->playlist_PlaylistAddExt_inner +# define playlist_PlaylistAddInput (p_symbols)->playlist_PlaylistAddInput_inner +# define playlist_BothAddInput (p_symbols)->playlist_BothAddInput_inner +# define __playlist_ItemNewFromInput (p_symbols)->__playlist_ItemNewFromInput_inner +# define input_ItemGetById (p_symbols)->input_ItemGetById_inner +# define playlist_LiveSearchUpdate (p_symbols)->playlist_LiveSearchUpdate_inner +# define vlc_input_item_AddOption (p_symbols)->vlc_input_item_AddOption_inner +# define playlist_DeleteFromInput (p_symbols)->playlist_DeleteFromInput_inner +# define playlist_DeleteAllFromInput (p_symbols)->playlist_DeleteAllFromInput_inner +# define playlist_LockDeleteAllFromInput (p_symbols)->playlist_LockDeleteAllFromInput_inner +# define playlist_AddWhereverNeeded (p_symbols)->playlist_AddWhereverNeeded_inner +# define playlist_DeleteFromItemId (p_symbols)->playlist_DeleteFromItemId_inner +# define playlist_NodeDump (p_symbols)->playlist_NodeDump_inner +# define __intf_UserOkayCancel (p_symbols)->__intf_UserOkayCancel_inner +# define __intf_UserStringInput (p_symbols)->__intf_UserStringInput_inner # elif defined (HAVE_DYNAMIC_PLUGINS) && !defined (__BUILTIN__) /****************************************************************** * STORE_SYMBOLS: store VLC APIs into p_symbols for plugin access. @@ -1218,16 +1233,8 @@ struct module_symbols_t ((p_symbols)->__playlist_ItemCopy_inner) = __playlist_ItemCopy; \ ((p_symbols)->playlist_ItemNewWithType_inner) = playlist_ItemNewWithType; \ ((p_symbols)->playlist_ItemDelete_inner) = playlist_ItemDelete; \ - ((p_symbols)->playlist_ItemAddParent_inner) = playlist_ItemAddParent; \ - ((p_symbols)->playlist_CopyParents_inner) = playlist_CopyParents; \ ((p_symbols)->playlist_ItemSetName_inner) = playlist_ItemSetName; \ ((p_symbols)->playlist_ItemSetDuration_inner) = playlist_ItemSetDuration; \ - ((p_symbols)->playlist_ViewInsert_inner) = playlist_ViewInsert; \ - ((p_symbols)->playlist_ViewDelete_inner) = playlist_ViewDelete; \ - ((p_symbols)->playlist_ViewFind_inner) = playlist_ViewFind; \ - ((p_symbols)->playlist_ViewUpdate_inner) = playlist_ViewUpdate; \ - ((p_symbols)->playlist_ViewDump_inner) = playlist_ViewDump; \ - ((p_symbols)->playlist_ViewEmpty_inner) = playlist_ViewEmpty; \ ((p_symbols)->playlist_NodeCreate_inner) = playlist_NodeCreate; \ ((p_symbols)->playlist_NodeAppend_inner) = playlist_NodeAppend; \ ((p_symbols)->playlist_NodeInsert_inner) = playlist_NodeInsert; \ @@ -1236,28 +1243,13 @@ struct module_symbols_t ((p_symbols)->playlist_ChildSearchName_inner) = playlist_ChildSearchName; \ ((p_symbols)->playlist_NodeDelete_inner) = playlist_NodeDelete; \ ((p_symbols)->playlist_NodeEmpty_inner) = playlist_NodeEmpty; \ - ((p_symbols)->playlist_Add_inner) = playlist_Add; \ - ((p_symbols)->playlist_AddExt_inner) = playlist_AddExt; \ - ((p_symbols)->playlist_ItemAdd_inner) = playlist_ItemAdd; \ ((p_symbols)->playlist_NodeAddItem_inner) = playlist_NodeAddItem; \ - ((p_symbols)->playlist_Delete_inner) = playlist_Delete; \ ((p_symbols)->playlist_LockDelete_inner) = playlist_LockDelete; \ - ((p_symbols)->playlist_Disable_inner) = playlist_Disable; \ - ((p_symbols)->playlist_Enable_inner) = playlist_Enable; \ ((p_symbols)->playlist_ItemToNode_inner) = playlist_ItemToNode; \ ((p_symbols)->playlist_LockItemToNode_inner) = playlist_LockItemToNode; \ - ((p_symbols)->playlist_Replace_inner) = playlist_Replace; \ - ((p_symbols)->playlist_LockReplace_inner) = playlist_LockReplace; \ ((p_symbols)->playlist_ItemGetById_inner) = playlist_ItemGetById; \ - ((p_symbols)->playlist_LockItemGetById_inner) = playlist_LockItemGetById; \ - ((p_symbols)->playlist_ItemGetByPos_inner) = playlist_ItemGetByPos; \ - ((p_symbols)->playlist_LockItemGetByPos_inner) = playlist_LockItemGetByPos; \ ((p_symbols)->playlist_ItemGetByInput_inner) = playlist_ItemGetByInput; \ - ((p_symbols)->playlist_LockItemGetByInput_inner) = playlist_LockItemGetByInput; \ - ((p_symbols)->playlist_GetPositionById_inner) = playlist_GetPositionById; \ ((p_symbols)->playlist_ItemAddOption_inner) = playlist_ItemAddOption; \ - ((p_symbols)->playlist_Sort_inner) = playlist_Sort; \ - ((p_symbols)->playlist_Move_inner) = playlist_Move; \ ((p_symbols)->playlist_NodeGroup_inner) = playlist_NodeGroup; \ ((p_symbols)->playlist_NodeSort_inner) = playlist_NodeSort; \ ((p_symbols)->playlist_RecursiveNodeSort_inner) = playlist_RecursiveNodeSort; \ @@ -1328,7 +1320,6 @@ struct module_symbols_t ((p_symbols)->net_ListenClose_inner) = net_ListenClose; \ ((p_symbols)->DigestMD5_inner) = DigestMD5; \ ((p_symbols)->ACL_Check_inner) = ACL_Check; \ - ((p_symbols)->playlist_NodeRemoveParent_inner) = playlist_NodeRemoveParent; \ ((p_symbols)->__ACL_Duplicate_inner) = __ACL_Duplicate; \ ((p_symbols)->__ACL_Create_inner) = __ACL_Create; \ ((p_symbols)->ACL_LoadFile_inner) = ACL_LoadFile; \ @@ -1439,9 +1430,53 @@ struct module_symbols_t ((p_symbols)->decode_URI_inner) = decode_URI; \ ((p_symbols)->encode_URI_component_inner) = encode_URI_component; \ ((p_symbols)->vlc_strlcpy_inner) = vlc_strlcpy; \ + ((p_symbols)->__input_ItemNewExt_inner) = __input_ItemNewExt; \ + ((p_symbols)->input_ItemNewWithType_inner) = input_ItemNewWithType; \ + ((p_symbols)->playlist_NodeAddInput_inner) = playlist_NodeAddInput; \ + ((p_symbols)->playlist_PlaylistAdd_inner) = playlist_PlaylistAdd; \ + ((p_symbols)->playlist_PlaylistAddExt_inner) = playlist_PlaylistAddExt; \ + ((p_symbols)->playlist_PlaylistAddInput_inner) = playlist_PlaylistAddInput; \ + ((p_symbols)->playlist_BothAddInput_inner) = playlist_BothAddInput; \ + ((p_symbols)->__playlist_ItemNewFromInput_inner) = __playlist_ItemNewFromInput; \ + ((p_symbols)->input_ItemGetById_inner) = input_ItemGetById; \ + ((p_symbols)->playlist_LiveSearchUpdate_inner) = playlist_LiveSearchUpdate; \ + ((p_symbols)->vlc_input_item_AddOption_inner) = vlc_input_item_AddOption; \ + ((p_symbols)->playlist_DeleteFromInput_inner) = playlist_DeleteFromInput; \ + ((p_symbols)->playlist_DeleteAllFromInput_inner) = playlist_DeleteAllFromInput; \ + ((p_symbols)->playlist_LockDeleteAllFromInput_inner) = playlist_LockDeleteAllFromInput; \ + ((p_symbols)->playlist_AddWhereverNeeded_inner) = playlist_AddWhereverNeeded; \ + ((p_symbols)->playlist_DeleteFromItemId_inner) = playlist_DeleteFromItemId; \ + ((p_symbols)->playlist_NodeDump_inner) = playlist_NodeDump; \ + ((p_symbols)->__intf_UserOkayCancel_inner) = __intf_UserOkayCancel; \ + ((p_symbols)->__intf_UserStringInput_inner) = __intf_UserStringInput; \ (p_symbols)->net_ConvertIPv4_deprecated = NULL; \ + (p_symbols)->playlist_ItemAddParent_deprecated = NULL; \ + (p_symbols)->playlist_CopyParents_deprecated = NULL; \ + (p_symbols)->playlist_ViewInsert_deprecated = NULL; \ + (p_symbols)->playlist_ViewDelete_deprecated = NULL; \ + (p_symbols)->playlist_ViewFind_deprecated = NULL; \ + (p_symbols)->playlist_ViewUpdate_deprecated = NULL; \ + (p_symbols)->playlist_ViewDump_deprecated = NULL; \ + (p_symbols)->playlist_ViewEmpty_deprecated = NULL; \ + (p_symbols)->playlist_Add_deprecated = NULL; \ + (p_symbols)->playlist_AddExt_deprecated = NULL; \ + (p_symbols)->playlist_ItemAdd_deprecated = NULL; \ + (p_symbols)->playlist_Delete_deprecated = NULL; \ + (p_symbols)->playlist_Disable_deprecated = NULL; \ + (p_symbols)->playlist_Enable_deprecated = NULL; \ + (p_symbols)->playlist_Replace_deprecated = NULL; \ + (p_symbols)->playlist_LockReplace_deprecated = NULL; \ + (p_symbols)->playlist_LockItemGetById_deprecated = NULL; \ + (p_symbols)->playlist_ItemGetByPos_deprecated = NULL; \ + (p_symbols)->playlist_LockItemGetByPos_deprecated = NULL; \ + (p_symbols)->playlist_LockItemGetByInput_deprecated = NULL; \ + (p_symbols)->playlist_GetPositionById_deprecated = NULL; \ + (p_symbols)->playlist_Sort_deprecated = NULL; \ + (p_symbols)->playlist_Move_deprecated = NULL; \ + (p_symbols)->playlist_NodeRemoveParent_deprecated = NULL; \ (p_symbols)->__stats_CounterGet_deprecated = NULL; \ (p_symbols)->__stats_TimerDumpAll_deprecated = NULL; \ + (p_symbols)->playlist_ItemNewFromInput_deprecated = NULL; \ # endif /* __PLUGIN__ */ #endif /* __VLC_SYMBOLS_H */ diff --git a/modules/access/cdda.c b/modules/access/cdda.c index 5b3dbf1bcc..db9860737b 100644 --- a/modules/access/cdda.c +++ b/modules/access/cdda.c @@ -216,7 +216,7 @@ static int Open( vlc_object_t *p_this ) if( !p_playlist ) return VLC_EGENERIC; /* Let's check if we need to play */ - if( &p_playlist->status.p_item->input == + if( p_playlist->status.p_item->p_input == ((input_thread_t *)p_access->p_parent)->input.p_item ) { p_item = p_playlist->status.p_item; @@ -290,8 +290,7 @@ static int Open( vlc_object_t *p_this ) if( b_play ) { playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, - p_playlist->status.i_view, p_playlist->status.p_item, - NULL ); + p_playlist->status.p_item, NULL ); } if( p_playlist ) vlc_object_release( p_playlist ); @@ -445,7 +444,7 @@ static int Control( access_t *p_access, int i_query, va_list args ) input_title_t ***ppp_title; int i; char *psz_title; - vlc_meta_t **pp_meta; + vlc_meta_t *p_meta; switch( i_query ) { @@ -511,9 +510,8 @@ static int Control( access_t *p_access, int i_query, va_list args ) psz_title = malloc( strlen( _("Audio CD - Track ") ) + 5 ); snprintf( psz_title, 100, _("Audio CD - Track %i" ), p_access->info.i_title+1 ); - pp_meta = (vlc_meta_t**)va_arg( args, vlc_meta_t** ); - *pp_meta = vlc_meta_New(); - vlc_meta_Add( *pp_meta, _(VLC_META_TITLE), psz_title ); + p_meta = (vlc_meta_t*)va_arg( args, vlc_meta_t* ); + vlc_meta_SetTitle( p_meta, psz_title ); free( psz_title ); break; @@ -534,7 +532,7 @@ static int GetTracks( access_t *p_access, vlc_bool_t b_separate, { access_sys_t *p_sys = p_access->p_sys; int i; - playlist_item_t *p_item; + input_item_t *p_input_item; char *psz_name; p_sys->i_titles = ioctl_GetTracksMap( VLC_OBJECT(p_access), p_sys->vcddev, &p_sys->p_sectors ); @@ -560,7 +558,7 @@ static int GetTracks( access_t *p_access, vlc_bool_t b_separate, playlist_ItemSetName( p_parent, psz_name ); vlc_mutex_unlock( &p_playlist->object_lock ); var_SetInteger( p_playlist, "item-change", - p_parent->input.i_id ); + p_parent->p_input->i_id ); free( psz_name ); #ifdef HAVE_LIBCDDB @@ -575,7 +573,7 @@ static int GetTracks( access_t *p_access, vlc_bool_t b_separate, playlist_ItemSetName( p_parent, psz_name ); vlc_mutex_unlock( &p_playlist->object_lock ); var_SetInteger( p_playlist, "item-change", - p_parent->input.i_id ); + p_parent->p_input->i_id ); free( psz_name ); } } @@ -615,9 +613,10 @@ static int GetTracks( access_t *p_access, vlc_bool_t b_separate, sprintf( psz_name, _("Audio CD - Track %i"), (i+1) ); /* Create playlist items */ - p_item = playlist_ItemNewWithType( VLC_OBJECT( p_playlist ), - psz_uri, psz_name, ITEM_TYPE_DISC ); - playlist_ItemAddOption( p_item, psz_opt ); + p_input_item = input_ItemNewWithType( VLC_OBJECT( p_playlist ), + psz_uri, psz_name, 0, NULL, -1, + ITEM_TYPE_DISC ); + vlc_input_item_AddOption( p_input_item, psz_opt ); #ifdef HAVE_LIBCDDB /* If we have CDDB info, change the name */ if( p_sys->p_disc ) @@ -628,28 +627,27 @@ static int GetTracks( access_t *p_access, vlc_bool_t b_separate, { if( cddb_track_get_title( t ) != NULL ) { - vlc_input_item_AddInfo( &p_item->input, + vlc_input_item_AddInfo( p_input_item, _(VLC_META_INFO_CAT), _(VLC_META_TITLE), cddb_track_get_title( t ) ); - if( p_item->input.psz_name ) - free( p_item->input.psz_name ); - asprintf( &p_item->input.psz_name, "%s", + if( p_input_item->psz_name ) + free( p_input_item->psz_name ); + asprintf( &p_input_item->psz_name, "%s", cddb_track_get_title( t ) ); } psz_result = cddb_track_get_artist( t ); if( psz_result ) { - vlc_input_item_AddInfo( &p_item->input, + vlc_input_item_AddInfo( p_input_item, _(VLC_META_INFO_CAT), _(VLC_META_ARTIST), psz_result ); } } } #endif - playlist_NodeAddItem( p_playlist, p_item, - p_parent->pp_parents[0]->i_view, - p_parent, PLAYLIST_APPEND, PLAYLIST_END ); + playlist_BothAddInput( p_playlist, p_input_item, p_parent, + PLAYLIST_APPEND, PLAYLIST_END ); free( psz_uri ); free( psz_opt ); free( psz_name ); } } diff --git a/modules/access/cdda/cdda.c b/modules/access/cdda/cdda.c index a890350994..227f76cf8c 100644 --- a/modules/access/cdda/cdda.c +++ b/modules/access/cdda/cdda.c @@ -40,7 +40,7 @@ #if LIBCDIO_VERSION_NUM >= 72 static char *psz_paranoia_list[] = { "none", "overlap", "full" }; static char *psz_paranoia_list_text[] = { N_("none"), N_("overlap"), - N_("full") }; + N_("full") }; #endif #define DEBUG_LONGTEXT N_( \ diff --git a/modules/access/directory.c b/modules/access/directory.c index 5d273207ca..4ebb1a0bfc 100644 --- a/modules/access/directory.c +++ b/modules/access/directory.c @@ -124,7 +124,7 @@ static int DemuxControl( demux_t *p_demux, int i_query, va_list args ); static int ReadDir( playlist_t *, const char *psz_name, int i_mode, - playlist_item_t * ); + playlist_item_t *, playlist_item_t * ); /***************************************************************************** * Open: open the directory @@ -198,9 +198,9 @@ static int Read( access_t *p_access, uint8_t *p_buffer, int i_len) { char *psz_name = NULL; char *psz; - int i_mode, i_pos; + int i_mode, i_activity; - playlist_item_t *p_item; + playlist_item_t *p_item, *p_root_category; vlc_bool_t b_play = VLC_FALSE; playlist_t *p_playlist = @@ -212,54 +212,41 @@ static int Read( access_t *p_access, uint8_t *p_buffer, int i_len) msg_Err( p_access, "can't find playlist" ); goto end; } - else - { - char *ptr; - psz_name = ToLocale( p_access->psz_path ); - ptr = strdup( psz_name ); - LocaleFree( psz_name ); - if( ptr == NULL ) - goto end; + char *ptr; + psz_name = ToLocale( p_access->psz_path ); + ptr = strdup( psz_name ); + LocaleFree( psz_name ); + if( ptr == NULL ) + goto end; - psz_name = ptr; + psz_name = ptr; - /* Remove the ending '/' char */ - ptr += strlen( ptr ); - if( ( ptr > psz_name ) ) + /* Remove the ending '/' char */ + ptr += strlen( ptr ); + if( ( ptr > psz_name ) ) + { + switch( *--ptr ) { - switch( *--ptr ) - { - case '/': - case '\\': - *ptr = '\0'; - } + case '/': + case '\\': + *ptr = '\0'; } } - /* Initialize structure */ + /* Handle mode */ psz = var_CreateGetString( p_access, "recursive" ); if( *psz == '\0' || !strncmp( psz, "none" , 4 ) ) - { i_mode = MODE_NONE; - } else if( !strncmp( psz, "collapse", 8 ) ) - { i_mode = MODE_COLLAPSE; - } else - { i_mode = MODE_EXPAND; - } free( psz ); - /* Make sure we are deleted when we are done */ - /* The playlist position we will use for the add */ - i_pos = p_playlist->i_index + 1; - msg_Dbg( p_access, "opening directory `%s'", p_access->psz_path ); - if( &p_playlist->status.p_item->input == + if( p_playlist->status.p_item->p_input == ((input_thread_t *)p_access->p_parent)->input.p_item ) { p_item = p_playlist->status.p_item; @@ -279,19 +266,29 @@ static int Read( access_t *p_access, uint8_t *p_buffer, int i_len) } b_play = VLC_FALSE; } + p_item->p_input->i_type = ITEM_TYPE_DIRECTORY; - p_item->input.i_type = ITEM_TYPE_DIRECTORY; - if( ReadDir( p_playlist, psz_name , i_mode, p_item ) != VLC_SUCCESS ) - { - } + p_root_category = playlist_LockItemToNode( p_playlist, p_item ); + + i_activity = var_GetInteger( p_playlist, "activity" ); + var_SetInteger( p_playlist, "activity", i_activity + + DIRECTORY_ACTIVITY ); + + ReadDir( p_playlist, psz_name , i_mode, p_item, p_root_category ); + + i_activity = var_GetInteger( p_playlist, "activity" ); + var_SetInteger( p_playlist, "activity", i_activity - + DIRECTORY_ACTIVITY ); end: /* Begin to read the directory */ if( b_play ) { - playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, - p_playlist->status.i_view, +#if 0 + /// \bug we can start playing an already deleted item. Fix ?*/ + playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, 1242, p_playlist->status.p_item, NULL ); +#endif } if( psz_name ) free( psz_name ); vlc_object_release( p_playlist ); @@ -387,7 +384,8 @@ static int Filter( const struct dirent *foo ) * ReadDir: read a directory and add its content to the list *****************************************************************************/ static int ReadDir( playlist_t *p_playlist, const char *psz_name, - int i_mode, playlist_item_t *p_parent ) + int i_mode, playlist_item_t *p_parent, + playlist_item_t *p_parent_category ) { struct dirent **pp_dir_content; int i_dir_content, i; @@ -424,12 +422,6 @@ static int ReadDir( playlist_t *p_playlist, const char *psz_name, } } - /* Change the item to a node */ - if( p_parent->i_children == -1 ) - { - playlist_LockItemToNode( p_playlist,p_parent ); - } - /* get the first directory entry */ i_dir_content = scandir( psz_name, &pp_dir_content, Filter, alphasort ); if( i_dir_content == -1 ) @@ -498,16 +490,22 @@ static int ReadDir( playlist_t *p_playlist, const char *psz_name, p_playlist, psz_tmp ); LocaleFree( psz_tmp ); - p_node = playlist_NodeCreate( p_playlist, - p_parent->pp_parents[0]->i_view, - psz_newname, p_parent ); - - playlist_CopyParents( p_parent, p_node ); - - p_node->input.i_type = ITEM_TYPE_DIRECTORY; + if( p_parent_category ) + { + p_node = playlist_NodeCreate( p_playlist, psz_newname, + p_parent_category ); + } + else + { + p_node = playlist_NodeCreate( p_playlist, psz_newname, + p_parent_category ); + } + /* If we had the parent in category, the it is now node. + * Else, we still don't have */ if( ReadDir( p_playlist, psz_uri , MODE_EXPAND, - p_node ) != VLC_SUCCESS ) + p_node, p_parent_category ? p_node : NULL ) + != VLC_SUCCESS ) { return VLC_EGENERIC; } @@ -518,7 +516,7 @@ static int ReadDir( playlist_t *p_playlist, const char *psz_name, } else { - playlist_item_t *p_item; + input_item_t *p_input; char *psz_tmp1, *psz_tmp2, *psz_loc; if( i_extensions > 0 ) @@ -551,15 +549,13 @@ static int ReadDir( playlist_t *p_playlist, const char *psz_name, psz_loc ); LocaleFree( psz_loc ); - p_item = playlist_ItemNewWithType( VLC_OBJECT(p_playlist), - psz_tmp1, psz_tmp2, ITEM_TYPE_VFILE ); - playlist_NodeAddItem( p_playlist,p_item, - p_parent->pp_parents[0]->i_view, - p_parent, - PLAYLIST_APPEND | PLAYLIST_PREPARSE, - PLAYLIST_END ); + p_input = input_ItemNewWithType( VLC_OBJECT(p_playlist), + psz_tmp1, psz_tmp2, 0, NULL, + -1, ITEM_TYPE_VFILE ); - playlist_CopyParents( p_parent, p_item ); + playlist_AddWhereverNeeded( p_playlist, p_input, p_parent, + p_parent_category, VLC_FALSE, + PLAYLIST_APPEND|PLAYLIST_PREPARSE); } } free( psz_uri ); diff --git a/modules/access/dvdnav.c b/modules/access/dvdnav.c index 387b32762e..f362e3eecf 100644 --- a/modules/access/dvdnav.c +++ b/modules/access/dvdnav.c @@ -543,10 +543,8 @@ static int Control( demux_t *p_demux, int i_query, va_list args ) dvdnav_get_title_string(p_sys->dvdnav, &title_name); if( (NULL != title_name) && ('\0' != title_name[0]) ) { - vlc_meta_t **pp_meta = (vlc_meta_t**)va_arg( args, vlc_meta_t** ); - vlc_meta_t *meta; - *pp_meta = meta = vlc_meta_New(); - vlc_meta_Add( meta, VLC_META_TITLE, title_name ); + vlc_meta_t *p_meta = (vlc_meta_t*)va_arg( args, vlc_meta_t* ); + vlc_meta_SetTitle( p_meta, title_name ); return VLC_SUCCESS; } return VLC_EGENERIC; diff --git a/modules/access/http.c b/modules/access/http.c index 2905d59c03..2bc605250e 100644 --- a/modules/access/http.c +++ b/modules/access/http.c @@ -337,9 +337,9 @@ connect: goto error; } - /* Change the uri */ + /* Change the URI */ vlc_mutex_lock( &p_playlist->object_lock ); - p_input_item = &p_playlist->status.p_item->input; + p_input_item = p_playlist->status.p_item->p_input; vlc_mutex_lock( &p_input_item->lock ); free( p_input_item->psz_uri ); free( p_access->psz_path ); @@ -696,7 +696,7 @@ static int Control( access_t *p_access, int i_query, va_list args ) vlc_bool_t *pb_bool; int *pi_int; int64_t *pi_64; - vlc_meta_t **pp_meta; + vlc_meta_t *p_meta; switch( i_query ) { @@ -736,18 +736,14 @@ static int Control( access_t *p_access, int i_query, va_list args ) break; case ACCESS_GET_META: - pp_meta = (vlc_meta_t**)va_arg( args, vlc_meta_t** ); - *pp_meta = vlc_meta_New(); + p_meta = (vlc_meta_t*)va_arg( args, vlc_meta_t* ); if( p_sys->psz_icy_name ) - vlc_meta_Add( *pp_meta, VLC_META_TITLE, - p_sys->psz_icy_name ); + vlc_meta_SetTitle( p_meta, p_sys->psz_icy_name ); if( p_sys->psz_icy_genre ) - vlc_meta_Add( *pp_meta, VLC_META_GENRE, - p_sys->psz_icy_genre ); + vlc_meta_SetGenre( p_meta, p_sys->psz_icy_genre ); if( p_sys->psz_icy_title ) - vlc_meta_Add( *pp_meta, VLC_META_NOW_PLAYING, - p_sys->psz_icy_title ); + vlc_meta_SetNowPlaying( p_meta, p_sys->psz_icy_title ); break; case ACCESS_GET_TITLE_INFO: diff --git a/modules/access/mms/mmsh.c b/modules/access/mms/mmsh.c index 4d32bd1f88..6786972d0d 100644 --- a/modules/access/mms/mmsh.c +++ b/modules/access/mms/mmsh.c @@ -118,10 +118,9 @@ int E_(MMSHOpen)( access_t *p_access ) free( psz_location ); return VLC_EGENERIC; } - p_playlist->pp_items[p_playlist->i_index]->b_autodeletion = VLC_TRUE; - playlist_Add( p_playlist, psz_location, psz_location, - PLAYLIST_INSERT | PLAYLIST_GO, - p_playlist->i_index + 1 ); + /** \bug we do not autodelete here */ + playlist_PlaylistAdd( p_playlist, psz_location, psz_location, + PLAYLIST_INSERT | PLAYLIST_GO, PLAYLIST_END ); vlc_object_release( p_playlist ); free( psz_location ); diff --git a/modules/codec/cmml/intf.c b/modules/codec/cmml/intf.c index b8a71fd124..7c633b594a 100644 --- a/modules/codec/cmml/intf.c +++ b/modules/codec/cmml/intf.c @@ -13,7 +13,7 @@ * 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 @@ -192,7 +192,7 @@ static void RunIntf( intf_thread_t *p_intf ) /* Main loop */ while( !p_intf->b_die ) { - + /* find a video output if we currently don't have one */ if( p_vout == NULL ) { @@ -412,7 +412,7 @@ static int KeyEvent( vlc_object_t *p_this, char const *psz_var, vlc_mutex_lock( &p_intf->change_lock ); p_intf->p_sys->b_key_pressed = VLC_TRUE; - + vlc_mutex_unlock( &p_intf->change_lock ); return VLC_SUCCESS; @@ -451,7 +451,7 @@ static void FollowAnchor ( intf_thread_t *p_intf ) mtime_t i_seconds; vlc_value_t time; - p_playlist = (playlist_t *) vlc_object_find( p_intf, + p_playlist = (playlist_t *) vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); if ( !p_playlist ) { @@ -460,13 +460,13 @@ static void FollowAnchor ( intf_thread_t *p_intf ) } /* Get new URL */ - p_current_item = p_playlist->pp_items[p_playlist->i_index]; + p_current_item = p_playlist->status.p_item; #ifdef CMML_INTF_DEBUG msg_Dbg( p_intf, "Current playlist item URL is \"%s\"", p_current_item->input.psz_uri ); #endif - psz_uri_to_load = XURL_Concat( p_current_item->input.psz_uri, + psz_uri_to_load = XURL_Concat( p_current_item->p_input->psz_uri, psz_url ); #ifdef CMML_INTF_DEBUG @@ -550,7 +550,7 @@ char *GetTimedURLFromPlaylistItem( intf_thread_t *p_intf, char *psz_return_value = NULL; char *psz_seconds = NULL; int i_seconds; - + psz_url = XURL_GetWithoutFragment( p_current_item->input->psz_uri ); /* Get current time as a string */ @@ -577,7 +577,7 @@ char *GetTimedURLFromPlaylistItem( intf_thread_t *p_intf, p = GetTimedURIFragmentForTime; /* unused */ p = GetCurrentTimeInSeconds; /* unused */ - return strdup( p_current_item->input.psz_uri ); + return strdup( p_current_item->p_input->psz_uri ); #endif } @@ -653,7 +653,7 @@ void GoBack( intf_thread_t *p_intf ) #endif /* Find the playlist */ - p_playlist = (playlist_t *) vlc_object_find( p_intf, + p_playlist = (playlist_t *) vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); if ( !p_playlist ) { @@ -686,7 +686,7 @@ void GoBack( intf_thread_t *p_intf ) return; } - p_current_item = p_playlist->pp_items[p_playlist->i_index]; + p_current_item = p_playlist->status.p_item; /* Save the currently-playing media in a new history item */ psz_timed_url = GetTimedURLFromPlaylistItem( p_intf, p_current_item ); @@ -731,7 +731,7 @@ void GoForward( intf_thread_t *p_intf ) #endif /* Find the playlist */ - p_playlist = (playlist_t *) vlc_object_find( p_intf, + p_playlist = (playlist_t *) vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); if ( !p_playlist ) { @@ -774,8 +774,8 @@ void GoForward( intf_thread_t *p_intf ) vlc_object_release( p_playlist ); return; } - p_current_item = p_playlist->pp_items[p_playlist->i_index]; - p_new_history_item->psz_uri = GetTimedURLFromPlaylistItem( p_intf, + p_current_item = p_playlist->status.p_item; + p_new_history_item->psz_uri = GetTimedURLFromPlaylistItem( p_intf, p_current_item ); p_new_history_item->psz_name = p_new_history_item->psz_uri; @@ -796,9 +796,8 @@ void GoForward( intf_thread_t *p_intf ) static void ReplacePlaylistItem( playlist_t *p_playlist, char *psz_uri ) { playlist_Stop( p_playlist ); - (void) playlist_Add( p_playlist, psz_uri, psz_uri, - PLAYLIST_REPLACE, p_playlist->i_index ); - playlist_Goto( p_playlist, p_playlist->i_index ); + (void) playlist_PlaylistAdd( p_playlist, psz_uri, psz_uri, + PLAYLIST_INSERT /* FIXME: used to be PLAYLIST_REPLACE */, PLAYLIST_END|PLAYLIST_GO /* FIXME: p_playlist->status.i_index */ ); } /**************************************************************************** diff --git a/modules/control/hotkeys.c b/modules/control/hotkeys.c index faee64c5a7..9b1c321d95 100644 --- a/modules/control/hotkeys.c +++ b/modules/control/hotkeys.c @@ -900,7 +900,7 @@ static int ActionKeyCB( vlc_object_t *p_this, char const *psz_var, static void PlayBookmark( intf_thread_t *p_intf, int i_num ) { vlc_value_t val; - int i_position; + int i; char psz_bookmark_name[11]; playlist_t *p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); @@ -912,12 +912,13 @@ static void PlayBookmark( intf_thread_t *p_intf, int i_num ) if( p_playlist ) { char *psz_bookmark = strdup( val.psz_string ); - for( i_position = 0; i_position < p_playlist->i_size; i_position++) + for( i = 0; i < p_playlist->pp_all_items; i++) { if( !strcmp( psz_bookmark, - p_playlist->pp_items[i_position]->input.psz_uri ) ) + p_playlist->pp_items[i]->p_input->psz_uri ) ) { - playlist_Goto( p_playlist, i_position ); + playlist_LockControl( p_playlist, PLAYLIST_ITEMPLAY, + p_playlist->pp_items[i] ); break; } } @@ -938,9 +939,9 @@ static void SetBookmark( intf_thread_t *p_intf, int i_num ) if( p_playlist->status.p_item ) { config_PutPsz( p_intf, psz_bookmark_name, - p_playlist->status.p_item->input.psz_uri); + p_playlist->status.p_item->p_input->psz_uri); msg_Info( p_intf, "setting playlist bookmark %i to %s", i_num, - p_playlist->status.p_item->input.psz_uri); + p_playlist->status.p_item->p_input->psz_uri); config_SaveConfigFile( p_intf, "hotkeys" ); } vlc_object_release( p_playlist ); diff --git a/modules/control/http/http.h b/modules/control/http/http.h index b08f558b9d..4d274c7429 100644 --- a/modules/control/http/http.h +++ b/modules/control/http/http.h @@ -130,7 +130,7 @@ char *E_(ExtractURIValue)( char *psz_uri, const char *psz_name, int E_(TestURIParam)( char *psz_uri, const char *psz_name ); /** This function parses a MRL */ -playlist_item_t *E_(MRLParse)( intf_thread_t *, char *psz, char *psz_name ); +input_item_t *E_(MRLParse)( intf_thread_t *, char *psz, char *psz_name ); /** Return the first word from a string (works in-place) */ char *E_(FirstWord)( char *psz, char *new ); diff --git a/modules/control/http/macro.c b/modules/control/http/macro.c index 60c5454248..34795bb65c 100644 --- a/modules/control/http/macro.c +++ b/modules/control/http/macro.c @@ -303,7 +303,7 @@ void E_(MacroDo)( httpd_file_sys_t *p_args, { char mrl[1024], psz_name[1024], tmp[1024]; char *p, *str; - playlist_item_t *p_item; + input_item_t *p_input; E_(ExtractURIValue)( p_request, "mrl", tmp, 1024 ); decode_URI( tmp ); @@ -327,16 +327,16 @@ void E_(MacroDo)( httpd_file_sys_t *p_args, } *p = '\0'; - p_item = E_(MRLParse)( p_intf, mrl, psz_name ); + p_input = E_(MRLParse)( p_intf, mrl, psz_name ); - if( !p_item || !p_item->input.psz_uri || - !*p_item->input.psz_uri ) + if( !p_input || p_input->psz_uri || + !*p_input->psz_uri ) { msg_Dbg( p_intf, "invalid requested mrl: %s", mrl ); } else { - playlist_AddItem( p_sys->p_playlist, p_item, + playlist_PlaylistAddInput( p_sys->p_playlist, p_input, PLAYLIST_APPEND, PLAYLIST_END ); msg_Dbg( p_intf, "requested mrl add: %s", mrl ); } @@ -401,11 +401,13 @@ void E_(MacroDo)( httpd_file_sys_t *p_args, for( j = 0 ; j < i_nb_items ; j++ ) { if( p_items[j] == - p_sys->p_playlist->pp_items[i]->input.i_id ) break; + p_sys->p_playlist->pp_items[i]->p_input->i_id ) + break; } if( j == i_nb_items ) { - playlist_LockDelete( p_sys->p_playlist, p_sys->p_playlist->pp_items[i]->input.i_id ); + playlist_LockDelete( p_sys->p_playlist, + p_sys->p_playlist->pp_items[i]->p_input->i_id ); msg_Dbg( p_intf, "requested playlist delete: %d", i ); } @@ -439,7 +441,8 @@ void E_(MacroDo)( httpd_file_sys_t *p_args, if( !strcmp( type , "title" ) ) { playlist_RecursiveNodeSort( p_sys->p_playlist, /*playlist_ItemGetById( p_sys->p_playlist, i_item ),*/ - p_sys->p_playlist->pp_views[0]->p_root, + /* Ugly hack,but not worse than before ... */ + p_sys->p_playlist->p_root_onelevel, SORT_TITLE_NODES_FIRST, ( i_order == 0 ) ? ORDER_NORMAL : ORDER_REVERSE ); msg_Dbg( p_intf, "requested playlist sort by title (%d)" , i_order ); @@ -447,7 +450,7 @@ void E_(MacroDo)( httpd_file_sys_t *p_args, else if( !strcmp( type , "author" ) ) { playlist_RecursiveNodeSort( p_sys->p_playlist, /*playlist_ItemGetById( p_sys->p_playlist, i_item ),*/ - p_sys->p_playlist->pp_views[0]->p_root, + p_sys->p_playlist->p_root_onelevel, SORT_AUTHOR, ( i_order == 0 ) ? ORDER_NORMAL : ORDER_REVERSE ); msg_Dbg( p_intf, "requested playlist sort by author (%d)" , i_order ); @@ -455,7 +458,7 @@ void E_(MacroDo)( httpd_file_sys_t *p_args, else if( !strcmp( type , "shuffle" ) ) { playlist_RecursiveNodeSort( p_sys->p_playlist, /*playlist_ItemGetById( p_sys->p_playlist, i_item ),*/ - p_sys->p_playlist->pp_views[0]->p_root, + p_sys->p_playlist->p_root_onelevel, SORT_RANDOM, ( i_order == 0 ) ? ORDER_NORMAL : ORDER_REVERSE ); msg_Dbg( p_intf, "requested playlist shuffle"); @@ -473,6 +476,8 @@ void E_(MacroDo)( httpd_file_sys_t *p_args, E_(ExtractURIValue)( p_request, "psz_newpos", psz_newpos, 6 ); i_pos = atoi( psz_pos ); i_newpos = atoi( psz_newpos ); + /* FIXME FIXME TODO TODO XXX XXX + ( duplicate from rpn.c ) if ( i_pos < i_newpos ) { playlist_Move( p_sys->p_playlist, i_pos, i_newpos + 1 ); @@ -482,6 +487,7 @@ void E_(MacroDo)( httpd_file_sys_t *p_args, playlist_Move( p_sys->p_playlist, i_pos, i_newpos ); } msg_Dbg( p_intf, "requested move playlist item %d to %d", i_pos, i_newpos); + FIXME FIXME TODO TODO XXX XXX */ break; } diff --git a/modules/control/http/mvar.c b/modules/control/http/mvar.c index e3d262bc0e..bbad22de3e 100644 --- a/modules/control/http/mvar.c +++ b/modules/control/http/mvar.c @@ -279,19 +279,10 @@ mvar_t *E_(mvar_IntegerSetNew)( const char *name, const char *arg ) mvar_t *E_(mvar_PlaylistSetNew)( intf_thread_t *p_intf, char *name, playlist_t *p_pl ) { - playlist_view_t *p_view; mvar_t *s = E_(mvar_New)( name, "set" ); - - vlc_mutex_lock( &p_pl->object_lock ); - - p_view = playlist_ViewFind( p_pl, VIEW_CATEGORY ); /* FIXME */ - - if( p_view != NULL ) - E_(PlaylistListNode)( p_intf, p_pl, p_view->p_root, name, s, 0 ); - + E_(PlaylistListNode)( p_intf, p_pl, p_pl->p_root_category , name, s, 0 ); vlc_mutex_unlock( &p_pl->object_lock ); - return s; } diff --git a/modules/control/http/rpn.c b/modules/control/http/rpn.c index 09b072f89d..14c15167fb 100644 --- a/modules/control/http/rpn.c +++ b/modules/control/http/rpn.c @@ -830,7 +830,7 @@ void E_(EvaluateRPN)( intf_thread_t *p_intf, mvar_t *vars, char *psz_name = E_(SSPop)( st ); char *mrl = E_(SSPop)( st ); char *tmp; - playlist_item_t *p_item; + input_item_t *p_input; int i_id; tmp = E_(ToUTF8)( p_intf, psz_name ); @@ -842,22 +842,21 @@ void E_(EvaluateRPN)( intf_thread_t *p_intf, mvar_t *vars, if( !*psz_name ) { - p_item = E_(MRLParse)( p_intf, mrl, mrl ); + p_input = E_(MRLParse)( p_intf, mrl, mrl ); } else { - p_item = E_(MRLParse)( p_intf, mrl, psz_name ); + p_input = E_(MRLParse)( p_intf, mrl, psz_name ); } - if( p_item == NULL || p_item->input.psz_uri == NULL || - !*p_item->input.psz_uri ) + if( !p_input || !p_input->psz_uri || !*p_input->psz_uri ) { i_id = VLC_EGENERIC; msg_Dbg( p_intf, "invalid requested mrl: %s", mrl ); } else { - i_id = playlist_AddItem( p_sys->p_playlist, p_item, + i_id = playlist_PlaylistAddInput( p_sys->p_playlist, p_input, PLAYLIST_APPEND, PLAYLIST_END ); msg_Dbg( p_intf, "requested mrl add: %s", mrl ); } @@ -879,8 +878,10 @@ void E_(EvaluateRPN)( intf_thread_t *p_intf, mvar_t *vars, } else if( !strcmp( s, "playlist_move" ) ) { - int i_newpos = E_(SSPopN)( st, vars ); - int i_pos = E_(SSPopN)( st, vars ); + /*int i_newpos =*/ E_(SSPopN)( st, vars ); + /*int i_pos =*/ E_(SSPopN)( st, vars ); + /* FIXME FIXME TODO TODO XXX XXX + do not release before fixing this if ( i_pos < i_newpos ) { playlist_Move( p_sys->p_playlist, i_pos, i_newpos + 1 ); @@ -891,6 +892,8 @@ void E_(EvaluateRPN)( intf_thread_t *p_intf, mvar_t *vars, } msg_Dbg( p_intf, "requested to move playlist item %d to %d", i_pos, i_newpos); + FIXME FIXME TODO TODO XXX XXX */ + msg_Err( p_intf, "moving using indexes is obsolete. We need to update this function" ); } else if( !strcmp( s, "playlist_sort" ) ) { @@ -898,11 +901,15 @@ void E_(EvaluateRPN)( intf_thread_t *p_intf, mvar_t *vars, int i_sort = E_(SSPopN)( st, vars ); i_order = i_order % 2; i_sort = i_sort % 9; + /* FIXME FIXME TODO TODO XXX XXX + do not release before fixing this playlist_RecursiveNodeSort( p_sys->p_playlist, p_sys->p_playlist->p_general, i_sort, i_order ); msg_Dbg( p_intf, "requested sort playlist by : %d in order : %d", i_sort, i_order ); + FIXME FIXME TODO TODO XXX XXX */ + msg_Err( p_intf, "this needs to be fixed to use the new playlist framework" ); } else if( !strcmp( s, "services_discovery_add" ) ) { diff --git a/modules/control/http/util.c b/modules/control/http/util.c index ae29a2caa3..6f2a32f9f4 100644 --- a/modules/control/http/util.c +++ b/modules/control/http/util.c @@ -428,14 +428,14 @@ void E_(PlaylistListNode)( intf_thread_t *p_intf, playlist_t *p_pl, sprintf( value, "%d", ( p_pl->status.p_item == p_node )? 1 : 0 ); E_(mvar_AppendNewVar)( itm, "current", value ); - sprintf( value, "%d", p_node->input.i_id ); + sprintf( value, "%d", p_node->p_input->i_id ); E_(mvar_AppendNewVar)( itm, "index", value ); - psz = E_(FromUTF8)( p_intf, p_node->input.psz_name ); + psz = E_(FromUTF8)( p_intf, p_node->p_input->psz_name ); E_(mvar_AppendNewVar)( itm, "name", psz ); free( psz ); - psz = E_(FromUTF8)( p_intf, p_node->input.psz_uri ); + psz = E_(FromUTF8)( p_intf, p_node->p_input->psz_uri ); E_(mvar_AppendNewVar)( itm, "uri", psz ); free( psz ); @@ -454,7 +454,7 @@ void E_(PlaylistListNode)( intf_thread_t *p_intf, playlist_t *p_pl, E_(mvar_AppendNewVar)( itm, "ro", "rw" ); } - sprintf( value, "%ld", (long)p_node->input.i_duration ); + sprintf( value, "%ld", (long)p_node->p_input->i_duration ); E_(mvar_AppendNewVar)( itm, "duration", value ); E_(mvar_AppendVar)( s, itm ); @@ -466,7 +466,7 @@ void E_(PlaylistListNode)( intf_thread_t *p_intf, playlist_t *p_pl, int i_child; mvar_t *itm = E_(mvar_New)( name, "set" ); - psz = E_(FromUTF8)( p_intf, p_node->input.psz_name ); + psz = E_(FromUTF8)( p_intf, p_node->p_input->psz_name ); E_(mvar_AppendNewVar)( itm, "name", psz ); E_(mvar_AppendNewVar)( itm, "uri", psz ); free( psz ); @@ -474,7 +474,7 @@ void E_(PlaylistListNode)( intf_thread_t *p_intf, playlist_t *p_pl, sprintf( value, "Node" ); E_(mvar_AppendNewVar)( itm, "type", value ); - sprintf( value, "%d", p_node->input.i_id ); + sprintf( value, "%d", p_node->p_input->i_id ); E_(mvar_AppendNewVar)( itm, "index", value ); sprintf( value, "%d", p_node->i_children); @@ -864,13 +864,13 @@ static char *FirstOption( char *psz, char *new ) return NULL; } -playlist_item_t *E_(MRLParse)( intf_thread_t *p_intf, char *_psz, - char *psz_name ) +input_item_t *E_(MRLParse)( intf_thread_t *p_intf, char *_psz, + char *psz_name ) { char *psz = strdup( _psz ); char *s_mrl = psz; char *s_temp; - playlist_item_t * p_item = NULL; + input_item_t * p_input = NULL; /* extract the mrl */ s_temp = FirstOption( s_mrl, s_mrl ); @@ -879,7 +879,7 @@ playlist_item_t *E_(MRLParse)( intf_thread_t *p_intf, char *_psz, s_temp = s_mrl + strlen( s_mrl ); } - p_item = playlist_ItemNew( p_intf, s_mrl, psz_name ); + p_input = input_ItemNew( p_intf, s_mrl, psz_name ); s_mrl = s_temp; /* now we can take care of the options */ @@ -892,13 +892,12 @@ playlist_item_t *E_(MRLParse)( intf_thread_t *p_intf, char *_psz, { s_temp = s_mrl + strlen( s_mrl ); } - playlist_ItemAddOption( p_item, s_mrl ); + vlc_input_item_AddOption( p_input, s_mrl ); s_mrl = s_temp; } free( psz ); - - return p_item; + return p_input; } /********************************************************************** diff --git a/modules/control/rc.c b/modules/control/rc.c index 05c104b182..897b8e2440 100644 --- a/modules/control/rc.c +++ b/modules/control/rc.c @@ -201,7 +201,6 @@ vlc_module_end(); static int Activate( vlc_object_t *p_this ) { intf_thread_t *p_intf = (intf_thread_t*)p_this; - playlist_t *p_playlist; char *psz_host, *psz_unix_path; int *pi_socket = NULL; @@ -321,17 +320,6 @@ static int Activate( vlc_object_t *p_this ) CONSOLE_INTRO_MSG; #endif - /* Force "no-view" mode */ - p_playlist = (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, - FIND_ANYWHERE ); - if( p_playlist ) - { - vlc_mutex_lock( &p_playlist->object_lock ); - p_playlist->status.i_view = -1; - vlc_mutex_unlock( &p_playlist->object_lock ); - vlc_object_release( p_playlist ); - } - msg_rc( _("Remote control interface initialized. Type `help' for help.") ); return VLC_SUCCESS; } @@ -1234,6 +1222,7 @@ static int Playlist( vlc_object_t *p_this, char const *psz_cmd, FIND_ANYWHERE ); if( !p_playlist ) { + msg_Err( p_this, "no playlist" ); return VLC_ENOOBJ; } @@ -1241,7 +1230,8 @@ static int Playlist( vlc_object_t *p_this, char const *psz_cmd, { vlc_value_t val; var_Get( p_playlist->p_input, "state", &val ); - if( ( val.i_int == PAUSE_S ) || ( val.i_int == PLAYLIST_PAUSED ) ) { + if( ( val.i_int == PAUSE_S ) || ( val.i_int == PLAYLIST_PAUSED ) ) + { msg_rc( _("Type 'menu select' or 'pause' to continue.") ); vlc_object_release( p_playlist ); return VLC_EGENERIC; @@ -1259,29 +1249,12 @@ static int Playlist( vlc_object_t *p_this, char const *psz_cmd, } else if( !strcmp( psz_cmd, "play" ) ) { - if( p_playlist->p_input ) - { - vlc_value_t val; - - var_Get( p_playlist->p_input, "rate", &val ); - if( val.i_int != INPUT_RATE_DEFAULT ) - { - val.i_int = INPUT_RATE_DEFAULT; - var_Set( p_playlist->p_input, "rate", val ); - } - else - { - playlist_Play( p_playlist ); - } - } + msg_Warn( p_playlist, "play" ); + playlist_Play( p_playlist ); } else if (!strcmp( psz_cmd, "goto" ) ) { - if( strlen( newval.psz_string ) > 0) - { - val.i_int = atoi( newval.psz_string ); - playlist_Goto( p_playlist, val.i_int); - } + msg_Err( p_playlist, "goto is deprecated" ); } else if( !strcmp( psz_cmd, "stop" ) ) { @@ -1302,26 +1275,16 @@ static int Playlist( vlc_object_t *p_this, char const *psz_cmd, if( p_item ) { msg_rc( "Trying to add %s to playlist.", newval.psz_string ); - playlist_AddItem( p_playlist, p_item, - PLAYLIST_GO|PLAYLIST_APPEND, PLAYLIST_END ); +// playlist_AddItem( p_playlist, p_item, +// PLAYLIST_GO|PLAYLIST_APPEND, PLAYLIST_END ); } } else if( !strcmp( psz_cmd, "playlist" ) ) { int i; - - for ( i = 0; i < p_playlist->i_size; i++ ) - { - msg_rc( "|%s%s %s|%s|", i == p_playlist->i_index ? "*" : " ", - p_playlist->pp_items[i]->input.psz_name, - p_playlist->pp_items[i]->input.psz_uri, - p_playlist->pp_items[i]->i_parents > 0 ? - p_playlist->pp_items[i]->pp_parents[0]->p_parent->input.psz_name : "" ); - } - if ( i == 0 ) - { - msg_rc( "| no entries" ); - } + playlist_view_t *p_view; + playlist_NodeDump( p_playlist, p_playlist->p_root_category, 0 ); + playlist_NodeDump( p_playlist, p_playlist->p_root_onelevel, 0 ); } else if( !strcmp( psz_cmd, "status" ) ) { diff --git a/modules/demux/asf/asf.c b/modules/demux/asf/asf.c index c315a0486f..79c00d9520 100644 --- a/modules/demux/asf/asf.c +++ b/modules/demux/asf/asf.c @@ -219,7 +219,7 @@ static int Control( demux_t *p_demux, int i_query, va_list args ) demux_sys_t *p_sys = p_demux->p_sys; int64_t *pi64; int i; - vlc_meta_t **pp_meta; + vlc_meta_t *p_meta; switch( i_query ) { @@ -232,8 +232,8 @@ static int Control( demux_t *p_demux, int i_query, va_list args ) return VLC_SUCCESS; case DEMUX_GET_META: - pp_meta = (vlc_meta_t**)va_arg( args, vlc_meta_t** ); - *pp_meta = vlc_meta_Duplicate( p_sys->meta ); + p_meta = (vlc_meta_t*)va_arg( args, vlc_meta_t* ); + vlc_meta_Merge( p_meta, p_sys->meta ); return VLC_SUCCESS; case DEMUX_SET_POSITION: @@ -812,25 +812,27 @@ static int DemuxInit( demux_t *p_demux ) { if( p_cd->psz_title && *p_cd->psz_title ) { - vlc_meta_Add( p_sys->meta, VLC_META_TITLE, p_cd->psz_title ); + vlc_meta_SetTitle( p_sys->meta, p_cd->psz_title ); } if( p_cd->psz_author && *p_cd->psz_author ) { - vlc_meta_Add( p_sys->meta, VLC_META_AUTHOR, p_cd->psz_author ); + vlc_meta_SetAuthor( p_sys->meta, p_cd->psz_author ); } if( p_cd->psz_copyright && *p_cd->psz_copyright ) { - vlc_meta_Add( p_sys->meta, VLC_META_COPYRIGHT, p_cd->psz_copyright ); + vlc_meta_SetCopyright( p_sys->meta, p_cd->psz_copyright ); } if( p_cd->psz_description && *p_cd->psz_description ) { - vlc_meta_Add( p_sys->meta, VLC_META_DESCRIPTION, p_cd->psz_description ); + vlc_meta_SetDescription( p_sys->meta, p_cd->psz_description ); } if( p_cd->psz_rating && *p_cd->psz_rating ) { - vlc_meta_Add( p_sys->meta, VLC_META_RATING, p_cd->psz_rating ); + vlc_meta_SetRating( p_sys->meta, p_cd->psz_rating ); } } + fprintf( stderr, "*********** Unhandled child meta\n" ); +#if 0 for( i_stream = 0, i = 0; i < 128; i++ ) { asf_object_codec_list_t *p_cl = ASF_FindObject( p_sys->p_root->p_hdr, @@ -859,6 +861,7 @@ static int DemuxInit( demux_t *p_demux ) i_stream++; } } +#endif es_out_Control( p_demux->out, ES_OUT_RESET_PCR ); return VLC_SUCCESS; diff --git a/modules/demux/avi/avi.c b/modules/demux/avi/avi.c index 98088fb490..73040eaacb 100644 --- a/modules/demux/avi/avi.c +++ b/modules/demux/avi/avi.c @@ -327,7 +327,7 @@ static int Open( vlc_object_t * p_this ) p_avih->i_flags&AVIF_MUSTUSEINDEX?" MUST_USE_INDEX":"", p_avih->i_flags&AVIF_ISINTERLEAVED?" IS_INTERLEAVED":"", p_avih->i_flags&AVIF_TRUSTCKTYPE?" TRUST_CKTYPE":"" ); - vlc_meta_Add( p_sys->meta, VLC_META_SETTING, buffer ); + vlc_meta_SetSetting( p_sys->meta, buffer ); } /* now read info on each stream and create ES */ @@ -1308,7 +1308,7 @@ static int Control( demux_t *p_demux, int i_query, va_list args ) int i; double f, *pf; int64_t i64, *pi64; - vlc_meta_t **pp_meta; + vlc_meta_t *p_meta; switch( i_query ) { @@ -1369,8 +1369,8 @@ static int Control( demux_t *p_demux, int i_query, va_list args ) } return VLC_SUCCESS; case DEMUX_GET_META: - pp_meta = (vlc_meta_t**)va_arg( args, vlc_meta_t** ); - *pp_meta = vlc_meta_Duplicate( p_sys->meta ); + p_meta = (vlc_meta_t*)va_arg( args, vlc_meta_t* ); + vlc_meta_Merge( p_meta, p_sys->meta ); return VLC_SUCCESS; default: diff --git a/modules/demux/flac.c b/modules/demux/flac.c index c007694168..64f302f9c5 100644 --- a/modules/demux/flac.c +++ b/modules/demux/flac.c @@ -91,7 +91,7 @@ static int Open( vlc_object_t * p_this ) p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) ); es_format_Init( &fmt, AUDIO_ES, VLC_FOURCC( 'f', 'l', 'a', 'c' ) ); p_sys->b_start = VLC_TRUE; - p_sys->p_meta = 0; + p_sys->p_meta = NULL; /* We need to read and store the STREAMINFO metadata */ i_peek = stream_Peek( p_demux->s, &p_peek, 8 ); @@ -231,10 +231,9 @@ static int Control( demux_t *p_demux, int i_query, va_list args ) if( i_query == DEMUX_SET_TIME ) return VLC_EGENERIC; else if( i_query == DEMUX_GET_META ) { - vlc_meta_t **pp_meta = (vlc_meta_t **)va_arg( args, vlc_meta_t** ); + vlc_meta_t *p_meta = (vlc_meta_t *)va_arg( args, vlc_meta_t* ); if( p_demux->p_sys->p_meta ) - *pp_meta = vlc_meta_Duplicate( p_demux->p_sys->p_meta ); - else *pp_meta = NULL; + vlc_meta_Merge( p_meta, p_demux->p_sys->p_meta ); return VLC_SUCCESS; } else return demux2_vaControlHelper( p_demux->s, 0, -1, diff --git a/modules/demux/m3u.c b/modules/demux/m3u.c index 161136aaca..a60812785b 100644 --- a/modules/demux/m3u.c +++ b/modules/demux/m3u.c @@ -68,10 +68,8 @@ vlc_module_begin(); set_description( _("Playlist metademux") ); set_capability( "demux2", 5 ); set_callbacks( Activate, Deactivate ); - add_shortcut( "m3u" ); add_shortcut( "asx" ); add_shortcut( "html" ); - add_shortcut( "pls" ); add_shortcut( "b4s" ); vlc_module_end(); @@ -91,10 +89,7 @@ static int Activate( vlc_object_t * p_this ) /* Check for m3u/asx file extension or if the demux has been forced */ psz_ext = strrchr ( p_demux->psz_path, '.' ); - if( ( psz_ext && !strcasecmp( psz_ext, ".m3u") ) || - /* a .ram file can contain a single rtsp link */ - ( psz_ext && !strcasecmp( psz_ext, ".ram") ) || - ( p_demux->psz_demux && !strcmp(p_demux->psz_demux, "m3u") ) ) + if(( psz_ext && !strcasecmp( psz_ext, ".ram") ) ) { i_type = TYPE_M3U; } @@ -108,11 +103,6 @@ static int Activate( vlc_object_t * p_this ) { i_type = TYPE_HTML; } - else if( ( psz_ext && !strcasecmp( psz_ext, ".pls") ) || - ( p_demux->psz_demux && !strcmp(p_demux->psz_demux, "pls") ) ) - { - i_type = TYPE_PLS; - } else if( ( psz_ext && !strcasecmp( psz_ext, ".b4s") ) || ( p_demux->psz_demux && !strcmp(p_demux->psz_demux, "b4s") ) ) { diff --git a/modules/demux/mkv.cpp b/modules/demux/mkv.cpp index cfaebc1c1a..a86f299174 100644 --- a/modules/demux/mkv.cpp +++ b/modules/demux/mkv.cpp @@ -1592,13 +1592,13 @@ static int Control( demux_t *p_demux, int i_query, va_list args ) int i_skp; size_t i_idx; - vlc_meta_t **pp_meta; + vlc_meta_t *p_meta; switch( i_query ) { case DEMUX_GET_META: - pp_meta = (vlc_meta_t**)va_arg( args, vlc_meta_t** ); - *pp_meta = vlc_meta_Duplicate( p_sys->meta ); + p_meta = (vlc_meta_t*)va_arg( args, vlc_meta_t* ); + vlc_meta_Merge( p_meta, p_sys->meta ); return VLC_SUCCESS; case DEMUX_GET_LENGTH: @@ -4917,54 +4917,30 @@ void matroska_segment_c::InformationCreate( ) if( psz_title ) { - vlc_meta_Add( sys.meta, VLC_META_TITLE, psz_title ); + vlc_meta_SetTitle( sys.meta, psz_title ); } if( psz_date_utc ) { - vlc_meta_Add( sys.meta, VLC_META_DATE, psz_date_utc ); + vlc_meta_SetDate( sys.meta, psz_date_utc ); } if( psz_segment_filename ) { - vlc_meta_Add( sys.meta, _("Segment filename"), psz_segment_filename ); + fprintf( stderr, "***** WARNING: Unhandled meta - Use custom\n" ); } if( psz_muxing_application ) { - vlc_meta_Add( sys.meta, _("Muxing application"), psz_muxing_application ); + fprintf( stderr, "***** WARNING: Unhandled meta - Use custom\n" ); } if( psz_writing_application ) { - vlc_meta_Add( sys.meta, _("Writing application"), psz_writing_application ); + fprintf( stderr, "***** WARNING: Unhandled meta - Use custom\n" ); } for( i_track = 0; i_track < tracks.size(); i_track++ ) { - mkv_track_t *tk = tracks[i_track]; - vlc_meta_t *mtk = vlc_meta_New(); - - sys.meta->track = (vlc_meta_t**)realloc( sys.meta->track, - sizeof( vlc_meta_t * ) * ( sys.meta->i_track + 1 ) ); - sys.meta->track[sys.meta->i_track++] = mtk; - - if( tk->fmt.psz_description ) - { - vlc_meta_Add( sys.meta, VLC_META_DESCRIPTION, tk->fmt.psz_description ); - } - if( tk->psz_codec_name ) - { - vlc_meta_Add( sys.meta, VLC_META_CODEC_NAME, tk->psz_codec_name ); - } - if( tk->psz_codec_settings ) - { - vlc_meta_Add( sys.meta, VLC_META_SETTING, tk->psz_codec_settings ); - } - if( tk->psz_codec_info_url ) - { - vlc_meta_Add( sys.meta, VLC_META_CODEC_DESCRIPTION, tk->psz_codec_info_url ); - } - if( tk->psz_codec_download_url ) - { - vlc_meta_Add( sys.meta, VLC_META_URL, tk->psz_codec_download_url ); - } +// mkv_track_t *tk = tracks[i_track]; +// vlc_meta_t *mtk = vlc_meta_New(); + fprintf( stderr, "***** WARNING: Unhandled child meta\n"); } if( i_tags_position >= 0 ) diff --git a/modules/demux/mp4/mp4.c b/modules/demux/mp4/mp4.c index 884aad8bd3..586bcfdc3b 100644 --- a/modules/demux/mp4/mp4.c +++ b/modules/demux/mp4/mp4.c @@ -387,6 +387,8 @@ static int Open( vlc_object_t * p_this ) !strncmp( psz_ref, "rtsp://", 7 ) ) { msg_Dbg( p_demux, "adding ref = `%s'", psz_ref ); + msg_Err( p_demux, "REF is broken (fix playlist") ; +#if 0 if( p_item ) { playlist_item_t *p_child = @@ -402,6 +404,7 @@ static int Open( vlc_object_t * p_this ) b_play = VLC_TRUE; } } +#endif } else { @@ -422,6 +425,8 @@ static int Open( vlc_object_t * p_this ) } strcat( psz_absolute, psz_ref ); msg_Dbg( p_demux, "adding ref = `%s'", psz_absolute ); + msg_Err( p_demux, "Ref broken (fix playlist" ); +#if 0 if( p_item ) { playlist_item_t *p_child = @@ -438,6 +443,7 @@ static int Open( vlc_object_t * p_this ) b_play = VLC_TRUE; } } +#endif } } else @@ -449,7 +455,6 @@ static int Open( vlc_object_t * p_this ) if( b_play == VLC_TRUE ) { playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, - p_playlist->status.i_view, p_playlist->status.p_item, NULL ); } vlc_object_release( p_playlist ); @@ -799,15 +804,13 @@ static int Control( demux_t *p_demux, int i_query, va_list args ) case DEMUX_GET_META: { - vlc_meta_t **pp_meta = (vlc_meta_t**)va_arg( args, vlc_meta_t** ); - vlc_meta_t *meta; + vlc_meta_t *p_meta = (vlc_meta_t *)va_arg( args, vlc_meta_t*); MP4_Box_t *p_udta = MP4_BoxGet( p_sys->p_root, "/moov/udta" ); MP4_Box_t *p_0xa9xxx; if( p_udta == NULL ) { return VLC_EGENERIC; } - *pp_meta = meta = vlc_meta_New(); for( p_0xa9xxx = p_udta->p_first; p_0xa9xxx != NULL; p_0xa9xxx = p_0xa9xxx->p_next ) { @@ -824,25 +827,25 @@ static int Control( demux_t *p_demux, int i_query, va_list args ) switch( p_0xa9xxx->i_type ) { case FOURCC_0xa9nam: /* Full name */ - vlc_meta_Add( meta, VLC_META_TITLE, psz_utf ); + vlc_meta_SetArtist( p_meta, psz_utf ); break; case FOURCC_0xa9aut: - vlc_meta_Add( meta, VLC_META_AUTHOR, psz_utf ); + vlc_meta_SetAuthor( p_meta, psz_utf ); break; case FOURCC_0xa9ART: - vlc_meta_Add( meta, VLC_META_ARTIST, psz_utf ); + vlc_meta_SetArtist( p_meta, psz_utf ); break; case FOURCC_0xa9cpy: - vlc_meta_Add( meta, VLC_META_COPYRIGHT, psz_utf ); + vlc_meta_SetCopyright( p_meta, psz_utf ); break; case FOURCC_0xa9day: /* Creation Date */ - vlc_meta_Add( meta, VLC_META_DATE, psz_utf ); + vlc_meta_SetDate( p_meta, psz_utf ); break; case FOURCC_0xa9des: /* Description */ - vlc_meta_Add( meta, VLC_META_DESCRIPTION, psz_utf ); + vlc_meta_SetDescription( p_meta, psz_utf ); break; case FOURCC_0xa9gen: /* Genre */ - vlc_meta_Add( meta, VLC_META_GENRE, psz_utf ); + vlc_meta_SetGenre( p_meta, psz_utf ); break; case FOURCC_0xa9swr: diff --git a/modules/demux/mpeg/mpga.c b/modules/demux/mpeg/mpga.c index 4d14fc74ce..e1e3951d6c 100644 --- a/modules/demux/mpeg/mpga.c +++ b/modules/demux/mpeg/mpga.c @@ -371,15 +371,14 @@ static int Control( demux_t *p_demux, int i_query, va_list args ) { demux_sys_t *p_sys = p_demux->p_sys; int64_t *pi64; - vlc_meta_t **pp_meta; + vlc_meta_t *p_meta; int i_ret; switch( i_query ) { case DEMUX_GET_META: - pp_meta = (vlc_meta_t **)va_arg( args, vlc_meta_t** ); - if( p_sys->meta ) *pp_meta = vlc_meta_Duplicate( p_sys->meta ); - else *pp_meta = NULL; + p_meta = (vlc_meta_t *)va_arg( args, vlc_meta_t* ); + vlc_meta_Merge( p_meta, p_sys->meta ); return VLC_SUCCESS; case DEMUX_GET_TIME: diff --git a/modules/demux/playlist/b4s.c b/modules/demux/playlist/b4s.c index da134dafa0..272490d4f4 100644 --- a/modules/demux/playlist/b4s.c +++ b/modules/demux/playlist/b4s.c @@ -38,10 +38,8 @@ struct demux_sys_t { char *psz_prefix; - playlist_t *p_playlist; xml_t *p_xml; xml_reader_t *p_xml_reader; - int b_shout; }; /***************************************************************************** @@ -51,9 +49,6 @@ static int Demux( demux_t *p_demux); static int Control( demux_t *p_demux, int i_query, va_list args ); static char *GetNextToken(char *psz_cur_string); static int IsWhitespace( char *psz_string ); -static void ShoutcastAdd( playlist_t *p_playlist, playlist_item_t* p_genre, - playlist_item_t *p_bitrate, playlist_item_t *p_item, - char *psz_genre, char *psz_bitrate ); /***************************************************************************** * Import_B4S: main import function @@ -68,8 +63,7 @@ int E_(Import_B4S)( vlc_object_t *p_this ) psz_ext = strrchr ( p_demux->psz_path, '.' ); if( ( psz_ext && !strcasecmp( psz_ext, ".b4s") ) || - ( p_demux->psz_demux && !strcmp(p_demux->psz_demux, "b4s-open") ) || - ( p_demux->psz_demux && !strcmp(p_demux->psz_demux, "shout-b4s") ) ) + ( p_demux->psz_demux && !strcmp(p_demux->psz_demux, "b4s-open") ) ) { ; } @@ -87,10 +81,7 @@ int E_(Import_B4S)( vlc_object_t *p_this ) msg_Err( p_demux, "out of memory" ); return VLC_ENOMEM; } - p_sys->b_shout = p_demux->psz_demux && - !strcmp(p_demux->psz_demux, "shout-b4s"); p_sys->psz_prefix = E_(FindPrefix)( p_demux ); - p_sys->p_playlist = NULL; p_sys->p_xml = NULL; p_sys->p_xml_reader = NULL; @@ -106,7 +97,6 @@ void E_(Close_B4S)( vlc_object_t *p_this ) demux_sys_t *p_sys = p_demux->p_sys; if( p_sys->psz_prefix ) free( p_sys->psz_prefix ); - if( p_sys->p_playlist ) vlc_object_release( p_sys->p_playlist ); if( p_sys->p_xml_reader ) xml_ReaderDelete( p_sys->p_xml, p_sys->p_xml_reader ); if( p_sys->p_xml ) xml_Delete( p_sys->p_xml ); free( p_sys ); @@ -115,44 +105,19 @@ void E_(Close_B4S)( vlc_object_t *p_this ) static int Demux( demux_t *p_demux ) { demux_sys_t *p_sys = p_demux->p_sys; - playlist_t *p_playlist; - playlist_item_t *p_item, *p_current; + playlist_item_t *p_item; playlist_item_t *p_bitrate = NULL, *p_genre = NULL; - vlc_bool_t b_play; - int i_ret; + int i_ret, i_parent_id; xml_t *p_xml; xml_reader_t *p_xml_reader; char *psz_elname = NULL; - int i_type, b_shoutcast; + int i_type; char *psz_mrl = NULL, *psz_name = NULL, *psz_genre = NULL; char *psz_now = NULL, *psz_listeners = NULL, *psz_bitrate = NULL; - - b_shoutcast = p_sys->b_shout; - - p_playlist = (playlist_t *) vlc_object_find( p_demux, VLC_OBJECT_PLAYLIST, - FIND_ANYWHERE ); - if( !p_playlist ) - { - msg_Err( p_demux, "can't find playlist" ); - return -1; - } - p_sys->p_playlist = p_playlist; - - b_play = E_(FindItem)( p_demux, p_playlist, &p_current ); - - playlist_ItemToNode( p_playlist, p_current ); - p_current->input.i_type = ITEM_TYPE_PLAYLIST; - if( b_shoutcast ) - { - p_genre = playlist_NodeCreate( p_playlist, p_current->pp_parents[0]->i_view, "Genre", p_current ); - playlist_CopyParents( p_current, p_genre ); - - p_bitrate = playlist_NodeCreate( p_playlist, p_current->pp_parents[0]->i_view, "Bitrate", p_current ); - playlist_CopyParents( p_current, p_bitrate ); - } + INIT_PLAYLIST_STUFF; p_xml = p_sys->p_xml = xml_Create( p_demux ); if( !p_xml ) return -1; @@ -170,6 +135,7 @@ static int Demux( demux_t *p_demux ) if( xml_ReaderRead( p_xml_reader ) != 1 ) { msg_Err( p_demux, "invalid file (no root node)" ); + vlc_object_release( p_playlist ); return -1; } @@ -180,6 +146,7 @@ static int Demux( demux_t *p_demux ) msg_Err( p_demux, "invalid root node %i, %s", xml_ReaderNodeType( p_xml_reader ), psz_elname ); if( psz_elname ) free( psz_elname ); + vlc_object_release( p_playlist ); return -1; } free( psz_elname ); @@ -317,82 +284,20 @@ static int Demux( demux_t *p_demux ) if( !psz_elname ) return -1; if( !strcmp( psz_elname, "entry" ) ) { - p_item = playlist_ItemNew( p_playlist, psz_mrl, psz_name ); + p_input = input_ItemNewExt( p_playlist, psz_mrl, psz_name, + 0, NULL, -1 ); if( psz_now ) - { - vlc_input_item_AddInfo( &(p_item->input), - _(VLC_META_INFO_CAT), - _( VLC_META_NOW_PLAYING ), - "%s", - psz_now ); - } + vlc_meta_SetNowPlaying( p_input->p_meta, psz_now ); if( psz_genre ) - { - vlc_input_item_AddInfo( &p_item->input, - _(VLC_META_INFO_CAT), - _( VLC_META_GENRE ), - "%s", - psz_genre ); - } + vlc_meta_SetGenre( p_input->p_meta, psz_genre ); if( psz_listeners ) - { - vlc_input_item_AddInfo( &p_item->input, - _(VLC_META_INFO_CAT), - _( "Listeners" ), - "%s", - psz_listeners ); - } + msg_Err( p_playlist, "Unsupported meta listeners" ); if( psz_bitrate ) - { - vlc_input_item_AddInfo( &p_item->input, - _(VLC_META_INFO_CAT), - _( "Bitrate" ), - "%s", - psz_bitrate ); - } - playlist_NodeAddItem( p_playlist, p_item, - p_current->pp_parents[0]->i_view, - p_current, PLAYLIST_APPEND, - PLAYLIST_END ); - - /* We need to declare the parents of the node as the - * * same of the parent's ones */ - playlist_CopyParents( p_current, p_item ); - - vlc_input_item_CopyOptions( &p_current->input, - &p_item->input ); - if( b_shoutcast ) - { - char *psz_genreToken; - char *psz_otherToken; - int i = 0; - - psz_genreToken = psz_genre; - - /* split up the combined genre string form - shoutcast and add the individual genres */ - while ( psz_genreToken && - ( psz_otherToken = GetNextToken(psz_genreToken ))) - { - if( strlen(psz_genreToken)>2 ) - /* We dont want genres below 2 letters, - this gets rid of alot of junk*/ - { - /* lowercase everything */ - for( i=0; psz_genreToken[i]!=0; i++ ) - psz_genreToken[i] = - tolower(psz_genreToken[i]); - /* Make first letter uppercase, purely cosmetical */ - psz_genreToken[0] = - toupper( psz_genreToken[0] ); - ShoutcastAdd( p_playlist, p_genre, - p_bitrate, p_item, - psz_genreToken, psz_bitrate ); - - psz_genreToken = psz_otherToken; - } - } - } + msg_Err( p_playlist, "Unsupported meta bitrate" ); + + playlist_AddWhereverNeeded( p_playlist, p_input, p_current, + p_item_in_category, (i_parent_id > 0 ) ? VLC_TRUE: + VLC_FALSE, PLAYLIST_APPEND ); #define FREE(a) if( a ) free( a ); a = NULL; FREE( psz_name ); @@ -415,25 +320,8 @@ static int Demux( demux_t *p_demux ) { msg_Warn( p_demux, "error while parsing data" ); } - if( b_shoutcast ) - { - vlc_mutex_lock( &p_playlist->object_lock ); - playlist_NodeSort( p_playlist, p_bitrate, SORT_TITLE_NUMERIC, ORDER_NORMAL ); - vlc_mutex_unlock( &p_playlist->object_lock ); - } - /* Go back and play the playlist */ - if( b_play && p_playlist->status.p_item && - p_playlist->status.p_item->i_children > 0 ) - { - playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, - p_playlist->status.i_view, - p_playlist->status.p_item, - p_playlist->status.p_item->pp_children[0] ); - } - - vlc_object_release( p_playlist ); - p_sys->p_playlist = NULL; + HANDLE_PLAY_AND_RELEASE; return VLC_SUCCESS; } @@ -476,38 +364,3 @@ static int IsWhitespace( char *psz_string ) } return VLC_TRUE; } - -static void ShoutcastAdd( playlist_t *p_playlist, playlist_item_t* p_genre, - playlist_item_t *p_bitrate, playlist_item_t *p_item, - char *psz_genre, char *psz_bitrate ) -{ - playlist_item_t *p_parent; - if( psz_bitrate ) - { - playlist_item_t *p_copy = playlist_ItemCopy(p_playlist,p_item); - p_parent = playlist_ChildSearchName( p_bitrate, psz_bitrate ); - if( !p_parent ) - { - p_parent = playlist_NodeCreate( p_playlist, p_genre->pp_parents[0]->i_view, psz_bitrate, - p_bitrate ); - playlist_CopyParents( p_bitrate, p_parent ); - } - playlist_NodeAddItem( p_playlist, p_copy, p_parent->pp_parents[0]->i_view, p_parent, PLAYLIST_APPEND, PLAYLIST_END ); - playlist_CopyParents( p_parent, p_copy ); - - } - - if( psz_genre ) - { - playlist_item_t *p_copy = playlist_ItemCopy(p_playlist,p_item); - p_parent = playlist_ChildSearchName( p_genre, psz_genre ); - if( !p_parent ) - { - p_parent = playlist_NodeCreate( p_playlist, p_genre->pp_parents[0]->i_view, psz_genre, - p_genre ); - playlist_CopyParents( p_genre, p_parent ); - } - playlist_NodeAddItem( p_playlist, p_copy, p_parent->pp_parents[0]->i_view, p_parent, PLAYLIST_APPEND, PLAYLIST_END ); - playlist_CopyParents( p_parent, p_copy ); - } -} diff --git a/modules/demux/playlist/dvb.c b/modules/demux/playlist/dvb.c index 8ad82ec160..e7e6b010fe 100644 --- a/modules/demux/playlist/dvb.c +++ b/modules/demux/playlist/dvb.c @@ -100,6 +100,7 @@ void E_(Close_DVB)( vlc_object_t *p_this ) *****************************************************************************/ static int Demux( demux_t *p_demux ) { +#if 0 playlist_t *p_playlist; char *psz_line; playlist_item_t *p_current; @@ -116,7 +117,7 @@ static int Demux( demux_t *p_demux ) b_play = E_(FindItem)( p_demux, p_playlist, &p_current ); playlist_ItemToNode( p_playlist, p_current ); - p_current->input.i_type = ITEM_TYPE_PLAYLIST; + p_current->p_input->i_type = ITEM_TYPE_PLAYLIST; while( (psz_line = stream_ReadLine( p_demux->s )) ) { @@ -166,6 +167,7 @@ static int Demux( demux_t *p_demux ) vlc_object_release( p_playlist ); return VLC_SUCCESS; +#endif } static struct diff --git a/modules/demux/playlist/m3u.c b/modules/demux/playlist/m3u.c index 6fadf92bbd..931ad9b062 100644 --- a/modules/demux/playlist/m3u.c +++ b/modules/demux/playlist/m3u.c @@ -107,34 +107,16 @@ void E_(Close_M3U)( vlc_object_t *p_this ) static int Demux( demux_t *p_demux ) { - playlist_t *p_playlist; char *psz_line; - char *psz_name = NULL; char *psz_artist = NULL; int i_parsed_duration = 0; mtime_t i_duration = -1; - char **ppsz_options = NULL; - int i_options = 0, i; - - playlist_item_t *p_item, *p_current; - - vlc_bool_t b_play; - + const char**ppsz_options = NULL; + int i_options = 0, i, i_parent_id; vlc_bool_t b_cleanup = VLC_FALSE; - p_playlist = (playlist_t *) vlc_object_find( p_demux, VLC_OBJECT_PLAYLIST, - FIND_ANYWHERE ); - if( !p_playlist ) - { - msg_Err( p_demux, "can't find playlist" ); - return -1; - } - - b_play = E_(FindItem)( p_demux, p_playlist, &p_current ); - - playlist_ItemToNode( p_playlist, p_current ); - p_current->input.i_type = ITEM_TYPE_PLAYLIST; + INIT_PLAYLIST_STUFF; psz_line = stream_ReadLine( p_demux->s ); while( psz_line ) @@ -172,7 +154,7 @@ static int Demux( demux_t *p_demux ) sizeof("EXTVLCOPT:") -1 ) ) { /* VLC Option */ - char *psz_option; + const char *psz_option; psz_parse += sizeof("EXTVLCOPT:") -1; if( !*psz_parse ) goto error; @@ -199,28 +181,18 @@ static int Demux( demux_t *p_demux ) EnsureUTF8( psz_name ); EnsureUTF8( psz_mrl ); - p_item = playlist_ItemNew( p_playlist, psz_mrl, psz_name ); for( i = 0; i< i_options; i++ ) - { - EnsureUTF8( ppsz_options[i] ); - playlist_ItemAddOption( p_item, ppsz_options[i] ); - } - p_item->input.i_duration = i_duration; + EnsureUTF8( (char*)ppsz_options[i] ); + + p_input = input_ItemNewExt( p_playlist, psz_mrl, psz_name, + i_options, ppsz_options, i_duration ); if ( psz_artist && *psz_artist ) - vlc_input_item_AddInfo( &p_item->input, _(VLC_META_INFO_CAT), + vlc_input_item_AddInfo( p_input, _(VLC_META_INFO_CAT), _(VLC_META_ARTIST), "%s", psz_artist ); - playlist_NodeAddItem( p_playlist, p_item, - p_current->pp_parents[0]->i_view, - p_current, PLAYLIST_APPEND, - PLAYLIST_END ); - - /* We need to declare the parents of the node as the - * * same of the parent's ones */ - playlist_CopyParents( p_current, p_item ); - - vlc_input_item_CopyOptions( &p_current->input, - &p_item->input ); - + fprintf( stderr, "Adding %s\n", p_input->psz_uri ); + playlist_AddWhereverNeeded( p_playlist, p_input, p_current, + p_item_in_category, (i_parent_id > 0 )? VLC_TRUE : VLC_FALSE, + PLAYLIST_APPEND ); free( psz_mrl ); } @@ -234,7 +206,7 @@ static int Demux( demux_t *p_demux ) if( b_cleanup ) { /* Cleanup state */ - while( i_options-- ) free( ppsz_options[i_options] ); + while( i_options-- ) free( (char*)ppsz_options[i_options] ); if( ppsz_options ) free( ppsz_options ); ppsz_options = NULL; i_options = 0; if( psz_name ) free( psz_name ); @@ -247,18 +219,7 @@ static int Demux( demux_t *p_demux ) b_cleanup = VLC_FALSE; } } - - /* Go back and play the playlist */ - if( b_play && p_playlist->status.p_item && - p_playlist->status.p_item->i_children > 0 ) - { - playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, - p_playlist->status.i_view, - p_playlist->status.p_item, - p_playlist->status.p_item->pp_children[0] ); - } - - vlc_object_release( p_playlist ); + HANDLE_PLAY_AND_RELEASE; return VLC_SUCCESS; } @@ -267,7 +228,7 @@ static int Control( demux_t *p_demux, int i_query, va_list args ) return VLC_EGENERIC; } -static void parseEXTINF(char *psz_string, char **ppsz_artist, +static void parseEXTINF(char *psz_string, char **ppsz_artist, char **ppsz_name, int *pi_duration) { char *end = NULL; @@ -306,7 +267,7 @@ static void parseEXTINF(char *psz_string, char **ppsz_artist, *ppsz_artist = psz_string; *ppsz_name = psz_item + 3; /* points directly after ' - ' */ return; - } + } /* reaching this point means: 0.8.1- with artist or something without artist */ if ( *psz_string == ',' ) @@ -315,7 +276,7 @@ static void parseEXTINF(char *psz_string, char **ppsz_artist, psz_string++; *ppsz_name = psz_string; return; - } + } psz_item = psz_string; psz_string = strchr( psz_string, ',' ); diff --git a/modules/demux/playlist/old.c b/modules/demux/playlist/old.c index 38323a329d..62da1368b5 100644 --- a/modules/demux/playlist/old.c +++ b/modules/demux/playlist/old.c @@ -75,7 +75,6 @@ static int Demux( demux_t *p_demux) return VLC_EGENERIC; } - p_playlist->pp_items[p_playlist->i_index]->b_autodeletion = VLC_TRUE; while( ( psz_line = stream_ReadLine( p_demux->s) ) != NULL ) { char *psz_unicode; @@ -95,8 +94,8 @@ static int Demux( demux_t *p_demux) } psz_unicode = FromLocale( psz_line ); - playlist_Add( p_playlist, psz_unicode, psz_unicode, PLAYLIST_APPEND, - PLAYLIST_END ); +// playlist_Add( p_playlist, psz_unicode, psz_unicode, PLAYLIST_APPEND, +// PLAYLIST_END ); free( psz_line ); LocaleFree( psz_line ); diff --git a/modules/demux/playlist/playlist.c b/modules/demux/playlist/playlist.c index d745944323..23f5ca6e4d 100644 --- a/modules/demux/playlist/playlist.c +++ b/modules/demux/playlist/playlist.c @@ -50,6 +50,8 @@ vlc_module_begin(); add_bool( "playlist-autostart", 1, NULL, AUTOSTART_TEXT, AUTOSTART_LONGTEXT, VLC_FALSE ); + add_integer( "parent-item", 0, NULL, NULL, NULL, VLC_TRUE ); + set_shortname( _("Playlist") ); set_description( _("Playlist") ); add_shortcut( "old-open" ); @@ -153,13 +155,37 @@ char *E_(ProcessMRL)( char *psz_mrl, char *psz_prefix ) return psz_mrl; } +void E_(AddToPlaylist)( demux_t *p_demux, playlist_t *p_playlist, + input_item_t *p_input, + playlist_item_t *p_item, int i_parent_id ) +{ + // Only add to parent if specific parent requested or not current + // playlist item + if( i_parent_id > 0 || ! ( + p_playlist->status.p_item && + p_playlist->status.p_item->p_input == + ((input_thread_t *)p_demux->p_parent)->input.p_item ) ) + { + playlist_NodeAddInput( p_playlist, p_input, p_item, + PLAYLIST_APPEND, PLAYLIST_END ); + } + // Else, add to both + else + { + playlist_BothAddInput( p_playlist, p_input, p_item, + PLAYLIST_APPEND, PLAYLIST_END ); + } + vlc_input_item_CopyOptions( p_item->p_input, p_input ); +} + + vlc_bool_t E_(FindItem)( demux_t *p_demux, playlist_t *p_playlist, playlist_item_t **pp_item ) { vlc_bool_t b_play = var_CreateGetBool( p_demux, "playlist-autostart" ); if( b_play && p_playlist->status.p_item && - &p_playlist->status.p_item->input == + p_playlist->status.p_item->p_input == ((input_thread_t *)p_demux->p_parent)->input.p_item ) { msg_Dbg( p_playlist, "starting playlist playback" ); diff --git a/modules/demux/playlist/playlist.h b/modules/demux/playlist/playlist.h index 542f2347de..a669849e6d 100644 --- a/modules/demux/playlist/playlist.h +++ b/modules/demux/playlist/playlist.h @@ -26,6 +26,8 @@ char *E_(FindPrefix)( demux_t * ); vlc_bool_t E_(FindItem)( demux_t *, playlist_t *, playlist_item_t **); +void E_(AddToPlaylist)( demux_t *, playlist_t*,input_item_t*,playlist_item_t*,int ); + int E_(Import_Old) ( vlc_object_t * ); int E_(Import_Native) ( vlc_object_t * ); @@ -50,3 +52,38 @@ int E_(xspf_import_Activate) ( vlc_object_t * ); int E_(Import_Shoutcast) ( vlc_object_t * ); void E_(Close_Shoutcast) ( vlc_object_t * ); + +#define INIT_PLAYLIST_STUFF \ + vlc_bool_t b_play; \ + playlist_item_t *p_current, *p_item_in_category = NULL; \ + input_item_t *p_input; \ + playlist_t *p_playlist = (playlist_t *) vlc_object_find( p_demux, \ + VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); \ + if( !p_playlist ) \ + { \ + msg_Err( p_demux, "can't find playlist" ); \ + return VLC_EGENERIC; \ + } \ + i_parent_id = var_CreateGetInteger( p_demux, "parent-item" ); \ + if( i_parent_id > 0 ) \ + { \ + b_play = VLC_FALSE; \ + p_current = playlist_ItemGetById( p_playlist, i_parent_id ); \ + } \ + else \ + { \ + b_play = E_(FindItem)( p_demux, p_playlist, &p_current ); \ + p_item_in_category = playlist_ItemToNode( p_playlist, p_current ); \ + p_current->p_input->i_type = ITEM_TYPE_PLAYLIST; \ + } + +#define HANDLE_PLAY_AND_RELEASE \ + /* Go back and play the playlist */ \ + if( b_play && p_playlist->status.p_item && \ + p_playlist->status.p_item->i_children > 0 ) \ + { \ + playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, 1242, \ + p_playlist->status.p_item, NULL ); \ + } \ + vlc_object_release( p_playlist ); + diff --git a/modules/demux/playlist/pls.c b/modules/demux/playlist/pls.c index 3341890cc1..e924f50df1 100644 --- a/modules/demux/playlist/pls.c +++ b/modules/demux/playlist/pls.c @@ -99,6 +99,7 @@ void E_(Close_PLS)( vlc_object_t *p_this ) static int Demux( demux_t *p_demux ) { +#if 0 mtime_t i_duration = -1; char *psz_name = NULL; char *psz_line; @@ -282,6 +283,7 @@ static int Demux( demux_t *p_demux ) } vlc_object_release( p_playlist ); return VLC_SUCCESS; +#endif } static int Control( demux_t *p_demux, int i_query, va_list args ) diff --git a/modules/demux/playlist/podcast.c b/modules/demux/playlist/podcast.c index 8122d967de..25f9846eb8 100644 --- a/modules/demux/playlist/podcast.c +++ b/modules/demux/playlist/podcast.c @@ -106,13 +106,10 @@ void E_(Close_podcast)( vlc_object_t *p_this ) static int Demux( demux_t *p_demux ) { demux_sys_t *p_sys = p_demux->p_sys; - playlist_t *p_playlist; - playlist_item_t *p_item, *p_current; - vlc_bool_t b_play; vlc_bool_t b_item = VLC_FALSE; vlc_bool_t b_image = VLC_FALSE; - int i_ret; + int i_ret, i_parent_id; xml_t *p_xml; xml_reader_t *p_xml_reader; @@ -130,19 +127,7 @@ static int Demux( demux_t *p_demux ) char *psz_item_summary = NULL; int i_type; - p_playlist = (playlist_t *) vlc_object_find( p_demux, VLC_OBJECT_PLAYLIST, - FIND_ANYWHERE ); - if( !p_playlist ) - { - msg_Err( p_demux, "can't find playlist" ); - return -1; - } - p_sys->p_playlist = p_playlist; - - b_play = E_(FindItem)( p_demux, p_playlist, &p_current ); - - playlist_ItemToNode( p_playlist, p_current ); - p_current->input.i_type = ITEM_TYPE_PLAYLIST; + INIT_PLAYLIST_STUFF; p_xml = p_sys->p_xml = xml_Create( p_demux ); if( !p_xml ) return -1; @@ -285,7 +270,7 @@ static int Demux( demux_t *p_demux ) else if( b_item == VLC_FALSE && b_image == VLC_FALSE && !strcmp( psz_elname, "link" ) ) { - vlc_input_item_AddInfo( &(p_current->input), + vlc_input_item_AddInfo( p_current->p_input, _( "Podcast Info" ), _( "Podcast Link" ), "%s", @@ -294,7 +279,7 @@ static int Demux( demux_t *p_demux ) else if( b_item == VLC_FALSE && b_image == VLC_FALSE && !strcmp( psz_elname, "copyright" ) ) { - vlc_input_item_AddInfo( &(p_current->input), + vlc_input_item_AddInfo( p_current->p_input, _( "Podcast Info" ), _( "Podcast Copyright" ), "%s", @@ -303,7 +288,7 @@ static int Demux( demux_t *p_demux ) else if( b_item == VLC_FALSE && b_image == VLC_FALSE && !strcmp( psz_elname, "itunes:category" ) ) { - vlc_input_item_AddInfo( &(p_current->input), + vlc_input_item_AddInfo( p_current->p_input, _( "Podcast Info" ), _( "Podcast Category" ), "%s", @@ -312,7 +297,7 @@ static int Demux( demux_t *p_demux ) else if( b_item == VLC_FALSE && b_image == VLC_FALSE && !strcmp( psz_elname, "itunes:keywords" ) ) { - vlc_input_item_AddInfo( &(p_current->input), + vlc_input_item_AddInfo( p_current->p_input, _( "Podcast Info" ), _( "Podcast Keywords" ), "%s", @@ -321,7 +306,7 @@ static int Demux( demux_t *p_demux ) else if( b_item == VLC_FALSE && b_image == VLC_FALSE && !strcmp( psz_elname, "itunes:subtitle" ) ) { - vlc_input_item_AddInfo( &(p_current->input), + vlc_input_item_AddInfo( p_current->p_input, _( "Podcast Info" ), _( "Podcast Subtitle" ), "%s", @@ -331,7 +316,7 @@ static int Demux( demux_t *p_demux ) && ( !strcmp( psz_elname, "itunes:summary" ) ||!strcmp( psz_elname, "description" ) ) ) { /* isn't standard iTunes podcast stuff */ - vlc_input_item_AddInfo( &(p_current->input), + vlc_input_item_AddInfo( p_current->p_input, _( "Podcast Info" ), _( "Podcast Summary" ), "%s", @@ -354,21 +339,12 @@ static int Demux( demux_t *p_demux ) if( !psz_elname ) return -1; if( !strcmp( psz_elname, "item" ) ) { - p_item = playlist_ItemNew( p_playlist, psz_item_mrl, - psz_item_name ); - if( p_item == NULL ) break; - playlist_NodeAddItem( p_playlist, p_item, - p_current->pp_parents[0]->i_view, - p_current, PLAYLIST_APPEND, - PLAYLIST_END ); - - /* We need to declare the parents of the node as the - * * same of the parent's ones */ - playlist_CopyParents( p_current, p_item ); - + p_input = input_ItemNewExt( p_playlist, psz_item_mrl, + psz_item_name, 0, NULL, -1 ); + if( p_input == NULL ) break; if( psz_item_date ) { - vlc_input_item_AddInfo( &p_item->input, + vlc_input_item_AddInfo( p_input, _( "Podcast Info" ), _( "Podcast Publication Date" ), "%s", @@ -376,7 +352,7 @@ static int Demux( demux_t *p_demux ) } if( psz_item_author ) { - vlc_input_item_AddInfo( &p_item->input, + vlc_input_item_AddInfo( p_input, _( "Podcast Info" ), _( "Podcast Author" ), "%s", @@ -384,7 +360,7 @@ static int Demux( demux_t *p_demux ) } if( psz_item_category ) { - vlc_input_item_AddInfo( &p_item->input, + vlc_input_item_AddInfo( p_input, _( "Podcast Info" ), _( "Podcast Subcategory" ), "%s", @@ -392,7 +368,7 @@ static int Demux( demux_t *p_demux ) } if( psz_item_duration ) { - vlc_input_item_AddInfo( &p_item->input, + vlc_input_item_AddInfo( p_input, _( "Podcast Info" ), _( "Podcast Duration" ), "%s", @@ -400,7 +376,7 @@ static int Demux( demux_t *p_demux ) } if( psz_item_keywords ) { - vlc_input_item_AddInfo( &p_item->input, + vlc_input_item_AddInfo( p_input, _( "Podcast Info" ), _( "Podcast Keywords" ), "%s", @@ -408,7 +384,7 @@ static int Demux( demux_t *p_demux ) } if( psz_item_subtitle ) { - vlc_input_item_AddInfo( &p_item->input, + vlc_input_item_AddInfo( p_input, _( "Podcast Info" ), _( "Podcast Subtitle" ), "%s", @@ -416,7 +392,7 @@ static int Demux( demux_t *p_demux ) } if( psz_item_summary ) { - vlc_input_item_AddInfo( &p_item->input, + vlc_input_item_AddInfo( p_input, _( "Podcast Info" ), _( "Podcast Summary" ), "%s", @@ -424,7 +400,7 @@ static int Demux( demux_t *p_demux ) } if( psz_item_size ) { - vlc_input_item_AddInfo( &p_item->input, + vlc_input_item_AddInfo( p_input, _( "Podcast Info" ), _( "Podcast Size" ), "%s bytes", @@ -432,13 +408,17 @@ static int Demux( demux_t *p_demux ) } if( psz_item_type ) { - vlc_input_item_AddInfo( &p_item->input, + vlc_input_item_AddInfo( p_input, _( "Podcast Info" ), _( "Podcast Type" ), "%s", psz_item_type ); } + fprintf( stderr, "Adding WHEREVER\n"); + playlist_AddWhereverNeeded( p_playlist, p_input, p_current, + p_item_in_category, (i_parent_id > 0 ) ? VLC_TRUE: + VLC_FALSE, PLAYLIST_APPEND ); #define FREE(a) if( a ) free( a ); a = NULL; FREE( psz_item_name ); FREE( psz_item_mrl ); @@ -472,18 +452,7 @@ static int Demux( demux_t *p_demux ) msg_Warn( p_demux, "error while parsing data" ); } - /* Go back and play the playlist */ - if( b_play && p_playlist->status.p_item && - p_playlist->status.p_item->i_children > 0 ) - { - playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, - p_playlist->status.i_view, - p_playlist->status.p_item, - p_playlist->status.p_item->pp_children[0] ); - } - - vlc_object_release( p_playlist ); - p_sys->p_playlist = NULL; + HANDLE_PLAY_AND_RELEASE; return VLC_SUCCESS; } diff --git a/modules/demux/playlist/shoutcast.c b/modules/demux/playlist/shoutcast.c index 14330329a8..438b6b0f08 100644 --- a/modules/demux/playlist/shoutcast.c +++ b/modules/demux/playlist/shoutcast.c @@ -119,6 +119,7 @@ void E_(Close_Shoutcast)( vlc_object_t *p_this ) static int Demux( demux_t *p_demux ) { +#if 0 demux_sys_t *p_sys = p_demux->p_sys; playlist_t *p_playlist; @@ -196,6 +197,7 @@ static int Demux( demux_t *p_demux ) vlc_object_release( p_playlist ); p_sys->p_playlist = NULL; +#endif return VLC_SUCCESS; } @@ -211,6 +213,7 @@ static int Demux( demux_t *p_demux ) **/ static int DemuxGenre( demux_t *p_demux ) { +#if 0 demux_sys_t *p_sys = p_demux->p_sys; char *psz_name = NULL; /* genre name */ char *psz_eltname = NULL; /* tag name */ @@ -303,6 +306,7 @@ static int DemuxGenre( demux_t *p_demux ) break; } } +#endif return 0; } @@ -333,6 +337,7 @@ static int DemuxGenre( demux_t *p_demux ) **/ static int DemuxStation( demux_t *p_demux ) { +#if 0 demux_sys_t *p_sys = p_demux->p_sys; char *psz_base = NULL; /* */ @@ -552,6 +557,7 @@ static int DemuxStation( demux_t *p_demux ) break; } } +#endif return 0; } #undef FREE diff --git a/modules/demux/playlist/xspf.c b/modules/demux/playlist/xspf.c index 34ae342a83..2b6c321ba4 100644 --- a/modules/demux/playlist/xspf.c +++ b/modules/demux/playlist/xspf.c @@ -61,6 +61,7 @@ int E_(xspf_import_Activate)( vlc_object_t *p_this ) */ int xspf_import_Demux( demux_t *p_demux ) { +#if 0 playlist_t *p_playlist = NULL; playlist_item_t *p_current = NULL; @@ -144,6 +145,7 @@ int xspf_import_Demux( demux_t *p_demux ) xml_Delete( p_xml ); return i_ret; +#endif } /** \brief dummy function for demux callback interface */ @@ -151,7 +153,7 @@ int xspf_import_Control( demux_t *p_demux, int i_query, va_list args ) { return VLC_EGENERIC; } - +#if 0 /** * \brief parse the root node of a XSPF playlist * \param p_demux demuxer instance @@ -680,3 +682,4 @@ static vlc_bool_t insert_new_item( playlist_t *p_pl, playlist_item_t *p_cur, return VLC_TRUE; } +#endif diff --git a/modules/demux/sgimb.c b/modules/demux/sgimb.c index 509ca1d9a9..08e5736277 100644 --- a/modules/demux/sgimb.c +++ b/modules/demux/sgimb.c @@ -404,6 +404,8 @@ static int Demux ( demux_t *p_demux ) free( temp ); } + msg_Err( p_playlist, "SGIMB playlist handling is broken" ); +#if 0 p_child = playlist_ItemNew( p_playlist, p_sys->psz_uri, p_sys->psz_name ? p_sys->psz_name : p_sys->psz_uri ); @@ -442,7 +444,7 @@ static int Demux ( demux_t *p_demux ) playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, p_playlist->status.i_view, p_playlist->status.p_item, NULL ); - +#endif vlc_object_release( p_playlist ); return VLC_SUCCESS; } diff --git a/modules/demux/ts.c b/modules/demux/ts.c index c6e23b3af5..3ae74b38db 100644 --- a/modules/demux/ts.c +++ b/modules/demux/ts.c @@ -74,6 +74,7 @@ * - ... */ +#define vlc_meta_Add(a,b,c) fprintf(stderr, "FIXME: TS demuxer meta is broken\n" ) /***************************************************************************** * Module descriptor *****************************************************************************/ diff --git a/modules/demux/util/id3tag.c b/modules/demux/util/id3tag.c index a7169392b1..0de160ce9c 100644 --- a/modules/demux/util/id3tag.c +++ b/modules/demux/util/id3tag.c @@ -76,6 +76,8 @@ static void ParseID3Tag( demux_t *p_demux, uint8_t *p_data, int i_size ) while( i_strings > 0 ) { + vlc_meta_t *p_meta = (vlc_meta_t *)(p_demux->p_private); + char *psz_temp = id3_ucs4_utf8duplicate( id3_field_getstrings( &p_frame->fields[1], --i_strings ) ); @@ -87,51 +89,41 @@ static void ParseID3Tag( demux_t *p_demux, uint8_t *p_data, int i_size ) if( psz_temp != psz_endptr && i_genre >= 0 && i_genre < NUM_GENRES ) { - vlc_meta_Add( (vlc_meta_t *)p_demux->p_private, - VLC_META_GENRE, ppsz_genres[atoi(psz_temp)]); + vlc_meta_SetGenre( p_meta, ppsz_genres[atoi(psz_temp)]); } else { /* Unknown genre */ - vlc_meta_Add( (vlc_meta_t *)p_demux->p_private, - VLC_META_GENRE, psz_temp ); + vlc_meta_SetGenre( p_meta,psz_temp ); } } else if( !strcmp(p_frame->id, ID3_FRAME_TITLE ) ) { - vlc_meta_Add( (vlc_meta_t *)p_demux->p_private, - VLC_META_TITLE, psz_temp ); + vlc_meta_SetTitle( p_meta, psz_temp ); } else if( !strcmp(p_frame->id, ID3_FRAME_ARTIST ) ) { - vlc_meta_Add( (vlc_meta_t *)p_demux->p_private, - VLC_META_ARTIST, psz_temp ); + vlc_meta_SetArtist( p_meta, psz_temp ); } else if( !strcmp(p_frame->id, ID3_FRAME_YEAR ) ) { - vlc_meta_Add( (vlc_meta_t *)p_demux->p_private, - VLC_META_DATE, psz_temp ); + vlc_meta_SetDate( p_meta, psz_temp ); } else if( !strcmp(p_frame->id, ID3_FRAME_COMMENT ) ) { - vlc_meta_Add( (vlc_meta_t *)p_demux->p_private, - VLC_META_DESCRIPTION, psz_temp ); + vlc_meta_SetDescription( p_meta, psz_temp ); } else if( strstr( (char*)p_frame->description, "Copyright" ) ) { - vlc_meta_Add( (vlc_meta_t *)p_demux->p_private, - VLC_META_COPYRIGHT, psz_temp ); + vlc_meta_SetCopyright( p_meta, psz_temp ); } else if( strstr( (char*)p_frame->description, "Publisher" ) ) { - vlc_meta_Add( (vlc_meta_t *)p_demux->p_private, - VLC_META_PUBLISHER, psz_temp ); + vlc_meta_SetPublisher( p_meta, psz_temp ); } else { - /* Unknown meta info */ - vlc_meta_Add( (vlc_meta_t *)p_demux->p_private, - (char *)p_frame->description, psz_temp ); + msg_Err(p_demux, "Fixme: unhandled meta" ); } free( psz_temp ); } diff --git a/modules/gui/macosx/applescript.m b/modules/gui/macosx/applescript.m index a6d059e25b..203a268978 100644 --- a/modules/gui/macosx/applescript.m +++ b/modules/gui/macosx/applescript.m @@ -52,16 +52,21 @@ if ( o_urlString ) { NSURL * o_url; - - playlist_Add( p_playlist, [o_urlString fileSystemRepresentation], - [[[NSFileManager defaultManager] displayNameAtPath: o_urlString] UTF8String], - PLAYLIST_INSERT, PLAYLIST_END ); + input_item_t *p_input; + + p_input = input_ItemNew( p_playlist, + [o_urlString fileSystemRepresentation], + [[[NSFileManager defaultManager] + displayNameAtPath: o_urlString] UTF8String] ); + playlist_PlaylistAddInput( p_playlist, p_input, PLAYLIST_INSERT, + PLAYLIST_END ); + o_url = [NSURL fileURLWithPath: o_urlString]; if( o_url != nil ) - { + { [[NSDocumentController sharedDocumentController] - noteNewRecentDocumentURL: o_url]; + noteNewRecentDocumentURL: o_url]; } } vlc_object_release( p_playlist ); diff --git a/modules/gui/macosx/intf.m b/modules/gui/macosx/intf.m index 2065392f39..9f539997e1 100644 --- a/modules/gui/macosx/intf.m +++ b/modules/gui/macosx/intf.m @@ -943,7 +943,6 @@ static VLCMain *_o_sharedMainInstance = nil; return; } -#define p_input p_intf->p_sys->p_input if( p_intf->p_sys->b_input_update ) { /* Called when new input is opened */ @@ -965,17 +964,17 @@ static VLCMain *_o_sharedMainInstance = nil; vlc_object_release( p_playlist ); - if( ( b_input = ( p_input != NULL ) ) ) + if( ( b_input = ( p_intf->p_sys->p_input != NULL ) ) ) { - vlc_object_yield( p_input ); + vlc_object_yield( p_intf->p_sys->p_input ); /* seekable streams */ - b_seekable = var_GetBool( p_input, "seekable" ); + b_seekable = var_GetBool( p_intf->p_sys->p_input, "seekable" ); /* check wether slow/fast motion is possible*/ - b_control = p_input->input.b_can_pace_control; + b_control = p_intf->p_sys->p_input->input.b_can_pace_control; /* chapters & titles */ - //b_chapters = p_input->stream.i_area_nb > 1; + //b_chapters = p_intf->p_sys->p_input->stream.i_area_nb > 1; vlc_object_release( p_input ); } @@ -1039,13 +1038,13 @@ static VLCMain *_o_sharedMainInstance = nil; return; } o_temp = [NSString stringWithUTF8String: - p_playlist->status.p_item->input.psz_name]; + p_playlist->status.p_item->p_input->psz_name]; if( o_temp == NULL ) o_temp = [NSString stringWithCString: - p_playlist->status.p_item->input.psz_name]; + p_playlist->status.p_item->p_input->psz_name]; [self setScrollField: o_temp stopAfter:-1]; - p_vout = vlc_object_find( p_input, VLC_OBJECT_VOUT, + p_vout = vlc_object_find( p_intf->p_sys->p_input, VLC_OBJECT_VOUT, FIND_PARENT ); if( p_vout != NULL ) { @@ -1069,7 +1068,7 @@ static VLCMain *_o_sharedMainInstance = nil; p_intf->p_sys->b_current_title_update = FALSE; } - if( p_input && [o_timeslider isEnabled] ) + if( p_intf->p_sys->p_input && [o_timeslider isEnabled] ) { /* Update the slider */ vlc_value_t time; @@ -1078,11 +1077,11 @@ static VLCMain *_o_sharedMainInstance = nil; vlc_value_t pos; float f_updated; - var_Get( p_input, "position", &pos ); + var_Get( p_intf->p_sys->p_input, "position", &pos ); f_updated = 10000. * pos.f_float; [o_timeslider setFloatValue: f_updated]; - var_Get( p_input, "time", &time ); + var_Get( p_intf->p_sys->p_input, "time", &time ); i_seconds = time.i_time / 1000000; o_time = [NSString stringWithFormat: @"%d:%02d:%02d", @@ -1108,7 +1107,7 @@ static VLCMain *_o_sharedMainInstance = nil; } /* Manage Playing status */ - var_Get( p_input, "state", &val ); + var_Get( p_intf->p_sys->p_input, "state", &val ); if( p_intf->p_sys->i_play_status != val.i_int ) { p_intf->p_sys->i_play_status = val.i_int; @@ -1125,7 +1124,6 @@ static VLCMain *_o_sharedMainInstance = nil; [self setSubmenusEnabled: FALSE]; } -#undef p_input [self updateMessageArray]; @@ -1225,8 +1223,7 @@ static VLCMain *_o_sharedMainInstance = nil; - (void)resetScrollField { i_end_scroll = -1; -#define p_input p_intf->p_sys->p_input - if( p_input && !p_input->b_die ) + if( p_intf->p_sys->p_input && !p_intf->p_sys->p_input->b_die ) { NSString *o_temp; playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, @@ -1236,15 +1233,14 @@ static VLCMain *_o_sharedMainInstance = nil; return; } o_temp = [NSString stringWithUTF8String: - p_playlist->status.p_item->input.psz_name]; + p_playlist->status.p_item->p_input->psz_name]; if( o_temp == NULL ) o_temp = [NSString stringWithCString: - p_playlist->status.p_item->input.psz_name]; + p_playlist->status.p_item->p_input->psz_name]; [self setScrollField: o_temp stopAfter:-1]; vlc_object_release( p_playlist ); return; } -#undef p_input [self setScrollField: _NS("VLC media player") stopAfter:-1]; } diff --git a/modules/gui/macosx/playlist.h b/modules/gui/macosx/playlist.h index 67ecdf3cc8..18ef164fca 100644 --- a/modules/gui/macosx/playlist.h +++ b/modules/gui/macosx/playlist.h @@ -42,7 +42,6 @@ IBOutlet id o_outline_view; NSMutableDictionary *o_outline_dict; - int i_current_view; } - (void)initStrings; @@ -140,7 +139,7 @@ - (IBAction)addNode:(id)sender; - (void)appendArray:(NSArray*)o_array atPos:(int)i_position enqueue:(BOOL)b_enqueue; -- (void)appendNodeArray:(NSArray*)o_array inNode:(playlist_item_t *)p_node atPos:(int)i_position inView:(int)i_view enqueue:(BOOL)b_enqueue; +- (void)appendNodeArray:(NSArray*)o_array inNode:(playlist_item_t *)p_node atPos:(int)i_position enqueue:(BOOL)b_enqueue; @end diff --git a/modules/gui/macosx/playlist.m b/modules/gui/macosx/playlist.m index 406ff1620b..07d8edc319 100644 --- a/modules/gui/macosx/playlist.m +++ b/modules/gui/macosx/playlist.m @@ -115,9 +115,6 @@ { playlist_t * p_playlist = vlc_object_find( VLCIntf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); - i_current_view = VIEW_CATEGORY; - playlist_ViewUpdate( p_playlist, i_current_view ); - [o_outline_view setTarget: self]; [o_outline_view setDelegate: self]; [o_outline_view setDataSource: self]; @@ -165,17 +162,9 @@ if( item == nil ) { /* root object */ - playlist_view_t *p_view; - p_view = playlist_ViewFind( p_playlist, i_current_view ); - if( p_view && p_view->p_root ) + if( p_playlist->p_root_category ) { - i_return = p_view->p_root->i_children; - - if( i_current_view == VIEW_CATEGORY ) - { - i_return--; /* remove the GENERAL item from the list */ - i_return += p_playlist->p_general->i_children; /* add the items of the general node */ - } + i_return = p_playlist->p_root_category->i_children; } } else @@ -185,10 +174,10 @@ i_return = p_item->i_children; } vlc_object_release( p_playlist ); - + if( i_return <= 0 ) i_return = 0; - + return i_return; } @@ -206,20 +195,9 @@ if( item == nil ) { /* root object */ - playlist_view_t *p_view; - p_view = playlist_ViewFind( p_playlist, i_current_view ); - if( p_view && p_view->p_root ) p_return = p_view->p_root->pp_children[index]; - - if( i_current_view == VIEW_CATEGORY ) + if( p_playlist->p_root_category ) { - if( p_playlist->p_general->i_children && index >= 0 && index < p_playlist->p_general->i_children ) - { - p_return = p_playlist->p_general->pp_children[index]; - } - else if( p_view && p_view->p_root && index >= 0 && index - p_playlist->p_general->i_children < p_view->p_root->i_children ) - { - p_return = p_view->p_root->pp_children[index - p_playlist->p_general->i_children + 1]; - } + p_return = p_playlist->p_root_category->pp_children[index]; } } else @@ -228,7 +206,6 @@ if( p_item && index < p_item->i_children && index >= 0 ) p_return = p_item->pp_children[index]; } - vlc_object_release( p_playlist ); @@ -252,14 +229,9 @@ if( item == nil ) { /* root object */ - playlist_view_t *p_view; - p_view = playlist_ViewFind( p_playlist, i_current_view ); - if( p_view && p_view->p_root ) i_return = p_view->p_root->i_children; - - if( i_current_view == VIEW_CATEGORY ) + if( p_playlist->p_root_category ) { - i_return--; - i_return += p_playlist->p_general->i_children; + i_return = p_playlist->p_root_category->i_children; } } else @@ -304,15 +276,15 @@ if( [[o_tc identifier] isEqualToString:@"1"] ) { o_value = [NSString stringWithUTF8String: - p_item->input.psz_name]; + p_item->p_input->psz_name]; if( o_value == NULL ) o_value = [NSString stringWithCString: - p_item->input.psz_name]; + p_item->p_input->psz_name]; } else if( [[o_tc identifier] isEqualToString:@"2"] ) { char *psz_temp; - psz_temp = vlc_input_item_GetInfo( &p_item->input ,_("Meta-information"),_("Artist") ); + psz_temp = vlc_input_item_GetInfo( p_item->p_input ,_("Meta-information"),_("Artist") ); if( psz_temp == NULL ) o_value = @""; @@ -329,7 +301,7 @@ else if( [[o_tc identifier] isEqualToString:@"3"] ) { char psz_duration[MSTRTIME_MAX_SIZE]; - mtime_t dur = p_item->input.i_duration; + mtime_t dur = p_item->p_input->i_duration; if( dur != -1 ) { secstotimestr( psz_duration, dur/1000000 ); @@ -577,19 +549,6 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ vlc_object_release( p_playlist ); } -- (playlist_item_t *)parentOfItem:(playlist_item_t *)p_item -{ - int i; - for( i = 0 ; i < p_item->i_parents; i++ ) - { - if( p_item->pp_parents[i]->i_view == i_current_view ) - { - return p_item->pp_parents[i]->p_parent; - } - } - return NULL; -} - - (void)updateRowSelection { int i_row; @@ -611,11 +570,10 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ } p_temp_item = p_item; - while( p_temp_item->i_parents > 0 ) + while( p_temp_item->p_parent ) { [o_array insertObject: [NSValue valueWithPointer: p_temp_item] atIndex: 0]; - - p_temp_item = [self parentOfItem: p_temp_item]; + p_temp_item = p_temp_item->p_parent; /*for (i = 0 ; i < p_temp_item->i_parents ; i++) { if( p_temp_item->pp_parents[i]->i_view == i_current_view ) @@ -626,13 +584,16 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ }*/ } - for (j = 0 ; j < [o_array count] - 1 ; j++) + for( j = 0; j < [o_array count] - 1; j++ ) { id o_item; if( ( o_item = [o_outline_dict objectForKey: [NSString stringWithFormat: @"%p", [[o_array objectAtIndex:j] pointerValue]]] ) != nil ) + { + msg_Err( p_playlist, "o_item: %p", o_item ); [o_outline_view expandItem: o_item]; + } } @@ -700,33 +661,15 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ } } - while( p_temp_item->i_parents > 0 ) + while( p_temp_item ) { - p_temp_item = [self parentOfItem: p_temp_item]; + p_temp_item = p_temp_item->p_parent; if( p_temp_item == p_node ) { vlc_mutex_unlock( &p_playlist->object_lock ); vlc_object_release( p_playlist ); return YES; } - -/* for( i = 0; i < p_temp_item->i_parents ; i++ ) - { - if( p_temp_item->pp_parents[i]->i_view == i_current_view ) - { - if( p_temp_item->pp_parents[i]->p_parent == p_node ) - { - vlc_mutex_unlock( &p_playlist->object_lock ); - vlc_object_release( p_playlist ); - return YES; - } - else - { - p_temp_item = p_temp_item->pp_parents[i]->p_parent; - break; - } - } - }*/ } vlc_mutex_unlock( &p_playlist->object_lock ); } @@ -816,7 +759,7 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ { o_real_filename = o_filename; } - playlist_Export( p_playlist, [o_real_filename fileSystemRepresentation], "export-m3u" ); + playlist_Export( p_playlist, [o_real_filename fileSystemRepresentation], p_playlist->p_local_category, "export-m3u" ); } } vlc_object_release( p_playlist ); @@ -840,15 +783,8 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ { if( p_item->i_children == -1 ) { - p_node = [self parentOfItem: p_item]; + p_node = p_item->p_parent; -/* for( i = 0 ; i < p_item->i_parents ; i++ ) - { - if( p_item->pp_parents[i]->i_view == i_current_view ) - { - p_node = p_item->pp_parents[i]->p_parent; - } - }*/ } else { @@ -862,7 +798,7 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ p_item = NULL; } } - playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, i_current_view, p_node, p_item ); + playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, 0, p_node, p_item ); } vlc_object_release( p_playlist ); } @@ -898,7 +834,7 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ { if( p_item->i_children == -1 ) { - playlist_PreparseEnqueue( p_playlist, &p_item->input ); + playlist_PreparseEnqueue( p_playlist, p_item->p_input ); } else { @@ -925,8 +861,6 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ [o_mi setState: playlist_IsServicesDiscoveryLoaded( p_playlist, [o_string cString] ) ? YES : NO]; - i_current_view = VIEW_CATEGORY; - playlist_ViewUpdate( p_playlist, i_current_view ); vlc_object_release( p_playlist ); [self playlistUpdated]; return; @@ -983,14 +917,7 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ } else { - if( p_playlist->status.i_status != PLAYLIST_STOPPED && - p_playlist->status.p_item == [[o_outline_view itemAtRow: i_row] pointerValue] ) - { - playlist_Stop( p_playlist ); - } - vlc_mutex_lock( &p_playlist->object_lock ); - playlist_Delete( p_playlist, p_item->input.i_id ); - vlc_mutex_unlock( &p_playlist->object_lock ); + playlist_LockDelete( p_playlist, p_item->i_id ); } } [self playlistUpdated]; @@ -1026,8 +953,7 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ else /*If no item is selected, sort the whole playlist*/ { - playlist_view_t * p_view = playlist_ViewFind( p_playlist, i_current_view ); - p_item = p_view->p_root; + p_item = p_playlist->p_root_category; } if( p_item->i_children > -1 ) // the item is a node @@ -1038,25 +964,16 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ } else { - int i; - - for( i = 0 ; i < p_item->i_parents ; i++ ) - { - if( p_item->pp_parents[i]->i_view == i_current_view ) - { - vlc_mutex_lock( &p_playlist->object_lock ); - playlist_RecursiveNodeSort( p_playlist, - p_item->pp_parents[i]->p_parent, i_mode, ORDER_NORMAL ); - vlc_mutex_unlock( &p_playlist->object_lock ); - break; - } - } + vlc_mutex_lock( &p_playlist->object_lock ); + playlist_RecursiveNodeSort( p_playlist, + p_item->p_parent, i_mode, ORDER_NORMAL ); + vlc_mutex_unlock( &p_playlist->object_lock ); } vlc_object_release( p_playlist ); [self playlistUpdated]; } -- (playlist_item_t *)createItem:(NSDictionary *)o_one_item +- (input_item_t *)createItem:(NSDictionary *)o_one_item { intf_thread_t * p_intf = VLCIntf; playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, @@ -1066,7 +983,7 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ { return NULL; } - playlist_item_t *p_item; + input_item_t *p_input; int i; BOOL b_rem = FALSE, b_dir = FALSE; NSString *o_uri, *o_name; @@ -1124,15 +1041,15 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ o_uri = o_temp; } - p_item = playlist_ItemNew( p_intf, [o_uri fileSystemRepresentation], [o_name UTF8String] ); - if( !p_item ) + p_input = input_ItemNew( p_playlist, [o_uri fileSystemRepresentation], [o_name UTF8String] ); + if( !p_input ) return NULL; if( o_options ) { for( i = 0; i < (int)[o_options count]; i++ ) { - playlist_ItemAddOption( p_item, strdup( [[o_options objectAtIndex:i] UTF8String] ) ); + vlc_input_item_AddOption( p_input, strdup( [[o_options objectAtIndex:i] UTF8String] ) ); } } @@ -1145,7 +1062,7 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ } vlc_object_release( p_playlist ); - return p_item; + return p_input; } - (void)appendArray:(NSArray*)o_array atPos:(int)i_position enqueue:(BOOL)b_enqueue @@ -1160,29 +1077,39 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ for( i_item = 0; i_item < (int)[o_array count]; i_item++ ) { - playlist_item_t *p_item; + input_item_t *p_input; NSDictionary *o_one_item; /* Get the item */ o_one_item = [o_array objectAtIndex: i_item]; - p_item = [self createItem: o_one_item]; - if( !p_item ) + p_input = [self createItem: o_one_item]; + if( !p_input ) { continue; } /* Add the item */ - playlist_AddItem( p_playlist, p_item, PLAYLIST_INSERT, i_position == -1 ? PLAYLIST_END : i_position + i_item ); + playlist_PlaylistAddInput( p_playlist, p_input, PLAYLIST_INSERT, + i_position == -1 ? PLAYLIST_END : i_position + i_item ); if( i_item == 0 && !b_enqueue ) { + playlist_item_t *p_item; + p_item = playlist_ItemGetByInput( p_playlist, p_input ); playlist_Control( p_playlist, PLAYLIST_ITEMPLAY, p_item ); } + else + { + playlist_item_t *p_item; + p_item = playlist_ItemGetByInput( p_playlist, p_input ); + playlist_Control( p_playlist, PLAYLIST_PREPARSE, p_item ); + } } + [self playlistUpdated]; vlc_object_release( p_playlist ); } -- (void)appendNodeArray:(NSArray*)o_array inNode:(playlist_item_t *)p_node atPos:(int)i_position inView:(int)i_view enqueue:(BOOL)b_enqueue +- (void)appendNodeArray:(NSArray*)o_array inNode:(playlist_item_t *)p_node atPos:(int)i_position enqueue:(BOOL)b_enqueue { int i_item; playlist_t * p_playlist = vlc_object_find( VLCIntf, VLC_OBJECT_PLAYLIST, @@ -1194,27 +1121,39 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ for( i_item = 0; i_item < (int)[o_array count]; i_item++ ) { - playlist_item_t *p_item; + input_item_t *p_input; NSDictionary *o_one_item; /* Get the item */ o_one_item = [o_array objectAtIndex: i_item]; - p_item = [self createItem: o_one_item]; - if( !p_item ) + p_input = [self createItem: o_one_item]; + if( !p_input ) { continue; } /* Add the item */ - playlist_NodeAddItem( p_playlist, p_item, i_view, p_node, PLAYLIST_INSERT, i_position + i_item ); + playlist_NodeAddInput( p_playlist, p_input, p_node, + PLAYLIST_INSERT, + i_position == -1 ? + PLAYLIST_END : i_position + i_item ); + if( i_item == 0 && !b_enqueue ) { + playlist_item_t *p_item; + p_item = playlist_ItemGetByInput( p_playlist, p_input ); playlist_Control( p_playlist, PLAYLIST_ITEMPLAY, p_item ); } + else + { + playlist_item_t *p_item; + p_item = playlist_ItemGetByInput( p_playlist, p_input ); + playlist_Control( p_playlist, PLAYLIST_PREPARSE, p_item ); + } } + [self playlistUpdated]; vlc_object_release( p_playlist ); - } - (IBAction)handlePopUp:(id)sender @@ -1288,8 +1227,8 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ vlc_mutex_lock( &p_playlist->object_lock ); o_current_name = [NSString stringWithUTF8String: - p_item->pp_children[i_current]->input.psz_name]; - psz_temp = vlc_input_item_GetInfo( &p_item->input , + p_item->pp_children[i_current]->p_input->psz_name]; + psz_temp = vlc_input_item_GetInfo( p_item->p_input , _("Meta-information"),_("Artist") ); o_current_author = [NSString stringWithUTF8String: psz_temp]; free( psz_temp); @@ -1339,7 +1278,6 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ { playlist_t * p_playlist = vlc_object_find( VLCIntf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); - playlist_view_t * p_view; id o_result; unsigned int i; @@ -1349,65 +1287,53 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ if( p_playlist == NULL ) return; - p_view = playlist_ViewFind( p_playlist, i_current_view ); - if( p_view ) - { /*First, only search after the selected item:* *(b_selected_item_met = NO) */ - o_result = [self subSearchItem:p_view->p_root]; - if( o_result == NULL ) - { - /* If the first search failed, search again from the beginning */ - o_result = [self subSearchItem:p_view->p_root]; - } - if( o_result != NULL ) - { - int i_start; - if( [[o_result objectAtIndex: 0] pointerValue] == - p_playlist->p_general ) - i_start = 1; - else - i_start = 0; + o_result = [self subSearchItem:p_playlist->p_root_category]; + if( o_result == NULL ) + { + /* If the first search failed, search again from the beginning */ + o_result = [self subSearchItem:p_playlist->p_root_category]; + } + if( o_result != NULL ) + { + int i_start; + if( [[o_result objectAtIndex: 0] pointerValue] == + p_playlist->p_local_category ) + i_start = 1; + else + i_start = 0; - for( i = i_start ; i < [o_result count] - 1 ; i++ ) - { - [o_outline_view expandItem: [o_outline_dict objectForKey: - [NSString stringWithFormat: @"%p", - [[o_result objectAtIndex: i] pointerValue]]]]; - } - i_row = [o_outline_view rowForItem: [o_outline_dict objectForKey: - [NSString stringWithFormat: @"%p", - [[o_result objectAtIndex: [o_result count] - 1 ] - pointerValue]]]]; - } - if( i_row > -1 ) + for( i = i_start ; i < [o_result count] - 1 ; i++ ) { - [o_outline_view selectRow:i_row byExtendingSelection: NO]; - [o_outline_view scrollRowToVisible: i_row]; + [o_outline_view expandItem: [o_outline_dict objectForKey: + [NSString stringWithFormat: @"%p", + [[o_result objectAtIndex: i] pointerValue]]]]; } + i_row = [o_outline_view rowForItem: [o_outline_dict objectForKey: + [NSString stringWithFormat: @"%p", + [[o_result objectAtIndex: [o_result count] - 1 ] + pointerValue]]]]; + } + if( i_row > -1 ) + { + [o_outline_view selectRow:i_row byExtendingSelection: NO]; + [o_outline_view scrollRowToVisible: i_row]; } vlc_object_release( p_playlist ); } - (IBAction)recursiveExpandNode:(id)sender { - int i; id o_item = [o_outline_view itemAtRow: [o_outline_view selectedRow]]; playlist_item_t *p_item = (playlist_item_t *)[o_item pointerValue]; if( ![[o_outline_view dataSource] outlineView: o_outline_view isItemExpandable: o_item] ) { - for( i = 0 ; i < p_item->i_parents ; i++ ) - { - if( p_item->pp_parents[i]->i_view == i_current_view ) - { - o_item = [o_outline_dict objectForKey: [NSString - stringWithFormat: @"%p", p_item->pp_parents[i]->p_parent]]; - break; - } - } + o_item = [o_outline_dict objectForKey: [NSString + stringWithFormat: @"%p", p_item->p_parent]]; } /* We need to collapse the node first, since OSX refuses to recursively @@ -1445,7 +1371,6 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ { int i_mode = 0, i_type; intf_thread_t *p_intf = VLCIntf; - playlist_view_t *p_view; playlist_t *p_playlist = (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); @@ -1462,8 +1387,6 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ return; } - p_view = playlist_ViewFind( p_playlist, i_current_view ); - if( o_tc_sortColumn == o_tc ) { b_isSortDescending = !b_isSortDescending; @@ -1492,7 +1415,7 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ } vlc_mutex_lock( &p_playlist->object_lock ); - playlist_RecursiveNodeSort( p_playlist, p_view->p_root, i_mode, i_type ); + playlist_RecursiveNodeSort( p_playlist, p_playlist->p_root_category, i_mode, i_type ); vlc_mutex_unlock( &p_playlist->object_lock ); vlc_object_release( p_playlist ); @@ -1552,15 +1475,14 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ return; } - playlist_item_t * p_item = playlist_NodeCreate( p_playlist, VIEW_CATEGORY, - _("Empty Folder"), p_playlist->p_general ); + playlist_item_t * p_item = playlist_NodeCreate( p_playlist, + _("Empty Folder"), p_playlist->p_local_category ); if(! p_item ) msg_Warn( VLCIntf, "node creation failed" ); - - playlist_ViewUpdate( p_playlist, VIEW_CATEGORY ); - + vlc_object_release( p_playlist ); + [self playlistUpdated]; } @end @@ -1621,7 +1543,7 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ /* Refuse to move items that are not in the General Node (Service Discovery) */ if( ![self isItem: [o_item pointerValue] inNode: - p_playlist->p_general checkItemExistence: NO]) + p_playlist->p_local_category checkItemExistence: NO]) { vlc_object_release(p_playlist); return NO; @@ -1671,7 +1593,7 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ /* We refuse to drop an item in anything else than a child of the General Node. We still accept items that would be root nodes of the outlineview however, to allow drop in an empty playlist. */ - if( !([self isItem: [item pointerValue] inNode: p_playlist->p_general + if( !([self isItem: [item pointerValue] inNode: p_playlist->p_local_category checkItemExistence: NO] || item == nil) ) { vlc_object_release( p_playlist ); @@ -1726,7 +1648,7 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ /* If the item is to be dropped as root item of the outline, make it a child of the General node. Else, choose the proposed parent as parent. */ - if( item == nil ) p_new_parent = p_playlist->p_general; + if( item == nil ) p_new_parent = p_playlist->p_local_category; else p_new_parent = [item pointerValue]; /* Make sure the proposed parent is a node. @@ -1743,7 +1665,7 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ int i_old_index = 0; p_item = [[o_all_items objectAtIndex:i] pointerValue]; - p_old_parent = [self parentOfItem: p_item]; + p_old_parent = p_item->p_parent; if( !p_old_parent ) continue; /* We may need the old index later */ @@ -1763,8 +1685,6 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ vlc_mutex_lock( &p_playlist->object_lock ); // Acually detach the item from the old position if( playlist_NodeRemoveItem( p_playlist, p_item, p_old_parent ) == - VLC_SUCCESS && - playlist_NodeRemoveParent( p_playlist, p_item, p_old_parent ) == VLC_SUCCESS ) { int i_new_index; @@ -1783,8 +1703,7 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ i_new_index = index + i - i_removed_from_node; } // Reattach the item to the new position - playlist_NodeInsert( p_playlist, i_current_view, p_item, - p_new_parent, i_new_index ); + playlist_NodeInsert( p_playlist, p_item, p_new_parent, i_new_index ); } vlc_mutex_unlock( &p_playlist->object_lock ); } @@ -1839,7 +1758,7 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ else { [self appendNodeArray: o_array inNode: p_node - atPos: index inView: i_current_view enqueue: YES]; + atPos: index enqueue: YES]; } vlc_object_release( p_playlist ); return YES; diff --git a/modules/gui/macosx/playlistinfo.m b/modules/gui/macosx/playlistinfo.m index a52a0d130a..8869e8d938 100644 --- a/modules/gui/macosx/playlistinfo.m +++ b/modules/gui/macosx/playlistinfo.m @@ -182,27 +182,27 @@ if(! [self isItemInPlaylist: p_item] ) return; char *psz_temp; - vlc_mutex_lock( &p_item->input.lock ); + vlc_mutex_lock( &p_item->p_input->lock ); /* fill uri / title / author info */ - if( p_item->input.psz_uri ) + if( p_item->p_input->psz_uri ) { [o_uri_txt setStringValue: - ([NSString stringWithUTF8String:p_item->input.psz_uri] == nil ) ? - [NSString stringWithCString:p_item->input.psz_uri] : - [NSString stringWithUTF8String:p_item->input.psz_uri]]; + ([NSString stringWithUTF8String:p_item->p_input->psz_uri] == nil ) ? + [NSString stringWithCString:p_item->p_input->psz_uri] : + [NSString stringWithUTF8String:p_item->p_input->psz_uri]]; } - if( p_item->input.psz_name ) + if( p_item->p_input->psz_name ) { [o_title_txt setStringValue: - ([NSString stringWithUTF8String:p_item->input.psz_name] == nil ) ? - [NSString stringWithCString:p_item->input.psz_name] : - [NSString stringWithUTF8String:p_item->input.psz_name]]; + ([NSString stringWithUTF8String:p_item->p_input->psz_name] == nil ) ? + [NSString stringWithCString:p_item->p_input->psz_name] : + [NSString stringWithUTF8String:p_item->p_input->psz_name]]; } - vlc_mutex_unlock( &p_item->input.lock ); + vlc_mutex_unlock( &p_item->p_input->lock ); - psz_temp = vlc_input_item_GetInfo( &p_item->input, _("Meta-information"), _("Artist") ); + psz_temp = vlc_input_item_GetInfo( p_item->p_input, _("Meta-information"), _("Artist") ); if( psz_temp ) { @@ -232,7 +232,7 @@ - (void)setMeta: (char *)meta forLabel: (id)theItem { - char *psz_meta = vlc_input_item_GetInfo( &p_item->input, \ + char *psz_meta = vlc_input_item_GetInfo( p_item->p_input, \ _(VLC_META_INFO_CAT), _(meta) ); if( psz_meta != NULL && *psz_meta) [theItem setStringValue: [NSString stringWithUTF8String: psz_meta]]; @@ -246,43 +246,43 @@ { /* we can only do that if there's a valid input around */ - vlc_mutex_lock( &p_item->input.p_stats->lock ); + vlc_mutex_lock( &p_item->p_input->p_stats->lock ); /* input */ [o_read_bytes_txt setStringValue: [NSString stringWithFormat: \ - @"%8.0f kB", (float)(p_item->input.p_stats->i_read_bytes)/1000]]; + @"%8.0f kB", (float)(p_item->p_input->p_stats->i_read_bytes)/1000]]; [o_input_bitrate_txt setStringValue: [NSString stringWithFormat: \ - @"%6.0f kb/s", (float)(p_item->input.p_stats->f_input_bitrate)*8000]]; + @"%6.0f kb/s", (float)(p_item->p_input->p_stats->f_input_bitrate)*8000]]; [o_demux_bytes_txt setStringValue: [NSString stringWithFormat: \ - @"%8.0f kB", (float)(p_item->input.p_stats->i_demux_read_bytes)/1000]]; + @"%8.0f kB", (float)(p_item->p_input->p_stats->i_demux_read_bytes)/1000]]; [o_demux_bitrate_txt setStringValue: [NSString stringWithFormat: \ - @"%6.0f kb/s", (float)(p_item->input.p_stats->f_demux_bitrate)*8000]]; + @"%6.0f kb/s", (float)(p_item->p_input->p_stats->f_demux_bitrate)*8000]]; /* Video */ [o_video_decoded_txt setStringValue: [NSString stringWithFormat: @"%5i", \ - p_item->input.p_stats->i_decoded_video]]; + p_item->p_input->p_stats->i_decoded_video]]; [o_displayed_txt setStringValue: [NSString stringWithFormat: @"%5i", \ - p_item->input.p_stats->i_displayed_pictures]]; + p_item->p_input->p_stats->i_displayed_pictures]]; [o_lost_frames_txt setStringValue: [NSString stringWithFormat: @"%5i", \ - p_item->input.p_stats->i_lost_pictures]]; + p_item->p_input->p_stats->i_lost_pictures]]; /* Sout */ [o_sent_packets_txt setStringValue: [NSString stringWithFormat: @"%5i", \ - p_item->input.p_stats->i_sent_packets]]; + p_item->p_input->p_stats->i_sent_packets]]; [o_sent_bytes_txt setStringValue: [NSString stringWithFormat: @"%8.0f kB", \ - (float)(p_item->input.p_stats->i_sent_bytes)/1000]]; + (float)(p_item->p_input->p_stats->i_sent_bytes)/1000]]; [o_sent_bitrate_txt setStringValue: [NSString stringWithFormat: \ - @"%6.0f kb/s", (float)(p_item->input.p_stats->f_send_bitrate*8)*1000]]; + @"%6.0f kb/s", (float)(p_item->p_input->p_stats->f_send_bitrate*8)*1000]]; /* Audio */ [o_audio_decoded_txt setStringValue: [NSString stringWithFormat: @"%5i", \ - p_item->input.p_stats->i_decoded_audio]]; + p_item->p_input->p_stats->i_decoded_audio]]; [o_played_abuffers_txt setStringValue: [NSString stringWithFormat: @"%5i", \ - p_item->input.p_stats->i_played_abuffers]]; + p_item->p_input->p_stats->i_played_abuffers]]; [o_lost_abuffers_txt setStringValue: [NSString stringWithFormat: @"%5i", \ - p_item->input.p_stats->i_lost_abuffers]]; + p_item->p_input->p_stats->i_lost_abuffers]]; - vlc_mutex_unlock( &p_item->input.p_stats->lock ); + vlc_mutex_unlock( &p_item->p_input->p_stats->lock ); } } @@ -302,12 +302,12 @@ if( [self isItemInPlaylist: p_item] ) { - vlc_mutex_lock( &p_item->input.lock ); + vlc_mutex_lock( &p_item->p_input->lock ); - p_item->input.psz_uri = strdup( [[o_uri_txt stringValue] UTF8String] ); - p_item->input.psz_name = strdup( [[o_title_txt stringValue] UTF8String] ); - vlc_mutex_unlock( &p_item->input.lock ); - vlc_input_item_AddInfo( &p_item->input, _("Meta-information"), _("Artist"), [[o_author_txt stringValue] UTF8String]); + p_item->p_input->psz_uri = strdup( [[o_uri_txt stringValue] UTF8String] ); + p_item->p_input->psz_name = strdup( [[o_title_txt stringValue] UTF8String] ); + vlc_mutex_unlock( &p_item->p_input->lock ); + vlc_input_item_AddInfo( p_item->p_input, _("Meta-information"), _("Artist"), [[o_author_txt stringValue] UTF8String]); val.b_bool = VLC_TRUE; var_Set( p_playlist, "intf-change", val ); @@ -461,37 +461,37 @@ static VLCInfoTreeItem *o_root_item = nil; { if( self == o_root_item ) { - vlc_mutex_lock( &p_item->input.lock ); + vlc_mutex_lock( &p_item->p_input->lock ); o_children = [[NSMutableArray alloc] initWithCapacity: - p_item->input.i_categories]; - for (i = 0 ; i < p_item->input.i_categories ; i++) + p_item->p_input->i_categories]; + for (i = 0 ; i < p_item->p_input->i_categories ; i++) { [o_children addObject:[[VLCInfoTreeItem alloc] initWithName: [NSString stringWithUTF8String: - p_item->input.pp_categories[i]->psz_name] + p_item->p_input->pp_categories[i]->psz_name] value: @"" ID: i parent: self]]; } - vlc_mutex_unlock( &p_item->input.lock ); + vlc_mutex_unlock( &p_item->p_input->lock ); } else if( o_parent == o_root_item ) { - vlc_mutex_lock( &p_item->input.lock ); + vlc_mutex_lock( &p_item->p_input->lock ); o_children = [[NSMutableArray alloc] initWithCapacity: - p_item->input.pp_categories[i_object_id]->i_infos]; + p_item->p_input->pp_categories[i_object_id]->i_infos]; - for (i = 0 ; i < p_item->input.pp_categories[i_object_id]->i_infos ; i++) + for (i = 0 ; i < p_item->p_input->pp_categories[i_object_id]->i_infos ; i++) { [o_children addObject:[[VLCInfoTreeItem alloc] initWithName: [NSString stringWithUTF8String: - p_item->input.pp_categories[i_object_id]->pp_infos[i]->psz_name] + p_item->p_input->pp_categories[i_object_id]->pp_infos[i]->psz_name] value: [NSString stringWithUTF8String: - p_item->input.pp_categories[i_object_id]->pp_infos[i]->psz_value] + p_item->p_input->pp_categories[i_object_id]->pp_infos[i]->psz_value] ID: i parent: self]]; } - vlc_mutex_unlock( &p_item->input.lock ); + vlc_mutex_unlock( &p_item->p_input->lock ); } else { diff --git a/modules/gui/macosx/wizard.m b/modules/gui/macosx/wizard.m index 8ef0f75225..388c02f33c 100644 --- a/modules/gui/macosx/wizard.m +++ b/modules/gui/macosx/wizard.m @@ -583,7 +583,7 @@ static VLCWizard *_o_sharedInstance = nil; NSMutableArray * tempArray = [[NSMutableArray alloc] init]; while( x != y ) { - playlist_item_t *p_item = + playlist_item_t *p_item = [[o_t2_tbl_plst itemAtRow: [[o_t2_tbl_plst selectedRowIndexes] indexGreaterThanOrEqualToIndex: x]] pointerValue]; @@ -591,7 +591,7 @@ static VLCWizard *_o_sharedInstance = nil; if( p_item->i_children <= 0 ) { [tempArray addObject: [NSString stringWithUTF8String: - p_item->input.psz_uri]]; + p_item->p_input->psz_uri]]; stop = NO; } else @@ -1289,17 +1289,17 @@ static VLCWizard *_o_sharedInstance = nil; NSString *tempString = [NSString stringWithFormat: \ @"%@ (%i/%i)", _NS("Streaming/Transcoding Wizard"), \ ( x + 1 ), y]; - playlist_item_t *p_item = playlist_ItemNew( p_playlist, \ + input_item_t *p_input = input_ItemNew( p_playlist, \ [[[o_userSelections objectForKey:@"pathToStrm"] \ objectAtIndex:x] UTF8String], \ [tempString UTF8String] ); - playlist_ItemAddOption( p_item, [[[o_userSelections \ + vlc_input_item_AddOption( p_input, [[[o_userSelections \ objectForKey:@"opts"] objectAtIndex: x] UTF8String]); if(! [[o_userSelections objectForKey:@"partExtractFrom"] \ isEqualToString:@""] ) { - playlist_ItemAddOption( p_item, [[NSString \ + vlc_input_item_AddOption( p_input, [[NSString \ stringWithFormat: @"start-time=%@", [o_userSelections \ objectForKey: @"partExtractFrom"]] UTF8String] ); } @@ -1307,26 +1307,27 @@ static VLCWizard *_o_sharedInstance = nil; if(! [[o_userSelections objectForKey:@"partExtractTo"] \ isEqualToString:@""] ) { - playlist_ItemAddOption( p_item, [[NSString \ + vlc_input_item_AddOption( p_input, [[NSString \ stringWithFormat: @"stop-time=%@", [o_userSelections \ objectForKey: @"partExtractTo"]] UTF8String] ); } - playlist_ItemAddOption( p_item, [[NSString stringWithFormat: \ + vlc_input_item_AddOption( p_input, [[NSString stringWithFormat: \ @"ttl=%@", [o_userSelections objectForKey:@"ttl"]] \ UTF8String] ); - playlist_AddItem( p_playlist, p_item, PLAYLIST_STOP, PLAYLIST_END ); - + playlist_PlaylistAddInput( p_playlist, p_input, PLAYLIST_STOP, PLAYLIST_END ); + if( x == 0 ) - /* play the first item and add the others afterwards */ + { + /* play the first item and add the others afterwards */ + playlist_item_t *p_item = playlist_ItemGetByInput( p_playlist, p_input ); playlist_Control( p_playlist, PLAYLIST_ITEMPLAY, p_item ); + } x += 1; } - playlist_ViewUpdate( p_playlist, VIEW_CATEGORY ); - vlc_object_release(p_playlist); } else { msg_Err( p_intf, "unable to find playlist" ); diff --git a/modules/gui/skins2/Modules.am b/modules/gui/skins2/Modules.am index b72118cf49..1951eec9a0 100644 --- a/modules/gui/skins2/Modules.am +++ b/modules/gui/skins2/Modules.am @@ -176,8 +176,6 @@ SOURCES_skins2 = \ \ vars/equalizer.cpp \ vars/equalizer.hpp \ - vars/playlist.cpp \ - vars/playlist.hpp \ vars/playtree.cpp \ vars/playtree.hpp \ vars/time.cpp \ diff --git a/modules/gui/skins2/commands/cmd_add_item.cpp b/modules/gui/skins2/commands/cmd_add_item.cpp index 9bf80b6744..771ec13c91 100644 --- a/modules/gui/skins2/commands/cmd_add_item.cpp +++ b/modules/gui/skins2/commands/cmd_add_item.cpp @@ -37,13 +37,13 @@ void CmdAddItem::execute() if( m_playNow ) { // Enqueue and play the item - playlist_Add( pPlaylist, m_name.c_str(),m_name.c_str(), - PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END ); + playlist_PlaylistAdd( pPlaylist, m_name.c_str(),m_name.c_str(), + PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END ); } else { // Enqueue the item only - playlist_Add( pPlaylist, m_name.c_str(), m_name.c_str(), - PLAYLIST_APPEND, PLAYLIST_END ); + playlist_PlaylistAdd( pPlaylist, m_name.c_str(), m_name.c_str(), + PLAYLIST_APPEND, PLAYLIST_END ); } } diff --git a/modules/gui/skins2/commands/cmd_playlist.cpp b/modules/gui/skins2/commands/cmd_playlist.cpp index 617dc564b4..a598ba89fa 100644 --- a/modules/gui/skins2/commands/cmd_playlist.cpp +++ b/modules/gui/skins2/commands/cmd_playlist.cpp @@ -33,18 +33,6 @@ void CmdPlaylistDel::execute() } -void CmdPlaylistSort::execute() -{ - // XXX add the mode and type - playlist_t *pPlaylist = getIntf()->p_sys->p_playlist; - if( pPlaylist != NULL ) - { - playlist_Sort( pPlaylist, SORT_TITLE, ORDER_NORMAL ); - } - -} - - void CmdPlaylistNext::execute() { playlist_t *pPlaylist = getIntf()->p_sys->p_playlist; @@ -118,7 +106,8 @@ void CmdPlaylistSave::execute() { // FIXME: when the PLS export will be working, we'll need to remove // this hardcoding... - playlist_Export( pPlaylist, m_file.c_str(), "export-m3u" ); + msg_Err( getIntf(), "need to fix playlist save" ); +// playlist_Export( pPlaylist, m_file.c_str(), "export-m3u" ); } } diff --git a/modules/gui/skins2/commands/cmd_playtree.cpp b/modules/gui/skins2/commands/cmd_playtree.cpp index e40da63519..68aac7d977 100644 --- a/modules/gui/skins2/commands/cmd_playtree.cpp +++ b/modules/gui/skins2/commands/cmd_playtree.cpp @@ -33,10 +33,11 @@ void CmdPlaytreeDel::execute() void CmdPlaytreeSort::execute() { /// \todo Choose sort method/order - Need more commands + /// \todo Choose the correct view playlist_t *p_playlist = getIntf()->p_sys->p_playlist; vlc_mutex_lock( &p_playlist->object_lock ); - playlist_view_t* p_view = playlist_ViewFind( p_playlist, p_playlist->status.i_view ); - playlist_RecursiveNodeSort( p_playlist, p_view->p_root , SORT_TITLE, ORDER_NORMAL ); + playlist_RecursiveNodeSort( p_playlist, p_playlist->p_root_onelevel, + SORT_TITLE, ORDER_NORMAL ); vlc_mutex_unlock( &p_playlist->object_lock ); // Ask for rebuild diff --git a/modules/gui/skins2/commands/cmd_vars.cpp b/modules/gui/skins2/commands/cmd_vars.cpp index ce08f35813..59c5848567 100644 --- a/modules/gui/skins2/commands/cmd_vars.cpp +++ b/modules/gui/skins2/commands/cmd_vars.cpp @@ -25,17 +25,9 @@ #include "../src/vlcproc.hpp" #include "../utils/var_text.hpp" #include "../vars/equalizer.hpp" -#include "../vars/playlist.hpp" #include "../vars/playtree.hpp" -void CmdNotifyPlaylist::execute() -{ - // Notify the playlist variable - Playlist &rVar = VlcProc::instance( getIntf() )->getPlaylistVar(); - rVar.onChange(); -} - void CmdPlaytreeChanged::execute() { // Notify the playtree variable @@ -43,7 +35,6 @@ void CmdPlaytreeChanged::execute() rVar.onChange(); } - void CmdPlaytreeUpdate::execute() { // Notify the playtree variable @@ -53,9 +44,8 @@ void CmdPlaytreeUpdate::execute() bool CmdPlaytreeUpdate::checkRemove( CmdGeneric *pQueuedCommand ) const { - + // We don't use RTTI - Use C-style cast CmdPlaytreeUpdate *pUpdateCommand = (CmdPlaytreeUpdate *)(pQueuedCommand); - //CmdPlaytreeUpdate *pUpdateCommand = dynamic_cast(pQueuedCommand); if( m_id == pUpdateCommand->m_id ) { return true; diff --git a/modules/gui/skins2/parser/interpreter.cpp b/modules/gui/skins2/parser/interpreter.cpp index b09e910e67..2ba41f6139 100644 --- a/modules/gui/skins2/parser/interpreter.cpp +++ b/modules/gui/skins2/parser/interpreter.cpp @@ -76,12 +76,8 @@ Interpreter::Interpreter( intf_thread_t *pIntf ): SkinObject( pIntf ) REGISTER_CMD( "playlist.load()", CmdDlgPlaylistLoad ) REGISTER_CMD( "playlist.save()", CmdDlgPlaylistSave ) REGISTER_CMD( "playlist.add()", CmdDlgAdd ) - VarList &rVar = VlcProc::instance( getIntf() )->getPlaylistVar(); - m_commandMap["playlist.del()"] = - CmdGenericPtr( new CmdPlaylistDel( getIntf(), rVar ) ); REGISTER_CMD( "playlist.next()", CmdPlaylistNext ) REGISTER_CMD( "playlist.previous()", CmdPlaylistPrevious ) - REGISTER_CMD( "playlist.sort()", CmdPlaylistSort ) m_commandMap["playlist.setRandom(true)"] = CmdGenericPtr( new CmdPlaylistRandom( getIntf(), true ) ); m_commandMap["playlist.setRandom(false)"] = diff --git a/modules/gui/skins2/parser/skin_parser.cpp b/modules/gui/skins2/parser/skin_parser.cpp index f3ea0c2f74..09a6dc71fc 100644 --- a/modules/gui/skins2/parser/skin_parser.cpp +++ b/modules/gui/skins2/parser/skin_parser.cpp @@ -291,12 +291,12 @@ void SkinParser::handleBeginElement( const string &rName, AttrList_t &attr ) m_pData->m_listLayout.push_back( layout ); m_curLayer = 0; } - else if( rName == "Playlist" ) { RequireDefault( "id" ); RequireDefault( "font" ); CheckDefault( "visible", "true" ); + CheckDefault( "flat", "true" ); // Only difference here CheckDefault( "x", "0" ); CheckDefault( "y", "0" ); CheckDefault( "width", "0" ); @@ -304,26 +304,33 @@ void SkinParser::handleBeginElement( const string &rName, AttrList_t &attr ) CheckDefault( "lefttop", "lefttop" ); CheckDefault( "rightbottom", "lefttop" ); CheckDefault( "bgimage", "none" ); + CheckDefault( "itemimage", "none" ); + CheckDefault( "openimage", "none" ); + CheckDefault( "closedimage", "none" ); CheckDefault( "fgcolor", "#000000" ); CheckDefault( "playcolor", "#FF0000" ); CheckDefault( "bgcolor1", "#FFFFFF" ); CheckDefault( "bgcolor2", "#FFFFFF" ); CheckDefault( "selcolor", "#0000FF" ); CheckDefault( "help", "" ); - - m_curListId = uniqueId( attr["id"] ); - const BuilderData::List listData( m_curListId, atoi( attr["x"] ) + + m_curTreeId = uniqueId( attr["id"] ); + const BuilderData::Tree treeData( m_curTreeId, atoi( attr["x"] ) + m_xOffset, atoi( attr["y"] ) + m_yOffset, attr["visible"], + attr["flat"], atoi( attr["width"]), atoi( attr["height"] ), - attr["lefttop"], attr["rightbottom"], attr["font"], - "playlist", attr["bgimage"], attr["fgcolor"], - attr["playcolor"], attr["bgcolor1"], attr["bgcolor2"], + attr["lefttop"], attr["rightbottom"], + attr["font"], "playtree", + attr["bgimage"], attr["itemimage"], + attr["openimage"], attr["closedimage"], + attr["fgcolor"], + attr["playcolor"], + attr["bgcolor1"], + attr["bgcolor2"], attr["selcolor"], attr["help"], m_curLayer, m_curWindowId, m_curLayoutId ); m_curLayer++; - m_pData->m_listList.push_back( listData ); + m_pData->m_listTree.push_back( treeData ); } - else if( rName == "Playtree" ) { RequireDefault( "id" ); @@ -412,12 +419,7 @@ void SkinParser::handleBeginElement( const string &rName, AttrList_t &attr ) CheckDefault( "help", "" ); string newValue = attr["value"]; - if( m_curListId != "" ) - { - // Slider associated to a list - newValue = "playlist.slider"; - } - else if( m_curTreeId != "" ) + if( m_curTreeId != "" ) { // Slider associated to a tree newValue = "playtree.slider"; @@ -560,11 +562,7 @@ void SkinParser::handleEndElement( const string &rName ) m_xOffsetList.pop_back(); m_yOffsetList.pop_back(); } - else if( rName == "Playlist" ) - { - m_curListId = ""; - } - else if( rName == "Playtree" ) + else if( rName == "Playtree" || rName == "Playlist" ) { m_curTreeId = ""; } diff --git a/modules/gui/skins2/src/skin_main.cpp b/modules/gui/skins2/src/skin_main.cpp index 503966114f..dccee59743 100644 --- a/modules/gui/skins2/src/skin_main.cpp +++ b/modules/gui/skins2/src/skin_main.cpp @@ -308,8 +308,8 @@ static int DemuxOpen( vlc_object_t *p_this ) if( p_playlist != NULL ) { // Make sure the item is deleted afterwards - p_playlist->pp_items[p_playlist->i_index]->b_autodeletion = - VLC_TRUE; + /// \bug does not always work + p_playlist->status.p_item->i_flags |= PLAYLIST_REMOVE_FLAG; vlc_object_release( p_playlist ); } diff --git a/modules/gui/skins2/src/vlcproc.cpp b/modules/gui/skins2/src/vlcproc.cpp index ec112348fd..dcd36ed537 100644 --- a/modules/gui/skins2/src/vlcproc.cpp +++ b/modules/gui/skins2/src/vlcproc.cpp @@ -79,11 +79,6 @@ VlcProc::VlcProc( intf_thread_t *pIntf ): SkinObject( pIntf ), #define REGISTER_VAR( var, type, name ) \ var = VariablePtr( new type( getIntf() ) ); \ pVarManager->registerVar( var, name ); - - /* Playlist variables */ - REGISTER_VAR( m_cPlaylist, Playlist, "playlist" ) - pVarManager->registerVar( getPlaylistVar().getPositionVarPtr(), - "playlist.slider" ); REGISTER_VAR( m_cVarRandom, VarBoolImpl, "playlist.isRandom" ) REGISTER_VAR( m_cVarLoop, VarBoolImpl, "playlist.isLoop" ) REGISTER_VAR( m_cVarRepeat, VarBoolImpl, "playlist.isRepeat" ) @@ -415,14 +410,11 @@ int VlcProc::onIntfChange( vlc_object_t *pObj, const char *pVariable, playlist_t *p_playlist = (playlist_t*)pObj; pThis->updateStreamName(p_playlist); - // Create a playlist notify command (for old style playlist) - CmdNotifyPlaylist *pCmd = new CmdNotifyPlaylist( pThis->getIntf() ); // Create a playtree notify command (for new style playtree) CmdPlaytreeChanged *pCmdTree = new CmdPlaytreeChanged( pThis->getIntf() ); // Push the command in the asynchronous command queue AsyncQueue *pQueue = AsyncQueue::instance( pThis->getIntf() ); - pQueue->push( CmdGenericPtr( pCmd ) ); pQueue->push( CmdGenericPtr( pCmdTree ) ); return VLC_SUCCESS; @@ -460,16 +452,12 @@ int VlcProc::onItemChange( vlc_object_t *pObj, const char *pVariable, playlist_t *p_playlist = (playlist_t*)pObj; pThis->updateStreamName(p_playlist); - // Create a playlist notify command - // TODO: selective update - CmdNotifyPlaylist *pCmd = new CmdNotifyPlaylist( pThis->getIntf() ); // Create a playtree notify command CmdPlaytreeUpdate *pCmdTree = new CmdPlaytreeUpdate( pThis->getIntf(), newVal.i_int ); // Push the command in the asynchronous command queue AsyncQueue *pQueue = AsyncQueue::instance( pThis->getIntf() ); - pQueue->push( CmdGenericPtr( pCmd ) ); pQueue->push( CmdGenericPtr( pCmdTree ), true ); return VLC_SUCCESS; @@ -491,12 +479,8 @@ int VlcProc::onItemAppend( vlc_object_t *pObj, const char *pVariable, p_add ); ptrTree = CmdGenericPtr( pCmdTree ); - // Create a playlist notify command (for old style playlist) - CmdNotifyPlaylist *pCmd = new CmdNotifyPlaylist( pThis->getIntf() ); - // Push the command in the asynchronous command queue AsyncQueue *pQueue = AsyncQueue::instance( pThis->getIntf() ); - pQueue->push( CmdGenericPtr( pCmd ) ); pQueue->push( ptrTree , false ); return VLC_SUCCESS; @@ -515,20 +499,14 @@ int VlcProc::onItemDelete( vlc_object_t *pObj, const char *pVariable, i_id); ptrTree = CmdGenericPtr( pCmdTree ); - // Create a playlist notify command (for old style playlist) - CmdNotifyPlaylist *pCmd = new CmdNotifyPlaylist( pThis->getIntf() ); - // Push the command in the asynchronous command queue AsyncQueue *pQueue = AsyncQueue::instance( pThis->getIntf() ); - pQueue->push( CmdGenericPtr( pCmd ) ); pQueue->push( ptrTree , false ); return VLC_SUCCESS; } - - int VlcProc::onPlaylistChange( vlc_object_t *pObj, const char *pVariable, vlc_value_t oldVal, vlc_value_t newVal, void *pParam ) @@ -541,10 +519,6 @@ int VlcProc::onPlaylistChange( vlc_object_t *pObj, const char *pVariable, playlist_t *p_playlist = (playlist_t*)pObj; pThis->updateStreamName(p_playlist); - // Create a playlist notify command (old style playlist) - // TODO: selective update - CmdNotifyPlaylist *pCmd = new CmdNotifyPlaylist( pThis->getIntf() ); - pQueue->push( CmdGenericPtr( pCmd ) ); // Create two playtree notify commands: one for old item, one for new CmdPlaytreeUpdate *pCmdTree = new CmdPlaytreeUpdate( pThis->getIntf(), oldVal.i_int ); diff --git a/modules/gui/skins2/src/vlcproc.hpp b/modules/gui/skins2/src/vlcproc.hpp index 9f0ecea61e..6008089a9b 100644 --- a/modules/gui/skins2/src/vlcproc.hpp +++ b/modules/gui/skins2/src/vlcproc.hpp @@ -28,7 +28,6 @@ #include #include "../vars/equalizer.hpp" -#include "../vars/playlist.hpp" #include "../vars/playtree.hpp" #include "../vars/time.hpp" #include "../vars/volume.hpp" @@ -52,9 +51,6 @@ class VlcProc: public SkinObject /// Delete the instance of VlcProc static void destroy( intf_thread_t *pIntf ); - /// Getter for the playlist variable - Playlist &getPlaylistVar() { return *((Playlist*)m_cPlaylist.get()); } - /// Getter for the playtree variable Playtree &getPlaytreeVar() { return *((Playtree*)m_cPlaytree.get()); } @@ -104,9 +100,7 @@ class VlcProc: public SkinObject private: /// Timer to call manage() regularly (via doManage()) OSTimer *m_pTimer; - /// Playlist variable - VariablePtr m_cPlaylist; - /// Playtree variable FIXME + /// Playtree variable VariablePtr m_cPlaytree; VariablePtr m_cVarRandom; VariablePtr m_cVarLoop; diff --git a/modules/gui/skins2/vars/playlist.cpp b/modules/gui/skins2/vars/playlist.cpp deleted file mode 100644 index 80d77d7809..0000000000 --- a/modules/gui/skins2/vars/playlist.cpp +++ /dev/null @@ -1,108 +0,0 @@ -/***************************************************************************** - * playlist.cpp - ***************************************************************************** - * Copyright (C) 2003 the VideoLAN team - * $Id$ - * - * Authors: Cyril Deguet - * - * 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. - *****************************************************************************/ - -#include - -#include "playlist.hpp" -#include "../utils/ustring.hpp" - -Playlist::Playlist( intf_thread_t *pIntf ): VarList( pIntf ) -{ - // Get the playlist VLC object - m_pPlaylist = pIntf->p_sys->p_playlist; - - buildList(); -} - - -Playlist::~Playlist() -{ -} - - -void Playlist::delSelected() -{ - // Remove the items from the VLC playlist - int index = 0; - ConstIterator it; - for( it = begin(); it != end(); it++ ) - { - if( (*it).m_selected ) - { - playlist_item_t *p_item = playlist_LockItemGetByPos( m_pPlaylist, - index ); - playlist_LockDelete( m_pPlaylist, p_item->input.i_id ); - } - else - { - index++; - } - } - - notify(); -} - - -void Playlist::action( Elem_t *pItem ) -{ - // Find the index of the item - int index = 0; - ConstIterator it; - for( it = begin(); it != end(); it++ ) - { - if( &*it == pItem ) break; - index++; - } - // Item found ? - if( index < size() ) - { - playlist_Goto( m_pPlaylist, index ); - } -} - - -void Playlist::onChange() -{ - buildList(); - notify(); -} - - -void Playlist::buildList() -{ - clear(); - - vlc_mutex_lock( &m_pPlaylist->object_lock ); - for( int i = 0; i < m_pPlaylist->i_size; i++ ) - { - // Get the name of the playlist item - UString *pName = - new UString( getIntf(), m_pPlaylist->pp_items[i]->input.psz_name ); - // Is it the played stream ? - bool playing = (i == m_pPlaylist->i_index ); - // Add the item in the list - m_list.push_back( Elem_t( UStringPtr( pName ), false, playing ) ); - } - vlc_mutex_unlock( &m_pPlaylist->object_lock ); -} - diff --git a/modules/gui/skins2/vars/playlist.hpp b/modules/gui/skins2/vars/playlist.hpp deleted file mode 100644 index 693f1c9ee9..0000000000 --- a/modules/gui/skins2/vars/playlist.hpp +++ /dev/null @@ -1,55 +0,0 @@ -/***************************************************************************** - * playlist.hpp - ***************************************************************************** - * Copyright (C) 2003 the VideoLAN team - * $Id$ - * - * Authors: Cyril Deguet - * Olivier Teulière - * - * 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. - *****************************************************************************/ - -#ifndef PLAYLIST_HPP -#define PLAYLIST_HPP - -#include "../utils/var_list.hpp" - -/// Variable for VLC playlist -class Playlist: public VarList -{ - public: - Playlist( intf_thread_t *pIntf ); - virtual ~Playlist(); - - /// Remove the selected elements from the list - virtual void delSelected(); - - /// Execute the action associated to this item - virtual void action( Elem_t *pItem ); - - /// Function called to notify playlist changes - void onChange(); - - private: - /// VLC playlist object - playlist_t *m_pPlaylist; - - /// Build the list from the VLC playlist - void buildList(); -}; - - -#endif diff --git a/modules/gui/skins2/vars/playtree.cpp b/modules/gui/skins2/vars/playtree.cpp index 944a2e7c04..bf12c7538a 100644 --- a/modules/gui/skins2/vars/playtree.cpp +++ b/modules/gui/skins2/vars/playtree.cpp @@ -80,8 +80,8 @@ void Playtree::delSelected() playlist_item_t *p_item = (playlist_item_t *)(it->m_pData); if( p_item->i_children == -1 ) { - playlist_Delete( getIntf()->p_sys->p_playlist, - p_item->input.i_id ); + playlist_DeleteFromItemId( getIntf()->p_sys->p_playlist, + p_item->i_id ); it2 = getNextVisibleItem( it ) ; it->parent()->removeChild( it ); it = it2; @@ -107,21 +107,21 @@ void Playtree::action( VarTree *pItem ) { vlc_mutex_lock( &m_pPlaylist->object_lock ); VarTree::Iterator it; - if( pItem->size() ) + + playlist_item_t *p_item = (playlist_item_t *)pItem->m_pData; + playlist_item_t *p_parent = p_item; + while( p_parent ) + { + if( p_parent == m_pPlaylist->p_root_category ) + break; + p_parent = p_parent->p_parent; + } + + if( p_parent ) { - it = pItem->begin(); - while( it->size() ) it = it->begin(); + playlist_Control( m_pPlaylist, PLAYLIST_VIEWPLAY, 1242, + p_parent, p_item ); } - playlist_Control( m_pPlaylist, - PLAYLIST_VIEWPLAY, - m_pPlaylist->status.i_view, - pItem->size() - ? (playlist_item_t *)pItem->m_pData - : (playlist_item_t *)pItem->parent()->m_pData, - pItem->size() - ? (playlist_item_t *)it->m_pData - : (playlist_item_t *)pItem->m_pData - ); vlc_mutex_unlock( &m_pPlaylist->object_lock ); } @@ -142,7 +142,7 @@ void Playtree::onUpdateItem( int id ) { // Update the item playlist_item_t* pNode = (playlist_item_t*)(it->m_pData); - UString *pName = new UString( getIntf(), pNode->input.psz_name ); + UString *pName = new UString( getIntf(), pNode->p_input->psz_name ); it->m_cString = UStringPtr( pName ); it->m_playing = m_pPlaylist->status.p_item == pNode; if( it->m_playing ) descr.b_active_item = true; @@ -185,7 +185,8 @@ void Playtree::onAppend( playlist_add_t *p_add ) playlist_item_t *p_item = playlist_ItemGetById( m_pPlaylist, p_add->i_item ); if( !p_item ) return; - UString *pName = new UString( getIntf(), p_item->input.psz_name ); + UString *pName = new UString( getIntf(), + p_item->p_input->psz_name ); node->add( p_add->i_item, UStringPtr( pName ), false,false, false, p_item->i_flags & PLAYLIST_RO_FLAG, p_item ); @@ -204,8 +205,8 @@ void Playtree::buildNode( playlist_item_t *pNode, VarTree &rTree ) for( int i = 0; i < pNode->i_children; i++ ) { UString *pName = new UString( getIntf(), - pNode->pp_children[i]->input.psz_name ); - rTree.add( pNode->pp_children[i]->input.i_id, UStringPtr( pName ), + pNode->pp_children[i]->p_input->psz_name ); + rTree.add( pNode->pp_children[i]->p_input->i_id, UStringPtr( pName ), false, m_pPlaylist->status.p_item == pNode->pp_children[i], false, pNode->pp_children[i]->i_flags & PLAYLIST_RO_FLAG, @@ -224,17 +225,16 @@ void Playtree::buildTree() i_items_to_append = 0; - playlist_view_t *p_view; - p_view = playlist_ViewFind( m_pPlaylist, VIEW_CATEGORY ); - /// \todo let the user chose the view - clear(); + /* TODO: Let user choose view - Stick with category ATM */ + /* Set the root's name */ - UString *pName = new UString( getIntf(), p_view->p_root->input.psz_name ); + UString *pName = new UString( getIntf(), + m_pPlaylist->p_root_category->p_input->psz_name ); m_cString = UStringPtr( pName ); - buildNode( p_view->p_root, *this ); + buildNode( m_pPlaylist->p_root_category, *this ); vlc_mutex_unlock( &m_pPlaylist->object_lock ); // What is it ? diff --git a/modules/gui/wxwidgets/dialogs.cpp b/modules/gui/wxwidgets/dialogs.cpp index 3f8aaa96ec..b9f9e04915 100644 --- a/modules/gui/wxwidgets/dialogs.cpp +++ b/modules/gui/wxwidgets/dialogs.cpp @@ -440,12 +440,12 @@ void DialogsProvider::OnOpenFileSimple( wxCommandEvent& event ) { char *psz_utf8 = wxFromLocale( paths[i] ); if( event.GetInt() ) - playlist_Add( p_playlist, psz_utf8, psz_utf8, + playlist_PlaylistAdd( p_playlist, psz_utf8, psz_utf8, PLAYLIST_APPEND | (i ? 0 : PLAYLIST_GO) | (i ? PLAYLIST_PREPARSE : 0 ), PLAYLIST_END ); else - playlist_Add( p_playlist, psz_utf8, psz_utf8, + playlist_PlaylistAdd( p_playlist, psz_utf8, psz_utf8, PLAYLIST_APPEND | PLAYLIST_PREPARSE , PLAYLIST_END ); wxLocaleFree( psz_utf8 ); } @@ -471,7 +471,7 @@ void DialogsProvider::OnOpenDirectory( wxCommandEvent& event ) { wxString path = p_dir_dialog->GetPath(); char *psz_utf8 = wxFromLocale( path ); - playlist_Add( p_playlist, psz_utf8, psz_utf8, + playlist_PlaylistAdd( p_playlist, psz_utf8, psz_utf8, PLAYLIST_APPEND | (event.GetInt() ? PLAYLIST_GO : 0), PLAYLIST_END ); wxLocaleFree( psz_utf8 ); diff --git a/modules/gui/wxwidgets/dialogs/infopanels.cpp b/modules/gui/wxwidgets/dialogs/infopanels.cpp index 16be914a81..7260265d77 100644 --- a/modules/gui/wxwidgets/dialogs/infopanels.cpp +++ b/modules/gui/wxwidgets/dialogs/infopanels.cpp @@ -98,6 +98,7 @@ MetaDataPanel::MetaDataPanel( intf_thread_t *_p_intf, ADD_META( VLC_META_LANGUAGE, language_text ); ADD_META( VLC_META_NOW_PLAYING, nowplaying_text ); ADD_META( VLC_META_PUBLISHER, publisher_text ); + ADD_META( VLC_META_SETTING, setting_text ); meta_sizer->Layout(); @@ -120,8 +121,7 @@ void MetaDataPanel::Update( input_item_t *p_item ) name_text->SetValue( wxU( p_item->psz_name ) ); #define UPDATE_META( meta, widget ) { \ - char *psz_meta = vlc_input_item_GetInfo( p_item, _(VLC_META_INFO_CAT), \ - _(meta) ); \ + char *psz_meta = p_item->p_meta->psz_##meta; \ if( psz_meta != NULL && *psz_meta) \ { \ widget->SetLabel( wxU( psz_meta ) ); \ @@ -129,17 +129,18 @@ void MetaDataPanel::Update( input_item_t *p_item ) else { widget->SetLabel( wxU( "-" ) ); } \ } - UPDATE_META( VLC_META_ARTIST, artist_text ); - UPDATE_META( VLC_META_GENRE, genre_text ); - UPDATE_META( VLC_META_COPYRIGHT, copyright_text ); - UPDATE_META( VLC_META_COLLECTION, collection_text ); - UPDATE_META( VLC_META_SEQ_NUM, seqnum_text ); - UPDATE_META( VLC_META_DESCRIPTION, description_text ); - UPDATE_META( VLC_META_RATING, rating_text ); - UPDATE_META( VLC_META_DATE, date_text ); - UPDATE_META( VLC_META_LANGUAGE, language_text ); - UPDATE_META( VLC_META_NOW_PLAYING, nowplaying_text ); - UPDATE_META( VLC_META_PUBLISHER, publisher_text ); + UPDATE_META( artist, artist_text ); + UPDATE_META( genre, genre_text ); + UPDATE_META( copyright, copyright_text ); + UPDATE_META( album, collection_text ); + UPDATE_META( tracknum, seqnum_text ); + UPDATE_META( description, description_text ); + UPDATE_META( rating, rating_text ); + UPDATE_META( date, date_text ); + UPDATE_META( language, language_text ); + UPDATE_META( nowplaying, nowplaying_text ); + UPDATE_META( publisher, publisher_text ); + UPDATE_META( setting, setting_text ); #undef UPDATE_META } diff --git a/modules/gui/wxwidgets/dialogs/iteminfo.cpp b/modules/gui/wxwidgets/dialogs/iteminfo.cpp index 7a92df0450..01cc2eaae1 100644 --- a/modules/gui/wxwidgets/dialogs/iteminfo.cpp +++ b/modules/gui/wxwidgets/dialogs/iteminfo.cpp @@ -70,7 +70,7 @@ ItemInfoDialog::ItemInfoDialog( intf_thread_t *_p_intf, /* Create the standard info panel */ info_panel = new MetaDataPanel(p_intf, panel, true ); - info_panel->Update( &(p_item->input) ); + info_panel->Update( p_item->p_input ); /* Separation */ wxStaticLine *static_line = new wxStaticLine( panel, wxID_OK ); @@ -107,10 +107,10 @@ ItemInfoDialog::~ItemInfoDialog() *****************************************************************************/ void ItemInfoDialog::OnOk( wxCommandEvent& WXUNUSED(event) ) { - vlc_mutex_lock( &p_item->input.lock ); - p_item->input.psz_name = info_panel->GetName(); - p_item->input.psz_uri = info_panel->GetURI(); - vlc_mutex_unlock( &p_item->input.lock ); + vlc_mutex_lock( &p_item->p_input->lock ); + p_item->p_input->psz_name = info_panel->GetName(); + p_item->p_input->psz_uri = info_panel->GetURI(); + vlc_mutex_unlock( &p_item->p_input->lock ); EndModal( wxID_OK ); } diff --git a/modules/gui/wxwidgets/dialogs/open.cpp b/modules/gui/wxwidgets/dialogs/open.cpp index d6a48cccef..d8c9a17ab2 100644 --- a/modules/gui/wxwidgets/dialogs/open.cpp +++ b/modules/gui/wxwidgets/dialogs/open.cpp @@ -1165,11 +1165,11 @@ void OpenDialog::OnOk( wxCommandEvent& WXUNUSED(event) ) for( int i = 0; i < (int)mrl.GetCount(); i++ ) { vlc_bool_t b_start = !i && i_open_arg; - playlist_item_t *p_item; + input_item_t *p_input; char *psz_utf8; psz_utf8 = wxFromLocale( mrl[i] ); - p_item = playlist_ItemNew( p_intf, psz_utf8, psz_utf8 ); + p_input = input_ItemNew( p_intf, psz_utf8, psz_utf8 ); wxLocaleFree( psz_utf8 ); /* Insert options */ @@ -1177,7 +1177,7 @@ void OpenDialog::OnOk( wxCommandEvent& WXUNUSED(event) ) ((const char *)mrl[i + 1].mb_str())[0] == ':' ) { psz_utf8 = wxFromLocale( mrl[i + 1] ); - playlist_ItemAddOption( p_item, psz_utf8 ); + vlc_input_item_AddOption( p_input, psz_utf8 ); wxLocaleFree( psz_utf8 ); i++; } @@ -1188,7 +1188,7 @@ void OpenDialog::OnOk( wxCommandEvent& WXUNUSED(event) ) for( int j = 0; j < (int)subsfile_mrl.GetCount(); j++ ) { psz_utf8 = wxFromLocale( subsfile_mrl[j] ); - playlist_ItemAddOption( p_item, psz_utf8 ); + vlc_input_item_AddOption( p_input, psz_utf8 ); wxLocaleFree( psz_utf8 ); } } @@ -1199,24 +1199,24 @@ void OpenDialog::OnOk( wxCommandEvent& WXUNUSED(event) ) for( int j = 0; j < (int)sout_mrl.GetCount(); j++ ) { psz_utf8 = wxFromLocale( sout_mrl[j] ); - playlist_ItemAddOption( p_item, psz_utf8 ); + vlc_input_item_AddOption( p_input, psz_utf8 ); wxLocaleFree( psz_utf8 ); } } - if( b_start ) { - playlist_AddItem( p_playlist, p_item, - PLAYLIST_APPEND, - PLAYLIST_END ); - playlist_Control( p_playlist, PLAYLIST_ITEMPLAY, p_item ); + playlist_PlaylistAddInput( p_playlist, p_input, PLAYLIST_APPEND, + PLAYLIST_END ); + msg_Err( p_playlist, "Item start not implemented" ); + // FIXME: Play only within the playlist node + //playlist_Control( p_playlist, PLAYLIST_ITEMPLAY, p_item ); } else { - playlist_AddItem( p_playlist, p_item, - PLAYLIST_APPEND|PLAYLIST_PREPARSE, - PLAYLIST_END ); + playlist_PlaylistAddInput( p_playlist, p_input, + PLAYLIST_APPEND|PLAYLIST_PREPARSE, + PLAYLIST_END ); } } diff --git a/modules/gui/wxwidgets/dialogs/playlist.cpp b/modules/gui/wxwidgets/dialogs/playlist.cpp index a1162bde2b..8802d70b32 100644 --- a/modules/gui/wxwidgets/dialogs/playlist.cpp +++ b/modules/gui/wxwidgets/dialogs/playlist.cpp @@ -102,6 +102,7 @@ enum Search_Event, /* controls */ + Source_Event, TreeCtrl_Event, Browse_Event, /* For export playlist */ @@ -114,6 +115,7 @@ enum MenuDummy_Event = wxID_HIGHEST + 999, FirstView_Event = wxID_HIGHEST + 1000, + CategoryView_Event, OneLevelView_Event, LastView_Event = wxID_HIGHEST + 1100, FirstSD_Event = wxID_HIGHEST + 2000, @@ -156,6 +158,8 @@ BEGIN_EVENT_TABLE(Playlist, wxFrame) EVT_MENU( PopupInfo_Event, Playlist::OnPopupInfo) EVT_MENU( PopupAddNode_Event, Playlist::OnPopupAddNode) + /* Source selector */ + EVT_LIST_ITEM_SELECTED( Source_Event, Playlist::OnSourceSelected ) /* Tree control events */ EVT_TREE_ITEM_ACTIVATED( TreeCtrl_Event, Playlist::OnActivateItem ) EVT_TREE_KEY_DOWN( -1, Playlist::OnKeyDown ) @@ -187,9 +191,11 @@ class PlaylistItem : public wxTreeItemData public: PlaylistItem( playlist_item_t *p_item ) : wxTreeItemData() { - i_id = p_item->input.i_id; + i_id = p_item->i_id; + i_input_id = p_item->p_input->i_id; } protected: + int i_input_id; int i_id; friend class Playlist; friend class PlaylistFileDropTarget; @@ -220,8 +226,9 @@ Playlist::Playlist( intf_thread_t *_p_intf, wxWindow *p_parent ): p_view_menu = NULL; p_sd_menu = SDMenu(); - i_current_view = VIEW_CATEGORY; - b_changed_view = VLC_FALSE; +// i_current_view = VIEW_ONELEVEL; + p_current_viewroot = p_playlist->p_root_onelevel; + p_current_treeroot = p_playlist->p_local_onelevel; i_title_sorted = 0; i_group_sorted = 0; @@ -331,6 +338,11 @@ Playlist::Playlist( intf_thread_t *_p_intf, wxWindow *p_parent ): search_button->SetDefault(); toolbar->Realize(); + /* Create teh source selector */ + source_sel = new wxListCtrl( playlist_panel, Source_Event, + wxDefaultPosition, wxDefaultSize, + wxLC_AUTOARRANGE|wxLC_SINGLE_SEL ); + /* Create the tree */ treectrl = new wxTreeCtrl( playlist_panel, TreeCtrl_Event, wxDefaultPosition, wxDefaultSize, @@ -362,7 +374,8 @@ Playlist::Playlist( intf_thread_t *_p_intf, wxWindow *p_parent ): font.SetPointSize(9); treectrl->SetFont( font ); - wxBoxSizer *panel_sizer = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer *panel_sizer = new wxBoxSizer( wxHORIZONTAL ); + panel_sizer->Add( source_sel, 0, wxALL | wxEXPAND, 5 ); panel_sizer->Add( treectrl, 1, wxEXPAND | wxALL, 5 ); panel_sizer->Layout(); @@ -380,9 +393,7 @@ Playlist::Playlist( intf_thread_t *_p_intf, wxWindow *p_parent ): #endif i_saved_id = -1; - - - /* We want to be noticed of playlist changes */ + i_saved_input_id = -1; /* Some global changes happened -> Rebuild all */ var_AddCallback( p_playlist, "intf-change", PlaylistChanged, this ); @@ -443,7 +454,7 @@ void Playlist::UpdateNode( playlist_item_t *p_node, wxTreeItemId node ) child = treectrl->GetNextChild( node, cookie ); } } - treectrl->SetItemImage( node, p_node->input.i_type ); + treectrl->SetItemImage( node, p_node->p_input->i_type ); } @@ -451,9 +462,9 @@ void Playlist::UpdateNode( playlist_item_t *p_node, wxTreeItemId node ) void Playlist::CreateNode( playlist_item_t *p_node, wxTreeItemId parent ) { wxTreeItemId node = - treectrl->AppendItem( parent, wxL2U( p_node->input.psz_name ), + treectrl->AppendItem( parent, wxL2U( p_node->p_input->psz_name ), -1,-1, new PlaylistItem( p_node ) ); - treectrl->SetItemImage( node, p_node->input.i_type ); + treectrl->SetItemImage( node, p_node->p_input->i_type ); UpdateNodeChildren( p_node, node ); } @@ -462,18 +473,20 @@ void Playlist::CreateNode( playlist_item_t *p_node, wxTreeItemId parent ) void Playlist::UpdateNodeChildren( playlist_item_t *p_node, wxTreeItemId node ) { - for( int i = 0; i< p_node->i_children ; i++ ) { /* Append the item */ if( p_node->pp_children[i]->i_children == -1 ) { - wxTreeItemId item = - treectrl->AppendItem( node, - wxL2U( p_node->pp_children[i]->input.psz_name ), -1,-1, + if( !(p_node->pp_children[i]->i_flags & PLAYLIST_DBL_FLAG) ) + { + wxTreeItemId item = + treectrl->AppendItem( node, + wxL2U( p_node->pp_children[i]->p_input->psz_name ), -1,-1, new PlaylistItem( p_node->pp_children[i]) ); - UpdateTreeItem( item ); + UpdateTreeItem( item ); + } } else { @@ -485,12 +498,12 @@ void Playlist::UpdateNodeChildren( playlist_item_t *p_node, /* Update an item in the tree */ void Playlist::UpdateTreeItem( wxTreeItemId item ) { + LockPlaylist( p_intf->p_sys, p_playlist ); if( ! item.IsOk() ) return; wxTreeItemData *p_data = treectrl->GetItemData( item ); if( !p_data ) return; - LockPlaylist( p_intf->p_sys, p_playlist ); playlist_item_t *p_item = playlist_ItemGetById( p_playlist, ((PlaylistItem *)p_data)->i_id ); if( !p_item ) @@ -501,16 +514,19 @@ void Playlist::UpdateTreeItem( wxTreeItemId item ) wxString msg; wxString duration = wxU( "" ); - char *psz_author = vlc_input_item_GetInfo( &p_item->input, - _(VLC_META_INFO_CAT), _(VLC_META_ARTIST) ); - if( !psz_author ) + + char *psz_author; + if( p_item->p_input->p_meta ) { - UnlockPlaylist( p_intf->p_sys, p_playlist ); - return; + psz_author= p_item->p_input->p_meta->psz_artist ? + strdup( p_item->p_input->p_meta->psz_artist ) : + strdup(""); } + else + psz_author = strdup( "" ); char psz_duration[MSTRTIME_MAX_SIZE]; - mtime_t dur = p_item->input.i_duration; + mtime_t dur = p_item->p_input->i_duration; if( dur != -1 ) { @@ -519,18 +535,18 @@ void Playlist::UpdateTreeItem( wxTreeItemId item ) wxU( " )" ) ); } - if( !strcmp( psz_author, "" ) || p_item->input.b_fixed_name == VLC_TRUE ) + if( !strcmp( psz_author, "" ) || p_item->p_input->b_fixed_name == VLC_TRUE ) { - msg = wxString( wxU( p_item->input.psz_name ) ) + duration; + msg = wxString( wxU( p_item->p_input->psz_name ) ) + duration; } else { msg = wxString(wxU( psz_author )) + wxT(" - ") + - wxString(wxU(p_item->input.psz_name)) + duration; + wxString(wxU(p_item->p_input->psz_name)) + duration; } free( psz_author ); treectrl->SetItemText( item , msg ); - treectrl->SetItemImage( item, p_item->input.i_type ); + treectrl->SetItemImage( item, p_item->p_input->i_type ); if( p_playlist->status.p_item == p_item ) { @@ -562,21 +578,20 @@ void Playlist::AppendItem( wxCommandEvent& event ) /* No need to do anything if the playlist is going to be rebuilt */ if( b_need_update ) return; - if( p_add->i_view != i_current_view ) goto update; - node = FindItem( treectrl->GetRootItem(), p_add->i_node ); if( !node.IsOk() ) goto update; p_item = playlist_ItemGetById( p_playlist, p_add->i_item ); if( !p_item ) goto update; + if( (p_item->i_flags & PLAYLIST_DBL_FLAG ) ) goto update; item = FindItem( treectrl->GetRootItem(), p_add->i_item ); if( item.IsOk() ) goto update; item = treectrl->AppendItem( node, - wxL2U( p_item->input.psz_name ), -1,-1, + wxL2U( p_item->p_input->psz_name ), -1,-1, new PlaylistItem( p_item ) ); - treectrl->SetItemImage( item, p_item->input.i_type ); + treectrl->SetItemImage( item, p_item->p_input->i_type ); if( item.IsOk() && p_item->i_children == -1 ) { @@ -585,26 +600,8 @@ void Playlist::AppendItem( wxCommandEvent& event ) update: int i_count = CountItems( treectrl->GetRootItem()); - if( i_count != p_playlist->i_size ) - { - statusbar->SetStatusText( wxString::Format( wxU(_( - "%i items in playlist (%i not shown)")), - p_playlist->i_size, - p_playlist->i_size - i_count ) ); - if( !b_changed_view ) - { - i_current_view = VIEW_CATEGORY; - b_changed_view = VLC_TRUE; - b_need_update = VLC_TRUE; - } - } - else - { - statusbar->SetStatusText( wxString::Format( wxU(_( - "%i items in playlist")), - p_playlist->i_size ), 0 ); - } - + statusbar->SetStatusText( wxString::Format( wxU(_( + "%i items in playlist" ) ), i_count ) ); return; } @@ -612,9 +609,7 @@ update: void Playlist::UpdateItem( int i ) { if( i < 0 ) return; /* Sanity check */ - - wxTreeItemId item = FindItem( treectrl->GetRootItem(), i ); - + wxTreeItemId item = FindItemByInput( treectrl->GetRootItem(), i ); if( item.IsOk() ) { UpdateTreeItem( item ); @@ -626,6 +621,11 @@ void Playlist::RemoveItem( int i ) if( i <= 0 ) return; /* Sanity check */ if( i == i_saved_id ) i_saved_id = -1; + /* Hack: always invalidate input item cache */ + i_saved_input_id = -1; + + /// \todo Check if it is in the source selector */ + wxTreeItemId item = FindItem( treectrl->GetRootItem(), i ); if( item.IsOk() ) @@ -641,6 +641,16 @@ void Playlist::RemoveItem( int i ) /* Find a wxItem from a playlist id */ wxTreeItemId Playlist::FindItem( wxTreeItemId root, int i_id ) +{ + return FindItemInner( root, i_id, false ); +} + +wxTreeItemId Playlist::FindItemByInput( wxTreeItemId root, int i_input_id ) +{ + return FindItemInner( root, i_input_id, true ); +} + +wxTreeItemId Playlist::FindItemInner( wxTreeItemId root, int i_id, bool b_byinput ) { wxTreeItemIdValue cookie; PlaylistItem *p_wxcurrent; @@ -652,51 +662,70 @@ wxTreeItemId Playlist::FindItem( wxTreeItemId root, int i_id ) if( i_id < 0 ) { - wxTreeItemId dummy; - return dummy; + wxTreeItemId dummy; dummy.Unset(); return dummy; } - if( i_saved_id == i_id ) - { + if( b_byinput && i_saved_input_id == i_id ) + return saved_input_tree_item; + if( !b_byinput && i_saved_id == i_id) return saved_tree_item; - } if( !p_wxcurrent ) { - wxTreeItemId dummy; - return dummy; + wxTreeItemId dummy; dummy.Unset(); return dummy; } - if( p_wxcurrent->i_id == i_id ) + if( !b_byinput && p_wxcurrent->i_id == i_id ) { i_saved_id = i_id; saved_tree_item = root; return root; } + if( b_byinput && p_wxcurrent->i_input_id == i_id ) + { + i_saved_input_id = i_id; + saved_input_tree_item = root; + return root; + } while( item.IsOk() ) { p_wxcurrent = (PlaylistItem *)treectrl->GetItemData( item ); - if( p_wxcurrent->i_id == i_id ) + if( !b_byinput && p_wxcurrent->i_id == i_id ) { i_saved_id = i_id; saved_tree_item = item; return item; } + else if( b_byinput && p_wxcurrent->i_input_id == i_id ) + { + i_saved_input_id = i_id; + saved_input_tree_item = item; + return item; + } if( treectrl->ItemHasChildren( item ) ) { - wxTreeItemId search = FindItem( item, i_id ); + wxTreeItemId search = FindItemInner( item, i_id, b_byinput ); if( search.IsOk() ) { - i_saved_id = i_id; - saved_tree_item = search; - return search; + if( !b_byinput ) + { + i_saved_id = i_id; + saved_tree_item = search; + return search; + } + else + { + i_saved_input_id = i_id; + saved_input_tree_item = search; + return search; + + } } } item = treectrl->GetNextChild( root, cookie ); } /* Not found */ - wxTreeItemId dummy; - return dummy; + wxTreeItemId dummy; dummy.Unset(); return dummy; } int Playlist::CountItems( wxTreeItemId root ) @@ -759,7 +788,7 @@ wxTreeItemId Playlist::FindItemByName( wxTreeItemId root, wxString search_string item = treectrl->GetNextChild( root, cookie); } /* Not found */ - wxTreeItemId dummy; + wxTreeItemId dummy; dummy.Unset(); return dummy; } @@ -768,8 +797,6 @@ wxTreeItemId Playlist::FindItemByName( wxTreeItemId root, wxString search_string **********************************************************************/ void Playlist::Rebuild( vlc_bool_t b_root ) { - playlist_view_t *p_view; - i_items_to_append = 0; /* We can remove the callbacks before locking, anyway, we won't @@ -785,39 +812,36 @@ void Playlist::Rebuild( vlc_bool_t b_root ) /* ...and rebuild it */ LockPlaylist( p_intf->p_sys, p_playlist ); } + /* Invalidate cache */ i_saved_id = -1; + i_saved_input_id = -1; - p_view = playlist_ViewFind( p_playlist, i_current_view ); /* FIXME */ + /* Rebuild the list */ + source_sel->ClearAll(); + for( int i = 0 ; i< p_current_viewroot->i_children ; i++ ) + { + source_sel->InsertItem( i, + wxL2U( p_current_viewroot->pp_children[i]->p_input->psz_name) ); + source_sel->SetItemData( i, + p_current_viewroot->pp_children[i]->i_id ); + if( p_current_viewroot->pp_children[i] == p_current_treeroot ) + source_sel->Select( i ); + } /* HACK we should really get new*/ treectrl->DeleteAllItems(); treectrl->AddRoot( wxU(_("root" )), -1, -1, - new PlaylistItem( p_view->p_root) ); + new PlaylistItem( p_current_treeroot ) ); wxTreeItemId root = treectrl->GetRootItem(); - UpdateNode( p_view->p_root, root ); + //UpdateNode( p_current_treeroot, root ); + //CreateNode( p_current_treeroot, root ); + UpdateNodeChildren( p_current_treeroot, root ); int i_count = CountItems( treectrl->GetRootItem() ); - if( i_count < p_playlist->i_size && !b_changed_view ) - { - i_current_view = VIEW_CATEGORY; - b_changed_view = VLC_TRUE; - Rebuild( VLC_FALSE ); - } - else if( i_count != p_playlist->i_size ) - { - statusbar->SetStatusText( wxString::Format( wxU(_( - "%i items in playlist (%i not shown)")), - p_playlist->i_size, - p_playlist->i_size - i_count ) ); - } - else - { - statusbar->SetStatusText( wxString::Format( wxU(_( - "%i items in playlist")), - p_playlist->i_size ), 0 ); - } + statusbar->SetStatusText( wxString::Format( wxU(_( + "%i items in playlist")), i_count ), 0 ); if( b_root ) { @@ -832,8 +856,6 @@ void Playlist::Rebuild( vlc_bool_t b_root ) } } - - void Playlist::ShowPlaylist( bool show ) { if( show ) Rebuild( VLC_TRUE ); @@ -876,16 +898,16 @@ void Playlist::DeleteTreeItem( wxTreeItemId item ) return; } - if( p_item->i_children == -1 ) DeleteItem( p_item->input.i_id ); + if( p_item->i_children == -1 ) DeleteItem( p_item->i_id ); else DeleteNode( p_item ); - RemoveItem( p_item->input.i_id ); + RemoveItem( p_item->i_id ); UnlockPlaylist( p_intf->p_sys, p_playlist ); } void Playlist::DeleteItem( int item_id ) { - playlist_Delete( p_playlist, item_id ); + playlist_DeleteFromItemId( p_playlist, item_id ); } void Playlist::DeleteNode( playlist_item_t *p_item ) @@ -937,8 +959,10 @@ void Playlist::OnSave( wxCommandEvent& WXUNUSED(event) ) { if( dialog.GetPath().mb_str() ) { - playlist_Export( p_playlist, dialog.GetPath().mb_str(), - formats[dialog.GetFilterIndex()].psz_module ); + abort(); +// playlist_Export( p_playlist, dialog.GetPath().mb_str(), +// /* ROOT */ +// formats[dialog.GetFilterIndex()].psz_module ); } } @@ -1010,28 +1034,16 @@ void Playlist::OnSort( wxCommandEvent& event ) void Playlist::OnSearch( wxCommandEvent& WXUNUSED(event) ) { wxString search_string = search_text->GetValue(); + PlaylistItem *p_wxroot; + p_wxroot = (PlaylistItem *)treectrl->GetItemData( treectrl->GetRootItem() ); + playlist_item_t *p_root = playlist_ItemGetById( p_playlist, p_wxroot->i_id ); - vlc_bool_t pb_found = VLC_FALSE; - - wxTreeItemId found = - FindItemByName( treectrl->GetRootItem(), search_string, - search_current, &pb_found ); - - if( !found.IsOk() ) - { - wxTreeItemId dummy; - search_current = dummy; - found = FindItemByName( treectrl->GetRootItem(), search_string, - search_current, &pb_found ); - } + if( !p_root ) abort(); + char *psz_name = wxFromLocale( search_string ); + playlist_LiveSearchUpdate( p_playlist, p_root, psz_name ); + Rebuild( VLC_TRUE ); - if( found.IsOk() ) - { - search_current = found; - treectrl->EnsureVisible( found ); - treectrl->UnselectAll(); - treectrl->SelectItem( found, true ); - } + wxLocaleFree( psz_name ); } /********************************************************************** @@ -1088,46 +1100,33 @@ void Playlist::OnRepeat( wxCommandEvent& event ) ********************************************************************/ void Playlist::OnActivateItem( wxTreeEvent& event ) { - playlist_item_t *p_item,*p_node,*p_item2,*p_node2; + playlist_item_t *p_item, *p_parent; PlaylistItem *p_wxitem = (PlaylistItem *)treectrl->GetItemData( event.GetItem() ); - wxTreeItemId parent = treectrl->GetItemParent( event.GetItem() ); - - PlaylistItem *p_wxparent = (PlaylistItem *)treectrl->GetItemData( parent ); LockPlaylist( p_intf->p_sys, p_playlist ); - if( !( p_wxitem && p_wxparent ) ) + if( !( p_wxitem ) ) { UnlockPlaylist( p_intf->p_sys, p_playlist ); return; } + p_item = playlist_ItemGetById( p_playlist, p_wxitem->i_id ); - p_item2 = playlist_ItemGetById(p_playlist, p_wxitem->i_id); - p_node2 = playlist_ItemGetById(p_playlist, p_wxparent->i_id); - if( p_item2 && p_item2->i_children == -1 ) + p_parent = p_item; + while( p_parent ) { - p_node = p_node2; - p_item = p_item2; + if( p_parent == p_current_treeroot ) + break; + p_parent = p_parent->p_parent; } - else + + if( p_parent ) { - p_node = p_item2; - p_item = NULL; -/* if( p_node && p_node->i_children > 0 && - p_node->pp_children[0]->i_children == -1) - { - p_item = p_node->pp_children[0]; - } - else - { - p_item = NULL; - }*/ + playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, 1242, + p_parent, p_item ); } - - playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, i_current_view, - p_node, p_item ); UnlockPlaylist( p_intf->p_sys, p_playlist ); } @@ -1157,11 +1156,6 @@ void Playlist::OnKeyDown( wxTreeEvent& event ) } } -void Playlist::OnEnDis( wxCommandEvent& event ) -{ - msg_Warn( p_intf, "not implemented" ); -} - void Playlist::OnDragItemBegin( wxTreeEvent& event ) { event.Allow(); @@ -1227,14 +1221,12 @@ void Playlist::OnDragItemEnd( wxTreeEvent& event ) { if( p_destitem2->pp_children[i] == p_destitem ) break; } - playlist_TreeMove( p_playlist, p_drageditem, p_destitem2, - i, i_current_view ); + playlist_TreeMove( p_playlist, p_drageditem, p_destitem2, i ); } else /* this is a node */ { - playlist_TreeMove( p_playlist, p_drageditem, p_destitem, - 0, i_current_view ); + playlist_TreeMove( p_playlist, p_drageditem, p_destitem, 0 ); } UnlockPlaylist( p_intf->p_sys, p_playlist ); @@ -1265,7 +1257,8 @@ bool PlaylistFileDropTarget::OnDropFiles( wxCoord x, wxCoord y, { /* We were droped below the last item so we append to the * general node */ - p_dest = p->p_playlist->p_general; + msg_Err( p->p_playlist, "USE OF P_GENERAL" ); + p_dest = p->p_playlist->p_local_category; i_pos = PLAYLIST_END; } else @@ -1308,10 +1301,10 @@ bool PlaylistFileDropTarget::OnDropFiles( wxCoord x, wxCoord y, for( size_t i = 0; i < filenames.GetCount(); i++ ) { const char *psz_utf8 = wxDnDFromLocale( filenames[i] ); - playlist_item_t *p_item = - playlist_ItemNew( p->p_playlist, psz_utf8, psz_utf8 ); - playlist_NodeAddItem( p->p_playlist, p_item, p->i_current_view, - p_dest, PLAYLIST_PREPARSE, i_pos ); + input_item_t *p_input = input_ItemNew( p->p_playlist, + psz_utf8, psz_utf8 ); + playlist_NodeAddInput( p->p_playlist, p_input, + p_dest, PLAYLIST_PREPARSE, i_pos ); wxDnDLocaleFree( psz_utf8 ); } @@ -1350,30 +1343,37 @@ void Playlist::OnMenuEvent( wxCommandEvent& event ) } else if( event.GetId() < LastView_Event ) { - - int i_new_view = event.GetId() - FirstView_Event; - - playlist_view_t *p_view = playlist_ViewFind( p_playlist, i_new_view ); - - if( p_view != NULL ) + if( event.GetId() == CategoryView_Event ) { - b_changed_view = VLC_TRUE; - i_current_view = i_new_view; - playlist_ViewUpdate( p_playlist, i_new_view ); - Rebuild( VLC_TRUE ); - return; + p_current_viewroot = p_playlist->p_root_category; + if( p_current_treeroot == p_playlist->p_local_category || + p_current_treeroot == p_playlist->p_local_onelevel ) + { + p_current_treeroot = p_playlist->p_local_category; + } + else if( p_current_treeroot == p_playlist->p_ml_category || + p_current_treeroot == p_playlist->p_ml_onelevel ) + { + p_current_treeroot = p_playlist->p_ml_category; + } } - else if( i_new_view >= VIEW_FIRST_SORTED && - i_new_view <= VIEW_LAST_SORTED ) + else if( event.GetId() == OneLevelView_Event ) { - b_changed_view = VLC_TRUE; - playlist_ViewInsert( p_playlist, i_new_view, "View" ); - playlist_ViewUpdate( p_playlist, i_new_view ); - - i_current_view = i_new_view; - - Rebuild( VLC_TRUE ); + p_current_viewroot = p_playlist->p_root_onelevel; + if( p_current_treeroot == p_playlist->p_local_category || + p_current_treeroot == p_playlist->p_local_onelevel ) + { + p_current_treeroot = p_playlist->p_local_onelevel; + } + else if( p_current_treeroot == p_playlist->p_ml_category || + p_current_treeroot == p_playlist->p_ml_onelevel ) + { + p_current_treeroot = p_playlist->p_ml_onelevel; + } } + wxCommandEvent event; + OnSearch( event ); + return; } else if( event.GetId() >= FirstSD_Event && event.GetId() < LastSD_Event ) { @@ -1410,14 +1410,8 @@ wxMenu * Playlist::ViewMenu() } } - /* FIXME : have a list of "should have" views */ - p_view_menu->Append( FirstView_Event + VIEW_CATEGORY, - wxU(_("Normal") ) ); - p_view_menu->Append( FirstView_Event + VIEW_S_AUTHOR, - wxU(_("Sorted by Artist") ) ); - p_view_menu->Append( FirstView_Event + VIEW_S_ALBUM, - wxU(_("Sorted by Album") ) ); - + p_view_menu->Append( CategoryView_Event, wxU(_("Normal") ) ); + p_view_menu->Append( OneLevelView_Event, wxU(_("One level") ) ); return p_view_menu; } @@ -1515,6 +1509,12 @@ void Playlist::OnPopup( wxContextMenuEvent& event ) void Playlist::OnPopupPlay( wxCommandEvent& event ) { playlist_item_t *p_popup_item, *p_popup_parent; + + + + abort(); + + LockPlaylist( p_intf->p_sys, p_playlist ); p_popup_item = playlist_ItemGetById( p_playlist, i_popup_item ); p_popup_parent = playlist_ItemGetById( p_playlist, i_popup_parent ); @@ -1526,13 +1526,13 @@ void Playlist::OnPopupPlay( wxCommandEvent& event ) p_popup_item->i_children > 0 ) { playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, - i_current_view, p_popup_item, + 1242, p_popup_item, p_popup_item->pp_children[0] ); } else { - playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, - i_current_view, p_popup_item, NULL ); + playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, 1242, + p_popup_item, NULL ); } } else @@ -1540,8 +1540,7 @@ void Playlist::OnPopupPlay( wxCommandEvent& event ) if( event.GetId() == PopupPlay_Event ) { playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, - i_current_view, p_popup_parent, - p_popup_item ); + 1242, p_popup_parent, p_popup_item ); } } } @@ -1563,7 +1562,7 @@ void Playlist::Preparse() { if( p_popup_item->i_children == -1 ) { - playlist_PreparseEnqueue( p_playlist, &p_popup_item->input ); + playlist_PreparseEnqueue( p_playlist, p_popup_item->p_input ); } else { @@ -1573,8 +1572,8 @@ void Playlist::Preparse() { wxMenuEvent dummy; i_wx_popup_item = FindItem( treectrl->GetRootItem(), - p_parent->pp_children[i]->input.i_id ); - i_popup_item = p_parent->pp_children[i]->input.i_id; + p_parent->pp_children[i]->i_id ); + i_popup_item = p_parent->pp_children[i]->i_id; Preparse(); } } @@ -1602,7 +1601,7 @@ void Playlist::OnPopupSort( wxCommandEvent& event ) SORT_TITLE_NODES_FIRST, ORDER_NORMAL ); treectrl->DeleteChildren( i_wx_popup_item ); - i_saved_id = -1; + i_saved_id = -1; i_saved_input_id = -1; UpdateNodeChildren( p_item, i_wx_popup_item ); } @@ -1642,7 +1641,7 @@ void Playlist::OnPopupAddNode( wxCommandEvent& event ) p_item = playlist_ItemGetById( p_playlist, p_wxitem->i_id ); - playlist_NodeCreate( p_playlist, i_current_view, psz_name, p_item ); + playlist_NodeCreate( p_playlist, psz_name, p_item ); UnlockPlaylist( p_intf->p_sys, p_playlist ); Rebuild( VLC_TRUE ); @@ -1650,6 +1649,17 @@ void Playlist::OnPopupAddNode( wxCommandEvent& event ) wxLocaleFree( psz_name ); } +void Playlist::OnSourceSelected( wxListEvent &event ) +{ + int i_id = event.GetData(); + + if( p_current_treeroot && i_id != p_current_treeroot->i_id ) + { + playlist_item_t *p_item = playlist_ItemGetById( p_playlist, i_id ); + if( p_item ) p_current_treeroot = p_item; + Rebuild( VLC_TRUE ); + } +} /***************************************************************************** * Custom events management @@ -1659,12 +1669,16 @@ void Playlist::OnPlaylistEvent( wxCommandEvent& event ) switch( event.GetId() ) { case UpdateItem_Event: + fprintf( stderr,"Update input item id %i\n", event.GetInt() ); UpdateItem( event.GetInt() ); break; case AppendItem_Event: + fprintf( stderr,"Append item id %i\n", + ((playlist_add_t*)event.GetClientData())->i_item ); AppendItem( event ); break; case RemoveItem_Event: + fprintf( stderr,"Remove item id %i\n", event.GetInt() ); RemoveItem( event.GetInt() ); break; } diff --git a/modules/gui/wxwidgets/dialogs/playlist.hpp b/modules/gui/wxwidgets/dialogs/playlist.hpp index 0c5461b679..ce2cd0fe6b 100644 --- a/modules/gui/wxwidgets/dialogs/playlist.hpp +++ b/modules/gui/wxwidgets/dialogs/playlist.hpp @@ -90,8 +90,6 @@ private: wxButton *search_button; wxTreeItemId search_current; - void OnEnDis( wxCommandEvent& event ); - /* Sort */ int i_sort_mode; void OnSort( wxCommandEvent& event ); @@ -136,6 +134,9 @@ private: void OnPopupEna( wxCommandEvent& event ); void OnPopupInfo( wxCommandEvent& event ); void OnPopupAddNode( wxCommandEvent& event ); + + /* List */ + void OnSourceSelected( wxListEvent &event ); protected: void Rebuild( vlc_bool_t ); private: @@ -151,11 +152,15 @@ private: /* Search (internal) */ int CountItems( wxTreeItemId); wxTreeItemId FindItem( wxTreeItemId, int ); + wxTreeItemId FindItemByInput( wxTreeItemId, int ); + wxTreeItemId FindItemInner( wxTreeItemId, int , bool ); wxTreeItemId FindItemByName( wxTreeItemId, wxString, wxTreeItemId, vlc_bool_t *); wxTreeItemId saved_tree_item; + wxTreeItemId saved_input_tree_item; int i_saved_id; + int i_saved_input_id; protected: playlist_t *p_playlist; @@ -179,7 +184,10 @@ private: protected: intf_thread_t *p_intf; wxTreeCtrl *treectrl; + wxListView *source_sel; int i_current_view; + playlist_item_t *p_current_treeroot; + playlist_item_t *p_current_viewroot; friend class PlaylistFileDropTarget; }; diff --git a/modules/gui/wxwidgets/dialogs/wizard.cpp b/modules/gui/wxwidgets/dialogs/wizard.cpp index 666d43250b..800915a583 100644 --- a/modules/gui/wxwidgets/dialogs/wizard.cpp +++ b/modules/gui/wxwidgets/dialogs/wizard.cpp @@ -591,6 +591,7 @@ wizInputPage::wizInputPage( wxWizard *parent, wxWizardPage *prev, intf_thread_t listview->InsertColumn( 1, wxU(_("URI")) ); listview->SetColumnWidth( 0, 250 ); listview->SetColumnWidth( 1, 100 ); +#if 0 for( int i=0 ; i < p_playlist->i_size ; i++ ) { wxString filename = wxL2U( p_playlist->pp_items[i]->input. @@ -602,6 +603,7 @@ wizInputPage::wizInputPage( wxWizard *parent, wxWizardPage *prev, intf_thread_t (long)p_playlist->pp_items[i]->input.i_id ); } listview->Select( p_playlist->i_index , TRUE); +#endif mainSizer->Add( listview, 1, wxALL|wxEXPAND, 5 ); listview->Hide(); @@ -727,7 +729,7 @@ void wizInputPage::OnWizardPageChanging(wxWizardEvent& event) i = listview->GetNextItem( i , wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED); if( i != -1 ) { - long data = listview->GetItemData( i ); + long data = listview->GetItemData( i ); playlist_t *p_playlist = (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE); if( p_playlist ) @@ -736,7 +738,7 @@ void wizInputPage::OnWizardPageChanging(wxWizardEvent& event) p_playlist, (int)data ); if( p_item ) { - p_parent->SetMrl( (const char*)p_item->input.psz_uri ); + p_parent->SetMrl( (const char*)p_item->p_input->psz_uri ); } else event.Veto(); @@ -1631,27 +1633,28 @@ void WizardDialog::Run() VLC_OBJECT_PLAYLIST, FIND_ANYWHERE); if( p_playlist ) { - playlist_item_t *p_item = playlist_ItemNew( p_playlist, mrl, - ITEM_NAME ); - playlist_ItemAddOption( p_item, psz_opt); + input_item_t *p_input = input_ItemNew( p_playlist, mrl, + ITEM_NAME ); + vlc_input_item_AddOption( p_input, psz_opt ); if( i_from != 0) { char psz_from[20]; snprintf( psz_from, 20, "start-time=%i", i_from); - playlist_ItemAddOption( p_item, psz_from); + vlc_input_item_AddOption( p_input, psz_from ); } if( i_to != 0) { char psz_to[20]; snprintf( psz_to, 20, "stop-time=%i", i_to); - playlist_ItemAddOption( p_item, psz_to); + vlc_input_item_AddOption( p_input, psz_to ); } char psz_ttl[20]; snprintf( psz_ttl, 20, "ttl=%i",i_ttl ); - playlist_ItemAddOption( p_item, psz_ttl ); + vlc_input_item_AddOption( p_input, psz_ttl ); - playlist_AddItem( p_playlist, p_item, PLAYLIST_GO, PLAYLIST_END ); + playlist_PlaylistAddInput( p_playlist, p_input, + PLAYLIST_GO, PLAYLIST_END ); vlc_object_release(p_playlist); } else diff --git a/modules/gui/wxwidgets/input_manager.cpp b/modules/gui/wxwidgets/input_manager.cpp index 210d90cd9a..ed3021002e 100644 --- a/modules/gui/wxwidgets/input_manager.cpp +++ b/modules/gui/wxwidgets/input_manager.cpp @@ -144,8 +144,9 @@ void InputManager::UpdateInput() void InputManager::UpdateNowPlaying() { - char *psz_now_playing = vlc_input_item_GetInfo( p_input->input.p_item, - _(VLC_META_INFO_CAT), _(VLC_META_NOW_PLAYING) ); + char *psz_now_playing = p_input->input.p_item->p_meta->psz_nowplaying ? + strdup( p_input->input.p_item->p_meta->psz_nowplaying ): + strdup( "" ); if( psz_now_playing && *psz_now_playing ) { p_main_intf->statusbar->SetStatusText( diff --git a/modules/gui/wxwidgets/interface.cpp b/modules/gui/wxwidgets/interface.cpp index 52f8666b58..fe8fb736ff 100644 --- a/modules/gui/wxwidgets/interface.cpp +++ b/modules/gui/wxwidgets/interface.cpp @@ -1287,7 +1287,7 @@ bool DragAndDrop::OnDropFiles( wxCoord, wxCoord, { char *psz_utf8 = wxDnDFromLocale( filenames[i] ); - playlist_Add( p_playlist, psz_utf8, psz_utf8, + playlist_PlaylistAdd( p_playlist, psz_utf8, psz_utf8, PLAYLIST_APPEND | ((i | b_enqueue) ? 0 : PLAYLIST_GO), PLAYLIST_END ); diff --git a/modules/gui/wxwidgets/playlist_manager.cpp b/modules/gui/wxwidgets/playlist_manager.cpp index c7b1ea0264..6c1191ca0b 100644 --- a/modules/gui/wxwidgets/playlist_manager.cpp +++ b/modules/gui/wxwidgets/playlist_manager.cpp @@ -87,7 +87,7 @@ END_EVENT_TABLE() class PlaylistItem : public wxTreeItemData { public: - PlaylistItem( playlist_item_t *p_item ) : i_id(p_item->input.i_id) {} + PlaylistItem( playlist_item_t *p_item ) : i_id(p_item->p_input->i_id) {} int i_id; }; @@ -220,9 +220,9 @@ static int PlaylistNext( vlc_object_t *p_this, const char *psz_variable, void PlaylistManager::CreateNode( playlist_item_t *p_node, wxTreeItemId parent) { wxTreeItemId node = - treectrl->AppendItem( parent, wxL2U( p_node->input.psz_name ), -1, -1, + treectrl->AppendItem( parent, wxL2U( p_node->p_input->psz_name ), -1, -1, new PlaylistItem( p_node ) ); - treectrl->SetItemImage( node, p_node->input.i_type ); + treectrl->SetItemImage( node, p_node->p_input->i_type ); UpdateNodeChildren( p_node, node ); } @@ -246,7 +246,7 @@ void PlaylistManager::UpdateNode( playlist_item_t *p_node, wxTreeItemId node ) } } - treectrl->SetItemImage( node, p_node->input.i_type ); + treectrl->SetItemImage( node, p_node->p_input->i_type ); } @@ -260,7 +260,7 @@ void PlaylistManager::UpdateNodeChildren( playlist_item_t *p_node, { wxTreeItemId item = treectrl->AppendItem( node, - wxL2U( p_node->pp_children[i]->input.psz_name ), -1,-1, + wxL2U( p_node->pp_children[i]->p_input->psz_name ), -1,-1, new PlaylistItem( p_node->pp_children[i]) ); UpdateTreeItem( item ); @@ -290,9 +290,9 @@ void PlaylistManager::UpdateTreeItem( wxTreeItemId item ) wxString msg; wxString duration = wxU( "" ); - char *psz_author = - vlc_input_item_GetInfo( &p_item->input, - _(VLC_META_INFO_CAT), _(VLC_META_ARTIST) ); + char *psz_author = p_item->p_input->p_meta->psz_artist ? + strdup( p_item->p_input->p_meta->psz_artist ) : + strdup( "" ); if( !psz_author ) { UnlockPlaylist( p_intf->p_sys, p_playlist ); @@ -300,7 +300,7 @@ void PlaylistManager::UpdateTreeItem( wxTreeItemId item ) } char psz_duration[MSTRTIME_MAX_SIZE]; - mtime_t dur = p_item->input.i_duration; + mtime_t dur = p_item->p_input->i_duration; if( dur != -1 ) { @@ -309,18 +309,18 @@ void PlaylistManager::UpdateTreeItem( wxTreeItemId item ) wxU( " )" ) ); } - if( !strcmp( psz_author, "" ) || p_item->input.b_fixed_name == VLC_TRUE ) + if( !strcmp( psz_author, "" ) || p_item->p_input->b_fixed_name == VLC_TRUE ) { - msg = wxString( wxU( p_item->input.psz_name ) ) + duration; + msg = wxString( wxU( p_item->p_input->psz_name ) ) + duration; } else { msg = wxString(wxU( psz_author )) + wxT(" - ") + - wxString(wxU(p_item->input.psz_name)) + duration; + wxString(wxU(p_item->p_input->psz_name)) + duration; } free( psz_author ); treectrl->SetItemText( item , msg ); - treectrl->SetItemImage( item, p_item->input.i_type ); + treectrl->SetItemImage( item, p_item->p_input->i_type ); if( p_playlist->status.p_item == p_item ) { @@ -360,9 +360,9 @@ void PlaylistManager::AppendItem( wxCommandEvent& event ) item = FindItem( treectrl->GetRootItem(), p_add->i_item ); if( item.IsOk() ) goto update; - item = treectrl->AppendItem( node, wxL2U( p_item->input.psz_name ), -1,-1, + item = treectrl->AppendItem( node, wxL2U( p_item->p_input->psz_name ), -1,-1, new PlaylistItem( p_item ) ); - treectrl->SetItemImage( item, p_item->input.i_type ); + treectrl->SetItemImage( item, p_item->p_input->i_type ); if( item.IsOk() && p_item->i_children == -1 ) UpdateTreeItem( item ); @@ -415,19 +415,15 @@ void PlaylistManager::Update() **********************************************************************/ void PlaylistManager::Rebuild( vlc_bool_t b_root ) { - playlist_view_t *p_view; - i_items_to_append = 0; i_cached_item_id = -1; - p_view = playlist_ViewFind( p_playlist, VIEW_CATEGORY ); - treectrl->DeleteAllItems(); treectrl->AddRoot( wxU(_("root" )), -1, -1, - new PlaylistItem( p_view->p_root ) ); + new PlaylistItem( p_playlist->p_root_category ) ); wxTreeItemId root = treectrl->GetRootItem(); - UpdateNode( p_view->p_root, root ); + UpdateNode( p_playlist->p_root_category, root ); } /********************************************************************** @@ -506,9 +502,7 @@ void PlaylistManager::OnActivateItem( wxTreeEvent& event ) p_node = p_item; p_item = NULL; } - - playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, VIEW_CATEGORY, - p_node, p_item ); + playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, p_node, p_item ); UnlockPlaylist( p_intf->p_sys, p_playlist ); } diff --git a/modules/misc/growl.c b/modules/misc/growl.c index db1d450a4c..162175d0a4 100644 --- a/modules/misc/growl.c +++ b/modules/misc/growl.c @@ -162,12 +162,12 @@ static int ItemChange( vlc_object_t *p_this, const char *psz_var, } /* Playing something ... */ - psz_artist = vlc_input_item_GetInfo( p_input->input.p_item, - _("Meta-information"), - _(VLC_META_ARTIST) ); - psz_album = vlc_input_item_GetInfo( p_input->input.p_item, - _("Meta-information"), - _("Album/movie/show title" ) ); + psz_artist = p_input->input.p_item->p_meta->psz_artist ? + strdup( p_input->input.p_item->p_meta->psz_artist ) : + strdup( "" ); + psz_album = p_input->input.p_item->p_meta->psz_album ? + strdup( p_input->input.p_item->p_meta->psz_album ) : + strdup( "" ); psz_title = strdup( p_input->input.p_item->psz_name ); if( psz_title == NULL ) psz_title = strdup( N_("(no title)") ); if( psz_artist == NULL ) psz_artist = strdup( N_("(no artist)") ); diff --git a/modules/misc/msn.c b/modules/misc/msn.c index 6150c7f901..9d4423964b 100644 --- a/modules/misc/msn.c +++ b/modules/misc/msn.c @@ -192,12 +192,12 @@ static int ItemChange( vlc_object_t *p_this, const char *psz_var, } /* Playing something ... */ - psz_artist = vlc_input_item_GetInfo( p_input->input.p_item, - _(VLC_META_INFO_CAT), - _(VLC_META_ARTIST) ); - psz_album = vlc_input_item_GetInfo( p_input->input.p_item, - _(VLC_META_INFO_CAT), - _(VLC_META_COLLECTION) ); + psz_artist = p_input->input.p_item->p_meta->psz_artist ? + strdup( p_input->input.p_item->p_meta->psz_artist ) : + strdup( "" ); + psz_album = p_input->input.p_item->p_meta->psz_album ? + strdup( p_input->input.p_item->p_meta->psz_album ) : + strdup( "" ); psz_title = strdup( p_input->input.p_item->psz_name ); if( psz_title == NULL ) psz_title = strdup( N_("(no title)") ); if( psz_artist == NULL ) psz_artist = strdup( N_("(no artist)") ); diff --git a/modules/misc/playlist/m3u.c b/modules/misc/playlist/m3u.c index bcf37e8d19..01f4dcfe32 100644 --- a/modules/misc/playlist/m3u.c +++ b/modules/misc/playlist/m3u.c @@ -52,51 +52,50 @@ int Export_M3U( vlc_object_t *p_this ) fprintf( p_export->p_file, "#EXTM3U\n" ); /* Go through the playlist and add items */ - for( i = 0; i< p_playlist->i_size ; i++) + for( i = 0; i< p_export->p_root->i_children ; i++) { - if( (p_playlist->pp_items[i]->i_flags & PLAYLIST_SAVE_FLAG) == 0 ) - { + playlist_item_t *p_current = p_export->p_root->pp_children[i]; + if( p_current->i_flags & PLAYLIST_SAVE_FLAG ) continue; - } /* General info */ - if( p_playlist->pp_items[i]->input.psz_name && - strcmp( p_playlist->pp_items[i]->input.psz_name, - p_playlist->pp_items[i]->input.psz_uri ) ) + if( p_current->p_input->psz_name && + strcmp( p_current->p_input->psz_uri, + p_current->p_input->psz_name ) ) { - char *psz_artist = - vlc_input_item_GetInfo( &p_playlist->pp_items[i]->input, - _(VLC_META_INFO_CAT), _(VLC_META_ARTIST) ); + char *psz_artist = p_current->p_input->p_meta->psz_artist ? + strdup( p_current->p_input->p_meta->psz_artist ): + strdup( "" ); if( psz_artist && *psz_artist ) { /* write EXTINF with artist */ fprintf( p_export->p_file, "#EXTINF:%i,%s - %s\n", - (int)(p_playlist->pp_items[i]->input.i_duration/1000000), - psz_artist, - p_playlist->pp_items[i]->input.psz_name ); + (int)( p_current->p_input->i_duration/1000000 ), + psz_artist, + p_current->p_input->psz_name); } else { /* write EXTINF without artist */ fprintf( p_export->p_file, "#EXTINF:%i,%s\n", - (int)(p_playlist->pp_items[i]->input.i_duration/1000000), - p_playlist->pp_items[i]->input.psz_name ); + (int)( p_current->p_input->i_duration/1000000 ), + p_current->p_input->psz_name); } if( psz_artist ) free( psz_artist ); } /* VLC specific options */ - for( j = 0; j < p_playlist->pp_items[i]->input.i_options; j++ ) + for( j = 0; j < p_current->p_input->i_options; j++ ) { fprintf( p_export->p_file, "#EXTVLCOPT:%s\n", - p_playlist->pp_items[i]->input.ppsz_options[j][0] == ':' ? - p_playlist->pp_items[i]->input.ppsz_options[j] + 1 : - p_playlist->pp_items[i]->input.ppsz_options[j] ); + p_current->p_input->ppsz_options[j][0] == ':' ? + p_current->p_input->ppsz_options[j] + 1 : + p_current->p_input->ppsz_options[j] ); } fprintf( p_export->p_file, "%s\n", - p_playlist->pp_items[i]->input.psz_uri ); + p_current->p_input->psz_uri ); } return VLC_SUCCESS; } diff --git a/modules/misc/playlist/old.c b/modules/misc/playlist/old.c index 5fd3793901..ea79b199ad 100644 --- a/modules/misc/playlist/old.c +++ b/modules/misc/playlist/old.c @@ -53,11 +53,12 @@ int Export_Old( vlc_object_t *p_this ) /* Write header */ fprintf( p_export->p_file , PLAYLIST_FILE_HEADER "\n" ); - for ( i = 0 ; i < p_playlist->i_size ; i++ ) + for ( i = 0 ; i < p_export->p_root->i_children ; i++ ) { char *psz_uri; - psz_uri = ToLocale( p_playlist->pp_items[i]->input.psz_uri ); + psz_uri = + ToLocale( p_export->p_root->pp_children[i]->p_input->psz_name ); fprintf( p_export->p_file , "%s\n" , psz_uri ); LocaleFree( psz_uri ); } diff --git a/modules/misc/playlist/xspf.c b/modules/misc/playlist/xspf.c index 59ab4b93e1..9366518237 100644 --- a/modules/misc/playlist/xspf.c +++ b/modules/misc/playlist/xspf.c @@ -55,56 +55,51 @@ int E_(xspf_export_playlist)( vlc_object_t *p_this ) #define p_item p_playlist->status.p_item if ( p_item ) { - for (i = 0; i < p_item->i_parents; i++ ) + if ( p_item->p_parent->p_input->i_type == ITEM_TYPE_PLAYLIST ) { - if ( p_item->pp_parents[i]->p_parent->input.i_type - == ITEM_TYPE_PLAYLIST ) - { - /* set the current node and its children */ - p_node = p_item->pp_parents[i]->p_parent; - pp_items = p_node->pp_children; - i_size = p_node->i_children; + /* set the current node and its children */ + p_node = p_item->p_parent; + pp_items = p_node->pp_children; + i_size = p_node->i_children; #undef p_item - /* save name of the playlist node */ - psz_temp = convert_xml_special_chars( p_node->input.psz_name ); - if ( *psz_temp ) - fprintf( p_export->p_file, "\t%s\n", - psz_temp ); - free( psz_temp ); - - /* save the creator of the playlist node */ - psz = vlc_input_item_GetInfo( &p_node->input, - _(VLC_META_INFO_CAT), - _(VLC_META_ARTIST) ); - if ( psz && !*psz ) - { - free ( psz ); - psz = NULL; - } - - if ( !psz ) - psz = vlc_input_item_GetInfo( &p_node->input, - _(VLC_META_INFO_CAT), - _(VLC_META_AUTHOR) ); - - psz_temp = convert_xml_special_chars( psz ); - - if ( psz ) free( psz ); - if ( *psz_temp ) - fprintf( p_export->p_file, "\t%s\n", - psz_temp ); - free( psz_temp ); - - /* save location of the playlist node */ - psz = assertUTF8URI( p_export->psz_filename ); - if ( psz && *psz ) - { - fprintf( p_export->p_file, "\t%s\n", - psz ); - free( psz ); - } - break; + /* save name of the playlist node */ + psz_temp = convert_xml_special_chars( p_node->p_input->psz_name ); + if ( *psz_temp ) + fprintf( p_export->p_file, "\t%s\n", + psz_temp ); + free( psz_temp ); + + /* save the creator of the playlist node */ + psz = p_node->p_input->p_meta->psz_artist ? + strdup( p_node->p_input->p_meta->psz_artist ): + strdup( "" ); + if ( psz && !*psz ) + { + free ( psz ); + psz = NULL; + } + + if ( !psz ) + psz = p_node->p_input->p_meta->psz_author ? + strdup( p_node->p_input->p_meta->psz_author ): + strdup( "" ); + + psz_temp = convert_xml_special_chars( psz ); + + if ( psz ) free( psz ); + if ( *psz_temp ) + fprintf( p_export->p_file, "\t%s\n", + psz_temp ); + free( psz_temp ); + + /* save location of the playlist node */ + psz = assertUTF8URI( p_export->psz_filename ); + if ( psz && *psz ) + { + fprintf( p_export->p_file, "\t%s\n", + psz ); + free( psz ); } } } @@ -161,37 +156,37 @@ static void xspf_export_item( playlist_item_t *p_item, FILE *p_file ) fprintf( p_file, "\t\t\n" ); /* -> the location */ - if ( p_item->input.psz_uri && *p_item->input.psz_uri ) + if ( p_item->p_input->psz_uri && *p_item->p_input->psz_uri ) { - psz = assertUTF8URI( p_item->input.psz_uri ); + psz = assertUTF8URI( p_item->p_input->psz_uri ); fprintf( p_file, "\t\t\t%s\n", psz ); free( psz ); } /* -> the name/title (only if different from uri)*/ - if ( p_item->input.psz_name && - p_item->input.psz_uri && - strcmp( p_item->input.psz_uri, p_item->input.psz_name ) ) + if ( p_item->p_input->psz_name && + p_item->p_input->psz_uri && + strcmp( p_item->p_input->psz_uri, p_item->p_input->psz_name ) ) { - psz_temp = convert_xml_special_chars( p_item->input.psz_name ); + psz_temp = convert_xml_special_chars( p_item->p_input->psz_name ); if ( *psz_temp ) fprintf( p_file, "\t\t\t%s\n", psz_temp ); free( psz_temp ); } /* -> the artist/creator */ - psz = vlc_input_item_GetInfo( &p_item->input, - _(VLC_META_INFO_CAT), - _(VLC_META_ARTIST) ); + psz = p_item->p_input->p_meta->psz_artist ? + strdup( p_item->p_input->p_meta->psz_artist ): + strdup( "" ); if ( psz && !*psz ) { free ( psz ); psz = NULL; } if ( !psz ) - psz = vlc_input_item_GetInfo( &p_item->input, - _(VLC_META_INFO_CAT), - _(VLC_META_AUTHOR) ); + psz = p_item->p_input->p_meta->psz_author ? + strdup( p_item->p_input->p_meta->psz_author ): + strdup( "" ); psz_temp = convert_xml_special_chars( psz ); if ( psz ) free( psz ); if ( *psz_temp ) @@ -199,9 +194,9 @@ static void xspf_export_item( playlist_item_t *p_item, FILE *p_file ) free( psz_temp ); /* -> the album */ - psz = vlc_input_item_GetInfo( &p_item->input, - _(VLC_META_INFO_CAT), - _(VLC_META_COLLECTION) ); + psz = p_item->p_input->p_meta->psz_album ? + strdup( p_item->p_input->p_meta->psz_album ): + strdup( "" ); psz_temp = convert_xml_special_chars( psz ); if ( psz ) free( psz ); if ( *psz_temp ) @@ -209,9 +204,9 @@ static void xspf_export_item( playlist_item_t *p_item, FILE *p_file ) free( psz_temp ); /* -> the track number */ - psz = vlc_input_item_GetInfo( &p_item->input, - _(VLC_META_INFO_CAT), - _(VLC_META_SEQ_NUM) ); + psz = p_item->p_input->p_meta->psz_tracknum ? + strdup( p_item->p_input->p_meta->psz_tracknum ): + strdup( "" ); if ( psz ) { if ( *psz ) @@ -220,10 +215,10 @@ static void xspf_export_item( playlist_item_t *p_item, FILE *p_file ) } /* -> the duration */ - if ( p_item->input.i_duration > 0 ) + if ( p_item->p_input->i_duration > 0 ) { fprintf( p_file, "\t\t\t%ld\n", - (long)(p_item->input.i_duration / 1000) ); + (long)(p_item->p_input->i_duration / 1000) ); } fprintf( p_file, "\t\t\n" ); diff --git a/modules/mux/mp4.c b/modules/mux/mp4.c index 59a436716f..6120257fd3 100644 --- a/modules/mux/mp4.c +++ b/modules/mux/mp4.c @@ -1031,38 +1031,28 @@ static bo_t *GetUdtaTag( sout_mux_t *p_mux ) /* Misc atoms */ if( p_meta ) { - int i; - for( i = 0; i < p_meta->i_meta; i++ ) - { - bo_t *box = NULL; - - if( !strcmp( p_meta->name[i], VLC_META_TITLE ) ) - box = box_new( "\251nam" ); - else if( !strcmp( p_meta->name[i], VLC_META_AUTHOR ) ) - box = box_new( "\251aut" ); - else if( !strcmp( p_meta->name[i], VLC_META_ARTIST ) ) - box = box_new( "\251ART" ); - else if( !strcmp( p_meta->name[i], VLC_META_GENRE ) ) - box = box_new( "\251gen" ); - else if( !strcmp( p_meta->name[i], VLC_META_COPYRIGHT ) ) - box = box_new( "\251cpy" ); - else if( !strcmp( p_meta->name[i], VLC_META_DESCRIPTION ) ) - box = box_new( "\251des" ); - else if( !strcmp( p_meta->name[i], VLC_META_DATE ) ) - box = box_new( "\251day" ); - else if( !strcmp( p_meta->name[i], VLC_META_URL ) ) - box = box_new( "\251url" ); - - if( box ) - { - bo_add_16be( box, strlen( p_meta->value[i] ) ); - bo_add_16be( box, 0 ); - bo_add_mem( box, strlen( p_meta->value[i] ), - (uint8_t*)(p_meta->value[i]) ); - box_fix( box ); - box_gather( udta, box ); - } - } +#define ADD_META_BOX( type, box_string ) { \ + bo_t *box = NULL; \ + if( p_meta->psz_##type ) box = box_new( "\251" box_string ); \ + if( box ) \ + { \ + bo_add_16be( box, strlen( p_meta->psz_##type ) ); \ + bo_add_16be( box, 0 ); \ + bo_add_mem( box, strlen( p_meta->psz_##type ), \ + (uint8_t*)(p_meta->psz_##type ) ); \ + box_fix( box ); \ + box_gather( udta, box ); \ + } } + + ADD_META_BOX( title, "nam" ); + ADD_META_BOX( author, "aut" ); + ADD_META_BOX( artist, "ART" ); + ADD_META_BOX( genre, "gen" ); + ADD_META_BOX( copyright, "cpy" ); + ADD_META_BOX( description, "des" ); + ADD_META_BOX( date, "day" ); + ADD_META_BOX( url, "url" ); +#undef ADD_META_BOX } box_fix( udta ); diff --git a/modules/services_discovery/daap.c b/modules/services_discovery/daap.c index 9790fb85d7..5051b0d8f1 100644 --- a/modules/services_discovery/daap.c +++ b/modules/services_discovery/daap.c @@ -181,8 +181,10 @@ static int Open( vlc_object_t *p_this ) msg_Warn( p_sd, "unable to find playlist, cancelling DAAP" ); return VLC_EGENERIC; } + msg_Err( p_sd, "DAAP IS BROKEN !! Fix it if you want it !" ); + return VLC_EGENERIC; - p_view = playlist_ViewFind( p_playlist, VIEW_CATEGORY ); +#if 0 p_sys->p_node = playlist_NodeCreate( p_playlist, VIEW_CATEGORY, _("DAAP shares"), p_view->p_root ); p_sys->p_node->i_flags |= PLAYLIST_RO_FLAG; @@ -192,10 +194,12 @@ static int Open( vlc_object_t *p_this ) vlc_object_release( p_playlist ); return VLC_SUCCESS; +#endif } static int OpenAccess( vlc_object_t *p_this ) { +#if 0 access_t *p_access = (access_t*)p_this; access_sys_t *p_sys; vlc_value_t val; @@ -294,7 +298,7 @@ static int OpenAccess( vlc_object_t *p_this ) if( i_ret != 0 ) return VLC_EGENERIC; - +#endif return VLC_SUCCESS; } @@ -303,6 +307,7 @@ static int OpenAccess( vlc_object_t *p_this ) *****************************************************************************/ static void Close( vlc_object_t *p_this ) { +#if 0 services_discovery_t *p_sd = ( services_discovery_t* )p_this; services_discovery_sys_t *p_sys = p_sd->p_sys; @@ -326,6 +331,7 @@ static void Close( vlc_object_t *p_this ) } free( p_sys ); +#endif } static void CloseAccess( vlc_object_t *p_this ) @@ -522,6 +528,7 @@ static int EnumerateCallback( DAAP_SClient *p_client, static void ProcessHost( services_discovery_t *p_sd, dhost_t *p_host ) { +#if 0 int i_dbsize, i_db, i, i_songsize, i_ret; int i_size = DAAP_ClientHost_GetSharename( p_host->p_host, NULL, 0 ); @@ -617,6 +624,7 @@ static void ProcessHost( services_discovery_t *p_sd, dhost_t *p_host ) DAAP_ClientHost_AsyncWaitUpdate( p_host->p_host ); vlc_object_release( p_playlist ); +#endif } static void FreeHost( services_discovery_t *p_sd, dhost_t *p_host ) diff --git a/modules/services_discovery/hal.c b/modules/services_discovery/hal.c index b336c0cebd..a344a7adb9 100644 --- a/modules/services_discovery/hal.c +++ b/modules/services_discovery/hal.c @@ -1,5 +1,5 @@ /***************************************************************************** - * sap.c : SAP interface module + * hal.c : HAL interface module ***************************************************************************** * Copyright (C) 2004 the VideoLAN team * $Id$ @@ -21,11 +21,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ -/***************************************************************************** - * Includes - *****************************************************************************/ -#include /* malloc(), free() */ - #include #include @@ -44,21 +39,26 @@ #include -/************************************************************************ - * Macros and definitions - ************************************************************************/ - #define MAX_LINE_LENGTH 256 - /***************************************************************************** - * Module descriptor + * Local prototypes *****************************************************************************/ +struct services_discovery_sys_t +{ + LibHalContext *p_ctx; + playlist_item_t *p_node_cat; + playlist_item_t *p_node_one; +}; +static void AddItem( services_discovery_t *p_sd, input_item_t * p_input ); +static void Run ( services_discovery_t *p_intf ); -/* Callbacks */ - static int Open ( vlc_object_t * ); - static void Close( vlc_object_t * ); +static int Open ( vlc_object_t * ); +static void Close( vlc_object_t * ); +/***************************************************************************** + * Module descriptor + *****************************************************************************/ vlc_module_begin(); set_description( _("HAL devices detection") ); set_category( CAT_PLAYLIST ); @@ -70,26 +70,6 @@ vlc_module_begin(); vlc_module_end(); -/***************************************************************************** - * Local structures - *****************************************************************************/ - -struct services_discovery_sys_t -{ - LibHalContext *p_ctx; - - /* playlist node */ - playlist_item_t *p_node; - -}; - -/***************************************************************************** - * Local prototypes - *****************************************************************************/ - -/* Main functions */ - static void Run ( services_discovery_t *p_intf ); - /***************************************************************************** * Open: initialize and create stuff *****************************************************************************/ @@ -101,7 +81,6 @@ static int Open( vlc_object_t *p_this ) vlc_value_t val; playlist_t *p_playlist; - playlist_view_t *p_view; DBusError dbus_error; DBusConnection *p_connection; @@ -148,11 +127,13 @@ static int Open( vlc_object_t *p_this ) return VLC_EGENERIC; } - p_view = playlist_ViewFind( p_playlist, VIEW_CATEGORY ); - p_sys->p_node = playlist_NodeCreate( p_playlist, VIEW_CATEGORY, - _("Devices"), p_view->p_root ); + p_sys->p_node_cat = playlist_NodeCreate( p_playlist, _("Devices"), + p_playlist->p_root_category ); + p_sys->p_node_cat->i_flags |= PLAYLIST_RO_FLAG; + p_sys->p_node_one = playlist_NodeCreate( p_playlist, _("Devices"), + p_playlist->p_root_onelevel ); + p_sys->p_node_one->i_flags |= PLAYLIST_RO_FLAG; - p_sys->p_node->i_flags |= PLAYLIST_RO_FLAG; val.b_bool = VLC_TRUE; var_Set( p_playlist, "intf-change", val ); @@ -172,7 +153,8 @@ static void Close( vlc_object_t *p_this ) VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); if( p_playlist ) { - playlist_NodeDelete( p_playlist, p_sys->p_node, VLC_TRUE, VLC_TRUE ); + playlist_NodeDelete( p_playlist, p_sys->p_node_cat, VLC_TRUE,VLC_TRUE ); + playlist_NodeDelete( p_playlist, p_sys->p_node_one, VLC_TRUE,VLC_TRUE ); vlc_object_release( p_playlist ); } free( p_sys ); @@ -183,9 +165,7 @@ static void AddDvd( services_discovery_t *p_sd, char *psz_device ) char *psz_name; char *psz_uri; char *psz_blockdevice; - services_discovery_sys_t *p_sys = p_sd->p_sys; - playlist_t *p_playlist; - playlist_item_t *p_item; + input_item_t *p_input; #ifdef HAVE_HAL_1 psz_name = libhal_device_get_property_string( p_sd->p_sys->p_ctx, psz_device, "volume.label", NULL ); @@ -199,29 +179,36 @@ static void AddDvd( services_discovery_t *p_sd, char *psz_device ) #endif asprintf( &psz_uri, "dvd://%s", psz_blockdevice ); /* Create the playlist item here */ - p_item = playlist_ItemNew( p_sd, psz_uri, - psz_name ); + p_input = input_ItemNew( p_sd, psz_uri, psz_name ); free( psz_uri ); #ifdef HAVE_HAL_1 libhal_free_string( psz_device ); #else hal_free_string( psz_device ); #endif - if( !p_item ) + if( !p_input ) { return; } - p_item->i_flags &= ~PLAYLIST_SKIP_FLAG; - p_playlist = (playlist_t *)vlc_object_find( p_sd, VLC_OBJECT_PLAYLIST, - FIND_ANYWHERE ); + AddItem( p_sd, p_input ); +} + +static void AddItem( services_discovery_t *p_sd, input_item_t * p_input ) +{ + playlist_item_t *p_item; + playlist_t *p_playlist = (playlist_t *)vlc_object_find( p_sd, + VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); if( !p_playlist ) { msg_Err( p_sd, "playlist not found" ); return; } - - playlist_NodeAddItem( p_playlist, p_item, VIEW_CATEGORY, p_sys->p_node, - PLAYLIST_APPEND, PLAYLIST_END ); + p_item = playlist_NodeAddInput( p_playlist, p_input,p_sd->p_sys->p_node_cat, + PLAYLIST_APPEND, PLAYLIST_END ); + p_item->i_flags &= ~PLAYLIST_SKIP_FLAG; + p_item = playlist_NodeAddInput( p_playlist, p_input,p_sd->p_sys->p_node_one, + PLAYLIST_APPEND, PLAYLIST_END ); + p_item->i_flags &= ~PLAYLIST_SKIP_FLAG; vlc_object_release( p_playlist ); } @@ -231,9 +218,7 @@ static void AddCdda( services_discovery_t *p_sd, char *psz_device ) char *psz_name = "Audio CD"; char *psz_uri; char *psz_blockdevice; - services_discovery_sys_t *p_sys = p_sd->p_sys; - playlist_t *p_playlist; - playlist_item_t *p_item; + input_item_t *p_input; #ifdef HAVE_HAL_1 psz_blockdevice = libhal_device_get_property_string( p_sd->p_sys->p_ctx, psz_device, "block.device", NULL ); @@ -243,32 +228,16 @@ static void AddCdda( services_discovery_t *p_sd, char *psz_device ) #endif asprintf( &psz_uri, "cdda://%s", psz_blockdevice ); /* Create the playlist item here */ - p_item = playlist_ItemNew( p_sd, psz_uri, - psz_name ); + p_input = input_ItemNew( p_sd, psz_uri, psz_name ); free( psz_uri ); #ifdef HAVE_HAL_1 libhal_free_string( psz_device ); #else hal_free_string( psz_device ); #endif - if( !p_item ) - { - return; - } - p_item->i_flags &= ~PLAYLIST_SKIP_FLAG; - p_playlist = (playlist_t *)vlc_object_find( p_sd, VLC_OBJECT_PLAYLIST, - FIND_ANYWHERE ); - if( !p_playlist ) - { - msg_Err( p_sd, "playlist not found" ); + if( !p_input ) return; - } - - playlist_NodeAddItem( p_playlist, p_item, VIEW_CATEGORY, p_sys->p_node, - PLAYLIST_APPEND, PLAYLIST_END ); - - vlc_object_release( p_playlist ); - + AddItem( p_sd, p_input ); } static void ParseDevice( services_discovery_t *p_sd, char *psz_device ) diff --git a/modules/services_discovery/podcast.c b/modules/services_discovery/podcast.c index 9b8d263d66..a0498bcfd0 100644 --- a/modules/services_discovery/podcast.c +++ b/modules/services_discovery/podcast.c @@ -80,7 +80,8 @@ vlc_module_end(); struct services_discovery_sys_t { /* playlist node */ - playlist_item_t *p_node; + playlist_item_t *p_node_cat; + playlist_item_t *p_node_one; input_thread_t **pp_input; char **ppsz_urls; @@ -150,29 +151,32 @@ static int Open( vlc_object_t *p_this ) return VLC_EGENERIC; } - p_view = playlist_ViewFind( p_playlist, VIEW_CATEGORY ); - p_sys->p_node = playlist_NodeCreate( p_playlist, VIEW_CATEGORY, - _("Podcast"), p_view->p_root ); + p_sys->p_node_cat = playlist_NodeCreate( p_playlist, _("Podcast"), + p_playlist->p_root_category ); + p_sys->p_node_one = playlist_NodeCreate( p_playlist, _("Podcast"), + p_playlist->p_root_onelevel ); + p_sys->p_node_one->p_input->i_id = p_sys->p_node_cat->p_input->i_id; + + p_sys->p_node_one->i_flags |= PLAYLIST_RO_FLAG; + p_sys->p_node_cat->i_flags |= PLAYLIST_RO_FLAG; + p_sys->p_node_one->i_flags |= PLAYLIST_SKIP_FLAG; + p_sys->p_node_cat->i_flags |= PLAYLIST_SKIP_FLAG; p_sys->pp_input = malloc( p_sys->i_urls * sizeof( input_thread_t * ) ); for( i = 0; i < p_sys->i_urls; i++ ) { + input_item_t *p_input; asprintf( &psz_buf, "%s", p_sys->ppsz_urls[i] ); - p_item = playlist_ItemNew( p_playlist, psz_buf, - p_sys->ppsz_urls[i] ); + p_input = input_ItemNewExt( p_playlist, psz_buf, + p_sys->ppsz_urls[i], 0, NULL, -1 ); + vlc_input_item_AddOption( p_input, "demux=podcast" ); + p_item = playlist_NodeAddInput( p_playlist, p_input, p_sys->p_node_cat, + PLAYLIST_APPEND, PLAYLIST_END ); + p_item = playlist_NodeAddInput( p_playlist, p_input, p_sys->p_node_one, + PLAYLIST_APPEND, PLAYLIST_END ); free( psz_buf ); - playlist_ItemAddOption( p_item, "demux=podcast" ); - playlist_NodeAddItem( p_playlist, p_item, - p_sys->p_node->pp_parents[0]->i_view, - p_sys->p_node, PLAYLIST_APPEND, - PLAYLIST_END ); - - /* We need to declare the parents of the node as the same of the - * parent's ones */ - playlist_CopyParents( p_sys->p_node, p_item ); - p_sys->pp_input[i] = input_CreateThread( p_playlist, &p_item->input ); + p_sys->pp_input[i] = input_CreateThread( p_playlist, p_input ); } - p_sys->p_node->i_flags |= PLAYLIST_RO_FLAG; val.b_bool = VLC_TRUE; var_Set( p_playlist, "intf-change", val ); @@ -205,7 +209,8 @@ static void Close( vlc_object_t *p_this ) free( p_sd->p_sys->pp_input ); if( p_playlist ) { - playlist_NodeDelete( p_playlist, p_sys->p_node, VLC_TRUE, VLC_TRUE ); + playlist_NodeDelete( p_playlist, p_sys->p_node_cat, VLC_TRUE, VLC_TRUE ); + playlist_NodeDelete( p_playlist, p_sys->p_node_one, VLC_TRUE, VLC_TRUE ); vlc_object_release( p_playlist ); } for( i = 0; i < p_sys->i_urls; i++ ) free( p_sys->ppsz_urls[i] ); diff --git a/modules/services_discovery/sap.c b/modules/services_discovery/sap.c index 612e42479c..9fd77d1fcd 100644 --- a/modules/services_discovery/sap.c +++ b/modules/services_discovery/sap.c @@ -210,8 +210,9 @@ struct sap_announce_t /* SAP annnounces must only contain one SDP */ sdp_t *p_sdp; - int i_item_id; -// playlist_item_t *p_item; + int i_input_id; + int i_item_id_cat; + int i_item_id_one; }; struct services_discovery_sys_t @@ -221,7 +222,8 @@ struct services_discovery_sys_t int *pi_fd; /* playlist node */ - playlist_item_t *p_node; + playlist_item_t *p_node_cat; + playlist_item_t *p_node_one; playlist_t *p_playlist; /* Table of announces */ @@ -316,12 +318,18 @@ static int Open( vlc_object_t *p_this ) msg_Warn( p_sd, "unable to find playlist, cancelling SAP listening"); return VLC_EGENERIC; } + p_sys->p_node_cat = playlist_NodeCreate( p_sys->p_playlist, + _("SAP sessions"), + p_sys->p_playlist->p_root_category ); + p_sys->p_node_cat->i_flags |= PLAYLIST_RO_FLAG; + p_sys->p_node_cat->i_flags |= PLAYLIST_SKIP_FLAG; + + p_sys->p_node_one = playlist_NodeCreate( p_sys->p_playlist, + _("SAP sessions"), + p_sys->p_playlist->p_root_onelevel ); + p_sys->p_node_one->i_flags |= PLAYLIST_RO_FLAG; + p_sys->p_node_one->i_flags |= PLAYLIST_SKIP_FLAG; - p_view = playlist_ViewFind( p_sys->p_playlist, VIEW_CATEGORY ); - p_sys->p_node = playlist_NodeCreate( p_sys->p_playlist, VIEW_CATEGORY, - _("Session Announcements (SAP)"), p_view->p_root ); - p_sys->p_node->i_flags |= PLAYLIST_RO_FLAG; - p_sys->p_node->i_flags &= ~PLAYLIST_SKIP_FLAG; val.b_bool = VLC_TRUE; var_Set( p_sys->p_playlist, "intf-change", val ); @@ -458,7 +466,9 @@ static void Close( vlc_object_t *p_this ) if( p_sys->p_playlist ) { - playlist_NodeDelete( p_sys->p_playlist, p_sys->p_node, VLC_TRUE, + playlist_NodeDelete( p_sys->p_playlist, p_sys->p_node_cat, VLC_TRUE, + VLC_TRUE ); + playlist_NodeDelete( p_sys->p_playlist, p_sys->p_node_one, VLC_TRUE, VLC_TRUE ); vlc_object_release( p_sys->p_playlist ); } @@ -544,8 +554,8 @@ static void Run( services_discovery_t *p_sd ) p_announce = p_sd->p_sys->pp_announces[i]; /* Remove the playlist item */ - playlist_LockDelete( p_sd->p_sys->p_playlist, - p_announce->i_item_id ); + playlist_LockDeleteAllFromInput( p_sd->p_sys->p_playlist, + p_announce->i_input_id ); /* Remove the sap_announce from the array */ REMOVE_ELEM( p_sd->p_sys->pp_announces, @@ -584,10 +594,9 @@ static int Demux( demux_t *p_demux ) p_playlist = (playlist_t *)vlc_object_find( p_demux, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); - p_playlist->status.p_item->i_flags |= PLAYLIST_DEL_FLAG; - - playlist_Add( p_playlist, p_sdp->psz_uri, p_sdp->psz_sessionname, - PLAYLIST_APPEND, PLAYLIST_END ); + /* TODO FIXME !! Add at the correct place */ + playlist_PlaylistAdd( p_playlist, p_sdp->psz_uri, p_sdp->psz_sessionname, + PLAYLIST_APPEND, PLAYLIST_END ); vlc_object_release( p_playlist ); if( p_sdp ) FreeSDP( p_sdp ); @@ -786,6 +795,7 @@ static int ParseSAP( services_discovery_t *p_sd, uint8_t *p_buffer, int i_read ) sap_announce_t *CreateAnnounce( services_discovery_t *p_sd, uint16_t i_hash, sdp_t *p_sdp ) { + input_item_t *p_input; playlist_item_t *p_item, *p_child; char *psz_value; sap_announce_t *p_sap = (sap_announce_t *)malloc( @@ -800,66 +810,67 @@ sap_announce_t *CreateAnnounce( services_discovery_t *p_sd, uint16_t i_hash, p_sap->i_last = mdate(); p_sap->i_hash = i_hash; p_sap->p_sdp = p_sdp; - p_sap->i_item_id = -1; /* Create the actual playlist item here */ - p_item = playlist_ItemNew( p_sd, p_sap->p_sdp->psz_uri, p_sdp->psz_sessionname ); - - if( !p_item ) + p_input = input_ItemNewWithType( VLC_OBJECT(p_sd), + p_sap->p_sdp->psz_uri, + p_sdp->psz_sessionname, + 0, NULL, -1, ITEM_TYPE_NET ); + p_sap->i_input_id = p_input->i_id; + if( !p_input ) { free( p_sap ); return NULL; } if( p_sys->b_timeshift ) - playlist_ItemAddOption( p_item, ":access-filter=timeshift" ); + vlc_input_item_AddOption( p_input, ":access-filter=timeshift" ); psz_value = GetAttribute( p_sap->p_sdp, "tool" ); if( psz_value != NULL ) { - vlc_input_item_AddInfo( &p_item->input, _("Session"), - _("Tool"), psz_value ); + vlc_input_item_AddInfo( p_input, _("Session"),_("Tool"), psz_value ); } if( strcmp( p_sdp->psz_username, "-" ) ) { - vlc_input_item_AddInfo( &p_item->input, _("Session"), + vlc_input_item_AddInfo( p_input, _("Session"), _("User"), p_sdp->psz_username ); } + /* Handle group */ psz_value = GetAttribute( p_sap->p_sdp, "x-plgroup" ); - if( psz_value == NULL ) - { psz_value = GetAttribute( p_sap->p_sdp, "plgroup" ); - } - /* Find or Create the group playlist non-playable item */ if( psz_value != NULL ) { EnsureUTF8( psz_value ); - p_child = playlist_ChildSearchName( p_sys->p_node, psz_value ); + p_child = playlist_ChildSearchName( p_sys->p_node_cat, psz_value ); if( p_child == NULL ) { - p_child = playlist_NodeCreate( p_sys->p_playlist, - VIEW_CATEGORY, psz_value, - p_sys->p_node ); + p_child = playlist_NodeCreate( p_sys->p_playlist, psz_value, + p_sys->p_node_cat ); p_child->i_flags &= ~PLAYLIST_SKIP_FLAG; } } else { - p_child = p_sys->p_node; + p_child = p_sys->p_node_cat; } + p_item = playlist_NodeAddInput( p_sys->p_playlist, p_input, p_child, + PLAYLIST_APPEND, PLAYLIST_END ); p_item->i_flags &= ~PLAYLIST_SKIP_FLAG; p_item->i_flags &= ~PLAYLIST_SAVE_FLAG; + p_sap->i_item_id_cat = p_item->i_id; - playlist_NodeAddItem( p_sys->p_playlist, p_item, VIEW_CATEGORY, p_child, - PLAYLIST_APPEND, PLAYLIST_END ); - - p_sap->i_item_id = p_item->input.i_id; + p_item = playlist_NodeAddInput( p_sys->p_playlist, p_input, + p_sys->p_node_one, PLAYLIST_APPEND, PLAYLIST_END ); + p_item->i_flags &= ~PLAYLIST_SKIP_FLAG; + p_item->i_flags &= ~PLAYLIST_SAVE_FLAG; + p_sap->i_item_id_one = p_item->i_id; TAB_APPEND( p_sys->i_announces, p_sys->pp_announces, p_sap ); @@ -1286,15 +1297,6 @@ static int Decompress( unsigned char *psz_src, unsigned char **_dst, int i_len ) printf( "inflateInit() failed. Result: %d\n", i_result ); return( -1 ); } -#if 0 - p_playlist->pp_items[p_playlist->i_index]->b_autodeletion = VLC_TRUE; - i_position = p_playlist->i_index; - - /* Gather the complete sdp file */ - for( ;; ) - { - int i_read = stream_Read( p_demux->s, &p_sdp[i_sdp], i_sdp_max - i_sdp - 1 ); -#endif d_stream.next_in = (Bytef *)psz_src; d_stream.avail_in = i_len; n = 0; @@ -1360,9 +1362,10 @@ static int RemoveAnnounce( services_discovery_t *p_sd, if( p_announce->p_sdp ) FreeSDP( p_announce->p_sdp ); - if( p_announce->i_item_id > -1 ) + if( p_announce->i_input_id > -1 ) { - playlist_LockDelete( p_sd->p_sys->p_playlist, p_announce->i_item_id ); + playlist_LockDeleteAllFromInput( + p_sd->p_sys->p_playlist, p_announce->i_input_id ); } for( i = 0; i< p_sd->p_sys->i_announces; i++) diff --git a/modules/visualization/xosd.c b/modules/visualization/xosd.c index 0d805e5433..44661ecf36 100644 --- a/modules/visualization/xosd.c +++ b/modules/visualization/xosd.c @@ -204,7 +204,6 @@ static void Close( vlc_object_t *p_this ) *****************************************************************************/ static void Run( intf_thread_t *p_intf ) { - int i_size,i_index; playlist_t *p_playlist; playlist_item_t *p_item = NULL; input_item_t item; @@ -223,7 +222,7 @@ static void Run( intf_thread_t *p_intf ) continue; } - if( p_playlist->i_size < 0 || p_playlist->i_index < 0 ) + if( p_playlist->i_size < 0 ) { vlc_object_release( p_playlist ); continue; @@ -245,18 +244,13 @@ static void Run( intf_thread_t *p_intf ) } else { - // vlc_mutex_lock(&p_playlist->object_lock ); p_item = p_playlist->status.p_item; item = p_item->input; if( !p_item ) { vlc_object_release( p_playlist ); - // vlc_mutex_unlock(&p_playlist->object_lock ); continue; } - i_size = p_playlist->i_size; - i_index = p_playlist->i_index+1; - // vlc_mutex_unlock(&p_playlist->object_lock ); vlc_object_release( p_playlist ); @@ -274,8 +268,8 @@ static void Run( intf_thread_t *p_intf ) psz_display = (char *)malloc( sizeof(char )* (strlen( item.psz_name ) + MSTRTIME_MAX_SIZE + 2+6 + 10 +10 )); - sprintf( psz_display," %i/%i - %s %s", - i_index,i_size, item.psz_name, psz_duration); + sprintf( psz_display,"%s %s", + item.psz_name, psz_duration); } /* Display */ diff --git a/src/Makefile.am b/src/Makefile.am index d82a251056..8bfaa552ed 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -256,13 +256,16 @@ SOURCES_libvlc_common = \ interface/interface.c \ interface/intf_eject.c \ interface/interaction.c \ - playlist/playlist.c \ + playlist/thread.c \ + playlist/control.c \ + playlist/engine.c \ playlist/sort.c \ playlist/loadsave.c \ - playlist/view.c \ + playlist/tree.c \ playlist/item.c \ - playlist/item-ext.c \ + playlist/search.c \ playlist/services_discovery.c \ + input/item.c \ input/access.c \ input/clock.c \ input/control.c \ diff --git a/src/control/mediacontrol_core.c b/src/control/mediacontrol_core.c index d7eaf7701b..3886e0fced 100644 --- a/src/control/mediacontrol_core.c +++ b/src/control/mediacontrol_core.c @@ -192,25 +192,17 @@ mediacontrol_start( mediacontrol_Instance *self, vlc_mutex_lock( &p_playlist->object_lock ); if( p_playlist->i_size ) { - int i_index; int i_from; char *psz_from = NULL; psz_from = ( char * )malloc( 20 * sizeof( char ) ); - if( psz_from ) + if( psz_from && p_playlist->status.p_item ) { i_from = mediacontrol_position2microsecond( p_playlist->p_input, a_position ) / 1000000; - i_index = p_playlist->i_index; - if( i_index < 0 ) - { - /* We know that there is at least 1 element, since i_size != 0 */ - i_index = 0; - } - /* Set start time */ snprintf( psz_from, 20, "start-time=%i", i_from ); - playlist_ItemAddOption( p_playlist->pp_items[i_index], psz_from ); + playlist_ItemAddOption( p_playlist->status.p_item, psz_from ); free( psz_from ); } @@ -345,7 +337,7 @@ mediacontrol_playlist_get_list( mediacontrol_Instance *self, for( i_index = 0 ; i_index < i_playlist_size ; i_index++ ) { - retval->data[i_index] = strdup( p_playlist->pp_items[i_index]->input.psz_uri ); + retval->data[i_index] = strdup( p_playlist->pp_items[i_index]->p_input->psz_uri ); } vlc_mutex_unlock( &p_playlist->object_lock ); diff --git a/src/control/playlist.c b/src/control/playlist.c index 871c3cfa59..408f64eca1 100644 --- a/src/control/playlist.c +++ b/src/control/playlist.c @@ -39,35 +39,15 @@ void libvlc_playlist_play( libvlc_instance_t *p_instance, int i_id, } if( i_id > 0 ) { - /* Always use the current view when using libvlc */ - playlist_view_t *p_view; - playlist_item_t *p_item; - - if( p_instance->p_playlist->status.i_view == -1 ) - { - playlist_Control( p_instance->p_playlist, PLAYLIST_GOTO, - i_id ); - } - p_view = playlist_ViewFind( p_instance->p_playlist, - p_instance->p_playlist->status.i_view ); - if( !p_view ) - { - libvlc_exception_raise( p_exception, - "Unable to find current playlist view "); - return; - } - - p_item = playlist_ItemGetById( p_instance->p_playlist, i_id ); + playlist_item_t *p_item = playlist_ItemGetById( p_instance->p_playlist, i_id ); if( !p_item ) { libvlc_exception_raise( p_exception, "Unable to find item " ); return; } - playlist_Control( p_instance->p_playlist, PLAYLIST_VIEWPLAY, - p_instance->p_playlist->status.i_view, - p_view->p_root, p_item ); + p_instance->p_playlist->status.p_node, p_item ); } else { diff --git a/src/input/es_out.c b/src/input/es_out.c index 862705c51e..f59ca7b80e 100644 --- a/src/input/es_out.c +++ b/src/input/es_out.c @@ -573,19 +573,8 @@ static void EsOutProgramMeta( es_out_t *out, int i_group, vlc_meta_t *p_meta ) msg_Dbg( p_input, "EsOutProgramMeta: number=%d", i_group ); sprintf( psz_cat, "%s %d", _("Program"), i_group ); - for( i = 0; i < p_meta->i_meta; i++ ) - { - msg_Dbg( p_input, " - %s = %s", p_meta->name[i], p_meta->value[i] ); - - input_Control( p_input, INPUT_ADD_INFO, psz_cat, - _(p_meta->name[i]), "%s", p_meta->value[i] ); - if( !strcasecmp( p_meta->name[i], "Name" ) ) - psz_name = p_meta->value[i]; - else if( !strcasecmp( p_meta->name[i], "Provider" ) ) - psz_provider = p_meta->value[i]; - else if( !strcasecmp( p_meta->name[i], VLC_META_NOW_PLAYING ) ) - psz_now_playing = p_meta->value[i]; - } +// if( p_meta->psz_provider) psz_provider = p_meta->psz_provider; + if( p_meta->psz_nowplaying ) psz_now_playing = p_meta->psz_nowplaying; if( !psz_name && !psz_now_playing ) { diff --git a/src/input/input.c b/src/input/input.c index ca3c51c0dc..2bbe51ca1e 100644 --- a/src/input/input.c +++ b/src/input/input.c @@ -57,7 +57,6 @@ static inline int ControlPopNoLock( input_thread_t *, int *, vlc_value_t * ); static void ControlReduce( input_thread_t * ); static vlc_bool_t Control( input_thread_t *, int, vlc_value_t ); - static int UpdateFromAccess( input_thread_t * ); static int UpdateFromDemux( input_thread_t * ); static int UpdateMeta( input_thread_t *, vlc_bool_t ); @@ -76,7 +75,7 @@ static void InputSourceClean( input_thread_t *, input_source_t * ); static void SlaveDemux( input_thread_t *p_input ); static void SlaveSeek( input_thread_t *p_input ); -static vlc_meta_t *InputMetaUser( input_thread_t *p_input ); +static void InputMetaUser( input_thread_t *p_input ); /***************************************************************************** * This function creates a new input, and returns a pointer @@ -150,6 +149,7 @@ static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item, p_input->input.b_eof = VLC_FALSE; p_input->input.i_cr_average = 0; + p_input->input.p_item->p_meta = vlc_meta_New(); stats_ReinitInputStats( p_item->p_stats ); /* No slave */ @@ -335,9 +335,6 @@ int __input_Preparse( vlc_object_t *p_parent, input_item_t *p_item ) /* Unload all modules */ if( p_input->p_es_out ) input_EsOutDelete( p_input->p_es_out ); - /* Delete meta */ - if( p_input->p_meta ) vlc_meta_Delete( p_input->p_meta ); - vlc_object_detach( p_input ); vlc_object_destroy( p_input ); @@ -667,7 +664,7 @@ static int Init( input_thread_t * p_input, vlc_bool_t b_quick ) char *psz_subtitle; vlc_value_t val; double f_fps; - vlc_meta_t *p_meta, *p_meta_tmp; + vlc_meta_t *p_meta; int i_es_out_mode; int i, i_delay; @@ -1017,79 +1014,32 @@ static int Init( input_thread_t * p_input, vlc_bool_t b_quick ) } } + p_meta = p_input->input.p_item->p_meta; /* Get meta data from users */ - p_meta_tmp = InputMetaUser( p_input ); - + InputMetaUser( p_input ); /* Get meta data from master input */ - if( demux2_Control( p_input->input.p_demux, DEMUX_GET_META, &p_meta ) ) - p_meta = NULL; - - /* Merge them */ - if( p_meta == NULL ) - { - p_meta = p_meta_tmp; - } - else if( p_meta_tmp ) - { - vlc_meta_Merge( p_meta, p_meta_tmp ); - vlc_meta_Delete( p_meta_tmp ); - } + demux2_Control( p_input->input.p_demux, DEMUX_GET_META, p_meta ); /* Access_file does not give any meta, and there are no slave */ if( !b_quick ) { - if( !p_input->input.p_access || + if( p_input->input.p_access ) access2_Control( p_input->input.p_access, ACCESS_GET_META, - &p_meta_tmp)) - p_meta_tmp = NULL; - - if( p_meta == NULL ) - { - p_meta = p_meta_tmp; - } - else if( p_meta_tmp ) - { - vlc_meta_Merge( p_meta, p_meta_tmp ); - vlc_meta_Delete( p_meta_tmp ); - } + p_meta ); /* Get meta data from slave input */ for( i = 0; i < p_input->i_slave; i++ ) { - vlc_meta_t *p_meta_slave; - - if( !demux2_Control( p_input->slave[i]->p_demux, - DEMUX_GET_META, &p_meta_slave ) ) + demux2_Control( p_input->slave[i]->p_demux, + DEMUX_GET_META, p_meta ); + if( p_input->slave[i]->p_access ) { - if( p_meta == NULL ) - { - p_meta = p_meta_slave; - } - else if( p_meta_slave ) - { - vlc_meta_Merge( p_meta, p_meta_slave ); - vlc_meta_Delete( p_meta_slave ); - } - } - - if( p_input->slave[i]->p_access && - !access2_Control( p_input->slave[i]->p_access, - ACCESS_GET_META, &p_meta_slave ) ) - { - if( p_meta == NULL ) - { - p_meta = p_meta_slave; - } - else if( p_meta_slave ) - { - vlc_meta_Merge( p_meta, p_meta_slave ); - vlc_meta_Delete( p_meta_slave ); - } + access2_Control( p_input->slave[i]->p_access, + ACCESS_GET_META, p_meta ); } } } - p_input->p_meta = p_meta; UpdateMeta( p_input, b_quick ); if( !b_quick ) @@ -1195,10 +1145,6 @@ static void End( input_thread_t * p_input ) vlc_object_release( p_pl ); } - /* Delete meta */ - if( p_input->p_meta ) - vlc_meta_Delete( p_input->p_meta ); - /* Tell we're dead */ p_input->b_dead = VLC_TRUE; } @@ -1669,8 +1615,7 @@ static vlc_bool_t Control( input_thread_t *p_input, int i_type, if( !InputSourceInit( p_input, slave, val.psz_string, NULL, VLC_FALSE ) ) { - vlc_meta_t *p_meta_new = NULL; - vlc_meta_t *p_meta; + vlc_meta_t *p_meta = p_input->input.p_item->p_meta; int64_t i_time; /* Add the slave */ @@ -1695,38 +1640,11 @@ static vlc_bool_t Control( input_thread_t *p_input, int i_type, break; } - /* Get meta (access and demux) */ - if( access2_Control( slave->p_access, - ACCESS_GET_META, &p_meta_new ) ) - p_meta_new = NULL; - if( !demux2_Control( slave->p_demux, - DEMUX_GET_META, &p_meta ) ) - { - if( p_meta_new ) - { - vlc_meta_Merge( p_meta_new, p_meta ); - vlc_meta_Delete( p_meta ); - } - else - { - p_meta_new = p_meta; - } - } - /* Update meta */ - if( p_meta_new ) - { - if( p_input->p_meta ) - { - vlc_meta_Merge( p_input->p_meta, p_meta_new ); - vlc_meta_Delete( p_meta_new ); - } - else - { - p_input->p_meta = p_meta_new; - } - UpdateMeta( p_input, VLC_FALSE ); - } + access2_Control( slave->p_access, ACCESS_GET_META, + p_meta ); + demux2_Control( slave->p_demux, DEMUX_GET_META, p_meta ); + UpdateMeta( p_input, VLC_FALSE ); TAB_APPEND( p_input->i_slave, p_input->slave, slave ); } @@ -1825,28 +1743,15 @@ static int UpdateFromAccess( input_thread_t *p_input ) { v.i_int = p_access->info.i_seekpoint; var_Change( p_input, "chapter", VLC_VAR_SETVALUE, &v, NULL); - p_access->info.i_update &= ~INPUT_UPDATE_SEEKPOINT; } if( p_access->info.i_update & INPUT_UPDATE_META ) { /* TODO maybe multi - access ? */ - vlc_meta_t *p_meta; - if( !access2_Control( p_input->input.p_access,ACCESS_GET_META,&p_meta)) - { - if( p_input->p_meta ) - { - vlc_meta_Merge( p_input->p_meta, p_meta ); - vlc_meta_Delete( p_meta ); - } - else - { - p_input->p_meta = p_meta; - } - - UpdateMeta( p_input, VLC_FALSE ); - var_SetBool( p_input, "item-change", p_input->input.p_item->i_id ); - } + vlc_meta_t *p_meta = p_input->input.p_item->p_meta; + access2_Control( p_input->input.p_access,ACCESS_GET_META, p_meta ); + UpdateMeta( p_input, VLC_FALSE ); + var_SetBool( p_input, "item-change", p_input->input.p_item->i_id ); p_access->info.i_update &= ~INPUT_UPDATE_META; } @@ -1884,58 +1789,14 @@ static int UpdateFromAccess( input_thread_t *p_input ) *****************************************************************************/ static int UpdateMeta( input_thread_t *p_input, vlc_bool_t b_quick ) { - vlc_meta_t *p_meta = p_input->p_meta; - int i; - - if( !p_meta || p_meta->i_meta == 0 ) + vlc_meta_t *p_meta = p_input->input.p_item->p_meta; + if( !p_meta ) return VLC_SUCCESS; - if( !b_quick ) msg_Dbg( p_input, "meta information:" ); - for( i = 0; i < p_meta->i_meta; i++ ) - { - if( !b_quick ) - msg_Dbg( p_input, " - '%s' = '%s'", - _(p_meta->name[i]), p_meta->value[i] ); - - if( !strcmp(p_meta->name[i], _(VLC_META_TITLE)) && p_meta->value[i] && - !p_input->input.p_item->b_fixed_name ) - input_Control( p_input, INPUT_SET_NAME, p_meta->value[i] ); - - if( !strcmp( p_meta->name[i], _(VLC_META_AUTHOR) ) ) - input_Control( p_input, INPUT_ADD_INFO, _("General"), - _(VLC_META_AUTHOR), p_meta->value[i] ); - - input_Control( p_input, INPUT_ADD_INFO, _(VLC_META_INFO_CAT), - _(p_meta->name[i]), "%s", p_meta->value[i] ); - } - - for( i = 0; i < p_meta->i_track; i++ ) - { - vlc_meta_t *tk = p_meta->track[i]; - int j; - - if( tk->i_meta > 0 ) - { - char *psz_cat = malloc( strlen(_("Stream")) + 10 ); + if( p_meta->psz_title && !p_input->input.p_item->b_fixed_name ) + input_Control( p_input, INPUT_SET_NAME, p_meta->psz_title ); - msg_Dbg( p_input, " - track[%d]:", i ); - - sprintf( psz_cat, "%s %d", _("Stream"), i ); - for( j = 0; j < tk->i_meta; j++ ) - { - msg_Dbg( p_input, " - '%s' = '%s'", _(tk->name[j]), - tk->value[j] ); - - input_Control( p_input, INPUT_ADD_INFO, psz_cat, - _(tk->name[j]), "%s", tk->value[j] ); - } - } - } - - if( p_input->p_sout && p_input->p_sout->p_meta == NULL ) - { - p_input->p_sout->p_meta = vlc_meta_Duplicate( p_meta ); - } + /** \todo handle sout meta */ return VLC_SUCCESS; } @@ -2355,32 +2216,31 @@ static void SlaveSeek( input_thread_t *p_input ) /***************************************************************************** * InputMetaUser: *****************************************************************************/ -static vlc_meta_t *InputMetaUser( input_thread_t *p_input ) +static void InputMetaUser( input_thread_t *p_input ) { - vlc_meta_t *p_meta; + vlc_meta_t *p_meta = p_input->input.p_item->p_meta; vlc_value_t val; - if( ( p_meta = vlc_meta_New() ) == NULL ) - return NULL; + if( !p_meta ) return; /* Get meta information from user */ -#define GET_META( c, s ) \ +#define GET_META( field, s ) \ var_Get( p_input, (s), &val ); \ - if( *val.psz_string ) \ - vlc_meta_Add( p_meta, _(c), val.psz_string ); \ + if( *val.psz_string ) { \ + if( p_meta->psz_ ## field ) free ( p_meta->psz_ ## field ); \ + p_meta->psz_ ## field = strdup( val.psz_string ); \ + } \ free( val.psz_string ) - GET_META( VLC_META_TITLE, "meta-title" ); - GET_META( VLC_META_AUTHOR, "meta-author" ); - GET_META( VLC_META_ARTIST, "meta-artist" ); - GET_META( VLC_META_GENRE, "meta-genre" ); - GET_META( VLC_META_COPYRIGHT, "meta-copyright" ); - GET_META( VLC_META_DESCRIPTION, "meta-description" ); - GET_META( VLC_META_DATE, "meta-date" ); - GET_META( VLC_META_URL, "meta-url" ); + GET_META( title, "meta-title" ); + GET_META( author, "meta-author" ); + GET_META( artist, "meta-artist" ); + GET_META( genre, "meta-genre" ); + GET_META( copyright, "meta-copyright" ); + GET_META( description, "meta-description" ); + GET_META( date, "meta-date" ); + GET_META( url, "meta-url" ); #undef GET_META - - return p_meta; } /***************************************************************************** @@ -2546,114 +2406,3 @@ static void MRLSections( input_thread_t *p_input, char *psz_source, psz_source, *pi_title_start, *pi_chapter_start, *pi_title_end, *pi_chapter_end ); } - - -/*********************************************************************** - * Info management functions - ***********************************************************************/ -/** - * Get a info item from a given category in a given input item. - * - * \param p_i The input item to get info from - * \param psz_cat String representing the category for the info - * \param psz_name String representing the name of the desired info - * \return A pointer to the string with the given info if found, or an - * empty string otherwise. The caller should free the returned - * pointer. - */ -char *vlc_input_item_GetInfo( input_item_t *p_i, - const char *psz_cat, - const char *psz_name ) -{ - int i,j; - - vlc_mutex_lock( &p_i->lock ); - - for( i = 0 ; i< p_i->i_categories ; i++ ) - { - info_category_t *p_cat = p_i->pp_categories[i]; - - if( !psz_cat || strcmp( p_cat->psz_name, psz_cat ) ) - continue; - - for( j = 0; j < p_cat->i_infos ; j++ ) - { - if( !strcmp( p_cat->pp_infos[j]->psz_name, psz_name ) ) - { - char *psz_ret = strdup( p_cat->pp_infos[j]->psz_value ); - vlc_mutex_unlock( &p_i->lock ); - return psz_ret; - } - } - } - vlc_mutex_unlock( &p_i->lock ); - return strdup( "" ); -} - -int vlc_input_item_AddInfo( input_item_t *p_i, - const char *psz_cat, - const char *psz_name, - const char *psz_format, ... ) -{ - va_list args; - int i; - info_t *p_info = NULL; - info_category_t *p_cat = NULL ; - - vlc_mutex_lock( &p_i->lock ); - - for( i = 0 ; i < p_i->i_categories ; i ++ ) - { - if( !strcmp( p_i->pp_categories[i]->psz_name, psz_cat ) ) - { - p_cat = p_i->pp_categories[i]; - break; - } - } - if( !p_cat ) - { - if( !(p_cat = (info_category_t *)malloc( sizeof(info_category_t) )) ) - { - vlc_mutex_unlock( &p_i->lock ); - return VLC_EGENERIC; - } - p_cat->psz_name = strdup( psz_cat ); - p_cat->i_infos = 0; - p_cat->pp_infos = 0; - INSERT_ELEM( p_i->pp_categories, p_i->i_categories, p_i->i_categories, - p_cat ); - } - - for( i = 0; i< p_cat->i_infos; i++ ) - { - if( !strcmp( p_cat->pp_infos[i]->psz_name, psz_name ) ) - { - p_info = p_cat->pp_infos[i]; - break; - } - } - - if( !p_info ) - { - if( ( p_info = (info_t *)malloc( sizeof( info_t ) ) ) == NULL ) - { - vlc_mutex_unlock( &p_i->lock ); - return VLC_EGENERIC; - } - INSERT_ELEM( p_cat->pp_infos, p_cat->i_infos, p_cat->i_infos, p_info ); - p_info->psz_name = strdup( psz_name ); - } - else - { - if( p_info->psz_value ) free( p_info->psz_value ); - } - - va_start( args, psz_format ); - vasprintf( &p_info->psz_value, psz_format, args); - va_end( args ); - - vlc_mutex_unlock( &p_i->lock ); - - return VLC_SUCCESS; -} - diff --git a/src/input/item.c b/src/input/item.c new file mode 100644 index 0000000000..9f893b73db --- /dev/null +++ b/src/input/item.c @@ -0,0 +1,313 @@ +/***************************************************************************** + * item.c: input_item management + ***************************************************************************** + * Copyright (C) 1998-2004 the VideoLAN team + * $Id$ + * + * Authors: Clément Stenac + * + * 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. + *****************************************************************************/ + +#include +#include +#include "vlc_playlist.h" +#include "vlc_interface.h" + +static void GuessType( input_item_t *p_item ); + +/** + * Get a info item from a given category in a given input item. + * + * \param p_i The input item to get info from + * \param psz_cat String representing the category for the info + * \param psz_name String representing the name of the desired info + * \return A pointer to the string with the given info if found, or an + * empty string otherwise. The caller should free the returned + * pointer. + */ +char *vlc_input_item_GetInfo( input_item_t *p_i, + const char *psz_cat, + const char *psz_name ) +{ + int i,j; + + vlc_mutex_lock( &p_i->lock ); + + for( i = 0 ; i< p_i->i_categories ; i++ ) + { + info_category_t *p_cat = p_i->pp_categories[i]; + + if( !psz_cat || strcmp( p_cat->psz_name, psz_cat ) ) + continue; + + for( j = 0; j < p_cat->i_infos ; j++ ) + { + if( !strcmp( p_cat->pp_infos[j]->psz_name, psz_name ) ) + { + char *psz_ret = strdup( p_cat->pp_infos[j]->psz_value ); + vlc_mutex_unlock( &p_i->lock ); + return psz_ret; + } + } + } + vlc_mutex_unlock( &p_i->lock ); + return strdup( "" ); +} + +static void vlc_input_item_Destroy ( gc_object_t *p_this ) +{ + vlc_object_t *p_obj = (vlc_object_t *)p_this->p_destructor_arg; + int i, i_top, i_bottom; + input_item_t *p_input = (input_item_t *) p_this; + + playlist_t *p_playlist = (playlist_t *)vlc_object_find( p_obj, + VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); + + fprintf( stderr, "Destroying item %s\n", p_input->psz_name ); + + + vlc_input_item_Clean( p_input ); + + if( p_playlist ) + { + i_bottom = 0; i_top = p_playlist->i_input_items - 1; + i = i_top / 2; + while( p_playlist->pp_input_items[i]->i_id != p_input->i_id && + i_top > i_bottom ) + { + if( p_playlist->pp_input_items[i]->i_id < p_input->i_id ) + i_bottom = i + 1; + else + i_top = i -1; + + i = i_bottom + ( i_top - i_bottom ) / 2; + + } + if( p_playlist->pp_input_items[i]->i_id == p_input->i_id ) + { + REMOVE_ELEM( p_playlist->pp_input_items, + p_playlist->i_input_items, i ); + } + vlc_object_release( p_playlist ); + } + free( p_input ); +} + +int vlc_input_item_AddInfo( input_item_t *p_i, + const char *psz_cat, + const char *psz_name, + const char *psz_format, ... ) +{ + va_list args; + int i; + info_t *p_info = NULL; + info_category_t *p_cat = NULL ; + + vlc_mutex_lock( &p_i->lock ); + + for( i = 0 ; i < p_i->i_categories ; i ++ ) + { + if( !strcmp( p_i->pp_categories[i]->psz_name, psz_cat ) ) + { + p_cat = p_i->pp_categories[i]; + break; + } + } + if( !p_cat ) + { + if( !(p_cat = (info_category_t *)malloc( sizeof(info_category_t) )) ) + { + vlc_mutex_unlock( &p_i->lock ); + return VLC_EGENERIC; + } + p_cat->psz_name = strdup( psz_cat ); + p_cat->i_infos = 0; + p_cat->pp_infos = 0; + INSERT_ELEM( p_i->pp_categories, p_i->i_categories, p_i->i_categories, + p_cat ); + } + + for( i = 0; i< p_cat->i_infos; i++ ) + { + if( !strcmp( p_cat->pp_infos[i]->psz_name, psz_name ) ) + { + p_info = p_cat->pp_infos[i]; + break; + } + } + + if( !p_info ) + { + if( ( p_info = (info_t *)malloc( sizeof( info_t ) ) ) == NULL ) + { + vlc_mutex_unlock( &p_i->lock ); + return VLC_EGENERIC; + } + INSERT_ELEM( p_cat->pp_infos, p_cat->i_infos, p_cat->i_infos, p_info ); + p_info->psz_name = strdup( psz_name ); + } + else + { + if( p_info->psz_value ) free( p_info->psz_value ); + } + + va_start( args, psz_format ); + vasprintf( &p_info->psz_value, psz_format, args); + va_end( args ); + + vlc_mutex_unlock( &p_i->lock ); + + return VLC_SUCCESS; +} + +void vlc_input_item_AddOption( input_item_t *p_input, + const char *psz_option ) +{ + if( !psz_option ) return; + vlc_mutex_lock( &p_input->lock ); + INSERT_ELEM( p_input->ppsz_options, p_input->i_options, + p_input->i_options, strdup( psz_option ) ); + vlc_mutex_unlock( &p_input->lock ); +}; + + +input_item_t *input_ItemGetById( playlist_t *p_playlist, int i_id ) +{ + int i, i_top, i_bottom; + i_bottom = 0; i_top = p_playlist->i_input_items -1; + i = i_top /2 ; + while( p_playlist->pp_input_items[i]->i_id != i_id && + i_top > i_bottom ) + { + if( p_playlist->pp_input_items[i]->i_id < i_id ) + i_bottom = i + 1; + else + i_top = i - 1; + i = i_bottom + ( i_top - i_bottom ) / 2; + } + if( p_playlist->pp_input_items[i]->i_id == i_id ) + { + return p_playlist->pp_input_items[i]; + } + return NULL; +} + +input_item_t *__input_ItemNewExt( vlc_object_t *p_obj, const char *psz_uri, + const char *psz_name, int i_options, + const char **ppsz_options, int i_duration ) +{ + return input_ItemNewWithType( p_obj, psz_uri, psz_name, + i_options, ppsz_options, + i_duration, ITEM_TYPE_UNKNOWN ); +} + + +input_item_t *input_ItemNewWithType( vlc_object_t *p_obj, const char *psz_uri, + const char *psz_name, int i_options, + const char **ppsz_options, int i_duration, + int i_type ) +{ + /* FIXME DON'T SEARCH PLAYLIST */ + /* FIXME SHOULD LOCK */ + input_item_t *p_input = (input_item_t *)malloc( sizeof( input_item_t ) ); + playlist_t *p_playlist = (playlist_t *) vlc_object_find( p_obj, + VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); + + vlc_input_item_Init( p_obj, p_input ); + vlc_gc_init( p_input, vlc_input_item_Destroy, (void *)p_obj ); + + p_input->i_id = ++p_playlist->i_last_input_id; + + INSERT_ELEM( p_playlist->pp_input_items, p_playlist->i_input_items, + p_playlist->i_input_items, p_input ); + vlc_object_release( p_playlist ); + + p_input->b_fixed_name = VLC_FALSE; + + if( psz_uri ) + p_input->psz_uri = strdup( psz_uri ); + else + p_input->psz_uri = NULL; + + if( psz_name != NULL ) + p_input->psz_name = strdup( psz_name ); + else + p_input->psz_name = strdup ( p_input->psz_uri ); + + p_input->i_type = i_type; + + if( p_input->i_type == ITEM_TYPE_UNKNOWN ) + GuessType( p_input ); + + p_input->i_duration = i_duration; + p_input->ppsz_options = NULL; + + for( p_input->i_options = 0; p_input->i_options < i_options; + p_input->i_options++ ) + { + if( !p_input->i_options ) + { + p_input->ppsz_options = malloc( i_options * sizeof(char *) ); + if( !p_input->ppsz_options ) break; + } + p_input->ppsz_options[p_input->i_options] = + strdup( ppsz_options[p_input->i_options] ); + } + return p_input; +} + +/* Guess the type of the item using the beginning of the mrl */ +static void GuessType( input_item_t *p_item) +{ + int i; + static struct { char *psz_search; int i_type; } types_array[] = + { + { "http", ITEM_TYPE_NET }, + { "dvd", ITEM_TYPE_DISC }, + { "cdda", ITEM_TYPE_CDDA }, + { "mms", ITEM_TYPE_NET }, + { "rtsp", ITEM_TYPE_NET }, + { "udp", ITEM_TYPE_NET }, + { "rtp", ITEM_TYPE_NET }, + { "vcd", ITEM_TYPE_DISC }, + { "v4l", ITEM_TYPE_CARD }, + { "dshow", ITEM_TYPE_CARD }, + { "pvr", ITEM_TYPE_CARD }, + { "dvb", ITEM_TYPE_CARD }, + { "qpsk", ITEM_TYPE_CARD }, + { "sdp", ITEM_TYPE_NET }, + { NULL, 0 } + }; + +#if 0 /* Unused */ + static struct { char *psz_search; int i_type; } exts_array[] = + { + { "mp3", ITEM_TYPE_AFILE }, + { NULL, 0 } + }; +#endif + + for( i = 0; types_array[i].psz_search != NULL; i++ ) + { + if( !strncmp( p_item->psz_uri, types_array[i].psz_search, + strlen( types_array[i].psz_search ) ) ) + { + p_item->i_type = types_array[i].i_type; + return; + } + } + p_item->i_type = ITEM_TYPE_VFILE; +} diff --git a/src/libvlc.c b/src/libvlc.c index d1b5b77c76..2b33b381fb 100644 --- a/src/libvlc.c +++ b/src/libvlc.c @@ -697,7 +697,7 @@ int VLC_Init( int i_object, int i_argc, char *ppsz_argv[] ) /* * Initialize playlist and get commandline files */ - p_playlist = playlist_Create( p_vlc ); + p_playlist = playlist_ThreadCreate( p_vlc ); if( !p_playlist ) { msg_Err( p_vlc, "playlist initialization failed" ); @@ -915,7 +915,7 @@ int VLC_CleanUp( int i_object ) { vlc_object_detach( p_playlist ); vlc_object_release( p_playlist ); - playlist_Destroy( p_playlist ); + playlist_ThreadDestroy( p_playlist ); } /* @@ -1198,7 +1198,7 @@ int VLC_AddTarget( int i_object, char const *psz_target, if( p_playlist == NULL ) { msg_Dbg( p_vlc, "no playlist present, creating one" ); - p_playlist = playlist_Create( p_vlc ); + p_playlist = playlist_ThreadCreate( p_vlc ); if( p_playlist == NULL ) { @@ -1209,7 +1209,7 @@ int VLC_AddTarget( int i_object, char const *psz_target, vlc_object_yield( p_playlist ); } - i_err = playlist_AddExt( p_playlist, psz_target, psz_target, + i_err = playlist_PlaylistAddExt( p_playlist, psz_target, psz_target, i_mode, i_pos, -1, ppsz_options, i_options); vlc_object_release( p_playlist ); @@ -1631,29 +1631,8 @@ float VLC_SpeedSlower( int i_object ) */ int VLC_PlaylistIndex( int i_object ) { - int i_index; - playlist_t * p_playlist; - vlc_t *p_vlc = vlc_current_object( i_object ); - - /* Check that the handle is valid */ - if( !p_vlc ) - { - return VLC_ENOOBJ; - } - - p_playlist = vlc_object_find( p_vlc, VLC_OBJECT_PLAYLIST, FIND_CHILD ); - - if( !p_playlist ) - { - if( i_object ) vlc_object_release( p_vlc ); - return VLC_ENOOBJ; - } - - i_index = p_playlist->i_index; - vlc_object_release( p_playlist ); - - if( i_object ) vlc_object_release( p_vlc ); - return i_index; + printf( "This function is deprecated and should not be used anymore" ); + return -1; } /** @@ -1763,7 +1742,6 @@ int VLC_PlaylistPrev( int i_object ) *****************************************************************************/ int VLC_PlaylistClear( int i_object ) { - int i_err; playlist_t * p_playlist; vlc_t *p_vlc = vlc_current_object( i_object ); @@ -1781,12 +1759,12 @@ int VLC_PlaylistClear( int i_object ) return VLC_ENOOBJ; } - i_err = playlist_Clear( p_playlist ); + playlist_Clear( p_playlist ); vlc_object_release( p_playlist ); if( i_object ) vlc_object_release( p_vlc ); - return i_err; + return VLC_SUCCESS; } /** diff --git a/src/playlist/control.c b/src/playlist/control.c new file mode 100644 index 0000000000..5ac0ee60b3 --- /dev/null +++ b/src/playlist/control.c @@ -0,0 +1,455 @@ +/***************************************************************************** + * control.c : Hanle control of the playlist & running through it + ***************************************************************************** + * Copyright (C) 1999-2004 the VideoLAN team + * $Id: /local/vlc/0.8.6-playlist-vlm/src/playlist/playlist.c 13741 2006-03-21T19:29:39.792444Z zorglub $ + * + * Authors: Samuel Hocevar + * Clément Stenac + * + * 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. + *****************************************************************************/ +#include +#include +#include "vlc_playlist.h" + +#define PLAYLIST_DEBUG 1 + +/***************************************************************************** + * Local prototypes + *****************************************************************************/ +int PlaylistVAControl( playlist_t * p_playlist, int i_query, va_list args ); + +void PreparseEnqueueItemSub( playlist_t *, playlist_item_t * ); + +playlist_item_t *playlist_RecursiveFindLast(playlist_t *p_playlist, + playlist_item_t *p_node ); + +/***************************************************************************** + * Playlist control + *****************************************************************************/ + +/** + * Do a playlist action. Should be entered without playlist lock + * \see playlist_Control + */ +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 = PlaylistVAControl( 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. + * Should be entered with playlist lock. See include/vlc_playlist.h for + * possible queries + * + * \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 = PlaylistVAControl( p_playlist, i_query, args ); + va_end( args ); + + return i_result; +} + +int PlaylistVAControl( playlist_t * p_playlist, int i_query, va_list args ) +{ + int i_view; + playlist_item_t *p_item, *p_node; + vlc_value_t val; + + if( p_playlist->i_size <= 0 ) + { + return VLC_EGENERIC; + } + + switch( i_query ) + { + case PLAYLIST_STOP: + p_playlist->request.i_status = PLAYLIST_STOPPED; + p_playlist->request.b_request = VLC_TRUE; + p_playlist->request.p_item = NULL; + break; + + case PLAYLIST_ITEMPLAY: + p_item = (playlist_item_t *)va_arg( args, playlist_item_t * ); + if ( p_item == NULL || p_item->p_input->psz_uri == NULL ) + return VLC_EGENERIC; + p_playlist->request.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.p_node = p_playlist->status.p_node; + break; + + case PLAYLIST_VIEWPLAY: + i_view = (int) va_arg( args, playlist_item_t *); + 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_playlist->status.i_status = PLAYLIST_STOPPED; + p_playlist->request.b_request = VLC_TRUE; + msg_Err( p_playlist, "null node" ); + return VLC_SUCCESS; + } + p_playlist->request.i_status = PLAYLIST_RUNNING; + p_playlist->request.i_skip = 0; + p_playlist->request.b_request = VLC_TRUE; + p_playlist->request.p_node = p_node; + p_playlist->request.p_item = p_item; + break; + + case PLAYLIST_PLAY: + p_playlist->request.i_status = PLAYLIST_RUNNING; + p_playlist->request.b_request = VLC_TRUE; + + if( p_playlist->p_input ) + { + val.i_int = PLAYING_S; + var_Set( p_playlist->p_input, "state", val ); + break; + } + p_playlist->request.p_node = p_playlist->status.p_node; + p_playlist->request.p_item = p_playlist->status.p_item; + p_playlist->request.i_skip = 0; + break; + + case PLAYLIST_AUTOPLAY: + p_playlist->status.i_status = PLAYLIST_RUNNING; + p_playlist->status.p_node = p_playlist->p_local_category; + p_playlist->request.b_request = VLC_FALSE; + break; + + case PLAYLIST_PAUSE: + val.i_int = 0; + if( p_playlist->p_input ) + var_Get( p_playlist->p_input, "state", &val ); + + if( val.i_int == PAUSE_S ) + { + p_playlist->status.i_status = PLAYLIST_RUNNING; + if( p_playlist->p_input ) + { + val.i_int = PLAYING_S; + var_Set( p_playlist->p_input, "state", val ); + } + } + else + { + p_playlist->status.i_status = PLAYLIST_PAUSED; + if( p_playlist->p_input ) + { + val.i_int = PAUSE_S; + var_Set( p_playlist->p_input, "state", val ); + } + } + break; + + case PLAYLIST_SKIP: + p_playlist->request.p_node = p_playlist->status.p_node; + p_playlist->request.p_item = p_playlist->status.p_item; + p_playlist->request.i_skip = (int) va_arg( args, int ); + p_playlist->request.b_request = VLC_TRUE; + break; + + default: + msg_Err( p_playlist, "unknown playlist query" ); + return VLC_EBADVAR; + break; + } + + return VLC_SUCCESS; +} + +/***************************************************************************** + * Preparse control + *****************************************************************************/ +/** Enqueue an item for preparsing */ +int playlist_PreparseEnqueue( playlist_t *p_playlist, + input_item_t *p_item ) +{ + vlc_mutex_lock( &p_playlist->p_preparse->object_lock ); + vlc_gc_incref( p_item ); + INSERT_ELEM( p_playlist->p_preparse->pp_waiting, + p_playlist->p_preparse->i_waiting, + p_playlist->p_preparse->i_waiting, + p_item ); + vlc_mutex_unlock( &p_playlist->p_preparse->object_lock ); + return VLC_SUCCESS; +} + +/** Enqueue a playlist item or a node for peparsing. + * This function should be entered without playlist and preparser locks */ +int playlist_PreparseEnqueueItem( playlist_t *p_playlist, + playlist_item_t *p_item ) +{ + vlc_mutex_lock( &p_playlist->object_lock ); + vlc_mutex_lock( &p_playlist->p_preparse->object_lock ); + PreparseEnqueueItemSub( p_playlist, p_item ); + vlc_mutex_unlock( &p_playlist->p_preparse->object_lock ); + vlc_mutex_unlock( &p_playlist->object_lock ); + return VLC_SUCCESS; +} + +void PreparseEnqueueItemSub( playlist_t *p_playlist, + playlist_item_t *p_item ) +{ + int i; + if( p_item->i_children == -1 ) + { + vlc_gc_incref( p_item ); + INSERT_ELEM( p_playlist->p_preparse->pp_waiting, + p_playlist->p_preparse->i_waiting, + p_playlist->p_preparse->i_waiting, + p_item->p_input ); + } + else + { + for( i = 0; i < p_item->i_children; i++) + { + PreparseEnqueueItemSub( p_playlist, + p_item->pp_children[i] ); + } + } +} + +/***************************************************************************** + * Playback logic + *****************************************************************************/ + +/** This function calculates the next playlist item, depending + * on the playlist course mode (forward, backward, random, view,...). */ +playlist_item_t * playlist_NextItem( playlist_t *p_playlist ) +{ + playlist_item_t *p_new = NULL; + int i_skip,i; + + vlc_bool_t b_loop = var_GetBool( p_playlist, "loop" ); + vlc_bool_t b_random = var_GetBool( p_playlist, "random" ); + vlc_bool_t b_repeat = var_GetBool( p_playlist, "repeat" ); + vlc_bool_t b_playstop = var_GetBool( p_playlist, "play-and-stop" ); + + /* Handle quickly a few special cases */ + + /* No items to play */ + if( p_playlist->i_size == 0 ) + { + msg_Info( p_playlist, "playlist is empty" ); + return NULL; + } + + /* Repeat and play/stop */ + if( !p_playlist->request.b_request && b_repeat == VLC_TRUE && + p_playlist->status.p_item ) + { + msg_Dbg( p_playlist,"repeating item" ); + return p_playlist->status.p_item; + } + if( !p_playlist->request.b_request && b_playstop == VLC_TRUE ) + { + msg_Dbg( p_playlist,"stopping (play and stop)"); + return NULL; + } + + if( !p_playlist->request.b_request && p_playlist->status.p_item && + p_playlist->status.p_item->i_flags & PLAYLIST_SKIP_FLAG ) + { + msg_Dbg( p_playlist, "blocking item, stopping") ; + return NULL; + } + + /* Random case. This is an exception: if request, but request is skip +- 1 + * we don't go to next item but select a new random one. */ + if( b_random ) + msg_Err( p_playlist, "random unsupported" ); +#if 0 + && + ( !p_playlist->request.b_request || + ( p_playlist->request.b_request && ( p_playlist->request.p_item == NULL || + p_playlist->request.i_skip == 1 || p_playlist->request.i_skip == -1 ) ) ) ) + { + /* how many items to choose from ? */ + i_count = 0; + for ( i = 0; i < p_playlist->i_size; i++ ) + { + if ( p_playlist->pp_items[i]->p_input->i_nb_played == 0 ) + i_count++; + } + /* Nothing left? */ + if ( i_count == 0 ) + { + /* Don't loop? Exit! */ + if( !b_loop ) + return NULL; + /* Otherwise reset the counter */ + for ( i = 0; i < p_playlist->i_size; i++ ) + { + p_playlist->pp_items[i]->p_input->i_nb_played = 0; + } + i_count = p_playlist->i_size; + } + srand( (unsigned int)mdate() ); + i = rand() % i_count + 1 ; + /* loop thru the list and count down the unplayed items to the selected one */ + for ( i_new = 0; i_new < p_playlist->i_size && i > 0; i_new++ ) + { + if ( p_playlist->pp_items[i_new]->p_input->i_nb_played == 0 ) + i--; + } + i_new--; + + p_playlist->request.i_skip = 0; + p_playlist->request.b_request = VLC_FALSE; + return p_playlist->pp_items[i_new]; + } +#endif + + /* Start the real work */ + if( p_playlist->request.b_request ) + { +#ifdef PLAYLIST_DEBUG + msg_Dbg( p_playlist,"processing request" ); +#endif + p_new = p_playlist->request.p_item; + i_skip = p_playlist->request.i_skip; + + p_playlist->status.p_node = p_playlist->request.p_node; + + /* If we are asked for a node, take its first item */ + if( i_skip == 0 && + ( p_new == NULL || p_new->i_children != -1 ) ) + { + i_skip++; + } + + if( i_skip > 0 ) + { + for( i = i_skip; i > 0 ; i-- ) + { + p_new = playlist_GetNextEnabledLeaf( p_playlist, + p_playlist->request.p_node, + p_new ); + if( p_new == NULL ) + { +#ifdef PLAYLIST_DEBUG + msg_Dbg( p_playlist, "looping - restarting at beginning " + "of node" ); +#endif + p_new = playlist_GetNextLeaf( p_playlist, + p_playlist->request.p_node, + NULL ); + if( p_new == NULL ) break; + } + } + } + else if( i_skip < 0 ) + { + for( i = i_skip; i < 0 ; i++ ) + { + p_new = playlist_GetPrevLeaf( p_playlist, + p_playlist->request.p_node, + p_new ); + if( p_new == NULL ) + { +#ifdef PLAYLIST_DEBUG + msg_Dbg( p_playlist, "looping - restarting at end " + "of node" ); +#endif + /** \bug This is needed because GetPrevLeaf does not loop + * by itself */ + p_new = playlist_GetLastLeaf( p_playlist, + p_playlist->request.p_node ); + } + if( p_new == NULL ) break; + } + } + /* Clear the request */ + p_playlist->request.b_request = VLC_FALSE; + } + /* "Automatic" item change ( next ) */ + else + { +#ifdef PLAYLIST_DEBUG + msg_Dbg( p_playlist,"changing item without a request" ); +#endif + /* Cant go to next from current item */ + if( p_playlist->status.p_item && + p_playlist->status.p_item->i_flags & PLAYLIST_SKIP_FLAG ) + return NULL; + + p_new = playlist_GetNextLeaf( p_playlist, + p_playlist->status.p_node, + p_playlist->status.p_item ); + if( p_new == NULL && b_loop ) + { +#ifdef PLAYLIST_DEBUG + msg_Dbg( p_playlist, "looping" ); +#endif + p_new = playlist_GetNextLeaf( p_playlist, + p_playlist->status.p_node, + NULL ); + } + /* The new item can't be autoselected */ + if( p_new != NULL && p_new->i_flags & PLAYLIST_SKIP_FLAG ) + return NULL; + } + if( p_new == NULL ) + { + msg_Dbg( p_playlist, "did not find something to play" ); + } + return p_new; +} + +/** Start the input for an item */ +int playlist_PlayItem( playlist_t *p_playlist, playlist_item_t *p_item ) +{ + vlc_value_t val; + int i_activity = var_GetInteger( p_playlist, "activity") ; + + msg_Dbg( p_playlist, "creating new input thread" ); + + p_item->p_input->i_nb_played++; + p_playlist->status.p_item = p_item; + + p_playlist->status.i_status = PLAYLIST_RUNNING; + + var_SetInteger( p_playlist, "activity", i_activity + + DEFAULT_INPUT_ACTIVITY ); + p_playlist->p_input = input_CreateThread( p_playlist, p_item->p_input ); + + val.i_int = p_item->p_input->i_id; + /* unlock the playlist to set the var...mmm */ + vlc_mutex_unlock( &p_playlist->object_lock); + var_Set( p_playlist, "playlist-current", val); + vlc_mutex_lock( &p_playlist->object_lock); + + return VLC_SUCCESS; +} diff --git a/src/playlist/engine.c b/src/playlist/engine.c new file mode 100644 index 0000000000..2d81f6fe3c --- /dev/null +++ b/src/playlist/engine.c @@ -0,0 +1,485 @@ +/***************************************************************************** + * engine.c : Run the playlist and handle its control + ***************************************************************************** + * Copyright (C) 1999-2004 the VideoLAN team + * $Id: /local/vlc/0.8.6-playlist-vlm/src/playlist/playlist.c 13741 2006-03-21T19:29:39.792444Z zorglub $ + * + * Authors: Samuel Hocevar + * Clément Stenac + * + * 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. + *****************************************************************************/ +#include +#include +#include +#include +#include "vlc_playlist.h" +#include "vlc_interaction.h" + +#undef PLAYLIST_DEBUG + +/***************************************************************************** + * Local prototypes + *****************************************************************************/ +static void VariablesInit( playlist_t *p_playlist ); + +/** + * 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; + + /* Allocate structure */ + p_playlist = vlc_object_create( p_parent, VLC_OBJECT_PLAYLIST ); + if( !p_playlist ) + { + msg_Err( p_parent, "out of memory" ); + return NULL; + } + + VariablesInit( p_playlist ); + + /* Initialise data structures */ + vlc_mutex_init( p_playlist, &p_playlist->gc_lock ); + p_playlist->i_last_playlist_id = 0; + p_playlist->i_last_input_id = 0; + p_playlist->p_input = NULL; + + p_playlist->i_size = 0; + p_playlist->pp_items = NULL; + p_playlist->i_all_size = 0; + p_playlist->pp_all_items = NULL; + + p_playlist->i_input_items = 0; + p_playlist->pp_input_items = NULL; + + p_playlist->p_root_category = playlist_NodeCreate( p_playlist, NULL, NULL); + p_playlist->p_root_onelevel = playlist_NodeCreate( p_playlist, NULL, NULL); + + /* Create playlist and media library */ + p_playlist->p_local_category = playlist_NodeCreate( p_playlist, + _( "Playlist" ),p_playlist->p_root_category ); + p_playlist->p_ml_category = playlist_NodeCreate( p_playlist, + _( "Media Library" ), p_playlist->p_root_category ); + p_playlist->p_local_onelevel = playlist_NodeCreate( p_playlist, + _( "Playlist" ), p_playlist->p_root_onelevel ); + p_playlist->p_ml_onelevel = playlist_NodeCreate( p_playlist, + _( "Media Library" ), p_playlist->p_root_onelevel ); + + /* This is a hack to find it later. Quite ugly, but I haven't found a + * better way */ + p_playlist->p_local_onelevel->p_input->i_id = + p_playlist->p_local_category->p_input->i_id; + p_playlist->p_ml_onelevel->p_input->i_id = + p_playlist->p_ml_category->p_input->i_id; + + /* Initial status */ + p_playlist->status.p_item = NULL; + p_playlist->status.p_node = p_playlist->p_root_onelevel; + 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; + + vlc_object_attach( p_playlist, p_parent ); + return p_playlist; +} + +void playlist_Destroy( playlist_t *p_playlist ) +{ + 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" ); + var_Destroy( p_playlist, "activity" ); + + playlist_LockClear( p_playlist ); + + if( p_playlist->p_stats ) + free( p_playlist->p_stats ); + + vlc_mutex_destroy( &p_playlist->gc_lock ); + vlc_object_destroy( p_playlist->p_preparse ); + vlc_object_destroy( p_playlist ); + +} +/* Destroy remaining objects */ +static mtime_t ObjectGarbageCollector( playlist_t *p_playlist, int i_type, + mtime_t destroy_date ) +{ + vlc_object_t *p_obj; + + if( destroy_date > mdate() ) return destroy_date; + + if( destroy_date == 0 ) + { + /* give a little time */ + return mdate() + I64C(1000000); + } + else + { + vlc_mutex_lock( &p_playlist->gc_lock ); + while( ( p_obj = vlc_object_find( p_playlist, i_type, FIND_CHILD ) ) ) + { + if( p_obj->p_parent != (vlc_object_t*)p_playlist ) + { + /* only first child (ie unused) */ + vlc_object_release( p_obj ); + break; + } + if( i_type == VLC_OBJECT_VOUT ) + { + msg_Dbg( p_playlist, "garbage collector destroying 1 vout" ); + vlc_object_detach( p_obj ); + vlc_object_release( p_obj ); + vout_Destroy( (vout_thread_t *)p_obj ); + } + else if( i_type == VLC_OBJECT_SOUT ) + { + vlc_object_release( p_obj ); + sout_DeleteInstance( (sout_instance_t*)p_obj ); + } + } + vlc_mutex_unlock( &p_playlist->gc_lock ); + return 0; + } +} + +/** Main loop for the playlist */ +void playlist_MainLoop( playlist_t *p_playlist ) +{ + playlist_item_t *p_item = NULL; + + mtime_t i_vout_destroyed_date = 0; + mtime_t i_sout_destroyed_date = 0; + + PL_LOCK + + /* First, check if we have something to do */ + /* FIXME : this can be called several times */ + if( p_playlist->request.b_request ) + { +#ifdef PLAYLIST_DEBUG + msg_Dbg(p_playlist, "incoming request - stopping current input" ); +#endif + /* Stop the existing input */ + if( p_playlist->p_input ) + { + input_StopThread( p_playlist->p_input ); + } + } + + /* If there is an input, check that it doesn't need to die. */ + if( p_playlist->p_input ) + { + /* This input is dead. Remove it ! */ + if( p_playlist->p_input->b_dead ) + { + int i_activity; + input_thread_t *p_input; + + p_input = p_playlist->p_input; + p_playlist->p_input = NULL; + + /* Release the playlist lock, because we may get stuck + * in input_DestroyThread() for some time. */ + PL_UNLOCK + + /* Destroy input */ + input_DestroyThread( p_input ); + + /* Unlink current input + * (_after_ input_DestroyThread for vout garbage collector) */ + vlc_object_detach( p_input ); + + /* Destroy object */ + vlc_object_destroy( p_input ); + + i_vout_destroyed_date = 0; + i_sout_destroyed_date = 0; + + if( p_playlist->status.p_item->i_flags + & PLAYLIST_REMOVE_FLAG ) + { + playlist_ItemDelete( p_playlist->status.p_item ); + p_playlist->status.p_item = NULL; + } + + i_activity= var_GetInteger( p_playlist, "activity") ; + var_SetInteger( p_playlist, "activity", i_activity - + DEFAULT_INPUT_ACTIVITY ); + + return; + } + /* This input is dying, let it do */ + else if( p_playlist->p_input->b_die ) + { + ; + } + /* This input has finished, ask it to die ! */ + else if( p_playlist->p_input->b_error + || p_playlist->p_input->b_eof ) + { + input_StopThread( p_playlist->p_input ); + /* Select the next playlist item */ + PL_UNLOCK + return; + } + else if( p_playlist->p_input->i_state != INIT_S ) + { + PL_UNLOCK + i_vout_destroyed_date = + ObjectGarbageCollector( p_playlist, VLC_OBJECT_VOUT, + i_vout_destroyed_date ); + i_sout_destroyed_date = + ObjectGarbageCollector( p_playlist, VLC_OBJECT_SOUT, + i_sout_destroyed_date ); + PL_LOCK + } + } + else + { + /* No input. Several cases + * - No request, running status -> start new item + * - No request, stopped status -> collect garbage + * - Request, running requested -> start new item + * - Request, stopped requested -> collect garbage + */ + if( (!p_playlist->request.b_request && + p_playlist->status.i_status != PLAYLIST_STOPPED) || + ( p_playlist->request.b_request && + p_playlist->request.i_status != PLAYLIST_STOPPED ) ) + { + msg_Dbg( p_playlist, "Starting new item" ); + stats_TimerStart( p_playlist, "Playlist walk", + STATS_TIMER_PLAYLIST_WALK ); + p_item = playlist_NextItem( p_playlist ); + stats_TimerStop( p_playlist, STATS_TIMER_PLAYLIST_WALK ); + + if( p_item == NULL ) + { + msg_Dbg( p_playlist, "nothing to play" ); + p_playlist->status.i_status = PLAYLIST_STOPPED; + PL_UNLOCK + return; + } + playlist_PlayItem( p_playlist, p_item ); + } + else + { + if( p_item && p_playlist->status.p_item && + p_playlist->status.p_item->i_flags & PLAYLIST_REMOVE_FLAG ) + { + playlist_ItemDelete( p_item ); + p_playlist->status.p_item = NULL; + } + + /* Collect garbage */ + PL_UNLOCK + i_sout_destroyed_date = + ObjectGarbageCollector( p_playlist, VLC_OBJECT_SOUT, mdate() ); + i_vout_destroyed_date = + ObjectGarbageCollector( p_playlist, VLC_OBJECT_VOUT, mdate() ); + PL_LOCK + } + } + PL_UNLOCK +} + +/** Playlist dying last loop */ +void playlist_LastLoop( playlist_t *p_playlist ) +{ + vlc_object_t *p_obj; + + /* If there is an input, kill it */ + while( 1 ) + { + PL_LOCK + + if( p_playlist->p_input == NULL ) + { + PL_UNLOCK + break; + } + + if( p_playlist->p_input->b_dead ) + { + input_thread_t *p_input; + + /* Unlink current input */ + p_input = p_playlist->p_input; + p_playlist->p_input = NULL; + PL_UNLOCK + + /* Destroy input */ + input_DestroyThread( p_input ); + /* Unlink current input (_after_ input_DestroyThread for vout + * garbage collector)*/ + vlc_object_detach( p_input ); + + /* Destroy object */ + vlc_object_destroy( p_input ); + continue; + } + else if( p_playlist->p_input->b_die ) + { + /* This input is dying, leave it alone */ + ; + } + else if( p_playlist->p_input->b_error || p_playlist->p_input->b_eof ) + { + input_StopThread( p_playlist->p_input ); + PL_UNLOCK + continue; + } + else + { + p_playlist->p_input->b_eof = 1; + } + + PL_UNLOCK + + msleep( INTF_IDLE_SLEEP ); + } + + /* close all remaining sout */ + while( ( p_obj = vlc_object_find( p_playlist, + VLC_OBJECT_SOUT, FIND_CHILD ) ) ) + { + vlc_object_release( p_obj ); + sout_DeleteInstance( (sout_instance_t*)p_obj ); + } + + /* close all remaining vout */ + while( ( p_obj = vlc_object_find( p_playlist, + VLC_OBJECT_VOUT, FIND_CHILD ) ) ) + { + vlc_object_detach( p_obj ); + vlc_object_release( p_obj ); + vout_Destroy( (vout_thread_t *)p_obj ); + } +} + +/** Main loop for preparser queue */ +void playlist_PreparseLoop( playlist_preparse_t *p_obj ) +{ + playlist_t *p_playlist = (playlist_t *)p_obj->p_parent; + int i_activity; + + vlc_mutex_lock( &p_obj->object_lock ); + + if( p_obj->i_waiting > 0 ) + { + input_item_t *p_current = p_playlist->p_preparse->pp_waiting[0]; + REMOVE_ELEM( p_obj->pp_waiting, p_obj->i_waiting, 0 ); + vlc_mutex_unlock( &p_obj->object_lock ); + vlc_mutex_lock( &p_playlist->object_lock ); + if( p_current ) + { + vlc_bool_t b_preparsed = VLC_FALSE; + if( strncmp( p_current->psz_uri, "http:", 5 ) && + strncmp( p_current->psz_uri, "rtsp:", 5 ) && + strncmp( p_current->psz_uri, "udp:", 4 ) && + strncmp( p_current->psz_uri, "mms:", 4 ) && + strncmp( p_current->psz_uri, "cdda:", 4 ) && + strncmp( p_current->psz_uri, "dvd:", 4 ) && + strncmp( p_current->psz_uri, "v4l:", 4 ) && + strncmp( p_current->psz_uri, "dshow:", 6 ) ) + { + b_preparsed = VLC_TRUE; + stats_TimerStart( p_playlist, "Preparse run", + STATS_TIMER_PREPARSE ); + input_Preparse( p_playlist, p_current ); + stats_TimerStop( p_playlist, STATS_TIMER_PREPARSE ); + } + vlc_mutex_unlock( &p_playlist->object_lock ); + if( b_preparsed ) + { + var_SetInteger( p_playlist, "item-change", + p_current->i_id ); + } + vlc_gc_decref( p_current ); + } + else + { + vlc_mutex_unlock( &p_playlist->object_lock ); + } + vlc_mutex_lock( &p_obj->object_lock ); + i_activity= var_GetInteger( p_playlist, "activity" ); + if( i_activity < 0 ) i_activity = 0; + msleep( (i_activity+1) * 1000 ); + } + + vlc_mutex_unlock( &p_obj->object_lock ); +} + +static void VariablesInit( playlist_t *p_playlist ) +{ + vlc_value_t val; + /* 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 ); + + var_Create( p_playlist, "activity", VLC_VAR_INTEGER ); + var_SetInteger( p_playlist, "activity", 0 ); + + /* 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" ); +} diff --git a/src/playlist/item-ext.c b/src/playlist/item-ext.c deleted file mode 100644 index 6b6830a7e8..0000000000 --- a/src/playlist/item-ext.c +++ /dev/null @@ -1,931 +0,0 @@ -/***************************************************************************** - * item-ext.c : Playlist item management functions (act on the playlist) - ***************************************************************************** - * Copyright (C) 1999-2004 the VideoLAN team - * $Id$ - * - * Authors: Samuel Hocevar - * Clément Stenac - * - * 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. - *****************************************************************************/ -#include /* free(), strtol() */ -#include /* sprintf() */ -#include /* strerror() */ - -#include -#include - -#include "vlc_playlist.h" - -/*************************************************************************** - * Item creation/addition functions - ***************************************************************************/ - -/** - * Add a MRL into the playlist, duration and options given - * - * \param p_playlist the playlist to add into - * \param psz_uri the mrl to add to the playlist - * \param psz_name a text giving a name or description of this item - * \param i_mode the mode used when adding - * \param i_pos the position in the playlist where to add. If this is - * PLAYLIST_END the item will be added at the end of the playlist - * regardless of it's size - * \param i_duration length of the item in milliseconds. - * \param ppsz_options an array of options - * \param i_options the number of options - * \return The id of the playlist item -*/ -int playlist_AddExt( playlist_t *p_playlist, const char * psz_uri, - const char *psz_name, int i_mode, int i_pos, - mtime_t i_duration, const char **ppsz_options, - int i_options ) -{ - playlist_item_t *p_item; - p_item = playlist_ItemNew( p_playlist , psz_uri, psz_name ); - - if( p_item == NULL ) - { - msg_Err( p_playlist, "unable to add item to playlist" ); - return -1; - } - - p_item->input.i_duration = i_duration; - p_item->input.i_options = i_options; - p_item->input.ppsz_options = NULL; - - for( p_item->input.i_options = 0; p_item->input.i_options < i_options; - p_item->input.i_options++ ) - { - if( !p_item->input.i_options ) - { - p_item->input.ppsz_options = malloc( i_options * sizeof(char *) ); - if( !p_item->input.ppsz_options ) break; - } - - p_item->input.ppsz_options[p_item->input.i_options] = - strdup( ppsz_options[p_item->input.i_options] ); - } - - return playlist_AddItem( p_playlist, p_item, i_mode, i_pos ); -} - -/** - * Add a MRL into the playlist. - * - * \param p_playlist the playlist to add into - * \param psz_uri the mrl to add to the playlist - * \param psz_name a text giving a name or description of this item - * \param i_mode the mode used when adding - * \param i_pos the position in the playlist where to add. If this is - * PLAYLIST_END the item will be added at the end of the playlist - * regardless of it's size - * \return The id of the playlist item -*/ -int playlist_Add( playlist_t *p_playlist, const char *psz_uri, - const char *psz_name, int i_mode, int i_pos ) -{ - return playlist_AddExt( p_playlist, psz_uri, psz_name, i_mode, i_pos, - -1, NULL, 0 ); -} - -/** - * Add a playlist item into a playlist - * - * \param p_playlist the playlist to insert into - * \param p_item the playlist item to insert - * \param i_mode the mode used when adding - * \param i_pos the possition in the playlist where to add. If this is - * PLAYLIST_END the item will be added at the end of the playlist - * regardless of it's size - * \return The id of the playlist item - */ -int playlist_AddItem( playlist_t *p_playlist, playlist_item_t *p_item, - int i_mode, int i_pos) -{ - vlc_value_t val; - vlc_bool_t b_end = VLC_FALSE; - playlist_view_t *p_view = NULL; - - playlist_add_t *p_add = (playlist_add_t *)malloc(sizeof( playlist_add_t)); - - vlc_mutex_lock( &p_playlist->object_lock ); - - /* - * CHECK_INSERT : checks if the item is already enqued before - * enqueing it - */ - - /* That should not change */ - if ( i_mode & PLAYLIST_CHECK_INSERT ) - { - int j; - - if ( p_playlist->pp_items ) - { - for ( j = 0; j < p_playlist->i_size; j++ ) - { - if ( !strcmp( p_playlist->pp_items[j]->input.psz_uri, - p_item->input.psz_uri ) ) - { - playlist_ItemDelete( p_item ); - vlc_mutex_unlock( &p_playlist->object_lock ); - return -1; - } - } - } - i_mode &= ~PLAYLIST_CHECK_INSERT; - i_mode |= PLAYLIST_APPEND; - } - - msg_Dbg( p_playlist, "adding playlist item `%s' ( %s )", - p_item->input.psz_name, p_item->input.psz_uri ); - - p_item->input.i_id = ++p_playlist->i_last_id; - - /* Do a few boundary checks and allocate space for the item */ - if( i_pos == PLAYLIST_END ) - { - b_end = VLC_TRUE; - if( i_mode & PLAYLIST_INSERT ) - { - i_mode &= ~PLAYLIST_INSERT; - i_mode |= PLAYLIST_APPEND; - } - - i_pos = p_playlist->i_size - 1; - } - - if( !(i_mode & PLAYLIST_REPLACE) - || i_pos < 0 || i_pos >= p_playlist->i_size ) - { - /* Additional boundary checks */ - if( i_mode & PLAYLIST_APPEND ) - { - i_pos++; - } - - if( i_pos < 0 ) - { - i_pos = 0; - } - else if( i_pos > p_playlist->i_size ) - { - i_pos = p_playlist->i_size; - } - - INSERT_ELEM( p_playlist->pp_items, p_playlist->i_size, i_pos, p_item ); - INSERT_ELEM( p_playlist->pp_all_items, p_playlist->i_all_size, - p_playlist->i_all_size, p_item ); - p_playlist->i_enabled ++; - - /* We update the ALL view directly */ - playlist_ViewUpdate( p_playlist, VIEW_ALL ); - - /* Add the item to the General category */ - if( b_end == VLC_TRUE ) - { - playlist_NodeAppend( p_playlist, VIEW_CATEGORY, p_item, - p_playlist->p_general ); - p_add->i_item = p_item->input.i_id; - p_add->i_node = p_playlist->p_general->input.i_id; - p_add->i_view = VIEW_CATEGORY; - val.p_address = p_add; - var_Set( p_playlist, "item-append", val ); - } - else - { - playlist_NodeInsert( p_playlist, VIEW_CATEGORY, p_item, - p_playlist->p_general, i_pos ); - } - - - p_view = playlist_ViewFind( p_playlist, VIEW_ALL ); - playlist_ItemAddParent( p_item, VIEW_ALL, p_view->p_root ); - - /* FIXME : Update sorted views */ - - if( p_playlist->i_index >= i_pos ) - { - p_playlist->i_index++; - } - } - else - { - msg_Err( p_playlist, "Insert mode not implemented" ); - } - - if( (i_mode & PLAYLIST_GO ) && p_view ) - { - p_playlist->request.b_request = VLC_TRUE; - /* FIXME ... */ - p_playlist->request.i_view = VIEW_CATEGORY; - p_playlist->request.p_node = p_view->p_root; - p_playlist->request.p_item = p_item; - - if( p_playlist->p_input ) - { - input_StopThread( p_playlist->p_input ); - } - p_playlist->status.i_status = PLAYLIST_RUNNING; - } - - if( i_mode & PLAYLIST_PREPARSE && - var_CreateGetBool( p_playlist, "auto-preparse" ) ) - { - playlist_PreparseEnqueue( p_playlist, &p_item->input ); - } - - vlc_mutex_unlock( &p_playlist->object_lock ); - - if( b_end == VLC_FALSE ) - { - val.b_bool = VLC_TRUE; - var_Set( p_playlist, "intf-change", val ); - } - - free( p_add ); - - return p_item->input.i_id; -} - - -/** - * Add a playlist item to a given node (in the category view ) - * - * \param p_playlist the playlist to insert into - * \param p_item the playlist item to insert - * \param i_view the view for which to add or TODO: ALL_VIEWS - * \param p_parent the parent node - * \param i_mode the mode used when adding - * \param i_pos the possition in the node where to add. If this is - * PLAYLIST_END the item will be added at the end of the node - ** \return The id of the playlist item - */ -int playlist_NodeAddItem( playlist_t *p_playlist, playlist_item_t *p_item, - int i_view,playlist_item_t *p_parent, - int i_mode, int i_pos) -{ - vlc_value_t val; - int i_position; - playlist_view_t *p_view; - - playlist_add_t *p_add = (playlist_add_t *)malloc(sizeof( playlist_add_t)); - - vlc_mutex_lock( &p_playlist->object_lock ); - - if ( i_pos == PLAYLIST_END ) i_pos = -1; - - /* Sanity checks */ - if( !p_parent || p_parent->i_children == -1 ) - { - msg_Err( p_playlist, "invalid node" ); - } - - /* - * CHECK_INSERT : checks if the item is already enqued before - * enqueing it - */ - if ( i_mode & PLAYLIST_CHECK_INSERT ) - { - int j; - - if ( p_playlist->pp_items ) - { - for ( j = 0; j < p_playlist->i_size; j++ ) - { - if ( !strcmp( p_playlist->pp_items[j]->input.psz_uri, - p_item->input.psz_uri ) ) - { - playlist_ItemDelete( p_item ); - vlc_mutex_unlock( &p_playlist->object_lock ); - free( p_add ); - return -1; - } - } - } - i_mode &= ~PLAYLIST_CHECK_INSERT; - i_mode |= PLAYLIST_APPEND; - } - - msg_Dbg( p_playlist, "adding playlist item `%s' ( %s )", - p_item->input.psz_name, p_item->input.psz_uri ); - - p_item->input.i_id = ++p_playlist->i_last_id; - - /* First, add the item at the right position in the item bank */ - /* WHY THAT ? */ - //i_position = p_playlist->i_index == -1 ? 0 : p_playlist->i_index; - i_position = p_playlist->i_size ; - - INSERT_ELEM( p_playlist->pp_items, - p_playlist->i_size, - i_position, - p_item ); - INSERT_ELEM( p_playlist->pp_all_items, - p_playlist->i_all_size, - p_playlist->i_all_size, - p_item ); - p_playlist->i_enabled ++; - - /* TODO: Handle modes */ - playlist_NodeInsert( p_playlist, i_view, p_item, p_parent, i_pos ); - - p_add->i_item = p_item->input.i_id; - p_add->i_node = p_parent->input.i_id; - p_add->i_view = i_view; - val.p_address = p_add; - var_Set( p_playlist, "item-append", val ); - - /* We update the ALL view directly */ - p_view = playlist_ViewFind( p_playlist, VIEW_ALL ); - playlist_ItemAddParent( p_item, VIEW_ALL, p_view->p_root ); - playlist_ViewUpdate( p_playlist, VIEW_ALL ); - - /* TODO : Update sorted views*/ - - if( i_mode & PLAYLIST_GO ) - { - p_playlist->request.b_request = VLC_TRUE; - p_playlist->request.i_view = VIEW_CATEGORY; - p_playlist->request.p_node = p_parent; - p_playlist->request.p_item = p_item; - if( p_playlist->p_input ) - { - input_StopThread( p_playlist->p_input ); - } - p_playlist->status.i_status = PLAYLIST_RUNNING; - } - if( i_mode & PLAYLIST_PREPARSE && - var_CreateGetBool( p_playlist, "auto-preparse" ) ) - { - playlist_PreparseEnqueue( p_playlist, &p_item->input ); - } - - vlc_mutex_unlock( &p_playlist->object_lock ); - - val.b_bool = VLC_TRUE; -// var_Set( p_playlist, "intf-change", val ); -// - free( p_add ); - - return p_item->input.i_id; -} - -/*************************************************************************** - * Item search functions - ***************************************************************************/ - -/** - * Search the position of an item by its id - * This function must be entered with the playlist lock - * - * \param p_playlist the playlist - * \param i_id the id to find - * \return the position, or VLC_EGENERIC on failure - */ -int playlist_GetPositionById( playlist_t * p_playlist , int i_id ) -{ - int i; - for( i = 0 ; i < p_playlist->i_size ; i++ ) - { - if( p_playlist->pp_items[i]->input.i_id == i_id ) - { - return i; - } - } - return VLC_EGENERIC; -} - - -/** - * Search an item by its position - * This function must be entered with the playlist lock - * - * \param p_playlist the playlist - * \param i_pos the position of the item to find - * \return the item, or NULL on failure - */ -playlist_item_t * playlist_ItemGetByPos( playlist_t * p_playlist , int i_pos ) -{ - if( i_pos >= 0 && i_pos < p_playlist->i_size) - { - return p_playlist->pp_items[i_pos]; - } - else if( p_playlist->i_size > 0) - { - return p_playlist->pp_items[p_playlist->i_index]; - } - else - { - return NULL; - } -} - -playlist_item_t *playlist_LockItemGetByPos( playlist_t *p_playlist, int i_pos ) -{ - playlist_item_t *p_ret; - vlc_mutex_lock( &p_playlist->object_lock ); - p_ret = playlist_ItemGetByPos( p_playlist, i_pos ); - vlc_mutex_unlock( &p_playlist->object_lock ); - return p_ret; -} - -/** - * Search an item by its id - * - * \param p_playlist the playlist - * \param i_id the id to find - * \return the item, or NULL on failure - */ -playlist_item_t * playlist_ItemGetById( playlist_t * p_playlist , int i_id ) -{ - int i, i_top, i_bottom; - 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 != i_id && - i_top > i_bottom ) - { - if( p_playlist->pp_all_items[i]->input.i_id < 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 == i_id ) - { - return p_playlist->pp_all_items[i]; - } - return NULL; -} - -playlist_item_t *playlist_LockItemGetById( playlist_t *p_playlist, int i_id) -{ - playlist_item_t *p_ret; - vlc_mutex_lock( &p_playlist->object_lock ); - p_ret = playlist_ItemGetById( p_playlist, i_id ); - vlc_mutex_unlock( &p_playlist->object_lock ); - return p_ret; -} - -/** - * Search an item by its input_item_t - * - * \param p_playlist the playlist - * \param p_item the input_item_t to find - * \return the item, or NULL on failure - */ -playlist_item_t * playlist_ItemGetByInput( playlist_t * p_playlist , - input_item_t *p_item ) -{ - int i; - if( &p_playlist->status.p_item->input == p_item ) - { - return p_playlist->status.p_item; - } - - for( i = 0 ; i < p_playlist->i_size ; i++ ) - { - if( &p_playlist->pp_items[i]->input == p_item ) - { - return p_playlist->pp_items[i]; - } - } - return NULL; -} - -playlist_item_t *playlist_LockItemGetByInput( playlist_t *p_playlist, - input_item_t *p_item ) -{ - playlist_item_t *p_ret; - vlc_mutex_lock( &p_playlist->object_lock ); - p_ret = playlist_ItemGetByInput( p_playlist, p_item ); - vlc_mutex_unlock( &p_playlist->object_lock ); - return p_ret; -} - - -/*********************************************************************** - * Misc functions - ***********************************************************************/ - -/** - * Transform an item to a node - * - * This function must be entered without the playlist lock - * - * \param p_playlist the playlist object - * \param p_item the item to transform - * \return nothing - */ -int playlist_ItemToNode( playlist_t *p_playlist,playlist_item_t *p_item ) -{ - int i = 0; - if( p_item->i_children == -1 ) - { - p_item->i_children = 0; - } - - /* Remove it from the array of available items */ - for( i = 0 ; i < p_playlist->i_size ; i++ ) - { - if( p_item == p_playlist->pp_items[i] ) - { - REMOVE_ELEM( p_playlist->pp_items, p_playlist->i_size, i ); - } - } - var_SetInteger( p_playlist, "item-change", p_item->input.i_id ); - - return VLC_SUCCESS; -} - -int playlist_LockItemToNode( playlist_t *p_playlist, playlist_item_t *p_item ) -{ - int i_ret; - vlc_mutex_lock( &p_playlist->object_lock ); - i_ret = playlist_ItemToNode( p_playlist, p_item ); - vlc_mutex_unlock( &p_playlist->object_lock ); - return i_ret; -} - -/** - * Replaces an item with another one - * This function must be entered without the playlist lock - * - * \see playlist_Replace - */ -int playlist_LockReplace( playlist_t *p_playlist, - playlist_item_t *p_olditem, - input_item_t *p_new ) -{ - int i_ret; - vlc_mutex_lock( &p_playlist->object_lock ); - i_ret = playlist_Replace( p_playlist, p_olditem, p_new ); - vlc_mutex_unlock( &p_playlist->object_lock ); - return i_ret; -} - -/** - * Replaces an item with another one - * This function must be entered with the playlist lock: - * - * \param p_playlist the playlist - * \param p_olditem the item to replace - * \param p_new the new input_item - * \return VLC_SUCCESS or an error - */ -int playlist_Replace( playlist_t *p_playlist, playlist_item_t *p_olditem, - input_item_t *p_new ) -{ - int i; - int j; - - if( p_olditem->i_children != -1 ) - { - msg_Err( p_playlist, "playlist_Replace can only be used on leafs"); - return VLC_EGENERIC; - } - - p_olditem->i_nb_played = 0; - memcpy( &p_olditem->input, p_new, sizeof( input_item_t ) ); - - p_olditem->i_nb_played = 0; - - for( i = 0 ; i< p_olditem->i_parents ; i++ ) - { - playlist_item_t *p_parent = p_olditem->pp_parents[i]->p_parent; - - for( j = 0 ; j< p_parent->i_children ; i++ ) - { - if( p_parent->pp_children[j] == p_olditem ) - { - p_parent->i_serial++; - } - } - } - return VLC_SUCCESS; -} - -/** - * Deletes an item from a playlist. - * - * This function must be entered without the playlist lock - * - * \param p_playlist the playlist to remove from. - * \param i_id the identifier of the item to delete - * \return returns VLC_SUCCESS or an error - */ -int playlist_Delete( playlist_t * p_playlist, int i_id ) -{ - int i, i_top, i_bottom; - int i_pos; - vlc_bool_t b_flag = VLC_FALSE; - - playlist_item_t *p_item = playlist_ItemGetById( p_playlist, i_id ); - - if( p_item == NULL ) - { - return VLC_EGENERIC; - } - if( p_item->i_children > -1 ) - { - return playlist_NodeDelete( p_playlist, p_item, VLC_TRUE, VLC_FALSE ); - } - - var_SetInteger( p_playlist, "item-deleted", 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 != i_id && - i_top > i_bottom ) - { - if( p_playlist->pp_all_items[i]->input.i_id < 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 == i_id ) - { - REMOVE_ELEM( p_playlist->pp_all_items, p_playlist->i_all_size, i ); - } - - /* Check if it is the current item */ - if( p_playlist->status.p_item == p_item ) - { - /* Hack we don't call playlist_Control for lock reasons */ - p_playlist->status.i_status = PLAYLIST_STOPPED; - p_playlist->request.b_request = VLC_TRUE; - p_playlist->request.p_item = NULL; - msg_Info( p_playlist, "stopping playback" ); - b_flag = VLC_TRUE; - } - - /* Get position and update index if needed */ - i_pos = playlist_GetPositionById( p_playlist, i_id ); - - if( i_pos >= 0 && i_pos <= p_playlist->i_index ) - { - p_playlist->i_index--; - } - - msg_Dbg( p_playlist, "deleting playlist item `%s'", - p_item->input.psz_name ); - - /* Remove the item from all its parent nodes */ - for ( i= 0 ; i < p_item->i_parents ; i++ ) - { - playlist_NodeRemoveItem( p_playlist, p_item, - p_item->pp_parents[i]->p_parent ); - if( p_item->pp_parents[i]->i_view == VIEW_ALL ) - { - p_playlist->i_size--; - } - } - - /* TODO : Update views */ - - if( b_flag == VLC_FALSE ) - playlist_ItemDelete( p_item ); - else - p_item->i_flags |= PLAYLIST_REMOVE_FLAG; - - return VLC_SUCCESS; -} - -int playlist_LockDelete( playlist_t * p_playlist, int i_id ) -{ - int i_ret; - vlc_mutex_lock( &p_playlist->object_lock ); - i_ret = playlist_Delete( p_playlist, i_id ); - vlc_mutex_unlock( &p_playlist->object_lock ); - return i_ret; -} - -/** - * Clear all playlist items - * - * \param p_playlist the playlist to be cleared. - * \return returns 0 - */ -int playlist_Clear( playlist_t * p_playlist ) -{ - int i; - for( i = p_playlist->i_size; i > 0 ; i-- ) - { - playlist_Delete( p_playlist, p_playlist->pp_items[0]->input.i_id ); - } - for( i = 0 ; i< p_playlist->i_views; i++ ) - { - playlist_ViewEmpty( p_playlist, i, VLC_TRUE ); - } - return VLC_SUCCESS; -} - -int playlist_LockClear( playlist_t *p_playlist ) -{ - int i_ret; - vlc_mutex_lock( &p_playlist->object_lock ); - i_ret = playlist_Clear( p_playlist ); - vlc_mutex_unlock( &p_playlist->object_lock ); - return i_ret; -} - - -/** - * Disables a playlist item - * - * \param p_playlist the playlist to disable from. - * \param i_pos the position of the item to disable - * \return returns 0 - */ -int playlist_Disable( playlist_t * p_playlist, playlist_item_t *p_item ) -{ - if( !p_item ) return VLC_EGENERIC; - - msg_Dbg( p_playlist, "disabling playlist item `%s'", - p_item->input.psz_name ); - - if( p_item->i_flags & PLAYLIST_ENA_FLAG ) - { - p_playlist->i_enabled--; - } - p_item->i_flags &= ~PLAYLIST_ENA_FLAG; - - var_SetInteger( p_playlist, "item-change", p_item->input.i_id ); - return VLC_SUCCESS; -} - -/** - * Enables a playlist item - * - * \param p_playlist the playlist to enable from. - * \param i_pos the position of the item to enable - * \return returns 0 - */ -int playlist_Enable( playlist_t * p_playlist, playlist_item_t *p_item ) -{ - if( !p_item ) return VLC_EGENERIC; - - msg_Dbg( p_playlist, "enabling playlist item `%s'", - p_item->input.psz_name ); - - if( p_item->i_flags & ~PLAYLIST_ENA_FLAG ) - { - p_playlist->i_enabled++; - } - p_item->i_flags |= PLAYLIST_ENA_FLAG; - - var_SetInteger( p_playlist, "item-change", p_item->input.i_id ); - return VLC_SUCCESS; -} - -/** - * Move an item in a playlist - * - * This function must be entered without the playlist lock - * - * Move the item in the playlist with position i_pos before the current item - * at position i_newpos. - * \param p_playlist the playlist to move items in - * \param i_pos the position of the item to move - * \param i_newpos the position of the item that will be behind the moved item - * after the move - * \return returns VLC_SUCCESS - */ -int playlist_Move( playlist_t * p_playlist, int i_pos, int i_newpos ) -{ - vlc_value_t val; - vlc_mutex_lock( &p_playlist->object_lock ); - - /* take into account that our own row disappears. */ - if( i_pos < i_newpos ) i_newpos--; - - if( i_pos >= 0 && i_newpos >=0 && i_pos <= p_playlist->i_size && - i_newpos <= p_playlist->i_size ) - { - playlist_item_t * temp; - - msg_Dbg( p_playlist, "moving playlist item `%s' (%i -> %i)", - p_playlist->pp_items[i_pos]->input.psz_name, i_pos, i_newpos); - - if( i_pos == p_playlist->i_index ) - { - p_playlist->i_index = i_newpos; - } - else if( i_pos > p_playlist->i_index && - i_newpos <= p_playlist->i_index ) - { - p_playlist->i_index++; - } - else if( i_pos < p_playlist->i_index && - i_newpos >= p_playlist->i_index ) - { - p_playlist->i_index--; - } - - if ( i_pos < i_newpos ) - { - temp = p_playlist->pp_items[i_pos]; - while ( i_pos < i_newpos ) - { - p_playlist->pp_items[i_pos] = p_playlist->pp_items[i_pos+1]; - i_pos++; - } - p_playlist->pp_items[i_newpos] = temp; - } - else if ( i_pos > i_newpos ) - { - temp = p_playlist->pp_items[i_pos]; - while ( i_pos > i_newpos ) - { - p_playlist->pp_items[i_pos] = p_playlist->pp_items[i_pos-1]; - i_pos--; - } - p_playlist->pp_items[i_newpos] = temp; - } - } - - vlc_mutex_unlock( &p_playlist->object_lock ); - - val.b_bool = VLC_TRUE; - var_Set( p_playlist, "intf-change", val ); - - 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 - * \param i_view the view in which the move must be done or ALL_VIEWS - * \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_view ) -{ - int i; - playlist_item_t *p_detach = NULL; - struct item_parent_t *p_parent; - - if( p_node->i_children == -1 ) return VLC_EGENERIC; - - /* Detach from the parent */ - for( i = 0 ; i< p_item->i_parents; i++ ) - { - if( p_item->pp_parents[i]->i_view == i_view ) - { - int j; - p_detach = p_item->pp_parents[i]->p_parent; - 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 ); - p_detach->i_serial++; - free( p_item->pp_parents[i] ); - REMOVE_ELEM( p_item->pp_parents, p_item->i_parents, i ); - i--; - } - } - - /* Attach to new parent */ - INSERT_ELEM( p_node->pp_children, p_node->i_children, i_newpos, p_item ); - - p_parent = malloc( sizeof( struct item_parent_t ) ); - p_parent->p_parent = p_node; - p_parent->i_view = i_view; - - INSERT_ELEM( p_item->pp_parents, p_item->i_parents, p_item->i_parents, - p_parent ); - p_node->i_serial++; - p_item->i_serial++; - - return VLC_SUCCESS; -} diff --git a/src/playlist/item.c b/src/playlist/item.c index f58cac634f..f9fb51589a 100644 --- a/src/playlist/item.c +++ b/src/playlist/item.c @@ -1,10 +1,11 @@ /***************************************************************************** - * item.c : Playlist item functions + * item.c : Playlist item creation/deletion/add/removal functions ***************************************************************************** * Copyright (C) 1999-2004 the VideoLAN team * $Id$ * * Authors: Samuel Hocevar + * Clément Stenac * * 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 @@ -20,18 +21,22 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ -#include /* free(), strtol() */ -#include /* sprintf() */ -#include /* strerror() */ - #include #include -#include "vlc_input.h" #include "vlc_playlist.h" -static void GuessType( input_item_t *p_item); +void AddItem( playlist_t *p_playlist, playlist_item_t *p_item, + playlist_item_t *p_node, int i_pos ); +void GoAndPreparse( playlist_t *p_playlist, int i_mode, + playlist_item_t *p_item ); +void ChangeToNode( playlist_t *p_playlist, playlist_item_t *p_item ); +int DeleteInner( playlist_t * p_playlist, playlist_item_t *p_item, + vlc_bool_t b_stop ); +/***************************************************************************** + * Playlist item creation + *****************************************************************************/ /** * Create a new item, without adding it to the playlist * @@ -40,63 +45,56 @@ static void GuessType( input_item_t *p_item); * \param psz_name a text giving a name or description of the item * \return the new item or NULL on failure */ - playlist_item_t * __playlist_ItemNew( vlc_object_t *p_obj, const char *psz_uri, const char *psz_name ) { return playlist_ItemNewWithType( p_obj, psz_uri, - psz_name, ITEM_TYPE_UNKNOWN ); + psz_name, 0, NULL, -1, + ITEM_TYPE_UNKNOWN ); } playlist_item_t * playlist_ItemNewWithType( vlc_object_t *p_obj, const char *psz_uri, const char *psz_name, + int i_options, + const char **ppsz_options, + int i_duration, int i_type ) { - playlist_item_t * p_item; - - if( psz_uri == NULL) return NULL; + if( psz_uri == NULL ) return NULL; + input_item_t *p_input = input_ItemNewWithType( p_obj, psz_uri, + psz_name, i_options, ppsz_options, + i_duration, i_type ); + return playlist_ItemNewFromInput( p_obj, p_input ); +} +playlist_item_t *__playlist_ItemNewFromInput( vlc_object_t *p_obj, + input_item_t *p_input ) +{ + /** FIXME !!!!! don't find playlist each time */ + playlist_t *p_playlist = (playlist_t *)vlc_object_find( p_obj, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); + playlist_item_t * p_item; p_item = malloc( sizeof( playlist_item_t ) ); if( p_item == NULL ) return NULL; - memset( p_item, 0, sizeof( playlist_item_t ) ); - - vlc_input_item_Init( p_obj, &p_item->input ); - p_item->input.b_fixed_name = VLC_FALSE; - - p_item->input.psz_uri = strdup( psz_uri ); - - if( psz_name != NULL ) p_item->input.psz_name = strdup( psz_name ); - else p_item->input.psz_name = strdup ( psz_uri ); - - p_item->input.i_type = i_type; + p_item->p_input = p_input; + vlc_gc_incref( p_item->p_input ); - p_item->b_enabled = VLC_TRUE; - p_item->i_nb_played = 0; + 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->i_flags |= PLAYLIST_SKIP_FLAG; - p_item->i_flags |= PLAYLIST_SAVE_FLAG; - - p_item->input.i_duration = -1; - p_item->input.ppsz_options = NULL; - p_item->input.i_options = 0; - - vlc_mutex_init( p_obj, &p_item->input.lock ); - if( p_item->input.i_type == ITEM_TYPE_UNKNOWN ) - GuessType( &p_item->input ); + vlc_object_release( p_playlist ); return p_item; } /** - * Copy a playlist item + * Copy a playlist item - FIXME: Rewrite FIXME * * Creates a new item with name, mrl and meta infor like the * source. Does not copy children for node type items. @@ -110,24 +108,24 @@ playlist_item_t *__playlist_ItemCopy( vlc_object_t *p_obj, { playlist_item_t *p_res; int i; - vlc_mutex_lock( &p_item->input.lock ); + vlc_mutex_lock( &p_item->p_input->lock ); p_res = malloc( sizeof( playlist_item_t ) ); if( p_res == NULL ) { - vlc_mutex_unlock( &p_item->input.lock ); + vlc_mutex_unlock( &p_item->p_input->lock ); return NULL; } *p_res = *p_item; - vlc_mutex_init( p_obj, &p_res->input.lock ); + vlc_mutex_init( p_obj, &p_res->p_input->lock ); - if( p_item->input.i_options ) - p_res->input.ppsz_options = - malloc( p_item->input.i_options * sizeof(char*) ); - for( i = 0; i < p_item->input.i_options; i++ ) + if( p_item->p_input->i_options ) + p_res->p_input->ppsz_options = + malloc( p_item->p_input->i_options * sizeof(char*) ); + for( i = 0; i < p_item->p_input->i_options; i++ ) { - p_res->input.ppsz_options[i] = strdup( p_item->input.ppsz_options[i] ); + p_res->p_input->ppsz_options[i] = strdup( p_item->p_input->ppsz_options[i] ); } if( p_item->i_children != -1 ) @@ -136,228 +134,479 @@ playlist_item_t *__playlist_ItemCopy( vlc_object_t *p_obj, p_res->i_children = -1; p_res->pp_children = NULL; } - p_res->i_parents = 0; - p_res->pp_parents = NULL; - - if( p_item->input.psz_name ) - p_res->input.psz_name = strdup( p_item->input.psz_name ); - if( p_item->input.psz_uri ) - p_res->input.psz_uri = strdup( p_item->input.psz_uri ); - - if( p_item->input.i_es ) + p_res->p_parent = NULL; + + if( p_item->p_input->psz_name ) + p_res->p_input->psz_name = strdup( p_item->p_input->psz_name ); + if( p_item->p_input->psz_uri ) + p_res->p_input->psz_uri = strdup( p_item->p_input->psz_uri ); + + if( p_item->p_input->i_es ) { - p_res->input.es = - (es_format_t**)malloc( p_item->input.i_es * sizeof(es_format_t*)); - for( i = 0; i < p_item->input.i_es; i++ ) + p_res->p_input->es = + (es_format_t**)malloc( p_item->p_input->i_es * sizeof(es_format_t*)); + for( i = 0; i < p_item->p_input->i_es; i++ ) { - p_res->input.es[ i ] = (es_format_t*)malloc(sizeof(es_format_t*)); - es_format_Copy( p_res->input.es[ i ], - p_item->input.es[ i ] ); + p_res->p_input->es[ i ] = (es_format_t*)malloc(sizeof(es_format_t*)); + es_format_Copy( p_res->p_input->es[ i ], + p_item->p_input->es[ i ] ); } } - if( p_item->input.i_categories ) + if( p_item->p_input->i_categories ) { - p_res->input.pp_categories = NULL; - p_res->input.i_categories = 0; - for( i = 0; i < p_item->input.i_categories; i++ ) + p_res->p_input->pp_categories = NULL; + p_res->p_input->i_categories = 0; + for( i = 0; i < p_item->p_input->i_categories; i++ ) { info_category_t *p_incat; - p_incat = p_item->input.pp_categories[i]; + p_incat = p_item->p_input->pp_categories[i]; if( p_incat->i_infos ) { int j; for( j = 0; j < p_incat->i_infos; j++ ) { - vlc_input_item_AddInfo( &p_res->input, p_incat->psz_name, + vlc_input_item_AddInfo( p_res->p_input, p_incat->psz_name, p_incat->pp_infos[j]->psz_name, - "%s", /* to be safe */ + "%s", p_incat->pp_infos[j]->psz_value ); } } } } - vlc_mutex_unlock( &p_item->input.lock ); + vlc_mutex_unlock( &p_item->p_input->lock ); return p_res; } +/*************************************************************************** + * Playlist item destruction + ***************************************************************************/ + +/** Delete a playlist item and detach its input item */ +int playlist_ItemDelete( playlist_item_t *p_item ) +{ + vlc_gc_decref( p_item->p_input ); + free( p_item ); + return VLC_SUCCESS; +} + +/** Remove an input item from ONELEVEL and CATEGORY */ +int playlist_DeleteAllFromInput( playlist_t *p_playlist, int i_input_id ) +{ + playlist_DeleteFromInput( p_playlist, i_input_id, + p_playlist->p_root_category, VLC_TRUE ); + playlist_DeleteFromInput( p_playlist, i_input_id, + p_playlist->p_root_onelevel, VLC_TRUE ); + return VLC_SUCCESS; +} + +/** Remove an input item from ONELEVEL and CATEGORY. + * This function must be entered without the playlist lock */ +int playlist_LockDeleteAllFromInput( playlist_t * p_playlist, int i_id ) +{ + int i_ret; + vlc_mutex_lock( &p_playlist->object_lock ); + i_ret = playlist_DeleteAllFromInput( p_playlist, i_id ); + vlc_mutex_unlock( &p_playlist->object_lock ); + return i_ret; +} + +/** Remove an input item when it appears from a root playlist item */ +int playlist_DeleteFromInput( playlist_t *p_playlist, int i_input_id, + playlist_item_t *p_root, vlc_bool_t b_do_stop ) +{ + int i; + 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 ); + } + else if( p_root->pp_children[i]->i_children >= 0 ) + { + return playlist_DeleteFromInput( p_playlist, i_input_id, + p_root->pp_children[i], b_do_stop ); + } + } +} + +/** Remove a playlist item from the playlist, given its id */ +int playlist_DeleteFromItemId( playlist_t *p_playlist, int i_id ) +{ + playlist_item_t *p_item = playlist_ItemGetById( p_playlist, i_id ); + if( !p_item ) return VLC_EGENERIC; + return DeleteInner( p_playlist, p_item, VLC_TRUE ); +} + +/** Remove a playlist item from the playlist, given its id + * This function should be entered without the playlist lock */ +int playlist_LockDelete( playlist_t * p_playlist, int i_id ) +{ + int i_ret; + vlc_mutex_lock( &p_playlist->object_lock ); + i_ret = playlist_DeleteFromItemId( p_playlist, i_id ); + vlc_mutex_unlock( &p_playlist->object_lock ); + return i_ret; +} + +/** Clear the playlist */ +void playlist_Clear( playlist_t * p_playlist ) +{ + playlist_NodeEmpty( p_playlist, p_playlist->p_root_category, VLC_TRUE ); + playlist_NodeEmpty( p_playlist, p_playlist->p_root_onelevel, VLC_TRUE ); +} +/** Clear the playlist. This function must be entered without the lock */ +void playlist_LockClear( playlist_t *p_playlist ) +{ + vlc_mutex_lock( &p_playlist->object_lock ); + playlist_Clear( p_playlist ); + vlc_mutex_unlock( &p_playlist->object_lock ); +} + +/*************************************************************************** + * Playlist item addition + ***************************************************************************/ + /** - * Deletes a playlist item + * Add a MRL into the playlist. * - * \param p_item the item to delete - * \return nothing + * \param p_playlist the playlist to add into + * \param psz_uri the mrl to add to the playlist + * \param psz_name a text giving a name or description of this item + * \param i_mode the mode used when adding + * \param i_pos the position in the playlist where to add. If this is + * PLAYLIST_END the item will be added at the end of the playlist + * regardless of it's size + * \return The id of the playlist item */ -int playlist_ItemDelete( playlist_item_t *p_item ) +int playlist_PlaylistAdd( playlist_t *p_playlist, const char *psz_uri, + const char *psz_name, int i_mode, int i_pos ) { - vlc_mutex_lock( &p_item->input.lock ); + return playlist_PlaylistAddExt( p_playlist, psz_uri, psz_name, + i_mode, i_pos, -1, NULL, 0 ); +} - if( p_item->input.psz_name ) free( p_item->input.psz_name ); - if( p_item->input.psz_uri ) free( p_item->input.psz_uri ); +/** + * Add a MRL into the playlist, duration and options given + * + * \param p_playlist the playlist to add into + * \param psz_uri the mrl to add to the playlist + * \param psz_name a text giving a name or description of this item + * \param i_mode the mode used when adding + * \param i_pos the position in the playlist where to add. If this is + * PLAYLIST_END the item will be added at the end of the playlist + * regardless of it's size + * \param i_duration length of the item in milliseconds. + * \param ppsz_options an array of options + * \param i_options the number of options + * \return The id of the playlist item +*/ +int playlist_PlaylistAddExt( playlist_t *p_playlist, const char * psz_uri, + const char *psz_name, int i_mode, int i_pos, + mtime_t i_duration, const char **ppsz_options, + int i_options ) +{ + input_item_t *p_input = input_ItemNewExt( p_playlist, psz_uri, psz_name, + i_options, ppsz_options, + i_duration ); - /* Free the info categories */ - if( p_item->input.i_categories > 0 ) - { - int i, j; + return playlist_PlaylistAddInput( p_playlist, p_input, i_mode, i_pos ); +} - for( i = 0; i < p_item->input.i_categories; i++ ) - { - info_category_t *p_category = p_item->input.pp_categories[i]; +/** Add an input item to the playlist node */ +int playlist_PlaylistAddInput( playlist_t* p_playlist, input_item_t *p_input, + int i_mode, int i_pos ) +{ + playlist_item_t *p_item; + p_input->i_id = ++p_playlist->i_last_input_id; - for( j = 0; j < p_category->i_infos; j++) - { - if( p_category->pp_infos[j]->psz_name ) - { - free( p_category->pp_infos[j]->psz_name); - } - if( p_category->pp_infos[j]->psz_value ) - { - free( p_category->pp_infos[j]->psz_value ); - } - free( p_category->pp_infos[j] ); - } + msg_Dbg( p_playlist, "adding playlist item `%s' ( %s )", + p_input->psz_name, p_input->psz_uri ); - if( p_category->i_infos ) free( p_category->pp_infos ); - if( p_category->psz_name ) free( p_category->psz_name ); - free( p_category ); - } + vlc_mutex_lock( &p_playlist->object_lock ); - free( p_item->input.pp_categories ); - } + /* Add to ONELEVEL */ + p_item = playlist_ItemNewFromInput( p_playlist, p_input ); + if( p_item == NULL ) return VLC_EGENERIC; + AddItem( p_playlist, p_item,p_playlist->p_local_onelevel, i_pos ); + + /* Add to CATEGORY */ + p_item = playlist_ItemNewFromInput( p_playlist, p_input ); + if( p_item == NULL ) return VLC_EGENERIC; + AddItem( p_playlist, p_item, p_playlist->p_local_category, i_pos ); + + GoAndPreparse( p_playlist, i_mode, p_item ); - for( ; p_item->input.i_options > 0; p_item->input.i_options-- ) + vlc_mutex_unlock( &p_playlist->object_lock ); + return VLC_SUCCESS; +} + +/** Add an input item to p_direct_parent in the category tree, and to the + * matching top category in onelevel **/ +int playlist_BothAddInput( playlist_t *p_playlist, + input_item_t *p_input, + playlist_item_t *p_direct_parent, + int i_mode, int i_pos ) +{ + playlist_item_t *p_item, *p_up; + int i_top; + vlc_mutex_lock( & p_playlist->object_lock ); + + /* Add to category */ + p_item = playlist_ItemNewFromInput( p_playlist, p_input ); + if( p_item == NULL ) return VLC_EGENERIC; + fprintf( stderr, "Adding to CATEGORY\n"); + AddItem( p_playlist, p_item, p_direct_parent, i_pos ); + + /* Add to onelevel */ + p_item = playlist_ItemNewFromInput( p_playlist, p_input ); + if( p_item == NULL ) return VLC_EGENERIC; + fprintf( stderr, "Adding to ONE\n"); + + p_up = p_direct_parent; + while( p_up->p_parent != p_playlist->p_root_category ) { - free( p_item->input.ppsz_options[p_item->input.i_options - 1] ); - if( p_item->input.i_options == 1 ) free( p_item->input.ppsz_options ); + p_up = p_up->p_parent; } - - for( ; p_item->i_parents > 0 ; ) + for( i_top = 0 ; i_top < p_playlist->p_root_onelevel->i_children; i_top++ ) { - struct item_parent_t *p_parent = p_item->pp_parents[0]; - REMOVE_ELEM( p_item->pp_parents, p_item->i_parents, 0 ); - free( p_parent ); + if( p_playlist->p_root_onelevel->pp_children[i_top]->p_input->i_id == p_up->p_input->i_id ) + { + AddItem( p_playlist, p_item, + p_playlist->p_root_onelevel->pp_children[i_top], i_pos ); + break; + } } + GoAndPreparse( p_playlist, i_mode, p_item ); - vlc_mutex_unlock( &p_item->input.lock ); - vlc_mutex_destroy( &p_item->input.lock ); - - free( p_item ); - + vlc_mutex_unlock( &p_playlist->object_lock ); return VLC_SUCCESS; } /** - * Add a option to one item ( no need for p_playlist ) - * - * \param p_item the item on which we want the info - * \param psz_option the option - * \return 0 on success + * Add an item where it should be added, when adding from a node + * (ex: directory access, playlist demuxers, services discovery, ... ) + * \param p_playlist the playlist + * \param p_input the input to add + * \param p_parent the direct node + * \param p_item_in_category the item within category root (as returned by playlist_ItemToNode) + * \param b_forced_parent Are we forced to add only to p_parent ? */ -int playlist_ItemAddOption( playlist_item_t *p_item, const char *psz_option ) +void playlist_AddWhereverNeeded( playlist_t *p_playlist, input_item_t *p_input, + playlist_item_t *p_parent, + playlist_item_t *p_item_in_category, + vlc_bool_t b_forced_parent, int i_mode ) +{ + /* If we have forced a parent : + * - Just add the input to the forced parent (which should be p_parent) + * Else + * - If we have item in category, add to it, and to onelevel (bothadd) + * - If we don't, just add to p_parent + */ + if( b_forced_parent == VLC_TRUE || !p_item_in_category ) + { + playlist_NodeAddInput( p_playlist, p_input, p_parent, i_mode, + PLAYLIST_END ); + } + else + { + playlist_BothAddInput( p_playlist, p_input, p_item_in_category, + i_mode, PLAYLIST_END ); + } +} + + +/** Add an input item to a given node */ +playlist_item_t * playlist_NodeAddInput( playlist_t *p_playlist, + input_item_t *p_input, + playlist_item_t *p_parent, + int i_mode, int i_pos ) { - if( !psz_option ) return VLC_EGENERIC; + playlist_item_t *p_item; + + /* Sanity checks */ + if( !p_parent || p_parent->i_children == -1 ) + { + msg_Err( p_playlist, "invalid node" ); + } - vlc_mutex_lock( &p_item->input.lock ); - INSERT_ELEM( p_item->input.ppsz_options, p_item->input.i_options, - p_item->input.i_options, strdup( psz_option ) ); - vlc_mutex_unlock( &p_item->input.lock ); + vlc_mutex_lock( &p_playlist->object_lock ); - return VLC_SUCCESS; + p_item = playlist_ItemNewFromInput( p_playlist, p_input ); + if( p_item == NULL ) return NULL; + AddItem( p_playlist, p_item, p_parent, i_pos ); + + vlc_mutex_unlock( &p_playlist->object_lock ); + + return p_item; } -/** - * Add a parent to an item - * - * \param p_item the item - * \param i_view the view in which the parent is - * \param p_parent the parent to add - * \return nothing - */ -int playlist_ItemAddParent( playlist_item_t *p_item, int i_view, - playlist_item_t *p_parent ) +/** Add a playlist item to a given node */ +void playlist_NodeAddItem( playlist_t *p_playlist, playlist_item_t *p_item, + playlist_item_t *p_parent, int i_mode, int i_pos ) { - vlc_bool_t b_found = VLC_FALSE; - int i; - - 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 ); - } - return VLC_SUCCESS; + vlc_mutex_lock( &p_playlist->object_lock ); + AddItem( p_playlist, p_item, p_parent, i_pos ); + vlc_mutex_unlock( &p_playlist->object_lock ); } +/***************************************************************************** + * Playlist item misc operations + *****************************************************************************/ + /** - * Copy all parents from parent to child + * Transform an item to a node. Return the node in the category tree, or NULL + * if not found there + * This function must be entered without the playlist lock */ -int playlist_CopyParents( playlist_item_t *p_parent, - playlist_item_t *p_child ) +playlist_item_t *playlist_ItemToNode( playlist_t *p_playlist, + playlist_item_t *p_item ) { - int i=0; - for( i= 0 ; i< p_parent->i_parents; i ++ ) + /* What we do + * Find the input in CATEGORY. + * - If we find it + * - change it to node + * - we'll return it at the end + * - Delete the input from ONELEVEL + * - If we don't find it, just change to node (we are probably in VLM) + * and return NULL + * + * If we were in ONELEVEL, we thus retrieve the node in CATEGORY (will be + * useful for later BothAddInput ) + */ + + /** \todo First look if we don't already have it */ + playlist_item_t *p_item_in_category = playlist_ItemFindFromInputAndRoot( + p_playlist, p_item->p_input->i_id, + p_playlist->p_root_category ); + + if( p_item_in_category ) { - playlist_ItemAddParent( p_child, - p_parent->pp_parents[i]->i_view, - p_parent ); + ChangeToNode( p_playlist, p_item_in_category ); + playlist_DeleteFromInput( p_playlist, p_item->p_input->i_id, + p_playlist->p_root_onelevel, VLC_FALSE ); + var_SetInteger( p_playlist, "item-change", p_item->p_input->i_id ); + return p_item_in_category; + } + else + { + ChangeToNode( p_playlist, p_item ); + return NULL; } - return VLC_SUCCESS; } +/** Transform an item to a node + * This function must be entered without the playlist lock + * \see playlist_ItemToNode + */ +playlist_item_t * playlist_LockItemToNode( playlist_t *p_playlist, + playlist_item_t *p_item ) +{ + playlist_item_t *p_ret; + vlc_mutex_lock( &p_playlist->object_lock ); + p_ret = playlist_ItemToNode( p_playlist, p_item ); + vlc_mutex_unlock( &p_playlist->object_lock ); + return p_ret; +} -/********************************************************************** - * playlist_item_t structure accessors - * These functions give access to the fields of the playlist_item_t - * structure - **********************************************************************/ +/** Find an item within a root, given its input id. + * \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 ) +{ + int i; + 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 ) + { + 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] ); + if( p_search ) return p_search; + } + } + return NULL; +} /** - * Set the name of a playlist item + * Moves an item + * + * This function must be entered with the playlist lock * - * \param p_item the item - * \param psz_name the new name - * \return VLC_SUCCESS on success, VLC_EGENERIC on failure + * \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 j; + playlist_item_t *p_detach = NULL; + + if( p_node->i_children == -1 ) return VLC_EGENERIC; + + p_detach = p_item->p_parent; + 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 ); + + /* Attach to new parent */ + INSERT_ELEM( p_node->pp_children, p_node->i_children, i_newpos, p_item ); + + return VLC_SUCCESS; +} + +/** Send a notification that an item has been added to a node */ +void playlist_SendAddNotify( playlist_t *p_playlist, int i_item_id, + int i_node_id ) +{ + vlc_value_t val; + playlist_add_t *p_add = (playlist_add_t *)malloc(sizeof( playlist_add_t)); + p_add->i_item = i_item_id; + p_add->i_node = i_node_id; + val.p_address = p_add; + var_Set( p_playlist, "item-append", val ); + free( p_add ); +} + +/***************************************************************************** + * Playlist item accessors + *****************************************************************************/ + +/** Set the name of a playlist item */ int playlist_ItemSetName( playlist_item_t *p_item, char *psz_name ) { if( psz_name && p_item ) { - if( p_item->input.psz_name ) free( p_item->input.psz_name ); - p_item->input.psz_name = strdup( psz_name ); + if( p_item->p_input->psz_name ) free( p_item->p_input->psz_name ); + p_item->p_input->psz_name = strdup( psz_name ); return VLC_SUCCESS; } return VLC_EGENERIC; } -/** - * Set the duration of a playlist item - * This function must be entered with the item lock - * - * \param p_item the item - * \param i_duration the new duration - * \return VLC_SUCCESS on success, VLC_EGENERIC on failure +/** Set the duration of a playlist item + * \param i_duration the new duration in microseconds */ int playlist_ItemSetDuration( playlist_item_t *p_item, mtime_t i_duration ) { char psz_buffer[MSTRTIME_MAX_SIZE]; if( p_item ) { - p_item->input.i_duration = i_duration; + p_item->p_input->i_duration = i_duration; if( i_duration != -1 ) { secstotimestr( psz_buffer, (int)(i_duration/1000000) ); @@ -366,7 +615,7 @@ int playlist_ItemSetDuration( playlist_item_t *p_item, mtime_t i_duration ) { memcpy( psz_buffer, "--:--:--", sizeof("--:--:--") ); } - vlc_input_item_AddInfo( &p_item->input, _("General") , _("Duration"), + vlc_input_item_AddInfo( p_item->p_input, _("General") , _("Duration"), "%s", psz_buffer ); return VLC_SUCCESS; @@ -374,46 +623,152 @@ int playlist_ItemSetDuration( playlist_item_t *p_item, mtime_t i_duration ) return VLC_EGENERIC; } -/* - * Guess the type of the item using the beginning of the mrl */ -static void GuessType( input_item_t *p_item) +/** Add an option to a playlist item */ +void playlist_ItemAddOption( playlist_item_t *p_item, + const char *psz_option) { - int i; - static struct { char *psz_search; int i_type; } types_array[] = + vlc_input_item_AddOption( p_item->p_input, psz_option ); +} + +/*************************************************************************** + * The following functions are local + ***************************************************************************/ + +/* Enqueue an item for preparsing, and play it, if needed */ +void GoAndPreparse( playlist_t *p_playlist, int i_mode, + playlist_item_t *p_item ) +{ +#if 0 + if( (i_mode & PLAYLIST_GO ) && p_view ) { - { "http", ITEM_TYPE_NET }, - { "dvd", ITEM_TYPE_DISC }, - { "cdda", ITEM_TYPE_CDDA }, - { "mms", ITEM_TYPE_NET }, - { "rtsp", ITEM_TYPE_NET }, - { "udp", ITEM_TYPE_NET }, - { "rtp", ITEM_TYPE_NET }, - { "vcd", ITEM_TYPE_DISC }, - { "v4l", ITEM_TYPE_CARD }, - { "dshow", ITEM_TYPE_CARD }, - { "pvr", ITEM_TYPE_CARD }, - { "dvb", ITEM_TYPE_CARD }, - { "qpsk", ITEM_TYPE_CARD }, - { "sdp", ITEM_TYPE_NET }, - { NULL, 0 } - }; - -#if 0 /* Unused */ - static struct { char *psz_search; int i_type; } exts_array[] = + p_playlist->request.b_request = VLC_TRUE; + /* FIXME ... */ + p_playlist->request.i_view = VIEW_CATEGORY; + p_playlist->request.p_node = p_view->p_root; + p_playlist->request.p_item = p_item; + + if( p_playlist->p_input ) + { + input_StopThread( p_playlist->p_input ); + } + p_playlist->status.i_status = PLAYLIST_RUNNING; + } +#endif + if( i_mode & PLAYLIST_PREPARSE && + var_CreateGetBool( p_playlist, "auto-preparse" ) ) { - { "mp3", ITEM_TYPE_AFILE }, - { NULL, 0 } - }; + playlist_PreparseEnqueue( p_playlist, p_item->p_input ); + } +} + +/* Add the playlist item to the requested node and fire a notification */ +void AddItem( playlist_t *p_playlist, playlist_item_t *p_item, + playlist_item_t *p_node, int i_pos ) +{ + INSERT_ELEM( p_playlist->pp_items, p_playlist->i_size, + p_playlist->i_size, p_item ); +#if 0 + fprintf( stderr, "Adding input %s (id %i) - playlist item id %i " + "to node %s (id %i)\n", + p_item->p_input->psz_name, p_item->p_input->i_id, + p_item->i_id, p_node->p_input->psz_name, + p_node->i_id ); #endif + INSERT_ELEM( p_playlist->pp_all_items, p_playlist->i_all_size, + p_playlist->i_all_size, p_item ); + p_playlist->i_enabled ++; + + if( i_pos == PLAYLIST_END ) + { + playlist_NodeAppend( p_playlist, p_item, p_node ); + } + else + { + playlist_NodeInsert( p_playlist, p_item, p_node, i_pos ); + } + + playlist_SendAddNotify( p_playlist, p_item->i_id, p_node->i_id ); +} + +/* Actually convert an item to a node */ +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 */ + for( i = 0 ; i < p_playlist->i_size ; i++ ) + { + if( p_item == p_playlist->pp_items[i] ) + { + REMOVE_ELEM( p_playlist->pp_items, p_playlist->i_size, i ); + } + } +} + +/* Do the actual removal */ +int DeleteInner( playlist_t * p_playlist, playlist_item_t *p_item, + vlc_bool_t b_stop ) +{ + int i, i_top, i_bottom; + int i_id = p_item->i_id; + vlc_bool_t b_flag = VLC_FALSE; + + //fprintf( stderr, "Deleting item %i - %s\n", i_id, + // p_item->p_input->psz_name ); + + if( p_item->i_children > -1 ) + { + return playlist_NodeDelete( p_playlist, p_item, VLC_TRUE, VLC_FALSE ); + } + var_SetInteger( p_playlist, "item-deleted", i_id ); + + /* Remove the item from the bank */ + i_bottom = 0; i_top = p_playlist->i_all_size - 1; + i = i_top / 2; + while( p_playlist->pp_all_items[i]->i_id != i_id && + i_top > i_bottom ) + { + if( p_playlist->pp_all_items[i]->i_id < 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]->i_id == i_id ) + { + REMOVE_ELEM( p_playlist->pp_all_items, p_playlist->i_all_size, i ); + } - for( i = 0; types_array[i].psz_search != NULL; i++ ) + /* Check if it is the current item */ + if( p_playlist->status.p_item == p_item ) { - if( !strncmp( p_item->psz_uri, types_array[i].psz_search, - strlen( types_array[i].psz_search ) ) ) + /* Hack we don't call playlist_Control for lock reasons */ + if( b_stop ) { - p_item->i_type = types_array[i].i_type; - return; + p_playlist->status.i_status = PLAYLIST_STOPPED; + p_playlist->request.b_request = VLC_TRUE; + p_playlist->request.p_item = NULL; + msg_Info( p_playlist, "stopping playback" ); } + b_flag = VLC_TRUE; } - p_item->i_type = ITEM_TYPE_VFILE; + + msg_Dbg( p_playlist, "deleting playlist item `%s'", + p_item->p_input->psz_name ); + + /* Remove the item from its parent */ + playlist_NodeRemoveItem( p_playlist, p_item, p_item->p_parent ); + + if( b_flag == VLC_FALSE ) + playlist_ItemDelete( p_item ); + else + p_item->i_flags |= PLAYLIST_REMOVE_FLAG; + + return VLC_SUCCESS; } diff --git a/src/playlist/loadsave.c b/src/playlist/loadsave.c index 2fae7bdf8a..3d02454e7d 100644 --- a/src/playlist/loadsave.c +++ b/src/playlist/loadsave.c @@ -57,12 +57,11 @@ int playlist_Import( playlist_t * p_playlist, const char *psz_filename ) psz_uri = (char *)malloc(sizeof(char)*strlen(psz_filename) + 17 ); sprintf( psz_uri, "file/playlist://%s", psz_filename); - i_id = playlist_Add( p_playlist, psz_uri, psz_uri, + i_id = playlist_PlaylistAdd( p_playlist, psz_uri, psz_uri, PLAYLIST_INSERT , PLAYLIST_END); vlc_mutex_lock( &p_playlist->object_lock ); p_item = playlist_ItemGetById( p_playlist, i_id ); - p_item->b_autodeletion = VLC_TRUE; vlc_mutex_unlock( &p_playlist->object_lock ); playlist_Play(p_playlist); @@ -91,12 +90,11 @@ int playlist_Load( playlist_t * p_playlist, const char *psz_filename ) psz_uri = (char *)malloc(sizeof(char)*strlen(psz_filename) + 17 ); sprintf( psz_uri, "file/playlist://%s", psz_filename); - i_id = playlist_Add( p_playlist, psz_uri, psz_uri, + i_id = playlist_PlaylistAdd( p_playlist, psz_uri, psz_uri, PLAYLIST_INSERT , PLAYLIST_END); vlc_mutex_lock( &p_playlist->object_lock ); p_item = playlist_ItemGetById( p_playlist, i_id ); - p_item->b_autodeletion = VLC_TRUE; vlc_mutex_unlock( &p_playlist->object_lock ); playlist_Play(p_playlist); @@ -105,26 +103,30 @@ int playlist_Load( playlist_t * p_playlist, const char *psz_filename ) } /** - * Export a playlist to a certain type of playlistfile + * Export a node of the playlist to a certain type of playlistfile * * \param p_playlist the playlist to export * \param psz_filename the location where the exported file will be saved + * \param p_export_root the root node to export * \param psz_type the type of playlist file to create. * \return VLC_SUCCESS on success */ int playlist_Export( playlist_t * p_playlist, const char *psz_filename , - const char *psz_type) + playlist_item_t *p_export_root,const char *psz_type ) { module_t *p_module; playlist_export_t *p_export; - msg_Info( p_playlist, "saving playlist to file %s", psz_filename ); + if( p_export_root == NULL ) return VLC_EGENERIC; + + msg_Info( p_playlist, "saving %s to file %s", + p_export_root->p_input->psz_name, psz_filename ); /* Prepare the playlist_export_t structure */ p_export = (playlist_export_t *)malloc( sizeof(playlist_export_t) ); if( !p_export) { - msg_Err( p_playlist, "out of memory"); + msg_Err( p_playlist, "out of memory" ); return VLC_ENOMEM; } p_export->psz_filename = NULL; @@ -138,9 +140,11 @@ int playlist_Export( playlist_t * p_playlist, const char *psz_filename , return VLC_EGENERIC; } - p_playlist->p_private = (void *)p_export; + p_export->p_root = p_export_root; + /* Lock the playlist */ vlc_mutex_lock( &p_playlist->object_lock ); + p_playlist->p_private = (void *)p_export; /* And call the module ! All work is done now */ p_module = module_Need( p_playlist, "playlist export", psz_type, VLC_TRUE); diff --git a/src/playlist/playlist.c b/src/playlist/playlist.c deleted file mode 100644 index c3195f4071..0000000000 --- a/src/playlist/playlist.c +++ /dev/null @@ -1,1239 +0,0 @@ -/***************************************************************************** - * playlist.c : Playlist management functions - ***************************************************************************** - * Copyright (C) 1999-2004 the VideoLAN team - * $Id$ - * - * Authors: Samuel Hocevar - * Clément Stenac - * - * 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. - *****************************************************************************/ -#include /* free(), strtol() */ -#include /* sprintf() */ -#include /* strerror() */ - -#include -#include -#include -#include - -#include "vlc_playlist.h" - -#include "vlc_interaction.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 * ); - -int playlist_vaControl( playlist_t * p_playlist, int i_query, va_list args ); - -void playlist_PreparseEnqueueItemSub( playlist_t *, playlist_item_t * ); - -playlist_item_t *playlist_RecursiveFindLast(playlist_t *p_playlist, - playlist_item_t *p_node ); - -/***************************************************************************** - * Helper Function for NextItem - *****************************************************************************/ - -playlist_item_t *playlist_RecursiveFindLast(playlist_t *p_playlist, - playlist_item_t *p_node ) -{ - int i; - playlist_item_t *p_item; - for ( i = p_node->i_children - 1; i >= 0; i-- ) - { - if( p_node->pp_children[i]->i_children == -1 ) - return p_node->pp_children[i]; - else if(p_node->pp_children[i]->i_children > 0) - { - p_item = playlist_RecursiveFindLast( p_playlist, - p_node->pp_children[i] ); - if ( p_item != NULL ) - return p_item; - } - else if( i == 0 ) - return NULL; - } - return NULL; -} - - -/** - * 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; - - p_playlist->p_stats = (global_stats_t *)malloc( sizeof( global_stats_t ) ); - vlc_mutex_init( p_playlist, &p_playlist->p_stats->lock ); - - /* 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; - } - - // Preparse - p_playlist->p_preparse->i_waiting = 0; - p_playlist->p_preparse->pi_waiting = NULL; - - // Interaction - p_playlist->p_interaction = 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 ); - } - - if( p_playlist->p_interaction ) - { - intf_InteractionDestroy( p_playlist->p_interaction ); - } - - 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 ); - } - - if( p_playlist->p_stats ) - free( p_playlist->p_stats ); - - 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; - p_playlist->request.p_item = NULL; - 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; - - /* Don't go further if the node doesn't want to */ - if( ! 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 ) - { - val.i_int = PLAYING_S; - var_Set( p_playlist->p_input, "state", val ); - break; - } - - /* FIXME : needed ? */ - p_playlist->request.b_request = VLC_TRUE; - p_playlist->request.i_view = p_playlist->status.i_view; - p_playlist->request.p_node = p_playlist->status.p_node; - p_playlist->request.p_item = p_playlist->status.p_item; - p_playlist->request.i_skip = 0; - p_playlist->request.i_goto = -1; - break; - - case PLAYLIST_AUTOPLAY: - p_playlist->status.i_status = PLAYLIST_RUNNING; - p_playlist->status.p_node = p_playlist->p_general; - - p_playlist->request.b_request = VLC_FALSE; - break; - - case PLAYLIST_PAUSE: - val.i_int = 0; - if( p_playlist->p_input ) - var_Get( p_playlist->p_input, "state", &val ); - - if( val.i_int == PAUSE_S ) - { - p_playlist->status.i_status = PLAYLIST_RUNNING; - if( p_playlist->p_input ) - { - val.i_int = PLAYING_S; - var_Set( p_playlist->p_input, "state", val ); - } - } - else - { - p_playlist->status.i_status = PLAYLIST_PAUSED; - if( p_playlist->p_input ) - { - val.i_int = PAUSE_S; - var_Set( p_playlist->p_input, "state", val ); - } - } - break; - - case PLAYLIST_SKIP: - p_playlist->request.i_view = p_playlist->status.i_view; - if( p_playlist->status.i_view > -1 ) - { - p_playlist->request.p_node = p_playlist->status.p_node; - p_playlist->request.p_item = p_playlist->status.p_item; - } - else - { - p_playlist->request.p_node = NULL; - p_playlist->request.p_item = NULL; - } - p_playlist->request.i_skip = (int) va_arg( args, int ); - p_playlist->request.b_request = VLC_TRUE; - break; - - case PLAYLIST_GOTO: - p_playlist->status.i_status = PLAYLIST_RUNNING; - p_playlist->request.p_node = NULL; - p_playlist->request.p_item = NULL; - p_playlist->request.i_view = -1; - p_playlist->request.i_goto = (int) va_arg( args, int ); - p_playlist->request.b_request = VLC_TRUE; - break; - - default: - msg_Err( p_playlist, "unknown playlist query" ); - return VLC_EBADVAR; - break; - } - - return VLC_SUCCESS; -} - -int playlist_PreparseEnqueue( playlist_t *p_playlist, - input_item_t *p_item ) -{ - vlc_mutex_lock( &p_playlist->p_preparse->object_lock ); - INSERT_ELEM( p_playlist->p_preparse->pi_waiting, - p_playlist->p_preparse->i_waiting, - p_playlist->p_preparse->i_waiting, - p_item->i_id ); - vlc_mutex_unlock( &p_playlist->p_preparse->object_lock ); - return VLC_SUCCESS; -} - -/* Should only be called if playlist and preparser are locked */ -void playlist_PreparseEnqueueItemSub( playlist_t *p_playlist, - playlist_item_t *p_item ) -{ - int i; - if( p_item->i_children == -1 ) - { - INSERT_ELEM( p_playlist->p_preparse->pi_waiting, - p_playlist->p_preparse->i_waiting, - p_playlist->p_preparse->i_waiting, - (p_item->input.i_id) ); - } - else - { - for( i = 0; i < p_item->i_children; i++) - { - playlist_PreparseEnqueueItemSub( p_playlist, - p_item->pp_children[i] ); - } - } -} - -int playlist_PreparseEnqueueItem( playlist_t *p_playlist, - playlist_item_t *p_item ) -{ - vlc_mutex_lock( &p_playlist->object_lock ); - vlc_mutex_lock( &p_playlist->p_preparse->object_lock ); - playlist_PreparseEnqueueItemSub( p_playlist, p_item ); - vlc_mutex_unlock( &p_playlist->p_preparse->object_lock ); - vlc_mutex_unlock( &p_playlist->object_lock ); - return VLC_SUCCESS; -} - - -/* Destroy remaining objects */ -static mtime_t ObjectGarbageCollector( playlist_t *p_playlist, int i_type, - mtime_t destroy_date ) -{ - vlc_object_t *p_obj; - - if( destroy_date > mdate() ) return destroy_date; - - if( destroy_date == 0 ) - { - /* give a little time */ - return mdate() + I64C(1000000); - } - else - { - vlc_mutex_lock( &p_playlist->gc_lock ); - while( ( p_obj = vlc_object_find( p_playlist, i_type, FIND_CHILD ) ) ) - { - if( p_obj->p_parent != (vlc_object_t*)p_playlist ) - { - /* only first child (ie unused) */ - vlc_object_release( p_obj ); - break; - } - if( i_type == VLC_OBJECT_VOUT ) - { - msg_Dbg( p_playlist, "garbage collector destroys 1 vout" ); - vlc_object_detach( p_obj ); - vlc_object_release( p_obj ); - vout_Destroy( (vout_thread_t *)p_obj ); - } - else if( i_type == VLC_OBJECT_SOUT ) - { - vlc_object_release( p_obj ); - sout_DeleteInstance( (sout_instance_t*)p_obj ); - } - } - vlc_mutex_unlock( &p_playlist->gc_lock ); - return 0; - } -} - -/***************************************************************************** - * RunThread: main playlist thread - *****************************************************************************/ -static void RunThread ( playlist_t *p_playlist ) -{ - vlc_object_t *p_obj; - playlist_item_t *p_item = NULL; - - mtime_t i_vout_destroyed_date = 0; - mtime_t i_sout_destroyed_date = 0; - - int i_loops = 0; - - playlist_item_t *p_autodelete_item = NULL; - - /* Tell above that we're ready */ - vlc_thread_ready( p_playlist ); - - while( !p_playlist->b_die ) - { - i_loops++; - if( p_playlist->p_interaction ) - { - stats_TimerStart( p_playlist, "Interaction thread", - STATS_TIMER_INTERACTION ); - intf_InteractionManage( p_playlist ); - stats_TimerStop( p_playlist, STATS_TIMER_INTERACTION ); - } - - if( i_loops %5 == 0 && p_playlist->p_stats ) - { - stats_ComputeGlobalStats( p_playlist, p_playlist->p_stats ); - } - - vlc_mutex_lock( &p_playlist->object_lock ); - - /* First, check if we have something to do */ - /* FIXME : this can be called several times */ - if( p_playlist->request.b_request ) - { -#ifdef PLAYLIST_PROFILE - msg_Dbg(p_playlist, "beginning processing of request, " - I64Fi" us ", mdate() - p_playlist->request_date ); -#endif - /* Stop the existing input */ - if( p_playlist->p_input ) - { - input_StopThread( p_playlist->p_input ); - } - /* The code below will start the next input for us */ - if( p_playlist->status.i_status == PLAYLIST_STOPPED ) - { - p_playlist->request.b_request = VLC_FALSE; - } - } - - /* If there is an input, check that it doesn't need to die. */ - if( p_playlist->p_input ) - { - if( i_loops % 5 == 0 ) - { - stats_ComputeInputStats( p_playlist->p_input, - p_playlist->p_input->input.p_item->p_stats ); -// stats_DumpInputStats( -// p_playlist->p_input->input.p_item->p_stats ); - } - - /* This input is dead. Remove it ! */ - if( p_playlist->p_input->b_dead ) - { - input_thread_t *p_input; - - p_input = p_playlist->p_input; - p_playlist->p_input = NULL; - - /* Release the playlist lock, because we may get stuck - * in input_DestroyThread() for some time. */ - vlc_mutex_unlock( &p_playlist->object_lock ); - - /* Destroy input */ - input_DestroyThread( p_input ); - - /* Unlink current input - * (_after_ input_DestroyThread for vout garbage collector) */ - vlc_object_detach( p_input ); - - /* Destroy object */ - vlc_object_destroy( p_input ); - - i_vout_destroyed_date = 0; - i_sout_destroyed_date = 0; - - if( p_playlist->status.p_item->i_flags - & PLAYLIST_REMOVE_FLAG ) - { - playlist_ItemDelete( p_item ); - p_playlist->status.p_item = NULL; - } - - continue; - } - /* This input is dying, let it do */ - else if( p_playlist->p_input->b_die ) - { - ; - } - /* This input has finished, ask it to die ! */ - else if( p_playlist->p_input->b_error - || p_playlist->p_input->b_eof ) - { - /* TODO FIXME XXX TODO FIXME XXX */ - /* Check for autodeletion */ - - if( p_playlist->status.p_item->i_flags & PLAYLIST_DEL_FLAG ) - { - p_autodelete_item = p_playlist->status.p_item; - } - input_StopThread( p_playlist->p_input ); - /* Select the next playlist item */ - vlc_mutex_unlock( &p_playlist->object_lock ); - continue; - } - else if( p_playlist->p_input->i_state != INIT_S ) - { - vlc_mutex_unlock( &p_playlist->object_lock ); - i_vout_destroyed_date = - ObjectGarbageCollector( p_playlist, VLC_OBJECT_VOUT, - i_vout_destroyed_date ); - i_sout_destroyed_date = - ObjectGarbageCollector( p_playlist, VLC_OBJECT_SOUT, - i_sout_destroyed_date ); - vlc_mutex_lock( &p_playlist->object_lock ); - } - } - else if( p_playlist->status.i_status != PLAYLIST_STOPPED ) - { - /* Start another input. - * Get the next item to play */ - stats_TimerStart( p_playlist, "Playlist walk", - STATS_TIMER_PLAYLIST_WALK ); - p_item = NextItem( p_playlist ); - stats_TimerStop( p_playlist, STATS_TIMER_PLAYLIST_WALK ); - - /* We must stop */ - if( p_item == NULL ) - { - if( p_autodelete_item ) - { - playlist_Delete( p_playlist, - p_autodelete_item->input.i_id ); - p_autodelete_item = NULL; - } - p_playlist->status.i_status = PLAYLIST_STOPPED; - vlc_mutex_unlock( &p_playlist->object_lock ); - continue; - } - - PlayItem( p_playlist, p_item ); - - if( p_autodelete_item ) - { - playlist_Delete( p_playlist, p_autodelete_item->input.i_id ); - p_autodelete_item = NULL; - } - } - else if( p_playlist->status.i_status == PLAYLIST_STOPPED ) - { - if( p_item && p_playlist->status.p_item && - p_playlist->status.p_item->i_flags & PLAYLIST_REMOVE_FLAG ) - { - playlist_ItemDelete( p_item ); - p_playlist->status.p_item = NULL; - } - - /* Collect garbage */ - vlc_mutex_unlock( &p_playlist->object_lock ); - i_sout_destroyed_date = - ObjectGarbageCollector( p_playlist, VLC_OBJECT_SOUT, mdate() ); - i_vout_destroyed_date = - ObjectGarbageCollector( p_playlist, VLC_OBJECT_VOUT, mdate() ); - vlc_mutex_lock( &p_playlist->object_lock ); - } - vlc_mutex_unlock( &p_playlist->object_lock ); - - msleep( INTF_IDLE_SLEEP / 2 ); - - /* Stop sleeping earlier if we have work */ - /* TODO : statistics about this */ - if ( p_playlist->request.b_request && - p_playlist->status.i_status == PLAYLIST_RUNNING ) - { - continue; - } - - msleep( INTF_IDLE_SLEEP / 2 ); - } - - /* Playlist dying */ - - /* If there is an input, kill it */ - while( 1 ) - { - vlc_mutex_lock( &p_playlist->object_lock ); - - if( p_playlist->p_input == NULL ) - { - vlc_mutex_unlock( &p_playlist->object_lock ); - break; - } - - if( p_playlist->p_input->b_dead ) - { - input_thread_t *p_input; - - /* Unlink current input */ - p_input = p_playlist->p_input; - p_playlist->p_input = NULL; - vlc_mutex_unlock( &p_playlist->object_lock ); - - /* Destroy input */ - input_DestroyThread( p_input ); - /* Unlink current input (_after_ input_DestroyThread for vout - * garbage collector)*/ - vlc_object_detach( p_input ); - - /* Destroy object */ - vlc_object_destroy( p_input ); - continue; - } - else if( p_playlist->p_input->b_die ) - { - /* This input is dying, leave it alone */ - ; - } - else if( p_playlist->p_input->b_error || p_playlist->p_input->b_eof ) - { - input_StopThread( p_playlist->p_input ); - vlc_mutex_unlock( &p_playlist->object_lock ); - continue; - } - else - { - p_playlist->p_input->b_eof = 1; - } - - vlc_mutex_unlock( &p_playlist->object_lock ); - - msleep( INTF_IDLE_SLEEP ); - } - - /* close all remaining sout */ - while( ( p_obj = vlc_object_find( p_playlist, - VLC_OBJECT_SOUT, FIND_CHILD ) ) ) - { - vlc_object_release( p_obj ); - sout_DeleteInstance( (sout_instance_t*)p_obj ); - } - - /* close all remaining vout */ - while( ( p_obj = vlc_object_find( p_playlist, - VLC_OBJECT_VOUT, FIND_CHILD ) ) ) - { - vlc_object_detach( p_obj ); - vlc_object_release( p_obj ); - vout_Destroy( (vout_thread_t *)p_obj ); - } -} - -/* Queue for items to preparse */ -static void RunPreparse ( playlist_preparse_t *p_obj ) -{ - playlist_t *p_playlist = (playlist_t *)p_obj->p_parent; - vlc_bool_t b_sleep; - - /* Tell above that we're ready */ - vlc_thread_ready( p_obj ); - - while( !p_playlist->b_die ) - { - vlc_mutex_lock( &p_obj->object_lock ); - - if( p_obj->i_waiting > 0 ) - { - int i_current_id = p_obj->pi_waiting[0]; - playlist_item_t *p_current; - REMOVE_ELEM( p_obj->pi_waiting, p_obj->i_waiting, 0 ); - vlc_mutex_unlock( &p_obj->object_lock ); - vlc_mutex_lock( &p_playlist->object_lock ); - - p_current = playlist_ItemGetById( p_playlist, i_current_id ); - if( p_current ) - { - vlc_bool_t b_preparsed = VLC_FALSE; - if( strncmp( p_current->input.psz_uri, "http:", 5 ) && - strncmp( p_current->input.psz_uri, "rtsp:", 5 ) && - strncmp( p_current->input.psz_uri, "udp:", 4 ) && - strncmp( p_current->input.psz_uri, "mms:", 4 ) && - strncmp( p_current->input.psz_uri, "cdda:", 4 ) && - strncmp( p_current->input.psz_uri, "dvd:", 4 ) && - strncmp( p_current->input.psz_uri, "v4l:", 4 ) && - strncmp( p_current->input.psz_uri, "dshow:", 6 ) ) - { - b_preparsed = VLC_TRUE; - stats_TimerStart( p_playlist, "Preparse run", - STATS_TIMER_PREPARSE ); - input_Preparse( p_playlist, &p_current->input ); - stats_TimerStop( p_playlist, STATS_TIMER_PREPARSE ); - } - vlc_mutex_unlock( &p_playlist->object_lock ); - if( b_preparsed ) - { - var_SetInteger( p_playlist, "item-change", - p_current->input.i_id ); - } - } - else - vlc_mutex_unlock( &p_playlist->object_lock ); - vlc_mutex_lock( &p_obj->object_lock ); - } - b_sleep = ( p_obj->i_waiting == 0 ); - - vlc_mutex_unlock( &p_obj->object_lock ); - - if( p_obj->i_waiting == 0 ) - { - msleep( INTF_IDLE_SLEEP ); - } - } -} - -/***************************************************************************** - * NextItem - ***************************************************************************** - * This function calculates the next playlist item, depending - * on the playlist course mode (forward, backward, random, view,...). - *****************************************************************************/ -static playlist_item_t * NextItem( playlist_t *p_playlist ) -{ - playlist_item_t *p_new = NULL; - int i_skip,i_goto,i, i_new, i_count ; - playlist_view_t *p_view; - - vlc_bool_t b_loop = var_GetBool( p_playlist, "loop" ); - vlc_bool_t b_random = var_GetBool( p_playlist, "random" ); - vlc_bool_t b_repeat = var_GetBool( p_playlist, "repeat" ); - vlc_bool_t b_playstop = var_GetBool( p_playlist, "play-and-stop" ); - -#ifdef PLAYLIST_PROFILE - /* Calculate time needed */ - int64_t start = mdate(); -#endif - /* Handle quickly a few special cases */ - - /* No items to play */ - if( p_playlist->i_size == 0 ) - { - msg_Info( p_playlist, "playlist is empty" ); - return NULL; - } - /* Nothing requested */ - if( !p_playlist->request.b_request && p_playlist->status.p_item == NULL ) - { - msg_Dbg( p_playlist,"nothing requested, starting" ); - } - - /* Repeat and play/stop */ - if( !p_playlist->request.b_request && b_repeat == VLC_TRUE && - p_playlist->status.p_item ) - { - msg_Dbg( p_playlist,"repeating item" ); - return p_playlist->status.p_item; - } - - if( !p_playlist->request.b_request && b_playstop == VLC_TRUE ) - { - msg_Dbg( p_playlist,"stopping (play and stop)"); - return NULL; - } - - if( !p_playlist->request.b_request && p_playlist->status.p_item && - !( p_playlist->status.p_item->i_flags & PLAYLIST_SKIP_FLAG ) ) - { - msg_Dbg( p_playlist, "no-skip mode, stopping") ; - return NULL; - } - - /* TODO: improve this (only use current node) */ - /* TODO: use the "shuffled view" internally ? */ - /* Random case. This is an exception: if request, but request is skip +- 1 - * we don't go to next item but select a new random one. */ - if( b_random && - ( !p_playlist->request.b_request || - ( p_playlist->request.b_request && ( p_playlist->request.p_item == NULL || - p_playlist->request.i_skip == 1 || p_playlist->request.i_skip == -1 ) ) ) ) - { - /* how many items to choose from ? */ - i_count = 0; - for ( i = 0; i < p_playlist->i_size; i++ ) - { - if ( p_playlist->pp_items[i]->i_nb_played == 0 ) - i_count++; - } - /* Nothing left? */ - if ( i_count == 0 ) - { - /* Don't loop? Exit! */ - if( !b_loop ) - return NULL; - /* Otherwise reset the counter */ - for ( i = 0; i < p_playlist->i_size; i++ ) - { - p_playlist->pp_items[i]->i_nb_played = 0; - } - i_count = p_playlist->i_size; - } - srand( (unsigned int)mdate() ); - i = rand() % i_count + 1 ; - /* loop thru the list and count down the unplayed items to the selected one */ - for ( i_new = 0; i_new < p_playlist->i_size && i > 0; i_new++ ) - { - if ( p_playlist->pp_items[i_new]->i_nb_played == 0 ) - i--; - } - i_new--; - - p_playlist->request.i_skip = 0; - p_playlist->request.b_request = VLC_FALSE; - return p_playlist->pp_items[i_new]; - } - - /* Start the real work */ - if( p_playlist->request.b_request ) - { -#ifdef PLAYLIST_DEBUG - msg_Dbg( p_playlist,"processing request" ); -#endif - /* We are not playing from a view */ - if( p_playlist->request.i_view == -1 ) - { -#ifdef PLAYLIST_DEBUG - msg_Dbg( p_playlist, "non-view mode request"); -#endif - /* Directly select the item, just like now */ - p_new = p_playlist->request.p_item; - i_skip = p_playlist->request.i_skip; - i_goto = p_playlist->request.i_goto; - - if( p_playlist->i_index < 0 ) p_playlist->i_index = 0; - if ( p_new == NULL ) - p_new = p_playlist->pp_items[p_playlist->i_index]; - - if( i_goto >= 0 && i_goto < p_playlist->i_size ) - { - p_playlist->i_index = i_goto; - p_new = p_playlist->pp_items[p_playlist->i_index]; - p_playlist->request.i_goto = -1; - } - - if( i_skip != 0 ) - { - if( p_playlist->i_index + i_skip < p_playlist->i_size && - p_playlist->i_index + i_skip >= 0 ) - { - p_playlist->i_index += i_skip; - p_new = p_playlist->pp_items[p_playlist->i_index]; - } - p_playlist->request.i_skip = 0; - } - if( !( p_new->i_flags & PLAYLIST_SKIP_FLAG ) ) - { - return NULL; - } - } - else - { -#ifdef PLAYLIST_DEBUG - msg_Dbg( p_playlist, "view mode request" ); -#endif - p_new = p_playlist->request.p_item; - i_skip = p_playlist->request.i_skip; - - /* If we are asked for a node, take its first item */ - if( p_playlist->request.p_item == NULL && i_skip == 0 ) - { - i_skip++; - } - - p_view = playlist_ViewFind( p_playlist,p_playlist->request.i_view ); - p_playlist->status.p_node = p_playlist->request.p_node; - p_playlist->status.i_view = p_playlist->request.i_view; - if( !p_view ) - { - msg_Err( p_playlist, "p_view is NULL and should not! (requested view is %i", p_playlist->request.i_view ); - } - else if( i_skip > 0 ) - { - for( i = i_skip; i > 0 ; i-- ) - { - p_new = playlist_FindNextFromParent( p_playlist, - p_playlist->request.i_view, - p_view->p_root, - p_playlist->request.p_node, - p_new ); - if( p_new == NULL ) - { -#ifdef PLAYLIST_DEBUG - msg_Dbg( p_playlist, "looping" ); -#endif - p_new = playlist_FindNextFromParent( p_playlist, - p_playlist->request.i_view, - p_view->p_root, - p_view->p_root, - NULL ); - if( p_new == NULL ) break; - } - } - } - else if( i_skip < 0 ) - { - for( i = i_skip; i < 0 ; i++ ) - { - p_new = playlist_FindPrevFromParent( p_playlist, - p_playlist->request.i_view, - p_view->p_root, - p_playlist->request.p_node, - p_new ); - if( p_new == NULL ) - { - /* We reach the beginning of the playlist. - Go back to the last item. */ - p_new = playlist_RecursiveFindLast( p_playlist, - p_view->p_root ); - } - if( p_new == NULL ) break; - } - - } - } - /* Clear the request */ - p_playlist->request.b_request = VLC_FALSE; - } - /* "Automatic" item change ( next ) */ - else - { - p_playlist->request_date = 0; - - if( p_playlist->status.i_view == -1 ) - { -#ifdef PLAYLIST_DEBUG - msg_Dbg( p_playlist, "no request - old mode" ); -#endif - if( p_playlist->i_index + 1 < p_playlist->i_size ) - { - p_playlist->i_index++; - p_new = p_playlist->pp_items[p_playlist->i_index]; - if( !( p_new->i_flags & PLAYLIST_SKIP_FLAG ) ) - { - return NULL; - } - } - else - { - if( b_loop && p_playlist->i_size > 0) - { - p_playlist->i_index = 0; - p_new = p_playlist->pp_items[0]; - } - else - p_new = NULL; - } - } - /* We are playing with a view */ - else - { -#ifdef PLAYLIST_DEBUG - msg_Dbg( p_playlist,"no request - from a view" ); -#endif - playlist_view_t *p_view = - playlist_ViewFind( p_playlist, - p_playlist->status.i_view ); - if( !p_view ) - { - msg_Err( p_playlist, "p_view is NULL and should not! (FIXME)" ); - } - else - { - p_new = playlist_FindNextFromParent( p_playlist, - p_playlist->status.i_view, - p_view->p_root, - p_playlist->status.p_node, - p_playlist->status.p_item ); - if( p_new == NULL && b_loop ) - { -#ifdef PLAYLIST_DEBUG - msg_Dbg( p_playlist, "looping" ); -#endif - p_new = playlist_FindNextFromParent( p_playlist, - p_playlist->status.i_view, - p_view->p_root, - p_view->p_root, - NULL ); - } - if( p_new != NULL && !(p_new->i_flags & PLAYLIST_SKIP_FLAG) ) - return NULL; - } - } - } - - /* Reset index */ - if( p_playlist->i_index >= 0 && p_new != NULL && - p_playlist->pp_items[p_playlist->i_index] != p_new ) - { - p_playlist->i_index = playlist_GetPositionById( p_playlist, - p_new->input.i_id ); - } - -#ifdef PLAYLIST_PROFILE - msg_Dbg(p_playlist,"next item found in "I64Fi " us", mdate()-start ); -#endif - - if( p_new == NULL ) - { - msg_Info( p_playlist, "nothing to play" ); - } - - return p_new; -} - -/***************************************************************************** - * PlayItem: start the input thread for an item - ****************************************************************************/ -static int PlayItem( playlist_t *p_playlist, playlist_item_t *p_item ) -{ - vlc_value_t val; - - msg_Dbg( p_playlist, "creating new input thread" ); - - p_item->i_nb_played++; - p_playlist->status.p_item = p_item; - - p_playlist->i_index = playlist_GetPositionById( p_playlist, - p_item->input.i_id ); - -#ifdef PLAYLIST_PROFILE - if( p_playlist->request_date != 0 ) - { - msg_Dbg( p_playlist, "request processed after "I64Fi " us", - mdate() - p_playlist->request_date ); - } -#endif - - p_playlist->p_input = input_CreateThread( p_playlist, &p_item->input ); - - val.i_int = p_item->input.i_id; - /* unlock the playlist to set the var...mmm */ - vlc_mutex_unlock( &p_playlist->object_lock); - var_Set( p_playlist, "playlist-current", val); - vlc_mutex_lock( &p_playlist->object_lock); - - return VLC_SUCCESS; - -} diff --git a/src/playlist/search.c b/src/playlist/search.c new file mode 100644 index 0000000000..29c0779620 --- /dev/null +++ b/src/playlist/search.c @@ -0,0 +1,109 @@ +/***************************************************************************** + * search.c : Search functions + ***************************************************************************** + * Copyright (C) 1999-2004 the VideoLAN team + * $Id$ + * + * Authors: Clément Stenac + * + * 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. + *****************************************************************************/ +#include +#include + +#include "vlc_playlist.h" + +/*************************************************************************** + * Item search functions + ***************************************************************************/ + +/** + * Search a playlist item by its playlist_item id + * + * \param p_playlist the playlist + * \param i_id the id to find + * \return the item or NULL on failure + */ +playlist_item_t * playlist_ItemGetById( playlist_t * p_playlist , int i_id ) +{ + int i, i_top, i_bottom; + i_bottom = 0; i_top = p_playlist->i_all_size - 1; + i = i_top / 2; + while( p_playlist->pp_all_items[i]->i_id != i_id && + i_top > i_bottom ) + { + if( p_playlist->pp_all_items[i]->i_id < 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]->i_id == i_id ) + { + return p_playlist->pp_all_items[i]; + } + return NULL; +} + +/** + * Search an item by its input_item_t + * + * \param p_playlist the playlist + * \param p_item the input_item_t to find + * \return the item, or NULL on failure + */ +playlist_item_t * playlist_ItemGetByInput( playlist_t * p_playlist , + input_item_t *p_item ) +{ + int i; + if( p_playlist->status.p_item && p_playlist->status.p_item->p_input == p_item ) + { + return p_playlist->status.p_item; + } + + for( i = 0 ; i < p_playlist->i_all_size; i++ ) + { +msg_Err( p_playlist, "%p, %p", p_item, p_playlist->pp_all_items[i]->p_input ); + if( p_playlist->pp_all_items[i]->p_input == p_item ) + { + return p_playlist->pp_all_items[i]; + } + } + return NULL; +} + +/*************************************************************************** + * Live search handling + ***************************************************************************/ + +int playlist_LiveSearchUpdate( playlist_t *p_playlist, playlist_item_t *p_root, + const char *psz_string ) +{ + int i; + for( i = 0 ; i< p_root->i_children ; i ++ ) + { + playlist_item_t *p_item = p_root->pp_children[i]; + if( p_item->i_children > -1 ) + { + playlist_LiveSearchUpdate( p_playlist, p_item, psz_string ); + } + /* Todo: Filter on all fields */ + if( strcasestr( p_item->p_input->psz_name, psz_string ) ) + p_item->i_flags &= ~PLAYLIST_DBL_FLAG; + else + p_item->i_flags |= PLAYLIST_DBL_FLAG; + } + return VLC_SUCCESS; +} diff --git a/src/playlist/sort.c b/src/playlist/sort.c index b530d93fc8..6d6e25f85b 100644 --- a/src/playlist/sort.c +++ b/src/playlist/sort.c @@ -36,49 +36,6 @@ int playlist_ItemArraySort( playlist_t *p_playlist, int i_items, playlist_item_t **pp_items, int i_mode, int i_type ); - -/** - * Sort the playlist. - * \param p_playlist the playlist - * \param i_mode: SORT_ID, SORT_TITLE, SORT_AUTHOR, SORT_ALBUM, SORT_RANDOM - * \param i_type: ORDER_NORMAL or ORDER_REVERSE (reversed order) - * \return VLC_SUCCESS on success - */ -int playlist_Sort( playlist_t * p_playlist , int i_mode, int i_type ) -{ - int i_id = -1; - vlc_value_t val; - val.b_bool = VLC_TRUE; - - vlc_mutex_lock( &p_playlist->object_lock ); - - p_playlist->i_sort = i_mode; - p_playlist->i_order = i_type; - - if( p_playlist->i_index >= 0 ) - { - i_id = p_playlist->pp_items[p_playlist->i_index]->input.i_id; - } - - playlist_ItemArraySort( p_playlist, p_playlist->i_size, - p_playlist->pp_items, i_mode, i_type ); - - if( i_id != -1 ) - { - p_playlist->i_index = playlist_GetPositionById( p_playlist, i_id ); - } - - /* ensure we are in no-view mode */ - p_playlist->status.i_view = -1; - - vlc_mutex_unlock( &p_playlist->object_lock ); - - /* Notify the interfaces */ - var_Set( p_playlist, "intf-change", val ); - - return VLC_SUCCESS; -} - /** * Sort a node. * @@ -97,8 +54,6 @@ int playlist_NodeSort( playlist_t * p_playlist , playlist_item_t *p_node, playlist_ItemArraySort( p_playlist,p_node->i_children, p_node->pp_children, i_mode, i_type ); - p_node->i_serial++; - return VLC_SUCCESS; } @@ -170,27 +125,23 @@ int playlist_ItemArraySort( playlist_t *p_playlist, int i_items, if( i_mode == SORT_TITLE ) { - i_test = strcasecmp( pp_items[i]->input.psz_name, - pp_items[i_small]->input.psz_name ); + i_test = strcasecmp( pp_items[i]->p_input->psz_name, + pp_items[i_small]->p_input->psz_name ); } else if( i_mode == SORT_TITLE_NUMERIC ) { - i_test = atoi( pp_items[i]->input.psz_name ) - - atoi( pp_items[i_small]->input.psz_name ); + i_test = atoi( pp_items[i]->p_input->psz_name ) - + atoi( pp_items[i_small]->p_input->psz_name ); } else if( i_mode == SORT_DURATION ) { - i_test = pp_items[i]->input.i_duration - - pp_items[i_small]->input.i_duration; + i_test = pp_items[i]->p_input->i_duration - + pp_items[i_small]->p_input->i_duration; } else if( i_mode == SORT_AUTHOR ) { - char *psz_a = vlc_input_item_GetInfo( - &pp_items[i]->input, - _(VLC_META_INFO_CAT), _(VLC_META_ARTIST) ); - char *psz_b = vlc_input_item_GetInfo( - &pp_items[i_small]->input, - _(VLC_META_INFO_CAT), _(VLC_META_ARTIST) ); + char *psz_a = pp_items[i]->p_input->p_meta->psz_artist; + char *psz_b = pp_items[i_small]->p_input->p_meta->psz_artist; if( pp_items[i]->i_children == -1 && pp_items[i_small]->i_children >= 0 ) { @@ -205,8 +156,8 @@ int playlist_ItemArraySort( playlist_t *p_playlist, int i_items, else if( pp_items[i]->i_children >= 0 && pp_items[i_small]->i_children >= 0 ) { - i_test = strcasecmp( pp_items[i]->input.psz_name, - pp_items[i_small]->input.psz_name ); + i_test = strcasecmp( pp_items[i]->p_input->psz_name, + pp_items[i_small]->p_input->psz_name ); } else if( psz_a == NULL && psz_b != NULL ) { @@ -218,8 +169,8 @@ int playlist_ItemArraySort( playlist_t *p_playlist, int i_items, } else if( psz_a == NULL && psz_b == NULL ) { - i_test = strcasecmp( pp_items[i]->input.psz_name, - pp_items[i_small]->input.psz_name ); + i_test = strcasecmp( pp_items[i]->p_input->psz_name, + pp_items[i_small]->p_input->psz_name ); } else { @@ -227,13 +178,9 @@ int playlist_ItemArraySort( playlist_t *p_playlist, int i_items, } } else if( i_mode == SORT_ALBUM ) - { - char *psz_a = vlc_input_item_GetInfo( - &pp_items[i]->input, - _(VLC_META_INFO_CAT), _(VLC_META_COLLECTION) ); - char *psz_b = vlc_input_item_GetInfo( - &pp_items[i_small]->input, - _(VLC_META_INFO_CAT), _(VLC_META_COLLECTION) ); + { + char *psz_a = pp_items[i]->p_input->p_meta->psz_album; + char *psz_b = pp_items[i_small]->p_input->p_meta->psz_album; if( pp_items[i]->i_children == -1 && pp_items[i_small]->i_children >= 0 ) { @@ -248,8 +195,8 @@ int playlist_ItemArraySort( playlist_t *p_playlist, int i_items, else if( pp_items[i]->i_children >= 0 && pp_items[i_small]->i_children >= 0 ) { - i_test = strcasecmp( pp_items[i]->input.psz_name, - pp_items[i_small]->input.psz_name ); + i_test = strcasecmp( pp_items[i]->p_input->psz_name, + pp_items[i_small]->p_input->psz_name ); } else if( psz_a == NULL && psz_b != NULL ) { @@ -261,14 +208,14 @@ int playlist_ItemArraySort( playlist_t *p_playlist, int i_items, } else if( psz_a == NULL && psz_b == NULL ) { - i_test = strcasecmp( pp_items[i]->input.psz_name, - pp_items[i_small]->input.psz_name ); + i_test = strcasecmp( pp_items[i]->p_input->psz_name, + pp_items[i_small]->p_input->psz_name ); } else { i_test = strcmp( psz_b, psz_a ); } - } + } else if( i_mode == SORT_TITLE_NODES_FIRST ) { /* Alphabetic sort, all nodes first */ @@ -285,8 +232,8 @@ int playlist_ItemArraySort( playlist_t *p_playlist, int i_items, } else { - i_test = strcasecmp( pp_items[i]->input.psz_name, - pp_items[i_small]->input.psz_name ); + i_test = strcasecmp( pp_items[i]->p_input->psz_name, + pp_items[i_small]->p_input->psz_name ); } } @@ -304,8 +251,7 @@ int playlist_ItemArraySort( playlist_t *p_playlist, int i_items, } -int playlist_NodeGroup( playlist_t * p_playlist , int i_view, - playlist_item_t *p_root, +int playlist_NodeGroup( playlist_t * p_playlist , playlist_item_t *p_root, playlist_item_t **pp_items,int i_item, int i_mode, int i_type ) { @@ -320,22 +266,19 @@ int playlist_NodeGroup( playlist_t * p_playlist , int i_view, if( psz_search ) free( psz_search ); if( i_mode == SORT_TITLE ) { - psz_search = strdup( pp_items[i]->input.psz_name ); + psz_search = strdup( pp_items[i]->p_input->psz_name ); } else if ( i_mode == SORT_AUTHOR ) { - psz_search = vlc_input_item_GetInfo( &pp_items[i]->input, - _(VLC_META_INFO_CAT), _(VLC_META_ARTIST) ); + psz_search = pp_items[i]->p_input->p_meta->psz_artist; } else if ( i_mode == SORT_ALBUM ) { - psz_search = vlc_input_item_GetInfo( &pp_items[i]->input, - _(VLC_META_INFO_CAT), _(VLC_META_COLLECTION) ); + psz_search = pp_items[i]->p_input->p_meta->psz_album; } else if ( i_mode == SORT_GENRE ) { - psz_search = vlc_input_item_GetInfo( &pp_items[i]->input, - _(VLC_META_INFO_CAT), _(VLC_META_GENRE) ); + psz_search = pp_items[i]->p_input->p_meta->psz_genre; } if( psz_search && !strcmp( psz_search, "" ) ) @@ -347,21 +290,18 @@ int playlist_NodeGroup( playlist_t * p_playlist , int i_view, b_found = VLC_FALSE; for( j = 0 ; j< i_nodes; j++ ) { - if( !strcasecmp( psz_search, pp_nodes[j]->input.psz_name ) ) + if( !strcasecmp( psz_search, pp_nodes[j]->p_input->psz_name ) ) { - playlist_NodeAppend( p_playlist, i_view, - pp_items[i], pp_nodes[j] ); + playlist_NodeAppend( p_playlist, pp_items[i], pp_nodes[j] ); b_found = VLC_TRUE; break; } } if( !b_found ) { - p_node = playlist_NodeCreate( p_playlist, i_view,psz_search, - NULL ); + p_node = playlist_NodeCreate( p_playlist, psz_search, NULL ); INSERT_ELEM( pp_nodes, i_nodes, i_nodes, p_node ); - playlist_NodeAppend( p_playlist, i_view, - pp_items[i],p_node ); + playlist_NodeAppend( p_playlist, pp_items[i],p_node ); } } @@ -375,8 +315,7 @@ int playlist_NodeGroup( playlist_t * p_playlist , int i_view, playlist_ItemArraySort( p_playlist, pp_nodes[i]->i_children, pp_nodes[i]->pp_children, SORT_TITLE, i_type ); - playlist_NodeAppend( p_playlist, i_view, - pp_nodes[i], p_root ); + playlist_NodeAppend( p_playlist, pp_nodes[i], p_root ); } return VLC_SUCCESS; } diff --git a/src/playlist/thread.c b/src/playlist/thread.c new file mode 100644 index 0000000000..9e36aca173 --- /dev/null +++ b/src/playlist/thread.c @@ -0,0 +1,241 @@ +/***************************************************************************** + * playlist.c : Playlist management functions + ***************************************************************************** + * Copyright (C) 1999-2004 the VideoLAN team + * $Id$ + * + * Authors: Samuel Hocevar + * Clément Stenac + * + * 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. + *****************************************************************************/ +#include +#include +#include "vlc_playlist.h" +#include "vlc_interaction.h" + +/***************************************************************************** + * Local prototypes + *****************************************************************************/ +static void RunControlThread ( playlist_t * ); +static void RunPreparse( playlist_preparse_t * ); + +static playlist_t * CreatePlaylist( vlc_object_t *p_parent ); +static void HandlePlaylist( playlist_t * ); +static void EndPlaylist( playlist_t * ); +static void DestroyPlaylist( playlist_t * ); + +static void HandleStats( playlist_t *, int ); + +static void HandleInteraction( playlist_t * ); +static void DestroyInteraction( playlist_t * ); + +/***************************************************************************** + * Main functions for the global thread + *****************************************************************************/ + +/** + * Create the main playlist thread + * Additionally to the playlist, this thread controls : + * - Interaction + * - Statistics + * - VLM + * \param p_parent + * \return an object with a started thread + */ +playlist_t * __playlist_ThreadCreate( vlc_object_t *p_parent ) +{ + playlist_t *p_playlist; + p_playlist = CreatePlaylist( p_parent ); + + if( !p_playlist ) return NULL; + + // Stats + p_playlist->p_stats = (global_stats_t *)malloc( sizeof( global_stats_t ) ); + vlc_mutex_init( p_playlist, &p_playlist->p_stats->lock ); + + // Interaction + p_playlist->p_interaction = NULL; + + // Preparse + 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; + } + + // Start the thread + if( vlc_thread_create( p_playlist, "playlist", RunControlThread, + VLC_THREAD_PRIORITY_LOW, VLC_TRUE ) ) + { + msg_Err( p_playlist, "cannot spawn playlist thread" ); + vlc_object_destroy( p_playlist ); + return NULL; + } + + /* The object has been initialized, now attach it */ + vlc_object_attach( p_playlist, p_parent ); + + return p_playlist; +} + +/** + * Destroy the playlist global thread. + * + * Deinits all things controlled by the playlist global thread + * \param p_playlist the playlist thread to destroy + * \return VLC_SUCCESS or an error + */ +int playlist_ThreadDestroy( playlist_t * p_playlist ) +{ + p_playlist->b_die = 1; + + DestroyInteraction( p_playlist ); + DestroyPlaylist( p_playlist ); + + return VLC_SUCCESS; +} + +/** + * Run the main control thread itself + */ +static void RunControlThread ( playlist_t *p_playlist ) +{ + int i_loops = 0; + + /* Tell above that we're ready */ + vlc_thread_ready( p_playlist ); + + while( !p_playlist->b_die ) + { + i_loops++; + + HandleInteraction( p_playlist ); + HandleStats( p_playlist, i_loops ); + + HandlePlaylist( p_playlist ); + + msleep( INTF_IDLE_SLEEP / 2 ); + + /* Stop sleeping earlier if we have work */ + /* TODO : statistics about this */ + if ( p_playlist->request.b_request && + p_playlist->status.i_status == PLAYLIST_RUNNING ) + { + continue; + } + + msleep( INTF_IDLE_SLEEP / 2 ); + } + + EndPlaylist( p_playlist ); +} + + +/***************************************************************************** + * Playlist-specific functions + *****************************************************************************/ +static playlist_t * CreatePlaylist( vlc_object_t *p_parent ) +{ + return playlist_Create( p_parent ); +} + +static void DestroyPlaylist( playlist_t *p_playlist ) +{ + playlist_Destroy( p_playlist ); +} + +static void HandlePlaylist( playlist_t *p_playlist ) +{ + playlist_MainLoop( p_playlist ); +} + +static void EndPlaylist( playlist_t *p_playlist ) +{ + playlist_LastLoop( p_playlist ); +} + +/***************************************************************************** + * Preparse-specific functions + *****************************************************************************/ +static void RunPreparse ( playlist_preparse_t *p_obj ) +{ + /* Tell above that we're ready */ + vlc_thread_ready( p_obj ); + playlist_t *p_playlist = (playlist_t *)p_obj->p_parent; + + while( !p_playlist->b_die ) + { + playlist_PreparseLoop( p_obj ); + if( p_obj->i_waiting == 0 ) + { + msleep( INTF_IDLE_SLEEP ); + } + } +} + +/***************************************************************************** + * Interaction functions + *****************************************************************************/ +static void DestroyInteraction( playlist_t *p_playlist ) +{ + if( p_playlist->p_interaction ) + { + intf_InteractionDestroy( p_playlist->p_interaction ); + } +} + +static void HandleInteraction( playlist_t *p_playlist ) +{ + if( p_playlist->p_interaction ) + { + stats_TimerStart( p_playlist, "Interaction thread", + STATS_TIMER_INTERACTION ); + intf_InteractionManage( p_playlist ); + stats_TimerStop( p_playlist, STATS_TIMER_INTERACTION ); + } +} + + +/***************************************************************************** + * Stats functions + *****************************************************************************/ +static void HandleStats( playlist_t *p_playlist, int i_loops ) +{ + if( i_loops %5 == 0 && p_playlist->p_stats ) + { + stats_ComputeGlobalStats( p_playlist, p_playlist->p_stats ); + if( p_playlist->p_input ) + { + stats_ComputeInputStats( p_playlist->p_input, + p_playlist->p_input->input.p_item->p_stats ); + } + } +} diff --git a/src/playlist/tree.c b/src/playlist/tree.c new file mode 100644 index 0000000000..c151dc1287 --- /dev/null +++ b/src/playlist/tree.c @@ -0,0 +1,673 @@ +/***************************************************************************** + * tree.c : Playlist tree walking functions + ***************************************************************************** + * Copyright (C) 1999-2004 the VideoLAN team + * $Id$ + * + * Authors: Clément Stenac + * + * 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. + *****************************************************************************/ +#include +#include +#include "vlc_playlist.h" + +#define PLAYLIST_DEBUG 1 + +/************************************************************************ + * Local prototypes + ************************************************************************/ +playlist_item_t *GetNextUncle( playlist_t *p_playlist, playlist_item_t *p_item, + playlist_item_t *p_root ); +playlist_item_t *GetPrevUncle( playlist_t *p_playlist, playlist_item_t *p_item, + playlist_item_t *p_root ); + +playlist_item_t *GetNextItem( playlist_t *p_playlist, + playlist_item_t *p_root, + playlist_item_t *p_item ); +playlist_item_t *GetPrevItem( playlist_t *p_playlist, + playlist_item_t *p_item, + playlist_item_t *p_root ); + +/** + * 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, char *psz_name, + playlist_item_t *p_parent ) +{ + input_item_t *p_input; + playlist_item_t *p_item; + + if( !psz_name ) psz_name = strdup( _("Undefined") ); + p_input = input_ItemNewWithType( VLC_OBJECT(p_playlist), NULL, psz_name, + 0, NULL, -1, ITEM_TYPE_NODE ); + p_input->i_id = ++p_playlist->i_last_input_id; + p_item = playlist_ItemNewFromInput( VLC_OBJECT(p_playlist), p_input ); + p_item->i_children = 0; + + if( p_item == NULL ) + { + return NULL; + } + 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, p_item, p_parent ); + } + + playlist_SendAddNotify( p_playlist, p_item->i_id, + p_parent ? p_parent->i_id : -1 ); + 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_DeleteFromItemId( p_playlist, + p_root->pp_children[i]->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 ) + { + playlist_DeleteFromItemId( p_playlist, + p_root->pp_children[i]->i_id ); + } + } + /* Delete the node */ + if( p_root->i_flags & PLAYLIST_RO_FLAG && !b_force ) + { + } + else + { + var_SetInteger( p_playlist, "item-deleted", p_root->p_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]->p_input->i_id != + p_root->p_input->i_id && i_top > i_bottom ) + { + if( p_playlist->pp_all_items[i]->p_input->i_id < + p_root->p_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]->p_input->i_id == + p_root->p_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 children of a node + * + * \param p_playlist the playlist + * \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, + playlist_item_t *p_item, + playlist_item_t *p_parent ) +{ + return playlist_NodeInsert( p_playlist, p_item, p_parent, -1 ); +} + +int playlist_NodeInsert( playlist_t *p_playlist, + playlist_item_t *p_item, + playlist_item_t *p_parent, + int i_position ) +{ + 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 ); + + p_item->p_parent = p_parent; + + 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 + */ +int playlist_NodeRemoveItem( playlist_t *p_playlist, + playlist_item_t *p_item, + playlist_item_t *p_parent ) +{ + int i; + for( i= 0; i< p_parent->i_children ; i++ ) + { + if( p_parent->pp_children[i] == p_item ) + { + REMOVE_ELEM( p_parent->pp_children, p_parent->i_children, i ); + } + } + + return VLC_SUCCESS; +} + + +/** + * Count the children of a node + * + * \param p_playlist the playlist + * \param p_node the node + * \return the number of children + */ +int playlist_NodeChildrenCount( playlist_t *p_playlist, playlist_item_t*p_node) +{ + int i; + int i_nb = 0; + if( p_node->i_children == -1 ) + return 0; + + for( i=0 ; i< p_node->i_children;i++ ) + { + if( p_node->pp_children[i]->i_children == -1 ) + i_nb++; + else + i_nb += playlist_NodeChildrenCount( p_playlist, + p_node->pp_children[i] ); + } + return i_nb; +} + +/** + * Search a child of a node by its name + * + * \param p_node the node + * \param psz_search the name of the child to search + * \return the child item or NULL if not found or error + */ +playlist_item_t *playlist_ChildSearchName( playlist_item_t *p_node, + const char *psz_search ) +{ + int i; + + if( p_node->i_children < 0 ) + { + return NULL; + } + for( i = 0 ; i< p_node->i_children; i++ ) + { + if( !strcmp( p_node->pp_children[i]->p_input->psz_name, psz_search ) ) + { + return p_node->pp_children[i]; + } + } + return NULL; +} + +/********************************************************************** + * Tree walking functions + **********************************************************************/ + +playlist_item_t *playlist_GetLastLeaf(playlist_t *p_playlist, + playlist_item_t *p_root ) +{ + int i; + playlist_item_t *p_item; + for ( i = p_root->i_children - 1; i >= 0; i-- ) + { + if( p_root->pp_children[i]->i_children == -1 ) + return p_root->pp_children[i]; + else if( p_root->pp_children[i]->i_children > 0) + { + p_item = playlist_GetLastLeaf( p_playlist, + p_root->pp_children[i] ); + if ( p_item != NULL ) + return p_item; + } + else if( i == 0 ) + return NULL; + } + return NULL; +} + +/** + * Finds the next item to play + * + * \param p_playlist the playlist + * \param p_root the root node + * \param p_item the previous item (NULL if none ) + * \return the next item to play, or NULL if none found + */ +playlist_item_t *playlist_GetNextLeaf( playlist_t *p_playlist, + playlist_item_t *p_root, + playlist_item_t *p_item ) +{ + playlist_item_t *p_next; + +#ifdef PLAYLIST_DEBUG + if( p_item != NULL ) + msg_Dbg( p_playlist, "finding next of %s within %s", + p_item->p_input->psz_name, p_root->p_input->psz_name ); + else + msg_Dbg( p_playlist, "finding something to play within %s", + p_root->p_input->psz_name ); +#endif + + if( !p_root || p_root->i_children == -1 ) + { + msg_Err( p_playlist,"invalid arguments for GetNextLeaf" ); + return NULL; + } + + /* Now, walk the tree until we find a suitable next item */ + p_next = p_item; + do + { + p_next = GetNextItem( p_playlist, p_root, p_next ); + } while ( p_next && p_next != p_root && p_next->i_children != -1 ); + +#ifdef PLAYLIST_DEBUG + if( p_next == NULL ) + msg_Dbg( p_playlist, "At end of node" ); +#endif + return p_next; +} + +playlist_item_t *playlist_GetNextEnabledLeaf( playlist_t *p_playlist, + playlist_item_t *p_root, + playlist_item_t *p_item ) +{ + playlist_item_t *p_next; + +#ifdef PLAYLIST_DEBUG + if( p_item != NULL ) + msg_Dbg( p_playlist, "finding next of %s within %s", + p_item->p_input->psz_name, p_root->p_input->psz_name ); + else + msg_Dbg( p_playlist, "finding something to play within %s", + p_root->p_input->psz_name ); +#endif + + if( !p_root || p_root->i_children == -1 ) + { + msg_Err( p_playlist,"invalid arguments for GetNextEnabledLeaf" ); + return NULL; + } + + /* Now, walk the tree until we find a suitable next item */ + p_next = p_item; + do + { + p_next = GetNextItem( p_playlist, p_root, p_next ); + } while ( p_next && p_next != p_root && + !( p_next->i_children == -1 && + !(p_next->i_flags & PLAYLIST_DBL_FLAG) ) ); + +#ifdef PLAYLIST_DEBUG + if( p_next == NULL ) + msg_Dbg( p_playlist, "At end of node" ); +#endif + return p_next; +} + +/** + * Finds the previous item to play + * + * \param p_playlist the playlist + * \param p_root the root node + * \param p_item the previous item (NULL if none ) + * \return the next item to play, or NULL if none found + */ +playlist_item_t *playlist_GetPrevLeaf( playlist_t *p_playlist, + playlist_item_t *p_root, + playlist_item_t *p_item ) +{ + playlist_item_t *p_prev; + +#ifdef PLAYLIST_DEBUG + if( p_item != NULL ) + msg_Dbg( p_playlist, "finding previous of %s within %s", + p_item->p_input->psz_name, p_root->p_input->psz_name ); + else + msg_Dbg( p_playlist, "finding previous to play within %s", + p_root->p_input->psz_name ); +#endif + + if( !p_root || p_root->i_children == -1 ) + { + msg_Err( p_playlist,"invalid arguments for GetPrevLeaf" ); + return NULL; + } + + /* Now, walk the tree until we find a suitable previous item */ + p_prev = p_item; + do + { + p_prev = GetPrevItem( p_playlist, p_root, p_prev ); + } while ( p_prev && p_prev != p_root && p_prev->i_children != -1 ); + +#ifdef PLAYLIST_DEBUG + if( p_prev == NULL ) + msg_Dbg( p_playlist, "At beginning of node" ); +#endif + return p_prev; +} + +/************************************************************************ + * Following functions are local + ***********************************************************************/ + +/** + * Get the next item in the tree + * If p_item is NULL, return the first child of root + **/ +playlist_item_t *GetNextItem( playlist_t *p_playlist, + playlist_item_t *p_root, + playlist_item_t *p_item ) +{ + playlist_item_t *p_parent; + int i; + + /* Node with children, get the first one */ + if( p_item && p_item->i_children > 0 ) + return p_item->pp_children[0]; + + if( p_item != NULL ) + p_parent = p_item->p_parent; + else + p_parent = p_root; + + for( i= 0 ; i < p_parent->i_children ; i++ ) + { + if( p_item == NULL || p_parent->pp_children[i] == p_item ) + { + if( p_item == NULL ) + i = -1; + + if( i+1 >= p_parent->i_children ) + { + /* Was already the last sibling. Look for uncles */ +#ifdef PLAYLIST_DEBUG + msg_Dbg( p_playlist, "Current item is the last of the node," + "looking for uncle from %s", + p_parent->p_input->psz_name ); +#endif + if( p_parent == p_root ) + { +#ifdef PLAYLIST_DEBUG + msg_Dbg( p_playlist, "Already at root" ); + return NULL; +#endif + } + return GetNextUncle( p_playlist, p_item, p_root ); + } + else + { + return p_parent->pp_children[i+1]; + } + } + } + msg_Err( p_playlist, "I should not be here" ); + return NULL; +} + +playlist_item_t *GetNextUncle( playlist_t *p_playlist, playlist_item_t *p_item, + playlist_item_t *p_root ) +{ + playlist_item_t *p_parent = p_item->p_parent; + playlist_item_t *p_grandparent; + vlc_bool_t b_found = VLC_FALSE; + + if( p_parent != NULL ) + { + p_grandparent = p_parent->p_parent; + while( 1 ) + { + int i; + for( i = 0 ; i< p_grandparent->i_children ; i++ ) + { + if( p_parent == p_grandparent->pp_children[i] ) + { +#ifdef PLAYLIST_DEBUG + msg_Dbg( p_playlist, "parent %s found as child %i of " + "grandparent %s", + p_parent->p_input->psz_name, i, + p_grandparent->p_input->psz_name ); +#endif + b_found = VLC_TRUE; + break; + } + } + if( b_found && i + 1 < p_grandparent->i_children ) + { + return p_grandparent->pp_children[i+1]; + } + /* Not found at root */ + if( p_grandparent == p_root ) + { + return NULL; + } + else + { + p_parent = p_grandparent; + p_grandparent = p_parent->p_parent; + } + } + } + /* We reached root */ + return NULL; +} + +playlist_item_t *GetPrevUncle( playlist_t *p_playlist, playlist_item_t *p_item, + playlist_item_t *p_root ) +{ + playlist_item_t *p_parent = p_item->p_parent; + playlist_item_t *p_grandparent; + vlc_bool_t b_found = VLC_FALSE; + + if( p_parent != NULL ) + { + p_grandparent = p_parent->p_parent; + while( 1 ) + { + int i; + for( i = p_grandparent->i_children -1 ; i >= 0; i-- ) + { + if( p_parent == p_grandparent->pp_children[i] ) + { + b_found = VLC_TRUE; + break; + } + } + if( b_found && i - 1 > 0 ) + { + return p_grandparent->pp_children[i-1]; + } + /* Not found at root */ + if( p_grandparent == p_root ) + { + return NULL; + } + else + { + p_parent = p_grandparent; + p_grandparent = p_parent->p_parent; + } + } + } + /* We reached root */ + return NULL; +} + + +/* Recursively search the tree for previous item */ +playlist_item_t *GetPrevItem( playlist_t *p_playlist, + playlist_item_t *p_root, + playlist_item_t *p_item ) +{ + playlist_item_t *p_parent; + int i; + + /* Node with children, get the last one */ + if( p_item && p_item->i_children > 0 ) + return p_item->pp_children[p_item->i_children - 1]; + + /* Last child of its parent ? */ + if( p_item != NULL ) + p_parent = p_item->p_parent; + else + { + msg_Err( p_playlist, "Get the last one" ); + abort(); + }; + + for( i = p_parent->i_children -1 ; i >= 0 ; i-- ) + { + if( p_parent->pp_children[i] == p_item ) + { + if( i-1 < 0 ) + { + /* Was already the first sibling. Look for uncles */ +#ifdef PLAYLIST_DEBUG + msg_Dbg( p_playlist, "Current item is the first of the node," + "looking for uncle from %s", + p_parent->p_input->psz_name ); +#endif + return GetPrevUncle( p_playlist, p_item, p_root ); + } + else + { + return p_parent->pp_children[i-1]; + } + } + } + msg_Err( p_playlist, "I should not be here" ); + return NULL; +} + +/* Dump the contents of a node */ +void playlist_NodeDump( playlist_t *p_playlist, playlist_item_t *p_item, + int i_level ) +{ + char str[512]; + int i; + + if( i_level == 1 ) + { + msg_Dbg( p_playlist, "%s (%i)", + p_item->p_input->psz_name, p_item->i_children ); + } + + if( p_item->i_children == -1 ) + { + return; + } + + for( i = 0; i< p_item->i_children; i++ ) + { + memset( str, 32, 512 ); + sprintf( str + 2 * i_level , "%s (%i)", + p_item->pp_children[i]->p_input->psz_name, + p_item->pp_children[i]->i_children ); + msg_Dbg( p_playlist, "%s",str ); + if( p_item->pp_children[i]->i_children >= 0 ) + { + playlist_NodeDump( p_playlist, p_item->pp_children[i], + i_level + 1 ); + } + } + return; +} diff --git a/src/playlist/view.c b/src/playlist/view.c deleted file mode 100644 index d0520629fb..0000000000 --- a/src/playlist/view.c +++ /dev/null @@ -1,1036 +0,0 @@ -/***************************************************************************** - * view.c : Playlist views functions - ***************************************************************************** - * Copyright (C) 1999-2004 the VideoLAN team - * $Id$ - * - * Authors: Clément Stenac - * - * 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. - *****************************************************************************/ -#include /* free(), strtol() */ -#include /* sprintf() */ -#include /* strerror() */ - -#include -#include - -#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_ALBUM: i_sort_type = SORT_ALBUM;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_serial = 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 a parent from the parent list 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 - */ -int playlist_NodeRemoveParent( playlist_t *p_playlist, - playlist_item_t *p_item, - playlist_item_t *p_parent ) -{ - int i; - if( !p_parent || p_parent->i_children == -1 ) - { - msg_Err( p_playlist, "invalid node" ); - } - - for( i = 0; i < p_item->i_parents; i++ ) - { - if( p_item->pp_parents[i]->p_parent == p_parent ) - { - if( p_item->pp_parents[i] ) - { - free( p_item->pp_parents[i] ); - } - REMOVE_ELEM( p_item->pp_parents, p_item->i_parents, i ); - } - } - p_item->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 - */ -int playlist_NodeRemoveItem( playlist_t *p_playlist, - playlist_item_t *p_item, - playlist_item_t *p_parent ) -{ - int i; - for( i= 0; i< p_parent->i_children ; i++ ) - { - if( p_parent->pp_children[i] == p_item ) - { - REMOVE_ELEM( p_parent->pp_children, p_parent->i_children, i ); - } - } - - /* Let the interface know this has been updated */ - p_parent->i_serial++; - - return VLC_SUCCESS; -} - - -/** - * Count the children of a node - * - * \param p_playlist the playlist - * \param p_node the node - * \return the number of children - */ -int playlist_NodeChildrenCount( playlist_t *p_playlist, playlist_item_t*p_node) -{ - int i; - int i_nb = 0; - if( p_node->i_children == -1 ) - { - return 0; - } - - for( i=0 ; i< p_node->i_children;i++ ) - { - if( p_node->pp_children[i]->i_children == -1 ) - { - i_nb++; - } - else - { - i_nb += playlist_NodeChildrenCount( p_playlist, - p_node->pp_children[i] ); - } - } - return i_nb; -} - -/** - * Search a child of a node by its name - * - * \param p_node the node - * \param psz_search the name of the child to search - * \return the child item or NULL if not found or error - */ -playlist_item_t *playlist_ChildSearchName( playlist_item_t *p_node, - const char *psz_search ) -{ - int i; - - if( p_node->i_children < 0 ) - { - return NULL; - } - for( i = 0 ; i< p_node->i_children; i++ ) - { - if( !strcmp( p_node->pp_children[i]->input.psz_name, psz_search ) ) - { - return p_node->pp_children[i]; - } - } - return NULL; -} - - -/********************************************************************** - * Tree functions - **********************************************************************/ - -/** - * Finds the next item to play - * - * \param p_playlist the playlist - * \param i_view the view - * \param p_root the root node - * \param p_node the node we are playing from - * \param p_item the item we were playing (NULL if none ) - * \return the next item to play, or NULL if none found - */ -playlist_item_t *playlist_FindNextFromParent( playlist_t *p_playlist, - int i_view, /* FIXME: useless */ - playlist_item_t *p_root, - playlist_item_t *p_node, - playlist_item_t *p_item ) -{ - playlist_item_t *p_search, *p_next; - -#ifdef PLAYLIST_DEBUG - if( p_item != NULL ) - { - msg_Dbg( p_playlist, "finding next of %s within %s - root %s", - p_item->input.psz_name, p_node->input.psz_name, - p_root->input.psz_name ); - } - else - { - msg_Dbg( p_playlist, "finding something to play within %s -root %s", - p_node->input.psz_name, p_root->input.psz_name ); - - } -#endif - - if( !p_node || p_node->i_children == -1 ) - { - msg_Err( p_playlist,"invalid arguments for FindNextFromParent" ); - return NULL; - } - - /* Find the parent node of the item */ - if( p_item != NULL ) - { - p_search = playlist_FindDirectParent( p_playlist, p_item, i_view ); - if( p_search == NULL ) - { - msg_Err( p_playlist, "parent node not found" ); - return NULL; - } - } - else - { - p_search = p_node; - } - - /* Now, go up the tree until we find a suitable next item */ - p_next = playlist_RecursiveFindNext( p_playlist,i_view, - p_node, p_item, p_search ); - - /* Not found, do we go past p_node ? */ - if( p_next == NULL ) - { - if( p_playlist->b_go_next ) - { -#ifdef PLAYLIST_DEBUG - msg_Dbg( p_playlist, "moving on to next node: search from %s", - p_root->input.psz_name ); -#endif - p_next = playlist_RecursiveFindNext( p_playlist, i_view, - p_root, p_item, p_search ); - if( p_next == NULL ) - { - return NULL; - } - /* OK, we could continue, so set our current node to the root */ - p_playlist->status.p_node = p_root; - } - else - { -#ifdef PLAYLIST_DEBUG - msg_Dbg( p_playlist, "not moving on to next node: you loose" ); -#endif - return NULL; - } - } - return p_next; -} - -/** - * Finds the previous item to play - * - * \param p_playlist the playlist - * \param i_view the view - * \param p_root the root node - * \param p_node the node we are playing from - * \param p_item the item we were playing (NULL if none ) - * \return the next item to play, or NULL if none found - */ -playlist_item_t *playlist_FindPrevFromParent( playlist_t *p_playlist, - int i_view, - playlist_item_t *p_root, - playlist_item_t *p_node, - playlist_item_t *p_item ) -{ - playlist_item_t *p_search, *p_next; - -#ifdef PLAYLIST_DEBUG - if( p_item != NULL ) - { - msg_Dbg( p_playlist, "finding prev of %s within %s", - p_item->input.psz_name, p_node->input.psz_name ); - } - else - { - msg_Dbg( p_playlist, "finding prev from %s",p_node->input.psz_name ); - } -#endif - - if( !p_node || p_node->i_children == -1 ) - { - msg_Err( p_playlist,"Invalid arguments for FindPrevFromParent" ); - return NULL; - } - - /* Find the parent node of the item */ - if( p_item != NULL ) - { - p_search = playlist_FindDirectParent( p_playlist, p_item, i_view ); - if( p_search == NULL ) - { - msg_Err( p_playlist, "parent node not found" ); - return NULL; - } - } - else - { - p_search = p_node; - } - - /* Now, go up the tree until we find a suitable next item */ - p_next = playlist_RecursiveFindPrev( p_playlist,i_view, - p_node, p_item, p_search ); - - if( p_next == NULL ) - { - if( p_playlist->b_go_next ) - { - p_next = playlist_RecursiveFindPrev( p_playlist, i_view, - p_root, p_item, p_search ); - if( p_next == NULL ) - { - return NULL; - } - /* OK, we could continue, so set our current node to the root */ - p_playlist->status.p_node = p_root; - } - else - { - return NULL; - } - } - return p_next; -} - -/************************************************************************ - * Following functions are local - ***********************************************************************/ - - -/* Recursively search the tree for next item */ -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 ) -{ - int i; - playlist_item_t *p_parent_parent; - - for( i= 0 ; i < p_parent->i_children ; i++ ) - { - if( p_parent->pp_children[i] == p_item || p_item == NULL ) - { - if( p_item == NULL ) - { - i = -1; - } -#ifdef PLAYLIST_DEBUG - msg_Dbg( p_playlist,"current item found, child %i of %s", - i , p_parent->input.psz_name ); -#endif - /* We found our item */ - if( i+1 >= p_parent->i_children ) - { - /* Too far... */ -#ifdef PLAYLIST_DEBUG - msg_Dbg( p_playlist, "going up the tree, at parent of %s", - p_parent->input.psz_name ); -#endif - if( p_parent == p_root ) - { -#ifdef PLAYLIST_DEBUG - msg_Dbg( p_playlist, "at root item (%s)", - p_root->input.psz_name ); -#endif - /* Hmm, seems it's the end for you, guy ! */ - return NULL; - } - - /* Go up one level */ - p_parent_parent = playlist_FindDirectParent( p_playlist, - p_parent, i_view ); - if( p_parent_parent == NULL ) - { - msg_Warn( p_playlist, "unable to find parent!"); - return NULL; - } - return playlist_RecursiveFindNext( p_playlist, i_view,p_root, - p_parent, p_parent_parent ); - } - else - { - if( p_parent->pp_children[i+1]->i_children == -1 ) - { - /* Cool, we have found a real item to play */ -#ifdef PLAYLIST_DEBUG - msg_Dbg( p_playlist, "playing child %i of %s", - i+1 , p_parent->input.psz_name ); -#endif - return p_parent->pp_children[i+1]; - } - else if( p_parent->pp_children[i+1]->i_children > 0 ) - { - /* Select the first child of this node */ -#ifdef PLAYLIST_DEBUG - msg_Dbg( p_playlist, "%s is a node with children, " - "playing the first", - p_parent->pp_children[i+1]->input.psz_name); -#endif - if( p_parent->pp_children[i+1]->pp_children[0] - ->i_children >= 0 ) - { - /* first child is a node ! */ - return playlist_RecursiveFindNext( p_playlist, i_view, - p_root, NULL , - p_parent->pp_children[i+1]->pp_children[0]); - } - return p_parent->pp_children[i+1]->pp_children[0]; - } - else - { - /* This node has no child... We must continue */ -#ifdef PLAYLIST_DEBUG - msg_Dbg( p_playlist, "%s is a node with no children", - p_parent->pp_children[i+1]->input.psz_name); -#endif - p_item = p_parent->pp_children[i+1]; - } - } - } - } - /* Just in case :) */ - return NULL; -} - -/* Recursively search the tree for previous item */ -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 ) -{ - int i; - playlist_item_t *p_parent_parent; - - for( i= p_parent->i_children - 1 ; i >= 0 ; i-- ) - { - if( p_parent->pp_children[i] == p_item || p_item == NULL ) - { - if( p_item == NULL ) - { - i = -1; - } -#ifdef PLAYLIST_DEBUG - msg_Dbg( p_playlist,"current item found, child %i of %s", - i , p_parent->input.psz_name ); -#endif - /* We found our item */ - if( i < 1 ) - { - /* Too far... */ -#ifdef PLAYLIST_DEBUG - msg_Dbg( p_playlist, "going up the tree, at parent of %s", - p_parent->input.psz_name ); -#endif - if( p_parent == p_root ) - { -#ifdef PLAYLIST_DEBUG - msg_Dbg( p_playlist, "at root item (%s)", - p_root->input.psz_name ); -#endif - /* Hmm, seems it's the end for you, guy ! */ - return NULL; - } - /* Go up one level */ - p_parent_parent = playlist_FindDirectParent( p_playlist, - p_parent, i_view ); - if( p_parent_parent == NULL ) - { -#ifdef PLAYLIST_DEBUG - msg_Dbg( p_playlist, "mmmh, couldn't find parent" ); -#endif - return NULL; - } - return playlist_RecursiveFindPrev( p_playlist, i_view,p_root, - p_parent, p_parent_parent ); - } - else - { - if( p_parent->pp_children[i-1]->i_children == -1 ) - { - /* Cool, we have found a real item to play */ -#ifdef PLAYLIST_DEBUG - msg_Dbg( p_playlist, "playing child %i of %s", - i-1, p_parent->input.psz_name ); -#endif - return p_parent->pp_children[i-1]; - } - else if( p_parent->pp_children[i-1]->i_children > 0 ) - { - /* Select the last child of this node */ -#ifdef PLAYLIST_DEBUG - msg_Dbg( p_playlist, "%s is a node with children," - " playing the last", - p_parent->pp_children[i-1]->input.psz_name); -#endif - if( p_parent->pp_children[i-1]->pp_children[p_parent-> - pp_children[i-1]->i_children-1]->i_children >= 0 ) - { - /* Last child is a node */ - return playlist_RecursiveFindPrev( p_playlist, i_view, - p_root,NULL, - p_parent->pp_children[i-1]->pp_children[ - p_parent->pp_children[i-1]->i_children-1]); - } - return p_parent->pp_children[i-1]->pp_children[ - p_parent->pp_children[i-1]->i_children-1]; - } - else - { - /* This node has no child... We must continue */ -#ifdef PLAYLIST_DEBUG - msg_Dbg( p_playlist, "%s is a node with no children", - p_parent->pp_children[i-1]->input.psz_name); -#endif - p_item = p_parent->pp_children[i-1]; - } - } - } - } - return NULL; -} - -/* This function returns the parent of an item in a view */ -playlist_item_t *playlist_FindDirectParent( playlist_t *p_playlist, - playlist_item_t *p_item, - int i_view ) -{ - int i = 0; - for( i= 0; i< p_item->i_parents ; i++ ) - { - if( p_item->pp_parents[i]->i_view == i_view ) - { - return p_item->pp_parents[i]->p_parent; - } - } - return NULL; -} - - -#ifdef PLAYLIST_DEBUG -/* This function dumps a node : to be used only for debug*/ -void playlist_NodeDump( playlist_t *p_playlist, playlist_item_t *p_item, - int i_level ) -{ - char str[512]; - int i; - - if( i_level == 1 ) - { - msg_Dbg( p_playlist, "%s (%i)", - p_item->input.psz_name, p_item->i_children ); - } - - if( p_item->i_children == -1 ) - { - return; - } - - for( i = 0; i< p_item->i_children; i++ ) - { - memset( str, 32, 512 ); - sprintf( str + 2 * i_level , "%s (%i)", - p_item->pp_children[i]->input.psz_name, - p_item->pp_children[i]->i_children ); - msg_Dbg( p_playlist, "%s",str ); - if( p_item->pp_children[i]->i_children >= 0 ) - { - playlist_NodeDump( p_playlist, p_item->pp_children[i], - i_level + 1 ); - } - } - return; -} -#endif diff --git a/test/NativeGcTest.py b/test/NativeGcTest.py new file mode 100644 index 0000000000..396d813fa5 --- /dev/null +++ b/test/NativeGcTest.py @@ -0,0 +1,8 @@ +import unittest + +import native_gc_test + +class NativeGcTestCase( unittest.TestCase ): + def testGc( self ): + """[GC] Test GC""" + native_gc_test.gc_test() diff --git a/test/native/gc.c b/test/native/gc.c new file mode 100644 index 0000000000..eaa5ff2820 --- /dev/null +++ b/test/native/gc.c @@ -0,0 +1,45 @@ +#include "../pyunit.h" +#include + +#include + +struct mygc +{ + VLC_GC_MEMBERS; + int i; +}; + +typedef struct mygc mygc; + +static void mygc_destructor( gc_object_t *p_gc ) +{ + free( p_gc ); + p_gc = NULL; +}; + +static PyObject *gc_test( PyObject *self, PyObject *args ) +{ + mygc *gc = (mygc *)malloc( sizeof( mygc ) ); + + vlc_gc_init( gc, mygc_destructor ); + gc->i_gc_refcount = 0; + + vlc_gc_incref( gc ); + ASSERT( gc->i_gc_refcount == 1, "Refcount should be 1" ); + vlc_gc_incref( gc ); + ASSERT( gc->i_gc_refcount == 2, "Refcount should be 2" ); + gc->i++; + vlc_gc_decref( gc ); + ASSERT( gc->i_gc_refcount == 1, "Refcount should be 1" ); + vlc_gc_decref( gc ); + + Py_INCREF( Py_None ); + return Py_None; +}; + +static PyMethodDef native_gc_test_methods[] = { + DEF_METHOD( gc_test, "Test GC" ) + { NULL, NULL, 0, NULL } +}; + +DECLARE_MODULE( native_gc_test )