[vlc-devel] [PATCH] libvlc_media_list: add parse_start / parse_stop

Thomas Guillem thomas at gllm.fr
Tue Dec 23 18:36:06 CET 2014


---
 include/vlc/libvlc_media_list.h |  27 ++++++++++
 lib/libvlc.sym                  |   2 +
 lib/media_list.c                | 108 ++++++++++++++++++++++++++++++++++++++++
 lib/media_list_internal.h       |   2 +
 4 files changed, 139 insertions(+)

diff --git a/include/vlc/libvlc_media_list.h b/include/vlc/libvlc_media_list.h
index 015824b..b950d84 100644
--- a/include/vlc/libvlc_media_list.h
+++ b/include/vlc/libvlc_media_list.h
@@ -93,6 +93,33 @@ LIBVLC_API libvlc_media_t *
     libvlc_media_list_media( libvlc_media_list_t *p_ml );
 
 /**
+ * Parse the media (a directory, an archive or a playlist) associated with this
+ * media list instance.
+ * Parsing is asynchronous, new items will be added in background.
+ * Listen to libvlc_MediaListItemAdded events to get notified of new items.
+ * The libvlc_media_list_lock should NOT be held upon entering this function.
+ *
+ * \see libvlc_media_list_set_media
+ * \see libvlc_media_list_parse_stop
+ *
+ * \param p_ml a media list instance
+ * \return 0 on success, -1 on error or if the media list is read-only
+ */
+LIBVLC_API int
+libvlc_media_list_parse_start( libvlc_media_list_t *p_ml );
+
+/**
+ * Stop previous media parsing initiated by parse_start.
+ * The libvlc_media_list_lock should NOT be held upon entering this function.
+ *
+ * \see libvlc_media_list_parse_start
+ *
+ * \param p_ml a media list instance
+ */
+LIBVLC_API void
+libvlc_media_list_parse_stop( libvlc_media_list_t *p_ml );
+
+/**
  * Add media instance to media list
  * The libvlc_media_list_lock should be held upon entering this function.
  *
diff --git a/lib/libvlc.sym b/lib/libvlc.sym
index f0512c6..38c17d7 100644
--- a/lib/libvlc.sym
+++ b/lib/libvlc.sym
@@ -107,6 +107,8 @@ libvlc_media_list_item_at_index
 libvlc_media_list_lock
 libvlc_media_list_media
 libvlc_media_list_new
+libvlc_media_list_parse_start
+libvlc_media_list_parse_stop
 libvlc_media_list_player_event_manager
 libvlc_media_list_player_get_state
 libvlc_media_list_player_is_playing
diff --git a/lib/media_list.c b/lib/media_list.c
index 39bc354..70f92c6 100644
--- a/lib/media_list.c
+++ b/lib/media_list.c
@@ -123,6 +123,33 @@ notify_item_deletion( libvlc_media_list_t * p_mlist,
 }
 
 /**************************************************************************
+ *       input_item_add_subitem (private)
+ *
+ * Callback when new item is found by input thread (via parse_start)
+ **************************************************************************/
+static void input_item_add_subitem ( const vlc_event_t * p_event,
+                                     void * user_data )
+{
+    libvlc_media_list_t *p_mlist = user_data;
+    input_item_t *p_item = p_event->u.input_item_subitem_added.p_new_child;
+    libvlc_media_t *p_md;
+
+    if (!p_item)
+        return;
+
+    p_md = libvlc_media_new_from_input_item( p_mlist->p_libvlc_instance,
+                                             p_item );
+    if (!p_md)
+        return;
+
+    vlc_mutex_lock( &p_mlist->object_lock );
+    _libvlc_media_list_add_media( p_mlist, p_md );
+    vlc_mutex_unlock( &p_mlist->object_lock );
+
+    libvlc_media_release( p_md );
+}
+
+/**************************************************************************
  *       static mlist_is_writable (private)
  **************************************************************************/
 static inline
@@ -179,11 +206,13 @@ libvlc_media_list_new( libvlc_instance_t * p_inst )
 
     vlc_mutex_init( &p_mlist->object_lock );
     vlc_mutex_init( &p_mlist->refcount_lock ); // FIXME: spinlock?
+    vlc_mutex_init( &p_mlist->input_lock );
 
     vlc_array_init( &p_mlist->items );
     assert( p_mlist->items.i_count == 0 );
     p_mlist->i_refcount = 1;
     p_mlist->p_md = NULL;
+    p_mlist->p_input_thread = NULL;
 
     return p_mlist;
 }
@@ -209,6 +238,8 @@ void libvlc_media_list_release( libvlc_media_list_t * p_mlist )
 
     /* Refcount null, time to free */
 
+    libvlc_media_list_parse_stop( p_mlist );
+
     libvlc_event_manager_release( p_mlist->p_event_manager );
 
     libvlc_media_release( p_mlist->p_md );
@@ -221,6 +252,7 @@ void libvlc_media_list_release( libvlc_media_list_t * p_mlist )
 
     vlc_mutex_destroy( &p_mlist->object_lock );
     vlc_mutex_destroy( &p_mlist->refcount_lock );
+    vlc_mutex_destroy( &p_mlist->input_lock );
     vlc_array_clear( &p_mlist->items );
 
     free( p_mlist );
@@ -284,6 +316,8 @@ void libvlc_media_list_set_media( libvlc_media_list_t * p_mlist,
                                   libvlc_media_t * p_md )
 
 {
+    libvlc_media_list_parse_stop( p_mlist );
+
     vlc_mutex_lock( &p_mlist->object_lock );
     libvlc_media_release( p_mlist->p_md );
     libvlc_media_retain( p_md );
@@ -315,6 +349,80 @@ libvlc_media_list_media( libvlc_media_list_t * p_mlist )
 }
 
 /**************************************************************************
+ *       parse_start (Public)
+ **************************************************************************/
+int libvlc_media_list_parse_start( libvlc_media_list_t * p_mlist )
+{
+    int ret = -1;
+    libvlc_media_t *p_md;
+
+    vlc_mutex_lock( &p_mlist->object_lock );
+    p_md = p_mlist->b_read_only ? NULL : p_mlist->p_md;
+    if( p_md )
+        libvlc_media_retain( p_md );
+    vlc_mutex_unlock( &p_mlist->object_lock );
+    if( !p_md )
+        return ret;
+
+    vlc_mutex_lock( &p_mlist->input_lock );
+    if( !p_mlist->p_input_thread )
+    {
+        vlc_event_manager_t *p_em = &p_md->p_input_item->event_manager;
+
+        vlc_event_attach( p_em, vlc_InputItemSubItemAdded,
+                          input_item_add_subitem, p_mlist );
+
+        p_mlist->p_input_thread = input_CreateAndStart(
+                                    p_mlist->p_libvlc_instance->p_libvlc_int,
+                                    p_md->p_input_item, NULL );
+
+        if( p_mlist->p_input_thread )
+            ret = 0;
+        else
+        {
+            vlc_event_detach( p_em, vlc_InputItemSubItemAdded,
+                              input_item_add_subitem, p_mlist );
+            libvlc_media_release( p_md );
+        }
+    }
+    vlc_mutex_unlock( &p_mlist->input_lock );
+    return ret;
+}
+
+/**************************************************************************
+ *       parse_stop (Public)
+ **************************************************************************/
+void libvlc_media_list_parse_stop( libvlc_media_list_t * p_mlist )
+{
+    libvlc_media_t *p_md;
+
+    vlc_mutex_lock( &p_mlist->object_lock );
+    p_md = p_mlist->p_md;
+    vlc_mutex_unlock( &p_mlist->object_lock );
+    if( !p_md )
+        return;
+
+    vlc_mutex_lock( &p_mlist->input_lock );
+    if( p_mlist->p_input_thread )
+    {
+        vlc_event_manager_t *p_em = &p_md->p_input_item->event_manager;
+
+        /* object_lock shouldn't be hold when detaching events since
+         * input_item_add_subitem callback can hold this mutex too */
+        vlc_event_detach( p_em, vlc_InputItemSubItemAdded,
+                          input_item_add_subitem, p_mlist );
+
+        input_Stop( p_mlist->p_input_thread, true );
+        input_Close( p_mlist->p_input_thread );
+
+        p_mlist->p_input_thread = NULL;
+
+        libvlc_media_release( p_md );
+    }
+    vlc_mutex_unlock( &p_mlist->input_lock );
+}
+
+/**************************************************************************
  *       libvlc_media_list_count (Public)
  *
  * Lock should be held when entering.
diff --git a/lib/media_list_internal.h b/lib/media_list_internal.h
index 8df6579..818908a 100644
--- a/lib/media_list_internal.h
+++ b/lib/media_list_internal.h
@@ -45,6 +45,8 @@ struct libvlc_media_list_t
     libvlc_media_t * p_md; /* The media from which the
                                        * mlist comes, if any. */
     vlc_array_t                items;
+    input_thread_t *           p_input_thread;
+    vlc_mutex_t                input_lock;
 
     /* This indicates if this media list is read-only
      * from a user point of view */
-- 
2.1.3




More information about the vlc-devel mailing list