[vlc-commits] input: extends vlc_readdir_helper_additem()

Thomas Guillem git at videolan.org
Wed Sep 20 17:38:42 CEST 2017


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

input: extends vlc_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=4ce1905da0591a6d137b65d1ffcc938a7ee25657
---

 include/vlc_input_item.h    |  13 +++++-
 modules/access/directory.c  |   2 +-
 modules/access/dsm/access.c |   2 +-
 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, 121 insertions(+), 17 deletions(-)

diff --git a/include/vlc_input_item.h b/include/vlc_input_item.h
index 3231c6ed01..d0f9587b7a 100644
--- a/include/vlc_input_item.h
+++ b/include/vlc_input_item.h
@@ -421,6 +421,8 @@ struct vlc_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 vlc_readdir_helper_finish(struct vlc_readdir_helper *p_rdh, bool b_
  *
  * \param p_rdh previously inited vlc_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 vlc_readdir_helper_additem(struct vlc_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 d398399b38..b8067140cf 100644
--- a/modules/access/directory.c
+++ b/modules/access/directory.c
@@ -181,7 +181,7 @@ int DirRead (stream_t *access, input_item_node_t *node)
             ret = VLC_ENOMEM;
             break;
         }
-        ret = vlc_readdir_helper_additem(&rdh, uri, entry, type,
+        ret = vlc_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 469f98d7b5..f97d488dbb 100644
--- a/modules/access/dsm/access.c
+++ b/modules/access/dsm/access.c
@@ -529,7 +529,7 @@ static int add_item( stream_t *p_access, struct vlc_readdir_helper *p_rdh,
     if( i_ret == -1 )
         return VLC_ENOMEM;
 
-    return vlc_readdir_helper_additem( p_rdh, psz_uri, psz_name, i_type,
+    return vlc_readdir_helper_additem( p_rdh, psz_uri, NULL, psz_name, i_type,
                                        ITEM_NET );
 }
 
diff --git a/modules/access/ftp.c b/modules/access/ftp.c
index 925f1d74e6..53541fd3e6 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 = vlc_readdir_helper_additem( &rdh, psz_uri, psz_file,
+            i_ret = vlc_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 39bbbff81b..3d415e0f5f 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 = vlc_readdir_helper_additem(&rdh, psz_url, p_nfsdirent->name,
+        i_ret = vlc_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 = vlc_readdir_helper_additem(&rdh, psz_url, psz_name,
+        i_ret = vlc_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 c9e498ed6a..c119a223f8 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 = vlc_readdir_helper_additem( &rdh, psz_full_uri, psz_file, i_type,
-                                            ITEM_NET );
+        i_ret = vlc_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 e17c320eaa..13d4e56118 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 = vlc_readdir_helper_additem( &rdh, psz_uri, p_entry->name,
+        i_ret = vlc_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 376cf59b08..0acb43d924 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 vlc_readdir_helper *p_rdh)
     }
 }
 
+static int rdh_unflatten(struct vlc_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 vlc_readdir_helper_init
 void vlc_readdir_helper_init(struct vlc_readdir_helper *p_rdh,
                              vlc_object_t *p_obj, input_item_node_t *p_node)
@@ -1600,6 +1672,7 @@ void vlc_readdir_helper_init(struct vlc_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 vlc_readdir_helper_finish(struct vlc_readdir_helper *p_rdh, bool b_success)
@@ -1623,15 +1696,28 @@ void vlc_readdir_helper_finish(struct vlc_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 vlc_readdir_helper_additem(struct vlc_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 vlc_readdir_helper_additem(struct vlc_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