[vlc-commits] access: attach slaves to input items

Benjamin Adolphi git at videolan.org
Thu May 19 15:57:27 CEST 2016


vlc | branch: master | Benjamin Adolphi <b.adolphi at gmail.com> | Tue May  3 18:34:57 2016 +0200| [40ccae76086d799da5508d6b42db12fdbc77aa59] | committer: Thomas Guillem

access: attach slaves to input items

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

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

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=40ccae76086d799da5508d6b42db12fdbc77aa59
---

 include/vlc_access.h |    3 +
 src/input/access.c   |  228 +++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 230 insertions(+), 1 deletion(-)

diff --git a/include/vlc_access.h b/include/vlc_access.h
index 7764716..dd288af 100644
--- a/include/vlc_access.h
+++ b/include/vlc_access.h
@@ -277,6 +277,9 @@ VLC_API int access_vaDirectoryControlHelper( access_t *p_access, int i_query, va
 struct access_fsdir
 {
     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;
     char *psz_sort;
diff --git a/src/input/access.c b/src/input/access.c
index aaf6530..28274de 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>
@@ -526,6 +527,180 @@ 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_t *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_t *p_slave,
+                                        const char *psz_slave_filename)
+{
+    uint8_t i_priority = SLAVE_PRIORITY_MATCH_NONE;
+    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)
+        goto done;
+
+    /* check if the names match exactly */
+    if (!strcmp(psz_item_name, psz_slave_name))
+    {
+        i_priority = SLAVE_PRIORITY_MATCH_ALL;
+        goto done;
+    }
+
+    /* "cdg" slaves have to be a full match */
+    if (p_slave->i_type == SLAVE_TYPE_SPU)
+    {
+        char *psz_ext = strrchr(psz_slave_name, '.');
+        if (psz_ext != NULL && strcasecmp(++psz_ext, "cdg") == 0)
+            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)
+        {
+            i_priority = SLAVE_PRIORITY_MATCH_RIGHT;
+            goto done;
+        }
+        else
+        {
+            i_priority = SLAVE_PRIORITY_MATCH_LEFT;
+            goto done;
+        }
+    }
+
+done:
+    free(psz_item_name);
+    free(psz_slave_name);
+    return i_priority;
+}
+
+static int fsdir_should_match_idx(struct access_fsdir *p_fsdir,
+                                  struct fsdir_slave *p_fsdir_sub)
+{
+    char *psz_ext = strrchr(p_fsdir_sub->psz_filename, '.');
+    if (!psz_ext)
+        return false;
+    psz_ext++;
+
+    if (strcasecmp(psz_ext, "sub") != 0)
+        return false;
+
+    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 || p_fsdir_slave == p_fsdir_sub)
+            continue;
+
+        /* check that priorities match */
+        if (p_fsdir_slave->p_slave->i_priority !=
+            p_fsdir_sub->p_slave->i_priority)
+            continue;
+
+        /* check that the filenames without extension match */
+        if (strncasecmp(p_fsdir_sub->psz_filename, p_fsdir_slave->psz_filename,
+                        strlen(p_fsdir_sub->psz_filename) - 3 ) != 0)
+            continue;
+
+        /* check that we have an idx file */
+        char *psz_ext_idx = strrchr(p_fsdir_slave->psz_filename, '.');
+        if (psz_ext_idx == NULL)
+            continue;
+        psz_ext_idx++;
+        if (strcasecmp(psz_ext_idx, "idx" ) == 0)
+            return true;
+    }
+    return false;
+}
+
+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)
+                continue;
+
+            uint8_t i_priority =
+                fsdir_get_slave_priority(p_item, p_fsdir_slave->p_slave,
+                                         p_fsdir_slave->psz_filename);
+
+            if (i_priority < p_fsdir->i_sub_autodetect_fuzzy)
+                continue;
+
+            /* Drop the ".sub" slave if a ".idx" slave matches */
+            if (p_fsdir_slave->p_slave->i_type == SLAVE_TYPE_SPU
+             && fsdir_should_match_idx(p_fsdir, p_fsdir_slave))
+                continue;
+
+            p_fsdir_slave->p_slave->i_priority = i_priority;
+            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)
 {
@@ -533,20 +708,65 @@ void access_fsdir_init(struct access_fsdir *p_fsdir,
     p_fsdir->b_show_hiddenfiles = var_InheritBool(p_access, "show-hiddenfiles");
     p_fsdir->psz_ignored_exts = var_InheritString(p_access, "ignore-filetypes");
     p_fsdir->psz_sort = var_InheritString(p_access, "directory-sort");
+    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);
     free(p_fsdir->psz_sort);
+
+    /* 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_MATCH_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;
 
@@ -556,7 +776,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;
 }



More information about the vlc-commits mailing list