X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=lib%2Fmedia.c;h=9ccfb25a4872737ec130d6a5856481d2b458f649;hb=6e8d1764f191317f793dbd4b5df60ce040d38358;hp=1f6fb9e8a1283add3aaee094114586f00beb30b9;hpb=41af9ab209cceb3b59cecc4173aeca72c7701198;p=vlc diff --git a/lib/media.c b/lib/media.c index 1f6fb9e8a1..9ccfb25a48 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[] = { @@ -68,7 +69,9 @@ static const vlc_meta_type_t libvlc_to_vlc_meta[] = [libvlc_meta_Season] = vlc_meta_Season, [libvlc_meta_Episode] = vlc_meta_Episode, [libvlc_meta_ShowName] = vlc_meta_ShowName, - [libvlc_meta_Actors] = vlc_meta_Actors + [libvlc_meta_Actors] = vlc_meta_Actors, + [libvlc_meta_AlbumArtist] = vlc_meta_AlbumArtist, + [libvlc_meta_DiscNumber] = vlc_meta_DiscNumber }; static const libvlc_meta_t vlc_to_libvlc_meta[] = @@ -86,6 +89,7 @@ static const libvlc_meta_t vlc_to_libvlc_meta[] = [vlc_meta_URL] = libvlc_meta_URL, [vlc_meta_Language] = libvlc_meta_Language, [vlc_meta_NowPlaying] = libvlc_meta_NowPlaying, + [vlc_meta_ESNowPlaying] = libvlc_meta_NowPlaying, [vlc_meta_Publisher] = libvlc_meta_Publisher, [vlc_meta_EncodedBy] = libvlc_meta_EncodedBy, [vlc_meta_ArtworkURL] = libvlc_meta_ArtworkURL, @@ -95,9 +99,31 @@ static const libvlc_meta_t vlc_to_libvlc_meta[] = [vlc_meta_Season] = libvlc_meta_Season, [vlc_meta_Episode] = libvlc_meta_Episode, [vlc_meta_ShowName] = libvlc_meta_ShowName, - [vlc_meta_Actors] = libvlc_meta_Actors + [vlc_meta_Actors] = libvlc_meta_Actors, + [vlc_meta_AlbumArtist] = libvlc_meta_AlbumArtist, + [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) **************************************************************************/ @@ -106,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( @@ -113,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; @@ -210,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) **************************************************************************/ @@ -235,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 ); } /************************************************************************** @@ -262,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 ); } /************************************************************************** @@ -294,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; @@ -380,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 ); @@ -391,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; } @@ -442,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; @@ -491,13 +551,21 @@ libvlc_media_get_mrl( libvlc_media_t * p_md ) char *libvlc_media_get_meta( libvlc_media_t *p_md, libvlc_meta_t e_meta ) { - char *psz_meta = input_item_GetMeta( p_md->p_input_item, - libvlc_to_vlc_meta[e_meta] ); - /* Should be integrated in core */ - if( psz_meta == NULL && e_meta == libvlc_meta_Title - && p_md->p_input_item->psz_name != NULL ) - psz_meta = strdup( p_md->p_input_item->psz_name ); + char *psz_meta = NULL; + if( e_meta == libvlc_meta_NowPlaying ) + { + psz_meta = input_item_GetNowPlayingFb( p_md->p_input_item ); + } + else + { + psz_meta = input_item_GetMeta( p_md->p_input_item, + libvlc_to_vlc_meta[e_meta] ); + /* Should be integrated in core */ + if( psz_meta == NULL && e_meta == libvlc_meta_Title + && p_md->p_input_item->psz_name != NULL ) + psz_meta = strdup( p_md->p_input_item->psz_name ); + } return psz_meta; } @@ -556,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; } /************************************************************************** @@ -627,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); - /* 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 (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; + + 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; } /************************************************************************** @@ -643,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 ); } /************************************************************************** @@ -666,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; } /************************************************************************** @@ -855,6 +949,26 @@ libvlc_media_tracks_get( libvlc_media_t *p_md, libvlc_media_track_t *** pp_es ) return i_es; } +/************************************************************************** + * Get codec description from media elementary stream + **************************************************************************/ +const char * +libvlc_media_get_codec_description( libvlc_track_type_t i_type, + uint32_t i_codec ) +{ + switch( i_type ) + { + case libvlc_track_audio: + return vlc_fourcc_GetDescription( AUDIO_ES, i_codec ); + case libvlc_track_video: + return vlc_fourcc_GetDescription( VIDEO_ES, i_codec ); + case libvlc_track_text: + return vlc_fourcc_GetDescription( SPU_ES, i_codec ); + case libvlc_track_unknown: + default: + return vlc_fourcc_GetDescription( UNKNOWN_ES, i_codec ); + } +} /************************************************************************** * Release media descriptor's elementary streams description array