[vlc-devel] [PATCH v5 2/3] Expose preparsing for media tree

Romain Vimont rom1v at videolabs.io
Tue Aug 21 16:29:29 CEST 2018


Expose a function to preparse an item in a media tree. If subitems are
detected during the preparsing, update the media tree accordingly.
---
 include/vlc_media_tree.h    | 17 ++++++++++
 src/libvlccore.sym          |  1 +
 src/media_tree/media_tree.c | 66 +++++++++++++++++++++++++++++++++++--
 3 files changed, 82 insertions(+), 2 deletions(-)

diff --git a/include/vlc_media_tree.h b/include/vlc_media_tree.h
index 779b095fd3..4f627db884 100644
--- a/include/vlc_media_tree.h
+++ b/include/vlc_media_tree.h
@@ -59,6 +59,14 @@ typedef struct vlc_media_tree_callbacks_t
      */
     void (*listener_added)(vlc_media_tree_t *, void *userdata);
 
+    /**
+     * Called when an input item notifies that a subtree has been added.
+     *
+     * Use vlc_media_tree_subtree_added_default implementation to call
+     * node_added() for every new node.
+     */
+    void (*subtree_added)(vlc_media_tree_t *, const input_item_node_t *, void *userdata);
+
     /**
      * Called after a new node has been added to the media tree, with lock held.
      */
@@ -83,6 +91,12 @@ typedef struct vlc_media_tree_listener_id vlc_media_tree_listener_id;
  **/
 VLC_API void vlc_media_tree_listener_added_default(vlc_media_tree_t *, void *userdata);
 
+/**
+ * Default implementation for subtree_added(), which calls node_added()
+ * for every new node.
+ **/
+VLC_API void vlc_media_tree_subtree_added_default(vlc_media_tree_t *, const input_item_node_t *, void *userdata);
+
 /**
  * Add a listener. The lock must NOT be held.
  */
@@ -118,6 +132,9 @@ VLC_API void vlc_media_tree_Unlock(vlc_media_tree_t *);
 VLC_API bool vlc_media_tree_Find(vlc_media_tree_t *, const input_item_t *,
                                  input_item_node_t **result, input_item_node_t **result_parent);
 
+VLC_API void vlc_media_tree_Preparse(vlc_media_tree_t *, libvlc_int_t *libvlc,
+                                     input_item_t *);
+
 /** @} */
 
 #ifdef __cplusplus
diff --git a/src/libvlccore.sym b/src/libvlccore.sym
index cb0958565e..0abfd86be9 100644
--- a/src/libvlccore.sym
+++ b/src/libvlccore.sym
@@ -789,3 +789,4 @@ vlc_media_tree_Lock
 vlc_media_tree_Unlock
 vlc_media_tree_Find
 vlc_media_tree_listener_added_default
+vlc_media_tree_subtree_added_default
diff --git a/src/media_tree/media_tree.c b/src/media_tree/media_tree.c
index 5a58771507..19b18c14b7 100644
--- a/src/media_tree/media_tree.c
+++ b/src/media_tree/media_tree.c
@@ -98,6 +98,17 @@ static void NotifyNodeRemoved(vlc_media_tree_t *tree, const input_item_node_t *p
             listener->cbs->node_removed(tree, parent, node, listener->userdata);
 }
 
+static void NotifySubtreeAdded(vlc_media_tree_t *tree, const input_item_node_t *node)
+{
+    AssertLocked(tree);
+    media_tree_private_t *priv = mt_priv(tree);
+
+    vlc_media_tree_listener_id *listener;
+    vlc_list_foreach(listener, &priv->listeners, node)
+        if (listener->cbs->subtree_added)
+            listener->cbs->subtree_added(tree, node, listener->userdata);
+}
+
 static bool FindNodeByInput(input_item_node_t *parent, const input_item_t *input,
                             input_item_node_t **result, input_item_node_t **result_parent)
 {
@@ -119,6 +130,41 @@ static bool FindNodeByInput(input_item_node_t *parent, const input_item_t *input
     return false;
 }
 
+static input_item_node_t *AddChild(input_item_node_t *parent, input_item_t *input);
+
+static void AddSubtree(input_item_node_t *to, input_item_node_t *from)
+{
+    for (int i = 0; i < from->i_children; ++i)
+    {
+        input_item_node_t *child = from->pp_children[i];
+        input_item_node_t *node = AddChild(to, child->p_item);
+        if (unlikely(!node))
+            break; /* what could we do? */
+
+        AddSubtree(node, child);
+    }
+}
+
+static void input_item_subtree_added(input_item_t *input, input_item_node_t *node,
+                                     void *userdata)
+{
+    vlc_media_tree_t *tree = userdata;
+
+    vlc_media_tree_Lock(tree);
+    input_item_node_t *subtree_root;
+    /* TODO retrieve the node without traversing the tree */
+    bool found = FindNodeByInput(&tree->root, input, &subtree_root, NULL);
+    if (!found) {
+        /* the node probably failed to be allocated */
+        vlc_media_tree_Unlock(tree);
+        return;
+    }
+
+    AddSubtree(subtree_root, node);
+    NotifySubtreeAdded(tree, subtree_root);
+    vlc_media_tree_Unlock(tree);
+}
+
 static void DestroyRootNode(vlc_media_tree_t *tree)
 {
     input_item_node_t *root = &tree->root;
@@ -189,7 +235,7 @@ static void NotifyChildren(vlc_media_tree_t *tree, const input_item_node_t *node
     }
 }
 
-void vlc_media_tree_listener_added_default(vlc_media_tree_t *tree, void *userdata)
+void vlc_media_tree_subtree_added_default(vlc_media_tree_t *tree, const input_item_node_t *node, void *userdata)
 {
     VLC_UNUSED(userdata);
     AssertLocked(tree);
@@ -198,7 +244,12 @@ void vlc_media_tree_listener_added_default(vlc_media_tree_t *tree, void *userdat
     vlc_list_foreach(listener, &priv->listeners, node)
         /* notify "node added" for every node */
         if (listener->cbs->node_added)
-            NotifyChildren(tree, &tree->root, listener);
+            NotifyChildren(tree, node, listener);
+}
+
+void vlc_media_tree_listener_added_default(vlc_media_tree_t *tree, void *userdata)
+{
+    vlc_media_tree_subtree_added_default(tree, &tree->root, userdata);
 }
 
 vlc_media_tree_listener_id *vlc_media_tree_AddListener(vlc_media_tree_t *tree,
@@ -265,3 +316,14 @@ bool vlc_media_tree_Remove(vlc_media_tree_t *tree, input_item_t *input)
     input_item_node_Delete(node);
     return true;
 }
+
+static const input_preparser_callbacks_t input_preparser_callbacks = {
+    .on_subtree_added = input_item_subtree_added,
+};
+
+void vlc_media_tree_Preparse(vlc_media_tree_t *media_tree,
+                             libvlc_int_t *libvlc, input_item_t *input)
+{
+    vlc_MetadataRequest(libvlc, input, META_REQUEST_OPTION_NONE,
+                        &input_preparser_callbacks, media_tree, -1, NULL);
+}
-- 
2.18.0



More information about the vlc-devel mailing list