]> git.sesse.net Git - vlc/blobdiff - lib/media.c
libvlc: add libvlc_media_get_type
[vlc] / lib / media.c
index 7e455f7a35a4558780a2c109752ba85f7303e0a7..1d01c11c425a60a050c891bc9321cffe9d4ed63a 100644 (file)
@@ -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;
+    }
+}