vlc | branch: master | Benjamin Adolphi <[email protected]> | Tue May 3 18:34:57 2016 +0200| [40ccae76086d799da5508d6b42db12fdbc77aa59] | committer: Thomas Guillem
access: attach slaves to input items Also-by: Thomas Guillem <[email protected]> Signed-off-by: Thomas Guillem <[email protected]> > 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; } _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
