[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