X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=lib%2Fmedia.c;h=1d01c11c425a60a050c891bc9321cffe9d4ed63a;hb=f3cc5c9f0f1512eb0a69ec4a080bebc609b3645c;hp=7e455f7a35a4558780a2c109752ba85f7303e0a7;hpb=7458af47e6db6134a8cd96098cbe542a5511e95c;p=vlc diff --git a/lib/media.c b/lib/media.c index 7e455f7a35..1d01c11c42 100644 --- a/lib/media.c +++ b/lib/media.c @@ -43,6 +43,7 @@ #include "libvlc_internal.h" #include "media_internal.h" +#include "media_list_internal.h" static const vlc_meta_type_t libvlc_to_vlc_meta[] = { @@ -103,6 +104,26 @@ static const libvlc_meta_t vlc_to_libvlc_meta[] = [vlc_meta_DiscNumber] = libvlc_meta_DiscNumber }; +static libvlc_media_list_t *media_get_subitems( libvlc_media_t * p_md, + bool b_create ) +{ + libvlc_media_list_t *p_subitems = NULL; + + vlc_mutex_lock( &p_md->subitems_lock ); + if( p_md->p_subitems == NULL && b_create ) + { + p_md->p_subitems = libvlc_media_list_new( p_md->p_libvlc_instance ); + if( p_md->p_subitems != NULL ) + { + p_md->p_subitems->b_read_only = true; + p_md->p_subitems->p_internal_md = p_md; + } + } + p_subitems = p_md->p_subitems; + vlc_mutex_unlock( &p_md->subitems_lock ); + return p_subitems; +} + /************************************************************************** * input_item_subitem_added (Private) (vlc event Callback) **************************************************************************/ @@ -111,6 +132,7 @@ static void input_item_subitem_added( const vlc_event_t *p_event, { libvlc_media_t * p_md = user_data; libvlc_media_t * p_md_child; + libvlc_media_list_t *p_subitems; libvlc_event_t event; p_md_child = libvlc_media_new_from_input_item( @@ -118,14 +140,13 @@ static void input_item_subitem_added( const vlc_event_t *p_event, p_event->u.input_item_subitem_added.p_new_child ); /* Add this to our media list */ - if( p_md->p_subitems == NULL ) + p_subitems = media_get_subitems( p_md, true ); + if( p_subitems != NULL ) { - p_md->p_subitems = libvlc_media_list_new( p_md->p_libvlc_instance ); - if( unlikely(p_md->p_subitems == NULL) ) - abort(); - libvlc_media_list_set_media( p_md->p_subitems, p_md ); + libvlc_media_list_lock( p_subitems ); + libvlc_media_list_internal_add_media( p_subitems, p_md_child ); + libvlc_media_list_unlock( p_subitems ); } - libvlc_media_list_add_media( p_md->p_subitems, p_md_child ); /* Construct the event */ event.type = libvlc_MediaSubItemAdded; @@ -215,6 +236,25 @@ static void input_item_preparsed_changed(const vlc_event_t *p_event, libvlc_event_send(media->p_event_manager, &event); } +/************************************************************************** + * input_item_preparse_ended (Private) (vlc event Callback) + **************************************************************************/ +static void input_item_preparse_ended( const vlc_event_t * p_event, + void * user_data ) +{ + VLC_UNUSED( p_event ); + libvlc_media_t * p_md = user_data; + libvlc_media_list_t *p_subitems = media_get_subitems( p_md, false ); + + if( p_subitems != NULL ) + { + /* notify the media list */ + libvlc_media_list_lock( p_subitems ); + libvlc_media_list_internal_end_reached( p_subitems ); + libvlc_media_list_unlock( p_subitems ); + } +} + /************************************************************************** * Install event handler (Private) **************************************************************************/ @@ -240,6 +280,10 @@ static void install_input_item_observer( libvlc_media_t *p_md ) vlc_InputItemSubItemTreeAdded, input_item_subitemtree_added, p_md ); + vlc_event_attach( &p_md->p_input_item->event_manager, + vlc_InputItemPreparseEnded, + input_item_preparse_ended, + p_md ); } /************************************************************************** @@ -267,6 +311,10 @@ static void uninstall_input_item_observer( libvlc_media_t *p_md ) vlc_InputItemSubItemTreeAdded, input_item_subitemtree_added, p_md ); + vlc_event_detach( &p_md->p_input_item->event_manager, + vlc_InputItemPreparseEnded, + input_item_preparse_ended, + p_md ); } /************************************************************************** @@ -299,6 +347,7 @@ libvlc_media_t * libvlc_media_new_from_input_item( vlc_cond_init(&p_md->parsed_cond); vlc_mutex_init(&p_md->parsed_lock); + vlc_mutex_init(&p_md->subitems_lock); p_md->state = libvlc_NothingSpecial; @@ -385,6 +434,7 @@ libvlc_media_t * libvlc_media_new_as_node( libvlc_instance_t *p_instance, { input_item_t * p_input_item; libvlc_media_t * p_md; + libvlc_media_list_t * p_subitems; p_input_item = input_item_New( "vlc://nop", psz_name ); @@ -396,7 +446,11 @@ libvlc_media_t * libvlc_media_new_as_node( libvlc_instance_t *p_instance, p_md = libvlc_media_new_from_input_item( p_instance, p_input_item ); - p_md->p_subitems = libvlc_media_list_new( p_md->p_libvlc_instance ); + p_subitems = media_get_subitems( p_md, true ); + if( p_subitems == NULL) { + libvlc_media_release( p_md ); + return NULL; + } return p_md; } @@ -447,6 +501,7 @@ void libvlc_media_release( libvlc_media_t *p_md ) vlc_cond_destroy( &p_md->parsed_cond ); vlc_mutex_destroy( &p_md->parsed_lock ); + vlc_mutex_destroy( &p_md->subitems_lock ); /* Construct the event */ libvlc_event_t event; @@ -569,9 +624,10 @@ libvlc_media_set_state( libvlc_media_t *p_md, libvlc_media_list_t * libvlc_media_subitems( libvlc_media_t * p_md ) { - if( p_md->p_subitems ) - libvlc_media_list_retain( p_md->p_subitems ); - return p_md->p_subitems; + libvlc_media_list_t *p_subitems = media_get_subitems( p_md, true ); + if( p_subitems ) + libvlc_media_list_retain( p_subitems ); + return p_subitems; } /************************************************************************** @@ -640,14 +696,51 @@ libvlc_media_get_duration( libvlc_media_t * p_md ) return from_mtime(input_item_GetDuration( p_md->p_input_item )); } -static int media_parse(libvlc_media_t *media) +static int media_parse(libvlc_media_t *media, bool b_async, + libvlc_media_parse_flag_t parse_flag) { - libvlc_int_t *libvlc = media->p_libvlc_instance->p_libvlc_int; - input_item_t *item = media->p_input_item; + bool needed; + + vlc_mutex_lock(&media->parsed_lock); + needed = !media->has_asked_preparse; + media->has_asked_preparse = true; + vlc_mutex_unlock(&media->parsed_lock); + + if (needed) + { + libvlc_int_t *libvlc = media->p_libvlc_instance->p_libvlc_int; + input_item_t *item = media->p_input_item; + input_item_meta_request_option_t art_scope = META_REQUEST_OPTION_NONE; + input_item_meta_request_option_t parse_scope = META_REQUEST_OPTION_SCOPE_LOCAL; + int ret; + + if (parse_flag & libvlc_media_fetch_local) + art_scope |= META_REQUEST_OPTION_SCOPE_LOCAL; + if (parse_flag & libvlc_media_fetch_network) + art_scope |= META_REQUEST_OPTION_SCOPE_NETWORK; + if (art_scope != META_REQUEST_OPTION_NONE) { + ret = libvlc_ArtRequest(libvlc, item, art_scope); + if (ret != VLC_SUCCESS) + return ret; + } + + if (parse_flag & libvlc_media_parse_network) + parse_scope |= META_REQUEST_OPTION_SCOPE_NETWORK; + ret = libvlc_MetaRequest(libvlc, item, parse_scope); + if (ret != VLC_SUCCESS) + return ret; + } + else + return VLC_EGENERIC; - /* TODO: Fetch art on need basis. But how not to break compatibility? */ - libvlc_ArtRequest(libvlc, item, META_REQUEST_OPTION_NONE); - return libvlc_MetaRequest(libvlc, item, META_REQUEST_OPTION_NONE); + if (!b_async) + { + vlc_mutex_lock(&media->parsed_lock); + while (!media->is_parsed) + vlc_cond_wait(&media->parsed_cond, &media->parsed_lock); + vlc_mutex_unlock(&media->parsed_lock); + } + return VLC_SUCCESS; } /************************************************************************** @@ -656,21 +749,7 @@ static int media_parse(libvlc_media_t *media) void libvlc_media_parse(libvlc_media_t *media) { - vlc_mutex_lock(&media->parsed_lock); - if (!media->has_asked_preparse) - { - media->has_asked_preparse = true; - vlc_mutex_unlock(&media->parsed_lock); - - if (media_parse(media)) - /* Parse failed: do not wait! */ - return; - vlc_mutex_lock(&media->parsed_lock); - } - - while (!media->is_parsed) - vlc_cond_wait(&media->parsed_cond, &media->parsed_lock); - vlc_mutex_unlock(&media->parsed_lock); + media_parse( media, false, libvlc_media_fetch_local ); } /************************************************************************** @@ -679,15 +758,17 @@ libvlc_media_parse(libvlc_media_t *media) void libvlc_media_parse_async(libvlc_media_t *media) { - bool needed; - - vlc_mutex_lock(&media->parsed_lock); - needed = !media->has_asked_preparse; - media->has_asked_preparse = true; - vlc_mutex_unlock(&media->parsed_lock); + media_parse( media, true, libvlc_media_fetch_local ); +} - if (needed) - media_parse(media); +/************************************************************************** + * Parse the media asynchronously with options. + **************************************************************************/ +int +libvlc_media_parse_with_options( libvlc_media_t *media, + libvlc_media_parse_flag_t parse_flag ) +{ + return media_parse( media, true, parse_flag ) == VLC_SUCCESS ? 0 : -1; } /************************************************************************** @@ -918,3 +999,35 @@ void libvlc_media_tracks_release( libvlc_media_track_t **p_tracks, unsigned i_co } free( p_tracks ); } + +/************************************************************************** + * Get the media type of the media descriptor object + **************************************************************************/ +libvlc_media_type_t libvlc_media_get_type( libvlc_media_t *p_md ) +{ + assert( p_md ); + + int i_type; + input_item_t *p_input_item = p_md->p_input_item; + + vlc_mutex_lock( &p_input_item->lock ); + i_type = p_md->p_input_item->i_type; + vlc_mutex_unlock( &p_input_item->lock ); + + switch( i_type ) + { + case ITEM_TYPE_FILE: + return libvlc_media_type_file; + case ITEM_TYPE_NODE: + case ITEM_TYPE_DIRECTORY: + return libvlc_media_type_directory; + case ITEM_TYPE_DISC: + return libvlc_media_type_disc; + case ITEM_TYPE_STREAM: + return libvlc_media_type_stream; + case ITEM_TYPE_PLAYLIST: + return libvlc_media_type_playlist; + default: + return libvlc_media_type_unknown; + } +}