[vlc-devel] [PATCHv2 12/13] access: attach slaves to input items

Thomas Guillem thomas at gllm.fr
Tue May 3 19:02:39 CEST 2016


From: Benjamin Adolphi <b.adolphi at gmail.com>

Also-by: Thomas Guillem <thomas at gllm.fr>

Signed-off-by: Thomas Guillem <thomas at gllm.fr>
---
 include/vlc_access.h |   3 +
 src/input/access.c   | 174 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 176 insertions(+), 1 deletion(-)

diff --git a/include/vlc_access.h b/include/vlc_access.h
index a35d62b..77297dc 100644
--- a/include/vlc_access.h
+++ b/include/vlc_access.h
@@ -278,6 +278,9 @@ struct access_fsdir
 {
     access_t *p_access;
     input_item_node_t *p_node;
+    void **pp_slaves;
+    unsigned int i_slaves;
+    int i_sub_autodetect_fuzzy;
     bool b_show_hiddenfiles;
     char *psz_ignored_exts;
 };
diff --git a/src/input/access.c b/src/input/access.c
index 73ac7b9..bd8e474 100644
--- a/src/input/access.c
+++ b/src/input/access.c
@@ -28,6 +28,7 @@
 #include <assert.h>
 #include <stdlib.h>
 #include <string.h>
+#include <ctype.h>
 
 #include <vlc_common.h>
 #include <vlc_url.h>
@@ -528,6 +529,126 @@ static bool fsdir_is_ignored(struct access_fsdir *p_fsdir,
          || fsdir_has_ext(psz_filename, p_fsdir->psz_ignored_exts));
 }
 
+struct fsdir_slave
+{
+    input_item_slave *p_slave;
+    char *psz_filename;
+    input_item_node_t *p_node;
+};
+
+static char *fsdir_name_from_filename(const char *psz_filename)
+{
+    /* remove leading white spaces */
+    while (*psz_filename != '\0' && *psz_filename == ' ')
+        psz_filename++;
+
+    char *psz_name = strdup(psz_filename);
+    if (!psz_name)
+        return NULL;
+
+    /* remove extension */
+    char *psz_ptr = strrchr(psz_name, '.');
+    if (psz_ptr)
+        *psz_ptr = '\0';
+
+    /* remove trailing white spaces */
+    int i = strlen(psz_name) - 1;
+    while (psz_name[i] == ' ' && i >= 0)
+        psz_name[i--] = '\0';
+
+    /* convert to lower case */
+    psz_ptr = psz_name;
+    while (*psz_ptr != '\0')
+    {
+        *psz_ptr = tolower(*psz_ptr);
+        psz_ptr++;
+    }
+
+    return psz_name;
+}
+
+static uint8_t fsdir_get_slave_priority(input_item_t *p_item,
+                                        input_item_slave *p_slave,
+                                        const char *psz_slave_filename)
+{
+    char *psz_item_name = fsdir_name_from_filename(p_item->psz_name);
+    char *psz_slave_name = fsdir_name_from_filename(psz_slave_filename);
+
+    if (!psz_item_name || !psz_slave_name)
+    {
+        p_slave->i_priority = SLAVE_PRIORITY_NONE;
+        goto done;
+    }
+
+    /* check if the names match exactly */
+    if (!strcmp(psz_item_name, psz_slave_name))
+    {
+        p_slave->i_priority = SLAVE_PRIORITY_MATCH_ALL;
+        goto done;
+    }
+
+    /* check if the item name is a substring of the slave name */
+    const char *psz_sub = strstr(psz_slave_name, psz_item_name);
+
+    if (psz_sub)
+    {
+        /* check if the item name was found at the end of the slave name */
+        if (strlen(psz_sub + strlen(psz_item_name)) == 0)
+        {
+            p_slave->i_priority = SLAVE_PRIORITY_MATCH_RIGHT;
+            goto done;
+        }
+        else
+        {
+            p_slave->i_priority = SLAVE_PRIORITY_MATCH_LEFT;
+            goto done;
+        }
+    }
+    p_slave->i_priority = SLAVE_PRIORITY_MATCH_NONE;
+done:
+    free(psz_item_name);
+    free(psz_slave_name);
+    return p_slave->i_priority;
+}
+
+static void fsdir_attach_slaves(struct access_fsdir *p_fsdir)
+{
+    if (p_fsdir->i_sub_autodetect_fuzzy == 0)
+        return;
+
+    /* Try to match slaves for each items of the node */
+    for (int i = 0; i < p_fsdir->p_node->i_children; i++)
+    {
+        input_item_node_t *p_node = p_fsdir->p_node->pp_children[i];
+        input_item_t *p_item = p_node->p_item;
+
+        for (unsigned int j = 0; j < p_fsdir->i_slaves; j++)
+        {
+            struct fsdir_slave *p_fsdir_slave = p_fsdir->pp_slaves[j];
+
+            if (p_fsdir_slave != NULL
+             && p_fsdir_slave->p_node != p_node
+             && fsdir_get_slave_priority(p_item, p_fsdir_slave->p_slave,
+                                         p_fsdir_slave->psz_filename)
+                                         >= p_fsdir->i_sub_autodetect_fuzzy)
+            {
+                input_item_AddSlave(p_item, p_fsdir_slave->p_slave);
+
+                /* Remove the corresponding node if any: This slave won't be
+                 * added in the parent node */
+                if (p_fsdir_slave->p_node != NULL)
+                    input_item_node_Delete(p_fsdir_slave->p_node);
+
+                /* Remove this slave from the list: we don't want to match
+                 * other items */
+                free(p_fsdir_slave->psz_filename);
+                free(p_fsdir_slave);
+                p_fsdir->pp_slaves[j] = NULL;
+            }
+        }
+    }
+}
+
 void access_fsdir_init(struct access_fsdir *p_fsdir,
                        access_t *p_access, input_item_node_t *p_node)
 {
@@ -535,19 +656,64 @@ void access_fsdir_init(struct access_fsdir *p_fsdir,
     p_fsdir->p_node = p_node;
     p_fsdir->b_show_hiddenfiles = var_InheritBool(p_access, "show-hiddenfiles");
     p_fsdir->psz_ignored_exts = var_InheritString(p_access, "ignore-filetypes");
+    p_fsdir->i_sub_autodetect_fuzzy =
+        var_InheritInteger(p_access, "sub-autodetect-fuzzy");
+    TAB_INIT(p_fsdir->i_slaves, p_fsdir->pp_slaves);
 }
 
 void access_fsdir_finish(struct access_fsdir *p_fsdir, bool b_success)
 {
     if (b_success)
+    {
+        fsdir_attach_slaves(p_fsdir);
         fsdir_sort(p_fsdir);
+    }
     free(p_fsdir->psz_ignored_exts);
+
+    /* Remove unmatched slaves */
+    for (unsigned int i = 0; i < p_fsdir->i_slaves; i++)
+    {
+        struct fsdir_slave *p_fsdir_slave = p_fsdir->pp_slaves[i];
+        if (p_fsdir_slave != NULL)
+        {
+            input_item_slave_Delete(p_fsdir_slave->p_slave);
+            free(p_fsdir_slave->psz_filename);
+            free(p_fsdir_slave);
+        }
+    }
+    TAB_CLEAN(p_fsdir->i_slaves, p_fsdir->pp_slaves);
 }
 
 int access_fsdir_additem(struct access_fsdir *p_fsdir,
                          const char *psz_uri, const char *psz_filename,
                          int i_type, int i_net)
 {
+    enum slave_type i_slave_type;
+    struct fsdir_slave *p_fsdir_slave = NULL;
+    input_item_node_t *p_node;
+
+    if (p_fsdir->i_sub_autodetect_fuzzy != 0
+     && input_item_slave_GetType(psz_filename, &i_slave_type))
+    {
+        p_fsdir_slave = malloc(sizeof(*p_fsdir_slave));
+        if (!p_fsdir_slave)
+            return VLC_ENOMEM;
+
+        p_fsdir_slave->p_node = NULL;
+        p_fsdir_slave->psz_filename = strdup(psz_filename);
+        p_fsdir_slave->p_slave = input_item_slave_New(psz_uri, i_slave_type,
+                                                      SLAVE_PRIORITY_NONE);
+        if (!p_fsdir_slave->p_slave || !p_fsdir_slave->psz_filename)
+        {
+            free(p_fsdir_slave->psz_filename);
+            free(p_fsdir_slave);
+            return VLC_ENOMEM;
+        }
+
+        INSERT_ELEM(p_fsdir->pp_slaves, p_fsdir->i_slaves,
+                    p_fsdir->i_slaves, p_fsdir_slave);
+    }
+
     if (fsdir_is_ignored(p_fsdir, psz_filename))
         return VLC_SUCCESS;
 
@@ -557,7 +723,13 @@ int access_fsdir_additem(struct access_fsdir *p_fsdir,
         return VLC_ENOMEM;
 
     input_item_CopyOptions(p_item, p_fsdir->p_node->p_item);
-    input_item_node_AppendItem(p_fsdir->p_node, p_item);
+    p_node = input_item_node_AppendItem(p_fsdir->p_node, p_item);
     input_item_Release(p_item);
+
+    /* A slave can also be an item. If there is a match, this item will be
+     * removed from the parent node. This is not a common case, since most
+     * slaves will be ignored by fsdir_is_ignored() */
+    if (p_fsdir_slave != NULL)
+        p_fsdir_slave->p_node = p_node;
     return VLC_SUCCESS;
 }
-- 
2.8.0.rc3



More information about the vlc-devel mailing list