control/dynamic_media_list.c: New dynamic media list object. It shouldn't have great...
authorPierre d'Herbemont <pdherbemont@videolan.org>
Mon, 20 Aug 2007 01:13:42 +0000 (01:13 +0000)
committerPierre d'Herbemont <pdherbemont@videolan.org>
Mon, 20 Aug 2007 01:13:42 +0000 (01:13 +0000)
The idea is to have create a media list using the item of an other that matches a certain query.

include/vlc/libvlc.h
include/vlc/libvlc_structures.h
src/control/dynamic_media_list.c [new file with mode: 0644]
src/control/libvlc_internal.h
src/control/media_list.c

index cf1bd8f..13358e4 100644 (file)
@@ -532,16 +532,35 @@ VLC_PUBLIC_API void
 VLC_PUBLIC_API libvlc_event_manager_t *
     libvlc_media_list_event_manager( libvlc_media_list_t *,
                                     libvlc_exception_t * );
 VLC_PUBLIC_API libvlc_event_manager_t *
     libvlc_media_list_event_manager( libvlc_media_list_t *,
                                     libvlc_exception_t * );
+/** @} */
 
 
-VLC_PUBLIC_API libvlc_media_list_t *
-    libvlc_media_list_dynamic_sublist( libvlc_media_list_t *,
-                                       libvlc_tag_query_t *,
-                                       libvlc_exception_t * );
+/*****************************************************************************
+ * Dynamic Media List
+ *****************************************************************************/
+/** defgroup libvlc_media_list MediaList
+ * \ingroup libvlc
+ * LibVLC Media List
+ * @{ */
+
+VLC_PUBLIC_API libvlc_dynamic_media_list_t *
+    libvlc_dynamic_media_list_new(  libvlc_media_list_t * p_mlist,
+                                    libvlc_tag_query_t * p_query,
+                                    libvlc_tag_t tag,
+                                    libvlc_exception_t * p_e );
+VLC_PUBLIC_API void
+    libvlc_dynamic_media_list_release( libvlc_dynamic_media_list_t * p_dmlist );
+
+VLC_PUBLIC_API void
+    libvlc_dynamic_media_list_retain( libvlc_dynamic_media_list_t * p_dmlist );
+
+libvlc_media_list_t *
+    libvlc_dynamic_media_list_media_list( libvlc_dynamic_media_list_t * p_dmlist,
+                                          libvlc_exception_t * p_e );
 
 /** @} */
 
 /*****************************************************************************
 
 /** @} */
 
 /*****************************************************************************
- * Media List
+ * Media Library
  *****************************************************************************/
 /** defgroup libvlc_media_library Media Library
  * \ingroup libvlc
  *****************************************************************************/
 /** defgroup libvlc_media_library Media Library
  * \ingroup libvlc
index 01ade2f..54c5b86 100644 (file)
@@ -151,6 +151,20 @@ typedef struct libvlc_media_list_t libvlc_media_list_t;
 
 /**@} */
 
 
 /**@} */
 
+/*****************************************************************************
+ * Dynamic Media List
+ *****************************************************************************/
+/** defgroup libvlc_media_list MediaList
+ * \ingroup libvlc
+ * LibVLC Dynamic Media list: Media list with content synchronized with
+ * an other playlist
+ * @{
+ */
+
+typedef struct libvlc_dynamic_media_list_t libvlc_dynamic_media_list_t;
+
+/**@} */
+
 /*****************************************************************************
  * Media List Player
  *****************************************************************************/
 /*****************************************************************************
  * Media List Player
  *****************************************************************************/
diff --git a/src/control/dynamic_media_list.c b/src/control/dynamic_media_list.c
new file mode 100644 (file)
index 0000000..7ba9339
--- /dev/null
@@ -0,0 +1,289 @@
+/*****************************************************************************
+ * dynamic_media_list.c: libvlc new API media list functions
+ *****************************************************************************
+ * Copyright (C) 2007 the VideoLAN team
+ * $Id$
+ *
+ * Authors: Pierre d'Herbemont <pdherbemont # videolan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#include "libvlc_internal.h"
+#include <vlc/libvlc.h>
+#include <assert.h>
+#include "vlc_arrays.h"
+
+static const char * libvlc_default_dynamic_media_list_tag_key = "VLCPlaylist";
+
+/*
+ * Private functions
+ */
+
+/**************************************************************************
+ *       own_media_list_item_added (private) (Event Callback)
+ **************************************************************************/
+static void
+own_media_list_item_added( const libvlc_event_t * p_event, void * p_user_data )
+{
+    /* Add our tag */
+    libvlc_dynamic_media_list_t * p_dmlist = p_user_data;
+    libvlc_media_descriptor_t * p_md = p_event->u.media_list_item_added.item;
+
+    if( !p_dmlist->tag || !p_dmlist->psz_tag_key )
+        return;
+
+    libvlc_media_descriptor_add_tag( p_md, p_dmlist->tag,
+                p_dmlist->psz_tag_key, NULL );
+}
+
+/**************************************************************************
+ *       own_media_list_item_removed (private) (Event Callback)
+ **************************************************************************/
+static void
+own_media_list_item_deleted( const libvlc_event_t * p_event, void * p_user_data )
+{
+    /* Remove our tag */
+    libvlc_dynamic_media_list_t * p_dmlist = p_user_data;
+    libvlc_media_descriptor_t * p_md = p_event->u.media_list_item_added.item;
+
+    if( !p_dmlist->tag || !p_dmlist->psz_tag_key )
+        return;
+
+    libvlc_media_descriptor_remove_tag( p_md, p_dmlist->tag,
+                p_dmlist->psz_tag_key, NULL );
+}
+
+
+/**************************************************************************
+ *       dynamic_list_propose_item (private) (Event Callback)
+ *
+ * This is called if the dynamic sublist's data provider adds a new item.
+ **************************************************************************/
+static void
+dynamic_list_propose_item( const libvlc_event_t * p_event, void * p_user_data )
+{
+    /* Check if the item matches our tag query */
+    libvlc_dynamic_media_list_t * p_dmlist = p_user_data;
+    libvlc_media_descriptor_t * p_md = p_event->u.media_list_item_added.item;
+
+    //libvlc_media_descriptor_lock( p_md );
+    if( libvlc_tag_query_match( p_dmlist->p_query, p_md, NULL ) )
+    {
+        int i = libvlc_media_list_index_of_item( p_dmlist->p_mlist, p_md, NULL );
+        if( i >= 0 )
+        {
+            /* We already have it */
+            libvlc_media_list_unlock( p_dmlist->p_mlist );
+            return;
+        }
+        
+        libvlc_media_list_lock( p_dmlist->p_mlist );
+        libvlc_media_list_add_media_descriptor( p_dmlist->p_mlist, p_md, NULL );
+        libvlc_media_list_unlock( p_dmlist->p_mlist );
+    }
+    //libvlc_media_descriptor_unlock( p_md );
+}
+
+/**************************************************************************
+ *       dynamic_list_remove_item (private) (Event Callback)
+ *
+ * This is called if the dynamic sublist's data provider adds a new item.
+ **************************************************************************/
+static void
+dynamic_list_remove_item( const libvlc_event_t * p_event, void * p_user_data )
+{
+    /* Remove the item here too if we have it */
+    libvlc_dynamic_media_list_t * p_dmlist = p_user_data;
+    libvlc_media_descriptor_t * p_md = p_event->u.media_list_item_deleted.item;
+
+    //libvlc_media_descriptor_lock( p_md );
+    if( libvlc_tag_query_match( p_dmlist->p_query, p_md, NULL ) )
+    {
+        int i;
+        libvlc_media_list_lock( p_dmlist->p_mlist );        
+        i = libvlc_media_list_index_of_item( p_dmlist->p_mlist, p_md, NULL );
+        if ( i < 0 )
+        {
+            /* We've missed one item addition, that could happen especially
+             * if we add item in a threaded maner, so we just ignore */
+            libvlc_media_list_unlock( p_dmlist->p_mlist );
+            //libvlc_media_descriptor_unlock( p_md );           
+            return;
+        }
+        libvlc_media_list_remove_index( p_dmlist->p_mlist, i, NULL );
+        libvlc_media_list_unlock( p_dmlist->p_mlist );
+    }
+    //libvlc_media_descriptor_unlock( p_md );
+}
+
+/**************************************************************************
+ *       dynamic_list_change_item (private) (Event Callback)
+ *
+ * This is called if the dynamic sublist's data provider adds a new item.
+ **************************************************************************/
+static void
+dynamic_list_change_item( const libvlc_event_t * p_event , void * p_user_data)
+{
+    /* Check if the item matches still our tag query */
+
+    libvlc_dynamic_media_list_t * p_dmlist = p_user_data;
+    libvlc_media_descriptor_t * p_md = p_event->u.media_list_item_changed.item;
+    int index;
+
+    libvlc_media_list_lock( p_dmlist->p_mlist );        
+    
+    index = libvlc_media_list_index_of_item( p_dmlist->p_mlist, p_md, NULL );
+    if( index < 0 )
+    {
+        libvlc_media_list_unlock( p_dmlist->p_mlist );     
+        return; /* Not found, no prob, just ignore */
+    }
+
+    //libvlc_media_descriptor_lock( p_md );
+    if( !libvlc_tag_query_match( p_dmlist->p_query, p_md, NULL ) )
+        libvlc_media_list_remove_index( p_dmlist->p_mlist, index, NULL );
+    //libvlc_media_descriptor_unlock( p_md );
+
+    libvlc_media_list_unlock( p_dmlist->p_mlist );        
+}
+
+/*
+ * Public libvlc functions
+ */
+
+/**************************************************************************
+ *       new (Public)
+ **************************************************************************/
+libvlc_dynamic_media_list_t *
+libvlc_dynamic_media_list_new(
+                libvlc_media_list_t * p_mlist,
+                libvlc_tag_query_t * p_query,
+                libvlc_tag_t tag,
+                libvlc_exception_t * p_e )
+{
+    libvlc_dynamic_media_list_t * p_dmlist;
+    libvlc_event_manager_t * p_em;
+    int count, i;
+
+    (void)p_e;
+
+    p_dmlist = malloc(sizeof(libvlc_dynamic_media_list_t));
+
+    if( !p_mlist )
+        return NULL;
+
+    p_dmlist->i_refcount = 1;
+    p_dmlist->p_libvlc_instance = p_mlist->p_libvlc_instance;
+    p_dmlist->tag = strdup( tag );
+    p_dmlist->psz_tag_key = strdup( libvlc_default_dynamic_media_list_tag_key );
+
+    p_dmlist->p_mlist = libvlc_media_list_new( p_mlist->p_libvlc_instance, p_e );
+    if( !p_dmlist->p_mlist )
+    {
+        if( !libvlc_exception_raised( p_e ) )
+            libvlc_exception_raise( p_e, "Can't get the new media_list" );
+        return NULL;
+    }
+
+    /* We have a query */
+    libvlc_tag_query_retain( p_query );
+    p_dmlist->p_query = p_query;
+
+    /* We have a media provider */
+    libvlc_media_list_retain( p_mlist );
+    p_dmlist->p_media_provider = p_mlist;
+
+    libvlc_media_list_lock( p_mlist );        
+    
+    count = libvlc_media_list_count( p_mlist, p_e );
+
+    /* This should be running in a thread, a good plan to achieve that
+     * move all the dynamic code to libvlc_tag_query. */
+    for( i = 0; i < count; i++ )
+    {
+        libvlc_media_descriptor_t * p_md;
+        p_md = libvlc_media_list_item_at_index( p_mlist, i, p_e );
+        if( libvlc_tag_query_match( p_query, p_md, NULL ) )
+            libvlc_media_list_add_media_descriptor( p_dmlist, p_md, p_e );
+    }
+
+    /* And we will listen to its event, so we can update p_dmlist->p_mlist
+     * accordingly */
+    p_em = libvlc_media_list_event_manager( p_mlist, p_e );
+    libvlc_event_attach( p_em, libvlc_MediaListItemAdded,
+                         dynamic_list_propose_item, p_dmlist, p_e );
+    libvlc_event_attach( p_em, libvlc_MediaListItemDeleted,
+                         dynamic_list_remove_item, p_dmlist, p_e );
+    libvlc_event_attach( p_em, libvlc_MediaListItemChanged,
+                         dynamic_list_change_item, p_dmlist, p_e );
+
+    libvlc_media_list_unlock( p_mlist );        
+
+    /* Make sure item added/removed will gain/loose our mark */
+    p_em = libvlc_media_list_event_manager( p_dmlist->p_mlist, p_e );
+    libvlc_event_attach( p_em, libvlc_MediaListItemAdded,
+                         own_media_list_item_added, p_dmlist, p_e );
+    libvlc_event_attach( p_em, libvlc_MediaListItemDeleted,
+                         own_media_list_item_deleted, p_dmlist, p_e );
+
+
+    return p_dmlist;
+}
+
+/**************************************************************************
+ *       release (Public)
+ *
+ * Release an object.
+ **************************************************************************/
+void libvlc_dynamic_media_list_release( libvlc_dynamic_media_list_t * p_dmlist )
+{
+    p_dmlist->i_refcount--;
+    if( p_dmlist->i_refcount > 0 )
+        return;
+
+    free( p_dmlist->tag );
+    free( p_dmlist->psz_tag_key );
+
+    /* Refcount null, time to free */
+    if( p_dmlist->p_media_provider )
+        libvlc_media_list_release( p_dmlist->p_media_provider );
+
+    if( p_dmlist->p_query )
+        libvlc_tag_query_release( p_dmlist->p_query );
+    free( p_dmlist );
+}
+
+/**************************************************************************
+ *       retain (Public)
+ **************************************************************************/
+void libvlc_dynamic_media_list_retain( libvlc_dynamic_media_list_t * p_dmlist )
+{
+    p_dmlist->i_refcount++;
+}
+
+
+/**************************************************************************
+ *       media_list (Public)
+ **************************************************************************/
+libvlc_media_list_t *
+libvlc_dynamic_media_list_media_list(
+                                libvlc_dynamic_media_list_t * p_dmlist,
+                                libvlc_exception_t * p_e )
+{
+    libvlc_media_list_retain( p_dmlist->p_mlist );
+    return p_dmlist->p_mlist;
+}
index 4d74fc3..088c739 100644 (file)
@@ -79,7 +79,6 @@ struct libvlc_tag_query_t
     int                i_refcount;
 };
 
     int                i_refcount;
 };
 
-
 struct libvlc_tree_t
 {
     int     i_refcount;
 struct libvlc_tree_t
 {
     int     i_refcount;
@@ -95,12 +94,22 @@ struct libvlc_media_list_t
     libvlc_instance_t *      p_libvlc_instance;
     int                      i_refcount;
     vlc_mutex_t              object_lock;
     libvlc_instance_t *      p_libvlc_instance;
     int                      i_refcount;
     vlc_mutex_t              object_lock;
-    libvlc_media_list_t *    p_media_provider; /* For dynamic sublist */
-    libvlc_tag_query_t *     p_query;              /* For dynamic sublist */
     char *                   psz_name; /* Usually NULL */
     DECL_ARRAY(void *) items;
 };
 
     char *                   psz_name; /* Usually NULL */
     DECL_ARRAY(void *) items;
 };
 
+struct libvlc_dynamic_media_list_t
+{
+    libvlc_instance_t *     p_libvlc_instance;
+    int                     i_refcount;
+    libvlc_media_list_t *   p_media_provider;
+    libvlc_tag_query_t *    p_query;
+    char *                  psz_tag_key;
+    libvlc_tag_t            tag;
+    struct libvlc_media_list_t *  p_mlist;
+    struct libvlc_media_list_t *  p_provider;
+};
+
 struct libvlc_media_instance_t
 {
     int                i_refcount;
 struct libvlc_media_instance_t
 {
     int                i_refcount;
index e717ff9..6b17aff 100644 (file)
@@ -153,87 +153,6 @@ uninstall_media_descriptor_observer( libvlc_media_list_t * p_mlist,
                          p_mlist, NULL );
 }
 
                          p_mlist, NULL );
 }
 
-/**************************************************************************
- *       dynamic_list_propose_item (private) (Event Callback)
- *
- * This is called if the dynamic sublist's data provider adds a new item.
- **************************************************************************/
-static void
-dynamic_list_propose_item( const libvlc_event_t * p_event, void * p_user_data )
-{
-    libvlc_media_list_t * p_submlist = p_user_data;
-    libvlc_media_descriptor_t * p_md = p_event->u.media_list_item_added.item;
-
-    //libvlc_media_descriptor_lock( p_md );
-    if( libvlc_tag_query_match( p_submlist->p_query, p_md, NULL ) )
-    {
-        libvlc_media_list_lock( p_submlist );
-        libvlc_media_list_add_media_descriptor( p_submlist, p_md, NULL );
-        libvlc_media_list_unlock( p_submlist );
-    }
-    //libvlc_media_descriptor_unlock( p_md );
-}
-
-/**************************************************************************
- *       dynamic_list_remove_item (private) (Event Callback)
- *
- * This is called if the dynamic sublist's data provider adds a new item.
- **************************************************************************/
-static void
-dynamic_list_remove_item( const libvlc_event_t * p_event, void * p_user_data )
-{
-    libvlc_media_list_t * p_submlist = p_user_data;
-    libvlc_media_descriptor_t * p_md = p_event->u.media_list_item_deleted.item;
-
-    //libvlc_media_descriptor_lock( p_md );
-    if( libvlc_tag_query_match( p_submlist->p_query, p_md, NULL ) )
-    {
-        int i;
-        libvlc_media_list_lock( p_submlist );        
-        i = libvlc_media_list_index_of_item( p_submlist, p_md, NULL );
-        if ( i < 0 )
-        {
-            /* We've missed one item addition, that could happen especially
-             * if we add item in a threaded maner, so we just ignore */
-            libvlc_media_list_unlock( p_submlist );
-            //libvlc_media_descriptor_unlock( p_md );           
-            return;
-        }
-        libvlc_media_list_remove_index( p_submlist, i, NULL );
-        libvlc_media_list_unlock( p_submlist );
-    }
-    //libvlc_media_descriptor_unlock( p_md );
-}
-
-/**************************************************************************
- *       dynamic_list_change_item (private) (Event Callback)
- *
- * This is called if the dynamic sublist's data provider adds a new item.
- **************************************************************************/
-static void
-dynamic_list_change_item( const libvlc_event_t * p_event , void * p_user_data)
-{
-    libvlc_media_list_t * p_submlist = p_user_data;
-    libvlc_media_descriptor_t * p_md = p_event->u.media_list_item_changed.item;
-    int index;
-
-    libvlc_media_list_lock( p_submlist );        
-    
-    index = libvlc_media_list_index_of_item( p_submlist, p_md, NULL );
-    if( index < 0 )
-    {
-        libvlc_media_list_unlock( p_submlist );     
-        return; /* Not found, no prob, just ignore */
-    }
-
-    //libvlc_media_descriptor_lock( p_md );
-    if( !libvlc_tag_query_match( p_submlist->p_query, p_md, NULL ) )
-        libvlc_media_list_remove_index( p_submlist, index, NULL );
-    //libvlc_media_descriptor_unlock( p_md );
-
-    libvlc_media_list_unlock( p_submlist );        
-}
-
 /*
  * Public libvlc functions
  */
 /*
  * Public libvlc functions
  */
@@ -275,7 +194,6 @@ libvlc_media_list_new( libvlc_instance_t * p_inst,
     
     ARRAY_INIT(p_mlist->items);
     p_mlist->i_refcount = 1;
     
     ARRAY_INIT(p_mlist->items);
     p_mlist->i_refcount = 1;
-    p_mlist->p_media_provider = NULL;
     p_mlist->psz_name = NULL;
 
     return p_mlist;
     p_mlist->psz_name = NULL;
 
     return p_mlist;
@@ -300,11 +218,6 @@ void libvlc_media_list_release( libvlc_media_list_t * p_mlist )
     vlc_mutex_unlock( &p_mlist->object_lock );        
 
     /* Refcount null, time to free */
     vlc_mutex_unlock( &p_mlist->object_lock );        
 
     /* Refcount null, time to free */
-    if( p_mlist->p_media_provider )
-        libvlc_media_list_release( p_mlist->p_media_provider );
-
-    if( p_mlist->p_query )
-        libvlc_tag_query_release( p_mlist->p_query );
 
     libvlc_event_manager_release( p_mlist->p_event_manager );
 
 
     libvlc_event_manager_release( p_mlist->p_event_manager );
 
@@ -537,65 +450,3 @@ libvlc_media_list_event_manager( libvlc_media_list_t * p_mlist,
     (void)p_e;
     return p_mlist->p_event_manager;
 }
     (void)p_e;
     return p_mlist->p_event_manager;
 }
-
-/**************************************************************************
- *       libvlc_media_list_dynamic_sublist (Public)
- *
- * Lock should be hold when entering.
- **************************************************************************/
-libvlc_media_list_t *
-libvlc_media_list_dynamic_sublist( libvlc_media_list_t * p_mlist,
-                                   libvlc_tag_query_t * p_query,
-                                   libvlc_exception_t * p_e )
-{
-    libvlc_media_list_t * p_submlist;
-    libvlc_event_manager_t * p_em;
-    int count, i;
-
-    (void)p_e;
-
-    p_submlist = libvlc_media_list_new( p_mlist->p_libvlc_instance, p_e );
-    if( !p_submlist )
-    {
-        if( !libvlc_exception_raised( p_e ) )
-            libvlc_exception_raise( p_e, "Can't get the new media_list" );
-        return NULL;
-    }
-
-    /* We have a query */
-    libvlc_tag_query_retain( p_query );
-    p_submlist->p_query = p_query;
-
-    /* We have a media provider */
-    libvlc_media_list_retain( p_mlist );
-    p_submlist->p_media_provider = p_mlist;
-
-
-    libvlc_media_list_lock( p_submlist );        
-    
-    count = libvlc_media_list_count( p_mlist, p_e );
-
-    /* This should be running in a thread, a good plan to achieve that
-     * move all the dynamic code to libvlc_tag_query. */
-    for( i = 0; i < count; i++ )
-    {
-        libvlc_media_descriptor_t * p_md;
-        p_md = libvlc_media_list_item_at_index( p_mlist, i, p_e );
-        if( libvlc_tag_query_match( p_query, p_md, NULL ) )
-            libvlc_media_list_add_media_descriptor( p_submlist, p_md, p_e );
-    }
-
-    /* And we will listen to its event, so we can update p_submlist
-     * accordingly */
-    p_em = libvlc_media_list_event_manager( p_mlist, p_e );
-    libvlc_event_attach( p_em, libvlc_MediaListItemAdded,
-                         dynamic_list_propose_item, p_submlist, p_e );
-    libvlc_event_attach( p_em, libvlc_MediaListItemDeleted,
-                         dynamic_list_remove_item, p_submlist, p_e );
-    libvlc_event_attach( p_em, libvlc_MediaListItemChanged,
-                         dynamic_list_change_item, p_submlist, p_e );
-
-    libvlc_media_list_unlock( p_submlist );        
-
-    return p_submlist;
-}