[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