Commit 4ce1905d authored by Thomas Guillem's avatar 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.
parent dee7e3d3
......@@ -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
......@@ -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);
}
......
......@@ -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 );
}
......
......@@ -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 );
}
......
......@@ -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);
}
......
......@@ -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 );
}
......
......@@ -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 );
}
......
......@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment