[vlc-devel] [PATCH 08/10] Removes xspf generation in access/directory.c in favor of new pf_readdir callback

Julien 'Lta' BALLET elthariel at gmail.com
Mon Jun 16 14:41:10 CEST 2014


From: Julien 'Lta' BALLET <contact at lta.io>

---
 modules/access/directory.c | 329 ++++++++++-----------------------------------
 1 file changed, 72 insertions(+), 257 deletions(-)

diff --git a/modules/access/directory.c b/modules/access/directory.c
index 3d72dc0..2d08178 100644
--- a/modules/access/directory.c
+++ b/modules/access/directory.c
@@ -44,18 +44,20 @@
 #include <vlc_url.h>
 #include <vlc_strings.h>
 #include <vlc_charset.h>
+#include <vlc_input_item.h>
 
-enum
-{
-    MODE_NONE,
-    MODE_COLLAPSE,
-    MODE_EXPAND,
-};
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static input_item_t *DirRead(access_t *);
 
-typedef struct directory_t directory_t;
-struct directory_t
+
+/*****************************************************************************
+ * Local data structures
+ *****************************************************************************/
+typedef struct directory directory;
+struct directory
 {
-    directory_t *parent;
     DIR         *handle;
     char        *uri;
     char       **filev;
@@ -70,15 +72,14 @@ struct directory_t
 
 struct access_sys_t
 {
-    directory_t *current;
-    char *ignored_exts;
-    char mode;
-    bool header;
-    int i_item_count;
-    char *xspf_ext;
-    int (*compar)(const char **a, const char **b);
+    directory    *current;
+    char         *ignored_exts;
+    int           (*compar)(const char **a, const char **b);
 };
 
+/*****************************************************************************
+ * Local helper functions
+ *****************************************************************************/
 /* Select non-hidden files only */
 static int visible (const char *name)
 {
@@ -134,7 +135,7 @@ int DirInit (access_t *p_access, DIR *handle)
         goto error;
 
     /* "Open" the base directory */
-    directory_t *root = malloc (sizeof (*root));
+    directory *root = malloc (sizeof (*root));
     if (unlikely(root == NULL))
     {
         free (uri);
@@ -152,7 +153,6 @@ int DirInit (access_t *p_access, DIR *handle)
         p_sys->compar = collate;
     free(psz_sort);
 
-    root->parent = NULL;
     root->handle = handle;
     root->uri = uri;
     root->filec = vlc_loaddir (handle, &root->filev, visible, p_sys->compar);
@@ -176,25 +176,9 @@ int DirInit (access_t *p_access, DIR *handle)
     p_access->p_sys = p_sys;
     p_sys->current = root;
     p_sys->ignored_exts = var_InheritString (p_access, "ignore-filetypes");
-    p_sys->header = true;
-    p_sys->i_item_count = 0;
-    p_sys->xspf_ext = strdup ("");
-
-    /* Handle mode */
-    char *psz = var_InheritString (p_access, "recursive");
-    if (psz == NULL || !strcasecmp (psz, "none"))
-        p_sys->mode = MODE_NONE;
-    else if( !strcasecmp( psz, "collapse" )  )
-        p_sys->mode = MODE_COLLAPSE;
-    else
-        p_sys->mode = MODE_EXPAND;
-    free( psz );
-
-    access_InitFields(p_access);
-    p_access->pf_read  = NULL;
-    p_access->pf_block = DirBlock;
-    p_access->pf_seek  = NULL;
-    p_access->pf_control = DirControl;
+
+    access_InitFields (p_access);
+    ACCESS_SET_CALLBACKS (NULL, NULL, DirRead, DirControl, NULL);
     return VLC_SUCCESS;
 
 error:
@@ -210,251 +194,86 @@ void DirClose( vlc_object_t * p_this )
 {
     access_t *p_access = (access_t*)p_this;
     access_sys_t *p_sys = p_access->p_sys;
+    directory *current = p_sys->current;
 
-    while (p_sys->current)
-    {
-        directory_t *current = p_sys->current;
-
-        p_sys->current = current->parent;
-        closedir (current->handle);
-        free (current->uri);
-        while (current->i < current->filec)
-            free (current->filev[current->i++]);
-        free (current->filev);
+    closedir (current->handle);
+    free (current->uri);
+    while (current->i < current->filec)
+        free (current->filev[current->i++]);
+    free (current->filev);
 #ifndef HAVE_OPENAT
-        free (current->path);
+    free (current->path);
 #endif
-        free (current);
-    }
+    free (current);
 
-    free (p_sys->xspf_ext);
     free (p_sys->ignored_exts);
     free (p_sys);
 }
 
-#ifdef HAVE_OPENAT
-/* Detect directories that recurse into themselves. */
-static bool has_inode_loop (const directory_t *dir, dev_t dev, ino_t inode)
-{
-    while (dir != NULL)
-    {
-        if ((dir->device == dev) && (dir->inode == inode))
-            return true;
-        dir = dir->parent;
-    }
-    return false;
-}
-#endif
-
-block_t *DirBlock (access_t *p_access)
+input_item_t *DirRead (access_t *p_access)
 {
     access_sys_t *p_sys = p_access->p_sys;
-    directory_t *current = p_sys->current;
+    directory *current = p_sys->current;
+    bool is_dir = false;
+    char *entry;
 
+    if (current->i >= current->filec)
+        p_access->info.b_eof = true;
     if (p_access->info.b_eof)
         return NULL;
 
-    if (p_sys->header)
-    {   /* Startup: send the XSPF header */
-        static const char header[] =
-            "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
-            "<playlist version=\"1\" xmlns=\"http://xspf.org/ns/0/\" xmlns:vlc=\"http://www.videolan.org/vlc/playlist/ns/0/\">\n"
-            " <trackList>\n";
-        block_t *block = block_Alloc (sizeof (header) - 1);
-        if (!block)
-            goto fatal;
-        memcpy (block->p_buffer, header, sizeof (header) - 1);
-        p_sys->header = false;
-        return block;
-    }
-
-    if (current->i >= current->filec)
-    {   /* End of directory, go back to parent */
-        closedir (current->handle);
-        p_sys->current = current->parent;
-        free (current->uri);
-        free (current->filev);
-#ifndef HAVE_OPENAT
-        free (current->path);
-#endif
-        free (current);
-
-        if (p_sys->current == NULL)
-        {   /* End of XSPF playlist */
-            char *footer;
-            int len = asprintf (&footer, " </trackList>\n"
-                " <extension application=\"http://www.videolan.org/"
-                                             "vlc/playlist/0\">\n"
-                "%s"
-                " </extension>\n"
-                "</playlist>\n", p_sys->xspf_ext ? p_sys->xspf_ext : "");
-            if (unlikely(len == -1))
-                goto fatal;
-
-            block_t *block = block_heap_Alloc (footer, len);
-            p_access->info.b_eof = true;
-            return block;
-        }
-        else
-        {
-            /* This was the end of a "subnode" */
-            /* Write the ID to the extension */
-            char *old_xspf_ext = p_sys->xspf_ext;
-            if (old_xspf_ext != NULL
-             && asprintf (&p_sys->xspf_ext, "%s  </vlc:node>\n",
-                          old_xspf_ext ? old_xspf_ext : "") == -1)
-                p_sys->xspf_ext = NULL;
-            free (old_xspf_ext);
-        }
-        return NULL;
-    }
+    entry = current->filev[current->i++];
 
-    char *entry = current->filev[current->i++];
-
-    /* Handle recursion */
-    if (p_sys->mode != MODE_COLLAPSE)
-    {
-        DIR *handle;
-#ifdef HAVE_OPENAT
-        int fd = vlc_openat (dirfd (current->handle), entry,
-                             O_RDONLY | O_DIRECTORY);
-        if (fd == -1)
-        {
-            if (errno == ENOTDIR)
-                goto notdir;
-            goto skip; /* File cannot be opened... forget it */
-        }
-
-        struct stat st;
-        if (fstat (fd, &st)
-         || p_sys->mode == MODE_NONE
-         || has_inode_loop (current, st.st_dev, st.st_ino)
-         || (handle = fdopendir (fd)) == NULL)
-        {
-            close (fd);
-            goto skip;
-        }
-#else
-        char *path;
-        if (asprintf (&path, "%s/%s", current->path, entry) == -1)
-            goto skip;
-        if ((handle = vlc_opendir (path)) == NULL)
-            goto notdir;
-        if (p_sys->mode == MODE_NONE)
-            goto skip;
-#endif
-        directory_t *sub = malloc (sizeof (*sub));
-        if (unlikely(sub == NULL))
-        {
-            closedir (handle);
-#ifndef HAVE_OPENAT
-            free (path);
-#endif
-            goto skip;
-        }
-        sub->parent = current;
-        sub->handle = handle;
-        sub->filec = vlc_loaddir (handle, &sub->filev, visible, p_sys->compar);
-        if (sub->filec < 0)
-            sub->filev = NULL;
-        sub->i = 0;
 #ifdef HAVE_OPENAT
-        sub->device = st.st_dev;
-        sub->inode = st.st_ino;
+    int fd = vlc_openat (dirfd (current->handle), entry,
+                         O_RDONLY | O_DIRECTORY);
+    if (fd >= 0)
+    {
+        is_dir = true;
+        close (fd);
+    }
+    else if (errno != ENOTDIR)
+        goto skip;
 #else
-        sub->path = path;
-#endif
-        p_sys->current = sub;
-
-        char *encoded = encode_URI_component (entry);
-        if (encoded == NULL
-         || (asprintf (&sub->uri, "%s/%s", current->uri, encoded) == -1))
-             sub->uri = NULL;
-        free (encoded);
-        if (unlikely(sub->uri == NULL))
-        {
-            free (entry);
-            goto fatal;
-        }
-
-        /* Add node to XSPF extension */
-        char *old_xspf_ext = p_sys->xspf_ext;
-        EnsureUTF8 (entry);
-        char *title = convert_xml_special_chars (entry);
-        if (old_xspf_ext != NULL
-         && asprintf (&p_sys->xspf_ext, "%s  <vlc:node title=\"%s\">\n",
-                      old_xspf_ext, title ? title : "?") == -1)
-            p_sys->xspf_ext = NULL;
-        free (old_xspf_ext);
-        free (title);
+    char *path;
+    DIR *handle;
+    if (asprintf (&path, "%s/%s", current->path, entry) == -1)
         goto skip;
-    }
-
-notdir:
-    /* Skip files with ignored extensions */
-    if (p_sys->ignored_exts != NULL)
+    if ((handle = vlc_opendir (path)) != NULL)
     {
-        const char *ext = strrchr (entry, '.');
-        if (ext != NULL)
-        {
-            size_t extlen = strlen (++ext);
-            for (const char *type = p_sys->ignored_exts, *end;
-                 type[0]; type = end + 1)
-            {
-                end = strchr (type, ',');
-                if (end == NULL)
-                    end = type + strlen (type);
-
-                if (type + extlen == end
-                 && !strncasecmp (ext, type, extlen))
-                {
-                    free (entry);
-                    return NULL;
-                }
-
-                if (*end == '\0')
-                    break;
-            }
-        }
+        is_dir = true;
+        closedir (handle);
     }
+#endif
+
+    if (!is_dir && p_sys->ignored_exts != NULL
+        && has_ext(entry, p_sys->ignored_exts))
+        goto skip;
 
     char *encoded = encode_URI_component (entry);
-    free (entry);
-    if (encoded == NULL)
-        goto fatal;
-    int len = asprintf (&entry,
-                        "  <track><location>%s/%s</location>\n" \
-                        "   <extension application=\"http://www.videolan.org/vlc/playlist/0\">\n" \
-                        "    <vlc:id>%d</vlc:id>\n" \
-                        "   </extension>\n" \
-                        "  </track>\n",
-                        current->uri, encoded, p_sys->i_item_count++);
+    char *uri;
+
+    if (encoded == NULL
+        || (asprintf (&uri, "%s/%s", current->uri, encoded) == -1))
+        uri = NULL;
     free (encoded);
-    if (len == -1)
-        goto fatal;
-
-    /* Write the ID to the extension */
-    char *old_xspf_ext = p_sys->xspf_ext;
-    if (old_xspf_ext != NULL
-     && asprintf (&p_sys->xspf_ext, "%s   <vlc:item tid=\"%i\" />\n",
-                  old_xspf_ext, p_sys->i_item_count - 1) == -1)
-        p_sys->xspf_ext = NULL;
-    free (old_xspf_ext);
-
-    block_t *block = block_heap_Alloc (entry, len);
-    if (unlikely(block == NULL))
-        goto fatal;
-    return block;
-
-fatal:
-    p_access->info.b_eof = true;
-    return NULL;
+    if (unlikely (uri == NULL))
+        goto skip;
+
+    int type = is_dir ? ITEM_TYPE_DIRECTORY : ITEM_TYPE_FILE;
+    input_item_t *item = input_item_NewWithType (uri, entry, 0, NULL, 0, 0, type);
+
+    free (uri);
+    free (entry);
+
+    return item;
 
 skip:
     free (entry);
     return NULL;
 }
 
+
 /*****************************************************************************
  * Control:
  *****************************************************************************/
@@ -476,10 +295,6 @@ int DirControl( access_t *p_access, int i_query, va_list args )
             *va_arg( args, int64_t * ) = DEFAULT_PTS_DELAY * 1000;
             break;
 
-        case ACCESS_GET_CONTENT_TYPE:
-            *va_arg( args, char** ) = strdup("application/xspf+xml");
-            return VLC_SUCCESS;
-
         default:
             return VLC_EGENERIC;
     }
-- 
1.9.3




More information about the vlc-devel mailing list