X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=lib%2Fmedia.c;h=1d01c11c425a60a050c891bc9321cffe9d4ed63a;hb=f3cc5c9f0f1512eb0a69ec4a080bebc609b3645c;hp=ef845cd7e855bd2186c9a1a5302b51b62184fac4;hpb=8db74e209c60dc5a529d114f7c0b51ead1c64955;p=vlc diff --git a/lib/media.c b/lib/media.c index ef845cd7e8..1d01c11c42 100644 --- a/lib/media.c +++ b/lib/media.c @@ -26,6 +26,7 @@ #endif #include +#include #include #include @@ -42,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[] = { @@ -67,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[] = @@ -85,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, @@ -94,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) **************************************************************************/ @@ -105,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( @@ -112,14 +140,12 @@ 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 ) - { - p_md->p_subitems = libvlc_media_list_new( p_md->p_libvlc_instance ); - libvlc_media_list_set_media( p_md->p_subitems, p_md ); - } - if( p_md->p_subitems ) + p_subitems = media_get_subitems( p_md, true ); + if( p_subitems != NULL ) { - libvlc_media_list_add_media( p_md->p_subitems, p_md_child ); + libvlc_media_list_lock( p_subitems ); + libvlc_media_list_internal_add_media( p_subitems, p_md_child ); + libvlc_media_list_unlock( p_subitems ); } /* Construct the event */ @@ -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; @@ -355,7 +409,7 @@ libvlc_media_t *libvlc_media_new_path( libvlc_instance_t *p_instance, char *mrl = vlc_path2uri( path, NULL ); if( unlikely(mrl == NULL) ) { - libvlc_printerr( "Not enough memory" ); + libvlc_printerr( "%s", vlc_strerror_c(errno) ); return NULL; } @@ -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; - /* TODO: Fetch art on need basis. But how not to break compatibility? */ - libvlc_ArtRequest(libvlc, item); - return libvlc_MetaRequest(libvlc, item); + 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; + + 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 @@ -885,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; + } +}