[vlc-commits] input: extends readdir_helper_additem()

Thomas Guillem git at videolan.org
Wed Sep 20 16:57:26 CEST 2017


vlc | branch: master | Thomas Guillem <thomas at gllm.fr> | Wed Sep 20 12:57:05 2017 +0200| [020de86e1a0c2becb43e47d7fa5298b392ece603] | committer: Thomas Guillem

input: extends readdir_helper_additem()

Add a new parameter: psz_flatpath. If not NULL, readdir_helper_additem() will
un-flatten the folder hierarchy. It will create an input item for each sub
folders (separated by '/') of psz_nullpath.

Example: a stream directory that have the following items:
 - "foo/bar/item1"
 - "foo/bar/item2"

will output the following items while using this new parameter:
 - foo
   - bar
     - item1
     - item2

This functionality can be used by "stream directory" modules that have a
flattened folder hierarchy, like libarchive.

Access modules should not need this functionality.

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

 include/vlc_input_item.h    |  13 +++++-
 modules/access/directory.c  |   3 +-
 modules/access/dsm/access.c |   3 +-
 modules/access/ftp.c        |   2 +-
 modules/access/nfs.c        |   4 +-
 modules/access/sftp.c       |   4 +-
 modules/access/smb.c        |   2 +-
 src/input/item.c            | 109 +++++++++++++++++++++++++++++++++++++++++---
 8 files changed, 123 insertions(+), 17 deletions(-)

diff --git a/include/vlc_input_item.h b/include/vlc_input_item.h
index 7ff57304d5..99f69eba96 100644
--- a/include/vlc_input_item.h
+++ b/include/vlc_input_item.h
@@ -421,6 +421,8 @@ struct readdir_helper
     input_item_node_t *p_node;
     void **pp_slaves;
     size_t i_slaves;
+    void **pp_dirs;
+    size_t i_dirs;
     int i_sub_autodetect_fuzzy;
     bool b_show_hiddenfiles;
     char *psz_ignored_exts;
@@ -449,12 +451,19 @@ VLC_API void readdir_helper_finish(struct readdir_helper *p_rdh, bool b_success)
  *
  * \param p_rdh previously inited readdir_helper struct
  * \param psz_uri uri of the new item
- * \param psz_filename file name of the new item
+ * \param psz_flatpath flattened path of the new item. If not NULL, this
+ *        function will create an input item for each sub folders (separated
+ *        by '/') of psz_flatpath (so, this will un-flatten the folder
+ *        hierarchy). Either psz_flatpath or psz_filename must be valid.
+ * \param psz_filename file name of the new item. If NULL, the file part of path
+ *        will be used as a filename. Either psz_flatpath or psz_filename must
+ *        be valid.
  * \param i_type see \ref input_item_type_e
  * \param i_net see \ref input_item_net_type
  */
 VLC_API int readdir_helper_additem(struct readdir_helper *p_rdh,
-                                   const char *psz_uri, const char *psz_filename,
+                                   const char *psz_uri, const char *psz_flatpath,
+                                   const char *psz_filename,
                                    int i_type, int i_net);
 
 #endif
diff --git a/modules/access/directory.c b/modules/access/directory.c
index 3f9b0b62fd..68bbcbddac 100644
--- a/modules/access/directory.c
+++ b/modules/access/directory.c
@@ -181,7 +181,8 @@ int DirRead (stream_t *access, input_item_node_t *node)
             ret = VLC_ENOMEM;
             break;
         }
-        ret = readdir_helper_additem(&rdh, uri, entry, type, ITEM_NET_UNKNOWN);
+        ret = readdir_helper_additem(&rdh, uri, NULL, entry, type,
+                                     ITEM_NET_UNKNOWN);
         free(uri);
     }
 
diff --git a/modules/access/dsm/access.c b/modules/access/dsm/access.c
index 6bbe3ebf32..72e647a896 100644
--- a/modules/access/dsm/access.c
+++ b/modules/access/dsm/access.c
@@ -529,7 +529,8 @@ static int add_item( stream_t *p_access, struct readdir_helper *p_rdh,
     if( i_ret == -1 )
         return VLC_ENOMEM;
 
-    return readdir_helper_additem( p_rdh, psz_uri, psz_name, i_type, ITEM_NET );
+    return readdir_helper_additem( p_rdh, psz_uri, NULL, psz_name, i_type,
+                                   ITEM_NET );
 }
 
 static int BrowseShare( stream_t *p_access, input_item_node_t *p_node )
diff --git a/modules/access/ftp.c b/modules/access/ftp.c
index 3a3c4105e2..6e648daad2 100644
--- a/modules/access/ftp.c
+++ b/modules/access/ftp.c
@@ -956,7 +956,7 @@ static int DirRead (stream_t *p_access, input_item_node_t *p_current_node)
                       p_sys->url.psz_path ? p_sys->url.psz_path : "",
                       psz_filename ) != -1 )
         {
-            i_ret = readdir_helper_additem( &rdh, psz_uri, psz_file,
+            i_ret = readdir_helper_additem( &rdh, psz_uri, NULL, psz_file,
                                             type, ITEM_NET );
             free( psz_uri );
         }
diff --git a/modules/access/nfs.c b/modules/access/nfs.c
index 93bbe4f0e7..f4390f90f9 100644
--- a/modules/access/nfs.c
+++ b/modules/access/nfs.c
@@ -361,7 +361,7 @@ DirRead(stream_t *p_access, input_item_node_t *p_node)
         default:
             i_type = ITEM_TYPE_UNKNOWN;
         }
-        i_ret = readdir_helper_additem(&rdh, psz_url, p_nfsdirent->name,
+        i_ret = readdir_helper_additem(&rdh, psz_url, NULL, p_nfsdirent->name,
                                        i_type, ITEM_NET);
         free(psz_url);
     }
@@ -391,7 +391,7 @@ MountRead(stream_t *p_access, input_item_node_t *p_node)
             i_ret = VLC_ENOMEM;
             break;
         }
-        i_ret = readdir_helper_additem(&rdh, psz_url, psz_name,
+        i_ret = readdir_helper_additem(&rdh, psz_url, NULL, psz_name,
                                        ITEM_TYPE_DIRECTORY, ITEM_NET);
         free(psz_url);
     }
diff --git a/modules/access/sftp.c b/modules/access/sftp.c
index e46d6c64d7..8e6aa4efdf 100644
--- a/modules/access/sftp.c
+++ b/modules/access/sftp.c
@@ -589,8 +589,8 @@ static int DirRead (stream_t *p_access, input_item_node_t *p_current_node)
         free( psz_uri );
 
         int i_type = LIBSSH2_SFTP_S_ISDIR( attrs.permissions ) ? ITEM_TYPE_DIRECTORY : ITEM_TYPE_FILE;
-        i_ret = readdir_helper_additem( &rdh, psz_full_uri, psz_file, i_type,
-                                        ITEM_NET );
+        i_ret = readdir_helper_additem( &rdh, psz_full_uri, NULL, psz_file,
+                                        i_type, ITEM_NET );
         free( psz_full_uri );
     }
 
diff --git a/modules/access/smb.c b/modules/access/smb.c
index 47e459f098..ba65ecc39c 100644
--- a/modules/access/smb.c
+++ b/modules/access/smb.c
@@ -388,7 +388,7 @@ static int DirRead (stream_t *p_access, input_item_node_t *p_node )
             break;
         }
         free(psz_encoded_name);
-        i_ret = readdir_helper_additem( &rdh, psz_uri, p_entry->name,
+        i_ret = readdir_helper_additem( &rdh, psz_uri, NULL, p_entry->name,
                                         i_type, ITEM_NET );
         free( psz_uri );
     }
diff --git a/src/input/item.c b/src/input/item.c
index 2e14218c2a..68bb68c2e0 100644
--- a/src/input/item.c
+++ b/src/input/item.c
@@ -1408,6 +1408,12 @@ struct rdh_slave
     input_item_node_t *p_node;
 };
 
+struct rdh_dir
+{
+    input_item_node_t *p_node;
+    char psz_path[];
+};
+
 static char *rdh_name_from_filename(const char *psz_filename)
 {
     /* remove leading white spaces */
@@ -1589,6 +1595,72 @@ static void rdh_attach_slaves(struct readdir_helper *p_rdh)
     }
 }
 
+static int rdh_unflatten(struct readdir_helper *p_rdh,
+                         input_item_node_t **pp_node, const char *psz_path,
+                         int i_net)
+{
+    /* Create an input input for each sub folders that is contained in the full
+     * path. Update pp_node to point to the direct parent of the future item to
+     * add. */
+
+    assert(psz_path != NULL);
+    const char *psz_subpaths = psz_path;
+
+    while ((psz_subpaths = strchr(psz_subpaths, '/')))
+    {
+        input_item_node_t *p_subnode = NULL;
+
+        /* Check if this sub folder item was already added */
+        for (size_t i = 0; i < p_rdh->i_dirs && p_subnode == NULL; i++)
+        {
+            struct rdh_dir *rdh_dir = p_rdh->pp_dirs[i];
+            if (!strncmp(rdh_dir->psz_path, psz_path, psz_subpaths - psz_path))
+                p_subnode = rdh_dir->p_node;
+        }
+
+        /* The sub folder item doesn't exist, so create it */
+        if (p_subnode == NULL)
+        {
+            size_t i_sub_path_len = psz_subpaths - psz_path;
+            struct rdh_dir *p_rdh_dir =
+                malloc(sizeof(struct rdh_dir) + 1 + i_sub_path_len);
+            if (p_rdh_dir == NULL)
+                return VLC_ENOMEM;
+            strncpy(p_rdh_dir->psz_path, psz_path, i_sub_path_len);
+            p_rdh_dir->psz_path[i_sub_path_len] = 0;
+
+            const char *psz_subpathname = strrchr(p_rdh_dir->psz_path, '/');
+            if (psz_subpathname != NULL)
+                ++psz_subpathname;
+            else
+                psz_subpathname = p_rdh_dir->psz_path;
+
+            input_item_t *p_item =
+                input_item_NewExt("vlc://nop", psz_subpathname, -1,
+                                  ITEM_TYPE_DIRECTORY, i_net);
+            if (p_item == NULL)
+            {
+                free(p_rdh_dir);
+                return VLC_ENOMEM;
+            }
+            input_item_CopyOptions(p_item, (*pp_node)->p_item);
+            *pp_node = input_item_node_AppendItem(*pp_node, p_item);
+            input_item_Release(p_item);
+            if (*pp_node == NULL)
+            {
+                free(p_rdh_dir);
+                return VLC_ENOMEM;
+            }
+            p_rdh_dir->p_node = *pp_node;
+            TAB_APPEND(p_rdh->i_dirs, p_rdh->pp_dirs, p_rdh_dir);
+        }
+        else
+            *pp_node = p_subnode;
+        psz_subpaths++;
+    }
+    return VLC_SUCCESS;
+}
+
 #undef readdir_helper_init
 void readdir_helper_init(struct readdir_helper *p_rdh,
                          vlc_object_t *p_obj, input_item_node_t *p_node)
@@ -1600,6 +1672,7 @@ void readdir_helper_init(struct readdir_helper *p_rdh,
     p_rdh->i_sub_autodetect_fuzzy = !b_autodetect ? 0 :
         var_InheritInteger(p_obj, "sub-autodetect-fuzzy");
     TAB_INIT(p_rdh->i_slaves, p_rdh->pp_slaves);
+    TAB_INIT(p_rdh->i_dirs, p_rdh->pp_dirs);
 }
 
 void readdir_helper_finish(struct readdir_helper *p_rdh, bool b_success)
@@ -1623,15 +1696,28 @@ void readdir_helper_finish(struct readdir_helper *p_rdh, bool b_success)
         }
     }
     TAB_CLEAN(p_rdh->i_slaves, p_rdh->pp_slaves);
+
+    for (size_t i = 0; i < p_rdh->i_dirs; i++)
+        free(p_rdh->pp_dirs[i]);
+    TAB_CLEAN(p_rdh->i_dirs, p_rdh->pp_dirs);
 }
 
 int readdir_helper_additem(struct readdir_helper *p_rdh,
-                           const char *psz_uri, const char *psz_filename,
-                           int i_type, int i_net)
+                           const char *psz_uri, const char *psz_flatpath,
+                           const char *psz_filename, int i_type, int i_net)
 {
     enum slave_type i_slave_type;
     struct rdh_slave *p_rdh_slave = NULL;
-    input_item_node_t *p_node;
+    assert(psz_flatpath || psz_filename);
+
+    if (psz_filename == NULL)
+    {
+        psz_filename = strrchr(psz_flatpath, '/');
+        if (psz_filename != NULL)
+            ++psz_filename;
+        else
+            psz_filename = psz_flatpath;
+    }
 
     if (p_rdh->i_sub_autodetect_fuzzy != 0
      && input_item_slave_GetType(psz_filename, &i_slave_type))
@@ -1657,13 +1743,22 @@ int readdir_helper_additem(struct readdir_helper *p_rdh,
     if (rdh_file_is_ignored(p_rdh, psz_filename))
         return VLC_SUCCESS;
 
-    input_item_t *p_item = input_item_NewExt(psz_uri, psz_filename, -1,
-                                             i_type, i_net);
+    input_item_node_t *p_node = p_rdh->p_node;
+
+    if (psz_flatpath != NULL)
+    {
+        int i_ret = rdh_unflatten(p_rdh, &p_node, psz_flatpath, i_net);
+        if (i_ret != VLC_SUCCESS)
+            return i_ret;
+    }
+
+    input_item_t *p_item = input_item_NewExt(psz_uri, psz_filename, -1, i_type,
+                                             i_net);
     if (p_item == NULL)
         return VLC_ENOMEM;
 
-    input_item_CopyOptions(p_item, p_rdh->p_node->p_item);
-    p_node = input_item_node_AppendItem(p_rdh->p_node, p_item);
+    input_item_CopyOptions(p_item, p_node->p_item);
+    p_node = input_item_node_AppendItem(p_node, p_item);
     input_item_Release(p_item);
     if (p_node == NULL)
         return VLC_ENOMEM;



More information about the vlc-commits mailing list