[vlc-devel] [PATCHv3 01/13] access: re-refactor pf_readdir
Thomas Guillem
thomas at gllm.fr
Tue May 17 18:24:45 CEST 2016
This commit changes pf_readdir callback to its original behavior. Accesses and
streams now add items to a node.
Archive stream_filters will now be able to add nodes to a node (when an archive
has directory). This was not possible before.
This commit also adds an access_fsdir helper to help fs accesses (file, smb,
nfs, ftp, sftp) adding items to a node. These accesses need the same treatment
that is now done by this helper:
- hide hidden files or not (depending on "show-hiddenfiles" option)
- skip some file extensions (depending on "ignore-filetypes" option)
- sort items by type and alphabetically (depending on "directory-sort"
option).
- For a next commit: attach slaves to items
The directory demux won't do these operations anymore for every access/stream.
This commit doesn't change the interruptible state of the pf_readdir function,
accesses/streams are still interruptible in the middle of a pf_readdir call.
This partially reverts commit 88ffe1587824c27f35705ee28e607f80ca335b46.
---
include/vlc_access.h | 57 +++++++++++++--
include/vlc_stream.h | 6 +-
modules/access/archive/stream.c | 25 ++++---
modules/access/directory.c | 39 ++++++----
modules/access/dsm/access.c | 119 +++++++++++++++---------------
modules/access/fs.h | 3 +-
modules/access/ftp.c | 57 ++++++++-------
modules/access/nfs.c | 71 ++++++++++--------
modules/access/sftp.c | 38 +++++-----
modules/access/smb.c | 31 ++++----
modules/demux/playlist/directory.c | 137 ++---------------------------------
modules/services_discovery/upnp.cpp | 112 ++++++++++++-----------------
modules/services_discovery/upnp.hpp | 14 ++--
modules/stream_filter/inflate.c | 6 +-
modules/stream_filter/prefetch.c | 6 +-
src/input/access.c | 139 ++++++++++++++++++++++++++++++++++--
src/input/stream.c | 9 ++-
src/input/stream_filter.c | 4 +-
src/libvlccore.sym | 3 +
19 files changed, 468 insertions(+), 408 deletions(-)
diff --git a/include/vlc_access.h b/include/vlc_access.h
index 4578734..9ac8a81 100644
--- a/include/vlc_access.h
+++ b/include/vlc_access.h
@@ -88,11 +88,7 @@ struct access_t
* XXX A access should set one and only one of them */
ssize_t (*pf_read) ( access_t *, uint8_t *, size_t ); /* Return -1 if no data yet, 0 if no more data, else real data read */
block_t *(*pf_block) ( access_t * ); /* Return a block of data in his 'natural' size, NULL if not yet data or eof */
-
- /* pf_readdir: Read the next input_item_t from the directory stream. It
- * returns the next input item on success or NULL in case of error or end
- * of stream. The item must be released with input_item_Release. */
- input_item_t *(*pf_readdir)( access_t * );
+ int (*pf_readdir)( access_t *, input_item_node_t * );/* Fills the provided item_node, see doc/browsing.txt for details */
/* Called for each seek.
* XXX can be null */
@@ -239,6 +235,11 @@ static inline void access_InitFields( access_t *p_a )
}
/**
+ * \defgroup access_helper Access Helpers
+ * @{
+ */
+
+/**
* Default pf_control callback for directory accesses.
*/
VLC_API int access_vaDirectoryControlHelper( access_t *p_access, int i_query, va_list args );
@@ -268,7 +269,51 @@ VLC_API int access_vaDirectoryControlHelper( access_t *p_access, int i_query, va
} while(0);
/**
- * @}
+ * Access pf_readdir helper struct
+ * \see access_fsdir_init()
+ * \see access_fsdir_additem()
+ * \see access_fsdir_finish()
+ */
+struct access_fsdir
+{
+ input_item_node_t *p_node;
+ bool b_show_hiddenfiles;
+ char *psz_ignored_exts;
+ char *psz_sort;
+};
+
+/**
+ * Init a access_fsdir struct
+ *
+ * \param p_fsdir need to be cleaned with access_fsdir_finish()
+ * \param p_node node that will be used to add items
+ */
+VLC_API void access_fsdir_init(struct access_fsdir *p_fsdir,
+ access_t *p_access, input_item_node_t *p_node);
+
+/**
+ * Finish adding items to the node
+ *
+ * \param b_success if true, items of the node will be sorted according
+ * "directory-sort" option.
+ */
+VLC_API void access_fsdir_finish(struct access_fsdir *p_fsdir, bool b_success);
+
+/**
+ * Add a new input_item_t entry to the node of the access_fsdir struct.
+ *
+ * \param p_fsdir previously inited access_fsdir struct
+ * \param psz_uri uri of the new item
+ * \param psz_filename file name of the new item
+ * \param i_type see \ref input_item_type_e
+ * \param i_net see \ref input_item_net_type
+ */
+VLC_API int access_fsdir_additem(struct access_fsdir *p_fsdir,
+ const char *psz_uri, const char *psz_filename,
+ int i_type, int i_net);
+
+/**
+ * @} @}
*/
#endif
diff --git a/include/vlc_stream.h b/include/vlc_stream.h
index d783487..0b64f61 100644
--- a/include/vlc_stream.h
+++ b/include/vlc_stream.h
@@ -57,7 +57,7 @@ struct stream_t
/* */
ssize_t (*pf_read)(stream_t *, void *, size_t);
- input_item_t *(*pf_readdir)( stream_t * );
+ int (*pf_readdir)( stream_t *, input_item_node_t * );
int (*pf_seek)(stream_t *, uint64_t);
int (*pf_control)( stream_t *, int i_query, va_list );
@@ -157,7 +157,7 @@ VLC_API void stream_Delete( stream_t *s );
VLC_API int stream_Control( stream_t *s, int i_query, ... );
VLC_API block_t * stream_Block( stream_t *s, size_t );
VLC_API char * stream_ReadLine( stream_t * );
-VLC_API input_item_t *stream_ReadDir( stream_t * );
+VLC_API int stream_ReadDir( stream_t *, input_item_node_t * );
/**
* Low level custom stream creation.
@@ -248,7 +248,7 @@ VLC_API stream_t* stream_FilterNew( stream_t *p_source, const char *psz_stream_f
* Default ReadDir implementation for stream Filter. This implementation just
* forward the pf_readdir call to the p_source stream.
*/
-VLC_API input_item_t *stream_FilterDefaultReadDir( stream_t *s );
+VLC_API int stream_FilterDefaultReadDir( stream_t *s, input_item_node_t *p_node );
/**
* Sets stream_FilterDefaultReadDir as the pf_readdir callback for this stream filter
diff --git a/modules/access/archive/stream.c b/modules/access/archive/stream.c
index 3d70725..2fb7986 100644
--- a/modules/access/archive/stream.c
+++ b/modules/access/archive/stream.c
@@ -128,34 +128,39 @@ static ssize_t SeekCallback(struct archive *p_archive, void *p_object, ssize_t i
return stream_Tell(p_stream->p_source);
}
-static input_item_t *Browse(stream_t *p_stream)
+static int Browse(stream_t *p_stream, input_item_node_t *p_node)
{
stream_sys_t *p_sys = p_stream->p_sys;
struct archive_entry *p_entry;
- input_item_t *p_item = NULL;
- if (archive_read_next_header(p_sys->p_archive, &p_entry) == ARCHIVE_OK)
+ while(archive_read_next_header(p_sys->p_archive, &p_entry) == ARCHIVE_OK)
{
char *psz_uri = NULL;
char *psz_access_uri = NULL;
int i_ret = asprintf(&psz_access_uri, "%s%c%s", p_stream->psz_url,
ARCHIVE_SEP_CHAR, archive_entry_pathname(p_entry));
if (i_ret == -1)
- return NULL;
+ goto error;
i_ret = asprintf(&psz_uri, "archive://%s", psz_access_uri);
free(psz_access_uri);
- if( i_ret == -1 )
- return NULL;
+ if(i_ret == -1)
+ goto error;
- p_item = input_item_New(psz_uri, archive_entry_pathname(p_entry));
+ input_item_t *p_item = input_item_New(psz_uri, archive_entry_pathname(p_entry));
free( psz_uri );
- if(p_item == NULL)
- return NULL;
+ if (p_item == NULL)
+ goto error;
+ input_item_CopyOptions(p_node->p_item, p_item);
+ input_item_node_AppendItem(p_node, p_item);
msg_Dbg(p_stream, "declaring playlist entry %s", archive_entry_pathname(p_entry));
+ input_item_Release(p_item);
}
- return p_item;
+ return VLC_SUCCESS;
+
+error:
+ return VLC_ENOMEM;
}
int StreamOpen(vlc_object_t *p_object)
diff --git a/modules/access/directory.c b/modules/access/directory.c
index ff908eb..683de55 100644
--- a/modules/access/directory.c
+++ b/modules/access/directory.c
@@ -46,7 +46,6 @@ struct access_sys_t
{
char *base_uri;
DIR *dir;
- bool special_files;
};
/*****************************************************************************
@@ -70,7 +69,6 @@ int DirInit (access_t *access, DIR *dir)
goto error;
sys->dir = dir;
- sys->special_files = var_InheritBool(access, "list-special-files");
access->p_sys = sys;
access->pf_readdir = DirRead;
@@ -113,12 +111,18 @@ void DirClose(vlc_object_t *obj)
free(sys);
}
-input_item_t *DirRead(access_t *access)
+int DirRead (access_t *access, input_item_node_t *node)
{
access_sys_t *sys = access->p_sys;
const char *entry;
+ int ret = VLC_SUCCESS;
- while ((entry = vlc_readdir(sys->dir)) != NULL)
+ bool special_files = var_InheritBool(access, "list-special-files");
+
+ struct access_fsdir fsdir;
+ access_fsdir_init(&fsdir, access, node);
+
+ while (ret == VLC_SUCCESS && (entry = vlc_readdir(sys->dir)) != NULL)
{
struct stat st;
int type;
@@ -136,17 +140,17 @@ input_item_t *DirRead(access_t *access)
switch (st.st_mode & S_IFMT)
{
case S_IFBLK:
- if (!sys->special_files)
+ if (!special_files)
continue;
type = ITEM_TYPE_DISC;
break;
case S_IFCHR:
- if (!sys->special_files)
+ if (!special_files)
continue;
type = ITEM_TYPE_CARD;
break;
case S_IFIFO:
- if (!sys->special_files)
+ if (!special_files)
continue;
type = ITEM_TYPE_STREAM;
break;
@@ -165,20 +169,25 @@ input_item_t *DirRead(access_t *access)
/* Create an input item for the current entry */
char *encoded = vlc_uri_encode(entry);
if (unlikely(encoded == NULL))
- continue;
+ {
+ ret = VLC_ENOMEM;
+ break;
+ }
char *uri;
if (unlikely(asprintf(&uri, "%s/%s", sys->base_uri, encoded) == -1))
uri = NULL;
free(encoded);
if (unlikely(uri == NULL))
- continue;
-
- input_item_t *item = input_item_NewExt(uri, entry, -1, type,
- ITEM_NET_UNKNOWN);
+ {
+ ret = VLC_ENOMEM;
+ break;
+ }
+ ret = access_fsdir_additem(&fsdir, uri, entry, type, ITEM_NET_UNKNOWN);
free(uri);
- if (likely(item != NULL))
- return item;
}
- return NULL;
+
+ access_fsdir_finish(&fsdir, ret == VLC_SUCCESS);
+
+ return ret;
}
diff --git a/modules/access/dsm/access.c b/modules/access/dsm/access.c
index bac034b..94155ca 100644
--- a/modules/access/dsm/access.c
+++ b/modules/access/dsm/access.c
@@ -98,7 +98,8 @@ static int BrowserInit( access_t *p_access );
static int get_address( access_t *p_access );
static int login( access_t *p_access );
static bool get_path( access_t *p_access );
-static input_item_t* new_item( access_t *p_access, const char *psz_name, int i_type );
+static int add_item( access_t *p_access, struct access_fsdir *p_fsdir,
+ const char *psz_name, int i_type );
struct access_sys_t
{
@@ -115,11 +116,6 @@ struct access_sys_t
smb_fd i_fd; /**< SMB fd for the file we're reading */
smb_tid i_tid; /**< SMB Tree ID we're connected to */
-
- size_t i_browse_count;
- size_t i_browse_idx;
- smb_share_list shares;
- smb_stat_list files;
};
/*****************************************************************************
@@ -211,11 +207,8 @@ static void Close( vlc_object_t *p_this )
if( p_sys->p_session )
smb_session_destroy( p_sys->p_session );
vlc_UrlClean( &p_sys->url );
- if( p_sys->shares )
- smb_share_list_destroy( p_sys->shares );
- if( p_sys->files )
- smb_stat_list_destroy( p_sys->files );
free( p_sys->psz_fullpath );
+
free( p_sys );
}
@@ -525,16 +518,15 @@ static int Control( access_t *p_access, int i_query, va_list args )
return VLC_SUCCESS;
}
-static input_item_t *new_item( access_t *p_access, const char *psz_name,
- int i_type )
+static int add_item( access_t *p_access, struct access_fsdir *p_fsdir,
+ const char *psz_name, int i_type )
{
- input_item_t *p_item;
char *psz_uri;
int i_ret;
char *psz_encoded_name = vlc_uri_encode( psz_name );
if( psz_encoded_name == NULL )
- return NULL;
+ return VLC_ENOMEM;
const char *psz_sep = p_access->psz_location[0] != '\0'
&& p_access->psz_location[strlen(p_access->psz_location) -1] != '/'
? "/" : "";
@@ -542,90 +534,91 @@ static input_item_t *new_item( access_t *p_access, const char *psz_name,
psz_sep, psz_encoded_name );
free( psz_encoded_name );
if( i_ret == -1 )
- return NULL;
-
- p_item = input_item_NewExt( psz_uri, psz_name, -1, i_type, ITEM_NET );
- free( psz_uri );
- if( p_item == NULL )
- return NULL;
+ return VLC_ENOMEM;
- return p_item;
+ return access_fsdir_additem( p_fsdir, psz_uri, psz_name, i_type, ITEM_NET );
}
-static input_item_t* BrowseShare( access_t *p_access )
+static int BrowseShare( access_t *p_access, input_item_node_t *p_node )
{
access_sys_t *p_sys = p_access->p_sys;
+ smb_share_list shares;
const char *psz_name;
- input_item_t *p_item = NULL;
+ size_t share_count;
+ int i_ret = VLC_SUCCESS;
- if( !p_sys->i_browse_count )
- {
- size_t i_count;
- if( smb_share_get_list( p_sys->p_session, &p_sys->shares, &i_count )
- != DSM_SUCCESS )
- return NULL;
- else
- p_sys->i_browse_count = i_count;
- }
- for( ; !p_item && p_sys->i_browse_idx < p_sys->i_browse_count
- ; p_sys->i_browse_idx++ )
+ if( smb_share_get_list( p_sys->p_session, &shares, &share_count )
+ != DSM_SUCCESS )
+ return VLC_EGENERIC;
+
+ struct access_fsdir fsdir;
+ access_fsdir_init( &fsdir, p_access, p_node );
+
+ for( size_t i = 0; i < share_count && i_ret == VLC_SUCCESS; i++ )
{
- psz_name = smb_share_list_at( p_sys->shares, p_sys->i_browse_idx );
+ psz_name = smb_share_list_at( shares, i );
if( psz_name[strlen( psz_name ) - 1] == '$')
continue;
- p_item = new_item( p_access, psz_name, ITEM_TYPE_DIRECTORY );
- if( !p_item )
- return NULL;
+ i_ret = add_item( p_access, &fsdir, psz_name, ITEM_TYPE_DIRECTORY );
}
- return p_item;
+
+ access_fsdir_finish( &fsdir, i_ret == VLC_SUCCESS );
+
+ smb_share_list_destroy( shares );
+ return i_ret;
}
-static input_item_t* BrowseDirectory( access_t *p_access )
+static int BrowseDirectory( access_t *p_access, input_item_node_t *p_node )
{
access_sys_t *p_sys = p_access->p_sys;
+ smb_stat_list files;
smb_stat st;
- input_item_t *p_item = NULL;
char *psz_query;
const char *psz_name;
- int i_ret;
+ size_t files_count;
+ int i_ret = VLC_SUCCESS;
- if( !p_sys->i_browse_count )
+ if( p_sys->psz_path != NULL )
{
- if( p_sys->psz_path != NULL )
- {
- i_ret = asprintf( &psz_query, "%s\\*", p_sys->psz_path );
- if( i_ret == -1 )
- return NULL;
- p_sys->files = smb_find( p_sys->p_session, p_sys->i_tid, psz_query );
- free( psz_query );
- }
- else
- p_sys->files = smb_find( p_sys->p_session, p_sys->i_tid, "\\*" );
- if( p_sys->files == NULL )
- return NULL;
- p_sys->i_browse_count = smb_stat_list_count( p_sys->files );
+ if( asprintf( &psz_query, "%s\\*", p_sys->psz_path ) == -1 )
+ return VLC_ENOMEM;
+ files = smb_find( p_sys->p_session, p_sys->i_tid, psz_query );
+ free( psz_query );
}
+ else
+ files = smb_find( p_sys->p_session, p_sys->i_tid, "\\*" );
+
+ if( files == NULL )
+ return VLC_EGENERIC;
+
+ struct access_fsdir fsdir;
+ access_fsdir_init( &fsdir, p_access, p_node );
- if( p_sys->i_browse_idx < p_sys->i_browse_count )
+ files_count = smb_stat_list_count( files );
+ for( size_t i = 0; i < files_count && i_ret == VLC_SUCCESS; i++ )
{
int i_type;
- st = smb_stat_list_at( p_sys->files, p_sys->i_browse_idx++ );
+ st = smb_stat_list_at( files, i );
if( st == NULL )
- return NULL;
+ {
+ continue;
+ }
psz_name = smb_stat_name( st );
i_type = smb_stat_get( st, SMB_STAT_ISDIR ) ?
ITEM_TYPE_DIRECTORY : ITEM_TYPE_FILE;
- p_item = new_item( p_access, psz_name, i_type );
- if( !p_item )
- return NULL;
+ i_ret = add_item( p_access, &fsdir, psz_name, i_type );
}
- return p_item;
+
+ access_fsdir_finish( &fsdir, i_ret == VLC_SUCCESS );
+
+ smb_stat_list_destroy( files );
+ return i_ret;
}
static int DirControl( access_t *p_access, int i_query, va_list args )
diff --git a/modules/access/fs.h b/modules/access/fs.h
index eb67411..3bcf048 100644
--- a/modules/access/fs.h
+++ b/modules/access/fs.h
@@ -25,5 +25,6 @@ void FileClose (vlc_object_t *);
int DirOpen (vlc_object_t *);
int DirInit (access_t *p_access, DIR *handle);
-input_item_t* DirRead (access_t *);
+int DirRead (access_t *, input_item_node_t *);
+int DirControl (access_t *, int, va_list);
void DirClose (vlc_object_t *);
diff --git a/modules/access/ftp.c b/modules/access/ftp.c
index 3a878b1..7017ea1 100644
--- a/modules/access/ftp.c
+++ b/modules/access/ftp.c
@@ -112,7 +112,7 @@ vlc_module_end ()
static ssize_t Read( access_t *, uint8_t *, size_t );
static int Seek( access_t *, uint64_t );
static int Control( access_t *, int, va_list );
-static input_item_t* DirRead( access_t * );
+static int DirRead( access_t *, input_item_node_t * );
static int DirControl( access_t *, int, va_list );
#ifdef ENABLE_SOUT
static int OutSeek( sout_access_out_t *, off_t );
@@ -877,37 +877,46 @@ static ssize_t Read( access_t *p_access, uint8_t *p_buffer, size_t i_len )
/*****************************************************************************
* DirRead:
*****************************************************************************/
-static input_item_t* DirRead( access_t *p_access )
+static int DirRead (access_t *p_access, input_item_node_t *p_current_node)
{
access_sys_t *p_sys = p_access->p_sys;
- input_item_t *p_item = NULL;
+ int i_ret = VLC_SUCCESS;
assert( p_sys->data.fd != -1 );
assert( !p_sys->out );
- char *psz_line;
- if( p_sys->data.p_tls != NULL )
- psz_line = vlc_tls_GetLine( p_sys->data.p_tls );
- else
- psz_line = net_Gets( p_access, p_sys->data.fd );
- if( psz_line == NULL )
- return NULL;
-
- char *psz_uri;
- if( asprintf( &psz_uri, "%s://%s:%d%s%s/%s",
- ( p_sys->tlsmode == NONE ) ? "ftp" :
- ( ( p_sys->tlsmode == IMPLICIT ) ? "ftps" : "ftpes" ),
- p_sys->url.psz_host, p_sys->url.i_port,
- p_sys->url.psz_path ? "/" : "",
- p_sys->url.psz_path ? p_sys->url.psz_path : "",
- psz_line ) != -1 )
+ struct access_fsdir fsdir;
+ access_fsdir_init( &fsdir, p_access, p_current_node );
+
+ while (i_ret == VLC_SUCCESS)
{
- p_item = input_item_NewExt( psz_uri, psz_line, -1, ITEM_TYPE_UNKNOWN,
- ITEM_NET );
- free( psz_uri );
+ char *psz_line;
+ if( p_sys->data.p_tls != NULL )
+ psz_line = vlc_tls_GetLine( p_sys->data.p_tls );
+ else
+ psz_line = net_Gets( p_access, p_sys->data.fd );
+
+ if( psz_line == NULL )
+ break;
+
+ char *psz_uri;
+ if( asprintf( &psz_uri, "%s://%s:%d%s%s/%s",
+ ( p_sys->tlsmode == NONE ) ? "ftp" :
+ ( ( p_sys->tlsmode == IMPLICIT ) ? "ftps" : "ftpes" ),
+ p_sys->url.psz_host, p_sys->url.i_port,
+ p_sys->url.psz_path ? "/" : "",
+ p_sys->url.psz_path ? p_sys->url.psz_path : "",
+ psz_line ) != -1 )
+ {
+ i_ret = access_fsdir_additem( &fsdir, psz_uri, psz_line,
+ ITEM_TYPE_UNKNOWN, ITEM_NET );
+ free( psz_uri );
+ }
+ free( psz_line );
}
- free( psz_line );
- return p_item;
+
+ access_fsdir_finish( &fsdir, i_ret == VLC_SUCCESS );
+ return i_ret;
}
static int DirControl( access_t *p_access, int i_query, va_list args )
diff --git a/modules/access/nfs.c b/modules/access/nfs.c
index 310bc95..9e5b6a2 100644
--- a/modules/access/nfs.c
+++ b/modules/access/nfs.c
@@ -83,7 +83,6 @@ struct access_sys_t
{
char ** ppsz_names;
int i_count;
- unsigned int i_current;
} exports;
struct
{
@@ -315,26 +314,33 @@ NfsGetUrl(vlc_url_t *p_url, const char *psz_file)
return psz_url;
}
-static input_item_t *
-DirRead(access_t *p_access)
+static int
+DirRead(access_t *p_access, input_item_node_t *p_node)
{
access_sys_t *p_sys = p_access->p_sys;
struct nfsdirent *p_nfsdirent;
+ int i_ret = VLC_SUCCESS;
assert(p_sys->p_nfsdir);
- p_nfsdirent = nfs_readdir(p_sys->p_nfs, p_sys->p_nfsdir);
- if (p_nfsdirent == NULL)
- return NULL;
- else
+ struct access_fsdir fsdir;
+ access_fsdir_init(&fsdir, p_access, p_node);
+
+ while (i_ret == VLC_SUCCESS
+ && (p_nfsdirent = nfs_readdir(p_sys->p_nfs, p_sys->p_nfsdir)) != NULL)
{
- input_item_t *p_item;
char *psz_name_encoded = vlc_uri_encode(p_nfsdirent->name);
if (psz_name_encoded == NULL)
- return NULL;
+ {
+ i_ret = VLC_ENOMEM;
+ break;
+ }
char *psz_url = NfsGetUrl(&p_sys->encoded_url, psz_name_encoded);
free(psz_name_encoded);
if (psz_url == NULL)
- return NULL;
+ {
+ i_ret = VLC_ENOMEM;
+ break;
+ }
int i_type;
switch (p_nfsdirent->type)
@@ -348,34 +354,44 @@ DirRead(access_t *p_access)
default:
i_type = ITEM_TYPE_UNKNOWN;
}
- p_item = input_item_NewExt(psz_url, p_nfsdirent->name, -1, i_type,
- ITEM_NET);
+ i_ret = access_fsdir_additem(&fsdir, psz_url, p_nfsdirent->name,
+ i_type, ITEM_NET);
free(psz_url);
- return p_item;
}
+
+ access_fsdir_finish(&fsdir, i_ret == VLC_SUCCESS);
+
+ return i_ret;
}
-static input_item_t *
-MountRead(access_t *p_access)
+static int
+MountRead(access_t *p_access, input_item_node_t *p_node)
{
access_sys_t *p_sys = p_access->p_sys;
assert(p_sys->p_mount != NULL && p_sys->res.exports.i_count >= 0);
+ int i_ret = VLC_SUCCESS;
- unsigned int i_count = p_sys->res.exports.i_count;
- unsigned int i_current = p_sys->res.exports.i_current;
- if (i_current >= i_count)
- return NULL;
+ struct access_fsdir fsdir;
+ access_fsdir_init(&fsdir, p_access, p_node);
- char *psz_name = p_sys->res.exports.ppsz_names[i_current];
- p_sys->res.exports.i_current++;
+ for (int i = 0; i < p_sys->res.exports.i_count && i_ret == VLC_SUCCESS; ++i)
+ {
+ char *psz_name = p_sys->res.exports.ppsz_names[i];
- char *psz_url = NfsGetUrl(&p_sys->encoded_url, psz_name);
- if (psz_url == NULL)
- return NULL;
+ char *psz_url = NfsGetUrl(&p_sys->encoded_url, psz_name);
+ if (psz_url == NULL)
+ {
+ i_ret = VLC_ENOMEM;
+ break;
+ }
+ i_ret = access_fsdir_additem(&fsdir, psz_url, psz_name,
+ ITEM_TYPE_DIRECTORY, ITEM_NET);
+ free(psz_url);
+ }
+
+ access_fsdir_finish(&fsdir, i_ret == VLC_SUCCESS);
- input_item_t *p_item = input_item_NewDirectory(psz_url, psz_name, ITEM_NET);
- free(psz_url);
- return p_item;
+ return i_ret;
}
static int
@@ -706,7 +722,6 @@ Open(vlc_object_t *p_obj)
p_sys->res.exports.ppsz_names = NULL;
p_sys->res.exports.i_count = -1;
- p_sys->res.exports.i_current = 0;
if (mount_getexports_async(p_sys->p_mount, p_sys->p_nfs_url->server,
mount_export_cb, p_access) < 0)
diff --git a/modules/access/sftp.c b/modules/access/sftp.c
index f5488df..550d69d 100644
--- a/modules/access/sftp.c
+++ b/modules/access/sftp.c
@@ -80,7 +80,7 @@ static ssize_t Read( access_t *, uint8_t *, size_t );
static int Seek( access_t *, uint64_t );
static int Control( access_t *, int, va_list );
-static input_item_t* DirRead( access_t *p_access );
+static int DirRead( access_t *, input_item_node_t * );
static int DirControl( access_t *, int, va_list );
struct access_sys_t
@@ -464,11 +464,11 @@ static int Control( access_t* p_access, int i_query, va_list args )
* Directory access
*****************************************************************************/
-static input_item_t* DirRead( access_t *p_access )
+static int DirRead (access_t *p_access, input_item_node_t *p_current_node)
{
access_sys_t *p_sys = p_access->p_sys;
LIBSSH2_SFTP_ATTRIBUTES attrs;
- input_item_t *p_item = NULL;
+ int i_ret = VLC_SUCCESS;
int err;
/* Allocate 1024 bytes for file name. Longer names are skipped.
* libssh2 does not support seeking in directory streams.
@@ -479,9 +479,13 @@ static input_item_t* DirRead( access_t *p_access )
char *psz_file = malloc( i_size );
if( !psz_file )
- return NULL;
+ return VLC_ENOMEM;
- while( !p_item && 0 != ( err = libssh2_sftp_readdir( p_sys->file, psz_file, i_size, &attrs ) ) )
+ struct access_fsdir fsdir;
+ access_fsdir_init( &fsdir, p_access, p_current_node );
+
+ while( i_ret == VLC_SUCCESS
+ && 0 != ( err = libssh2_sftp_readdir( p_sys->file, psz_file, i_size, &attrs ) ) )
{
if( err < 0 )
{
@@ -499,38 +503,34 @@ static input_item_t* DirRead( access_t *p_access )
break;
}
- if( psz_file[0] == '.' )
- {
- continue;
- }
-
/* Create an input item for the current entry */
char *psz_full_uri, *psz_uri;
psz_uri = vlc_uri_encode( psz_file );
if( psz_uri == NULL )
- continue;
+ {
+ i_ret = VLC_ENOMEM;
+ break;
+ }
if( asprintf( &psz_full_uri, "%s/%s", p_sys->psz_base_url, psz_uri ) == -1 )
{
free( psz_uri );
- continue;
+ i_ret = VLC_ENOMEM;
+ break;
}
free( psz_uri );
int i_type = LIBSSH2_SFTP_S_ISDIR( attrs.permissions ) ? ITEM_TYPE_DIRECTORY : ITEM_TYPE_FILE;
- p_item = input_item_NewExt( psz_full_uri, psz_file, -1, i_type, ITEM_NET );
+ i_ret = access_fsdir_additem( &fsdir, psz_full_uri, psz_file, i_type,
+ ITEM_NET );
free( psz_full_uri );
-
- if( p_item == NULL )
- {
- break;
- }
}
+ access_fsdir_finish( &fsdir, i_ret == VLC_SUCCESS );
free( psz_file );
- return p_item;
+ return i_ret;
}
static int DirControl( access_t *p_access, int i_query, va_list args )
diff --git a/modules/access/smb.c b/modules/access/smb.c
index c007f71..5f6bd2e 100644
--- a/modules/access/smb.c
+++ b/modules/access/smb.c
@@ -84,7 +84,7 @@ static ssize_t Read( access_t *, uint8_t *, size_t );
static int Seek( access_t *, uint64_t );
static int Control( access_t *, int, va_list );
#ifndef _WIN32
-static input_item_t* DirRead( access_t * );
+static int DirRead( access_t *, input_item_node_t * );
static int DirControl( access_t *, int, va_list );
#endif
@@ -344,13 +344,16 @@ static ssize_t Read( access_t *p_access, uint8_t *p_buffer, size_t i_len )
/*****************************************************************************
* DirRead:
*****************************************************************************/
-static input_item_t* DirRead (access_t *p_access )
+static int DirRead (access_t *p_access, input_item_node_t *p_node )
{
access_sys_t *p_sys = p_access->p_sys;
struct smbc_dirent *p_entry;
- input_item_t *p_item = NULL;
+ int i_ret = VLC_SUCCESS;
- while( !p_item && ( p_entry = smbc_readdir( p_sys->i_smb ) ) )
+ struct access_fsdir fsdir;
+ access_fsdir_init( &fsdir, p_access, p_node );
+
+ while( i_ret == VLC_SUCCESS && ( p_entry = smbc_readdir( p_sys->i_smb ) ) )
{
char *psz_uri;
const char *psz_server = p_sys->url.psz_host;
@@ -383,22 +386,26 @@ static input_item_t* DirRead (access_t *p_access )
char *psz_encoded_name = NULL;
if( psz_name != NULL
&& ( psz_encoded_name = vlc_uri_encode( psz_name ) ) == NULL )
- return NULL;
+ {
+ i_ret = VLC_ENOMEM;
+ break;
+ }
if( smb_get_uri( p_access, &psz_uri, NULL, NULL, NULL,
psz_server, psz_path, psz_encoded_name ) < 0 )
{
free(psz_encoded_name);
- return NULL;
+ i_ret = VLC_ENOMEM;
+ break;
}
free(psz_encoded_name);
-
- p_item = input_item_NewExt( psz_uri, p_entry->name, -1, i_type,
- ITEM_NET );
+ i_ret = access_fsdir_additem( &fsdir, psz_uri, p_entry->name,
+ i_type, ITEM_NET );
free( psz_uri );
- if( !p_item )
- return NULL;
}
- return p_item;
+
+ access_fsdir_finish( &fsdir, i_ret == VLC_SUCCESS );
+
+ return i_ret;
}
static int DirControl( access_t *p_access, int i_query, va_list args )
diff --git a/modules/demux/playlist/directory.c b/modules/demux/playlist/directory.c
index e1ff41d..314568f 100644
--- a/modules/demux/playlist/directory.c
+++ b/modules/demux/playlist/directory.c
@@ -67,146 +67,17 @@ void Close_Dir ( vlc_object_t *p_this )
free( p_demux->p_sys );
}
-/**
- * Does the provided URI/path/stuff has one of the extension provided ?
- *
- * \param psz_exts A comma separated list of extension without dot, or only
- * one ext (ex: "avi,mkv,webm")
- * \param psz_uri The uri/path to check (ex: "file:///home/foo/bar.avi"). If
- * providing an URI, it must not contain a query string.
- *
- * \return true if the uri/path has one of the provided extension
- * false otherwise.
- */
-static bool has_ext( const char *psz_exts, const char *psz_uri )
-{
- if( psz_exts == NULL )
- return false;
-
- const char *ext = strrchr( psz_uri, '.' );
- if( ext == NULL )
- return false;
-
- size_t extlen = strlen( ++ext );
-
- for( const char *type = psz_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 ) )
- return true;
-
- if( *end == '\0' )
- break;
- }
-
- return false;
-}
-
-static int compar_type( input_item_t *p1, input_item_t *p2 )
-{
- if( p1->i_type != p2->i_type )
- {
- if( p1->i_type == ITEM_TYPE_DIRECTORY )
- return -1;
- if( p2->i_type == ITEM_TYPE_DIRECTORY )
- return 1;
- }
- return 0;
-}
-
-static int compar_collate( input_item_t *p1, input_item_t *p2 )
-{
- int i_ret = compar_type( p1, p2 );
-
- if( i_ret != 0 )
- return i_ret;
-
-#ifdef HAVE_STRCOLL
- /* The program's LOCAL defines if case is ignored */
- return strcoll( p1->psz_name, p2->psz_name );
-#else
- return strcasecmp( p1->psz_name, p2->psz_name );
-#endif
-}
-
-static int compar_version( input_item_t *p1, input_item_t *p2 )
-{
- int i_ret = compar_type( p1, p2 );
-
- if( i_ret != 0 )
- return i_ret;
-
- return strverscmp( p1->psz_name, p2->psz_name );
-}
-
static int Demux( demux_t *p_demux )
{
- int i_ret = VLC_SUCCESS;
- input_item_t *p_input;
- input_item_node_t *p_node;
- input_item_t *p_item;
- char *psz_ignored_exts;
- bool b_show_hiddenfiles;
-
- p_input = GetCurrentItem( p_demux );
- p_node = input_item_node_Create( p_input );
- if( p_node == NULL )
- {
- input_item_Release( p_input );
- return VLC_ENOMEM;
- }
- p_node->b_can_loop = p_demux->p_sys->b_dir_can_loop;
+ input_item_t *p_input = GetCurrentItem(p_demux);
+ input_item_node_t *p_node = input_item_node_Create( p_input );
input_item_Release(p_input);
- b_show_hiddenfiles = var_InheritBool( p_demux, "show-hiddenfiles" );
- psz_ignored_exts = var_InheritString( p_demux, "ignore-filetypes" );
-
- while( !i_ret && ( p_item = stream_ReadDir( p_demux->s ) ) )
- {
- int i_name_len = p_item->psz_name ? strlen( p_item->psz_name ) : 0;
-
- /* skip null, "." and ".." and hidden files if option is activated */
- if( !i_name_len || strcmp( p_item->psz_name, "." ) == 0
- || strcmp( p_item->psz_name, ".." ) == 0
- || ( !b_show_hiddenfiles && p_item->psz_name[0] == '.' ) )
- goto skip_item;
- /* skip ignored files */
- if( has_ext( psz_ignored_exts, p_item->psz_name ) )
- goto skip_item;
-
- input_item_CopyOptions( p_item, p_node->p_item );
- if( !input_item_node_AppendItem( p_node, p_item ) )
- i_ret = VLC_ENOMEM;
-skip_item:
- input_item_Release( p_item );
- }
- free( psz_ignored_exts );
-
- if( i_ret )
+ if( stream_ReadDir( p_demux->s, p_node ) )
{
msg_Warn( p_demux, "unable to read directory" );
input_item_node_Delete( p_node );
- return i_ret;
- }
-
- if( !p_demux->p_sys->b_dir_sorted )
- {
- input_item_compar_cb compar_cb = NULL;
- char *psz_sort = var_InheritString( p_demux, "directory-sort" );
-
- if( psz_sort )
- {
- if( !strcasecmp( psz_sort, "version" ) )
- compar_cb = compar_version;
- else if( strcasecmp( psz_sort, "none" ) )
- compar_cb = compar_collate;
- }
- free( psz_sort );
- if( compar_cb )
- input_item_node_Sort( p_node, compar_cb );
+ return VLC_EGENERIC;
}
input_item_node_PostAndDelete( p_node );
diff --git a/modules/services_discovery/upnp.cpp b/modules/services_discovery/upnp.cpp
index bc54024..c5c30a8 100644
--- a/modules/services_discovery/upnp.cpp
+++ b/modules/services_discovery/upnp.cpp
@@ -69,7 +69,6 @@ struct services_discovery_sys_t
struct access_sys_t
{
UpnpInstanceWrapper* p_upnp;
- Access::MediaServer* p_server;
};
UpnpInstanceWrapper* UpnpInstanceWrapper::s_instance;
@@ -755,15 +754,9 @@ int Upnp_i11e_cb::run( Upnp_EventType eventType, void *p_event, void *p_cookie )
return 0;
}
-MediaServer::MediaServer( access_t *p_access )
- : psz_root_( NULL )
- , psz_objectId_( NULL )
- , access_( p_access )
- , xmlDocument_( NULL )
- , containerNodeList_( NULL )
- , containerNodeIndex_( 0 )
- , itemNodeList_( NULL )
- , itemNodeIndex_( 0 )
+MediaServer::MediaServer( access_t *p_access, input_item_node_t *node )
+ : access_( p_access )
+ , node_( node )
{
vlc_url_t url;
vlc_UrlParse( &url, p_access->psz_location );
@@ -778,29 +771,24 @@ MediaServer::MediaServer( access_t *p_access )
MediaServer::~MediaServer()
{
- ixmlNodeList_free( containerNodeList_ );
- ixmlNodeList_free( itemNodeList_ );
- ixmlDocument_free( xmlDocument_ );
free( psz_objectId_ );
free( psz_root_ );
}
-input_item_t* MediaServer::newItem( const char *objectID, const char *title )
+void MediaServer::addItem(const char *objectID, const char *title )
{
char* psz_url;
if( asprintf( &psz_url, "upnp://%s?ObjectID=%s", psz_root_, objectID ) < 0 )
- return NULL;
+ return;
input_item_t* p_item = input_item_NewDirectory( psz_url, title, ITEM_NET );
free( psz_url);
- return p_item;
-}
-
-input_item_t* MediaServer::newItem(const char* title, const char*,
- mtime_t duration, const char* psz_url)
-{
- return input_item_NewFile( psz_url, title, duration, ITEM_NET );
+ if ( !p_item )
+ return;
+ input_item_CopyOptions( p_item, node_->p_item );
+ input_item_node_AppendItem( node_, p_item );
+ input_item_Release( p_item );
}
int MediaServer::sendActionCb( Upnp_EventType eventType,
@@ -922,7 +910,7 @@ browseActionCleanup:
/*
* Fetches and parses the UPNP response
*/
-void MediaServer::fetchContents()
+bool MediaServer::fetchContents()
{
IXML_Document* p_response = _browseAction( psz_objectId_,
"BrowseDirectChildren",
@@ -933,45 +921,31 @@ void MediaServer::fetchContents()
if ( !p_response )
{
msg_Err( access_, "No response from browse() action" );
- return;
+ return false;
}
- xmlDocument_ = parseBrowseResult( p_response );
+ IXML_Document* p_result = parseBrowseResult( p_response );
ixmlDocument_free( p_response );
- if ( !xmlDocument_ )
+ if ( !p_result )
{
msg_Err( access_, "browse() response parsing failed" );
- return;
+ return false;
}
#ifndef NDEBUG
- msg_Dbg( access_, "Got DIDL document: %s", ixmlPrintDocument( xmlDocument_ ) );
+ msg_Dbg( access_, "Got DIDL document: %s", ixmlPrintDocument( p_result ) );
#endif
- containerNodeList_ = ixmlDocument_getElementsByTagName( xmlDocument_, "container" );
- itemNodeList_ = ixmlDocument_getElementsByTagName( xmlDocument_, "item" );
-}
-
-input_item_t* MediaServer::getNextItem()
-{
- input_item_t *p_item = NULL;
+ IXML_NodeList* containerNodeList =
+ ixmlDocument_getElementsByTagName( p_result, "container" );
- if( !xmlDocument_ )
+ if ( containerNodeList )
{
- fetchContents();
- if( !xmlDocument_ )
- return NULL;
- }
-
- if ( containerNodeList_ )
- {
- for ( ; !p_item && containerNodeIndex_ < ixmlNodeList_length( containerNodeList_ )
- ; containerNodeIndex_++ )
+ for ( unsigned int i = 0; i < ixmlNodeList_length( containerNodeList ); i++ )
{
- IXML_Element* containerElement = (IXML_Element*)ixmlNodeList_item( containerNodeList_,
- containerNodeIndex_ );
+ IXML_Element* containerElement = (IXML_Element*)ixmlNodeList_item( containerNodeList, i );
const char* objectID = ixmlElement_getAttribute( containerElement,
"id" );
@@ -982,18 +956,22 @@ input_item_t* MediaServer::getNextItem()
"dc:title" );
if ( !title )
continue;
- p_item = newItem(objectID, title);
+ addItem(objectID, title);
}
+ ixmlNodeList_free( containerNodeList );
}
- if( itemNodeList_ )
+ IXML_NodeList* itemNodeList = ixmlDocument_getElementsByTagName( p_result,
+ "item" );
+ if ( itemNodeList )
{
- for ( ; !p_item && itemNodeIndex_ < ixmlNodeList_length( itemNodeList_ ) ; itemNodeIndex_++ )
+ for ( unsigned int i = 0; i < ixmlNodeList_length( itemNodeList ); i++ )
{
- IXML_Element* itemElement = ( IXML_Element* )ixmlNodeList_item( itemNodeList_,
- itemNodeIndex_ );
+ IXML_Element* itemElement =
+ ( IXML_Element* )ixmlNodeList_item( itemNodeList, i );
- const char* objectID = ixmlElement_getAttribute( itemElement, "id" );
+ const char* objectID =
+ ixmlElement_getAttribute( itemElement, "id" );
if ( !objectID )
continue;
@@ -1029,8 +1007,9 @@ input_item_t* MediaServer::getNextItem()
i_seconds );
}
- p_item = newItem( title, objectID, i_duration,
- psz_resource_url );
+ input_item_t* p_item =
+ input_item_NewExt( psz_resource_url, title, i_duration,
+ ITEM_TYPE_FILE, ITEM_NET );
if ( p_item != NULL )
{
const char* psz_artist = xml_getChildElementValue( itemElement, "upnp:artist" );
@@ -1055,17 +1034,26 @@ input_item_t* MediaServer::getNextItem()
if ( psz_albumArt != NULL )
input_item_SetArtworkURL( p_item, psz_albumArt );
}
+ input_item_CopyOptions( p_item, node_->p_item );
+ input_item_node_AppendItem( node_, p_item );
+ input_item_Release( p_item );
}
ixmlNodeList_free( p_resource_list );
}
+ ixmlNodeList_free( itemNodeList );
}
- return p_item;
+ ixmlDocument_free( p_result );
+ return true;
}
-static input_item_t* ReadDirectory( access_t *p_access )
+static int ReadDirectory( access_t *p_access, input_item_node_t* p_node )
{
- return p_access->p_sys->p_server->getNextItem();
+ MediaServer server( p_access, p_node );
+
+ if ( !server.fetchContents() )
+ return VLC_EGENERIC;
+ return VLC_SUCCESS;
}
static int ControlDirectory( access_t *p_access, int i_query, va_list args )
@@ -1091,16 +1079,9 @@ static int Open( vlc_object_t *p_this )
return VLC_ENOMEM;
p_access->p_sys = p_sys;
- p_sys->p_server = new(std::nothrow) MediaServer( p_access );
- if ( !p_sys->p_server )
- {
- delete p_sys;
- return VLC_EGENERIC;
- }
p_sys->p_upnp = UpnpInstanceWrapper::get( p_this, NULL, NULL );
if ( !p_sys->p_upnp )
{
- delete p_sys->p_server;
delete p_sys;
return VLC_EGENERIC;
}
@@ -1115,7 +1096,6 @@ static void Close( vlc_object_t* p_this )
{
access_t* p_access = (access_t*)p_this;
p_access->p_sys->p_upnp->release( false );
- delete p_access->p_sys->p_server;
delete p_access->p_sys;
}
diff --git a/modules/services_discovery/upnp.hpp b/modules/services_discovery/upnp.hpp
index 1ef8803..26593d0 100644
--- a/modules/services_discovery/upnp.hpp
+++ b/modules/services_discovery/upnp.hpp
@@ -141,17 +141,15 @@ private:
class MediaServer
{
public:
- MediaServer( access_t* p_access );
+ MediaServer( access_t* p_access, input_item_node_t* node );
~MediaServer();
- input_item_t* getNextItem();
+ bool fetchContents();
private:
MediaServer(const MediaServer&);
MediaServer& operator=(const MediaServer&);
- void fetchContents();
- input_item_t* newItem(const char* objectID, const char* title);
- input_item_t* newItem(const char* title, const char* psz_objectID, mtime_t duration, const char* psz_url );
+ void addItem(const char* objectID, const char* title);
IXML_Document* _browseAction(const char*, const char*,
const char*, const char*, const char* );
@@ -161,11 +159,7 @@ private:
char* psz_root_;
char* psz_objectId_;
access_t* access_;
- IXML_Document* xmlDocument_;
- IXML_NodeList* containerNodeList_;
- unsigned int containerNodeIndex_;
- IXML_NodeList* itemNodeList_;
- unsigned int itemNodeIndex_;
+ input_item_node_t* node_;
};
}
diff --git a/modules/stream_filter/inflate.c b/modules/stream_filter/inflate.c
index 543d563..fd9a902 100644
--- a/modules/stream_filter/inflate.c
+++ b/modules/stream_filter/inflate.c
@@ -101,10 +101,10 @@ static ssize_t Read(stream_t *stream, void *buf, size_t buflen)
return -1;
}
-static input_item_t *ReadDir(stream_t *stream)
+static int ReadDir(stream_t *stream, input_item_node_t *node)
{
- (void) stream;
- return NULL;
+ (void) stream; (void) node;
+ return VLC_EGENERIC;
}
static int Seek(stream_t *stream, uint64_t offset)
diff --git a/modules/stream_filter/prefetch.c b/modules/stream_filter/prefetch.c
index 09b9db9..09467ad 100644
--- a/modules/stream_filter/prefetch.c
+++ b/modules/stream_filter/prefetch.c
@@ -348,10 +348,10 @@ static ssize_t Read(stream_t *stream, void *buf, size_t buflen)
return copy;
}
-static input_item_t *ReadDir(stream_t *stream)
+static int ReadDir(stream_t *stream, input_item_node_t *node)
{
- (void) stream;
- return NULL;
+ (void) stream; (void) node;
+ return VLC_EGENERIC;
}
static int Control(stream_t *stream, int query, va_list args)
diff --git a/src/input/access.c b/src/input/access.c
index aac3d43..520e450 100644
--- a/src/input/access.c
+++ b/src/input/access.c
@@ -194,10 +194,10 @@ static ssize_t AStreamNoRead(stream_t *s, void *buf, size_t len)
return -1;
}
-static input_item_t *AStreamNoReadDir(stream_t *s)
+static int AStreamNoReadDir(stream_t *s, input_item_node_t *p_node)
{
- (void) s;
- return NULL;
+ (void) s; (void) p_node;
+ return VLC_EGENERIC;;
}
/* Block access */
@@ -282,11 +282,11 @@ static ssize_t AStreamReadStream(stream_t *s, void *buf, size_t len)
}
/* Directory */
-static input_item_t *AStreamReadDir(stream_t *s)
+static int AStreamReadDir(stream_t *s, input_item_node_t *p_node)
{
stream_sys_t *sys = s->p_sys;
- return sys->access->pf_readdir(sys->access);
+ return sys->access->pf_readdir(sys->access, p_node);
}
/* Common */
@@ -432,3 +432,132 @@ error:
stream_CommonDelete(s);
return NULL;
}
+
+static int compar_type(input_item_t *p1, input_item_t *p2)
+{
+ if (p1->i_type != p2->i_type)
+ {
+ if (p1->i_type == ITEM_TYPE_DIRECTORY)
+ return -1;
+ if (p2->i_type == ITEM_TYPE_DIRECTORY)
+ return 1;
+ }
+ return 0;
+}
+
+static int compar_collate(input_item_t *p1, input_item_t *p2)
+{
+ int i_ret = compar_type(p1, p2);
+
+ if (i_ret != 0)
+ return i_ret;
+
+#ifdef HAVE_STRCOLL
+ /* The program's LOCAL defines if case is ignored */
+ return strcoll(p1->psz_name, p2->psz_name);
+#else
+ return strcasecmp(p1->psz_name, p2->psz_name);
+#endif
+}
+
+static int compar_version(input_item_t *p1, input_item_t *p2)
+{
+ int i_ret = compar_type(p1, p2);
+
+ if (i_ret != 0)
+ return i_ret;
+
+ return strverscmp(p1->psz_name, p2->psz_name);
+}
+
+static void fsdir_sort(struct access_fsdir *p_fsdir)
+{
+ input_item_compar_cb pf_compar = NULL;
+
+ if (p_fsdir->psz_sort != NULL)
+ {
+ if (!strcasecmp(p_fsdir->psz_sort, "version"))
+ pf_compar = compar_version;
+ else if(strcasecmp(p_fsdir->psz_sort, "none"))
+ pf_compar = compar_collate;
+
+ if (pf_compar != NULL)
+ input_item_node_Sort(p_fsdir->p_node, pf_compar);
+ }
+}
+
+/**
+ * Does the provided file name has one of the extension provided ?
+ */
+static bool fsdir_has_ext(const char *psz_filename,
+ const char *psz_ignored_exts)
+{
+ if (psz_ignored_exts == NULL)
+ return false;
+
+ const char *ext = strrchr(psz_filename, '.');
+ if (ext == NULL)
+ return false;
+
+ size_t extlen = strlen(++ext);
+
+ for (const char *type = psz_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))
+ return true;
+
+ if (*end == '\0')
+ break;
+ }
+
+ return false;
+}
+
+static bool fsdir_is_ignored(struct access_fsdir *p_fsdir,
+ const char *psz_filename)
+{
+ return (psz_filename[0] == '\0'
+ || strcmp(psz_filename, ".") == 0
+ || strcmp(psz_filename, "..") == 0
+ || (!p_fsdir->b_show_hiddenfiles && psz_filename[0] == '.')
+ || fsdir_has_ext(psz_filename, p_fsdir->psz_ignored_exts));
+}
+
+void access_fsdir_init(struct access_fsdir *p_fsdir,
+ access_t *p_access, input_item_node_t *p_node)
+{
+ p_fsdir->p_node = p_node;
+ 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");
+}
+
+void access_fsdir_finish(struct access_fsdir *p_fsdir, bool b_success)
+{
+ if (b_success)
+ fsdir_sort(p_fsdir);
+ free(p_fsdir->psz_ignored_exts);
+ free(p_fsdir->psz_sort);
+}
+
+int access_fsdir_additem(struct access_fsdir *p_fsdir,
+ const char *psz_uri, const char *psz_filename,
+ int i_type, int i_net)
+{
+ if (fsdir_is_ignored(p_fsdir, psz_filename))
+ return VLC_SUCCESS;
+
+ 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_fsdir->p_node->p_item);
+ input_item_node_AppendItem(p_fsdir->p_node, p_item);
+ input_item_Release(p_item);
+ return VLC_SUCCESS;
+}
diff --git a/src/input/stream.c b/src/input/stream.c
index ea04873..c7cb4b4 100644
--- a/src/input/stream.c
+++ b/src/input/stream.c
@@ -617,11 +617,10 @@ block_t *stream_Block( stream_t *s, size_t size )
}
/**
- * Read the next input_item_t from the directory stream. It returns the next
- * input item on success or NULL in case of error or end of stream. The item
- * must be released with input_item_Release.
+ * Returns a node containing all the input_item of the directory pointer by
+ * this stream. returns VLC_SUCCESS on success.
*/
-input_item_t *stream_ReadDir( stream_t *s )
+int stream_ReadDir( stream_t *s, input_item_node_t *p_node )
{
- return s->pf_readdir( s );
+ return s->pf_readdir( s, p_node );
}
diff --git a/src/input/stream_filter.c b/src/input/stream_filter.c
index b7b0fdb..c34a442 100644
--- a/src/input/stream_filter.c
+++ b/src/input/stream_filter.c
@@ -114,8 +114,8 @@ static void StreamDelete( stream_t *s )
stream_Delete( s->p_source );
}
-input_item_t *stream_FilterDefaultReadDir( stream_t *s )
+int stream_FilterDefaultReadDir( stream_t *s, input_item_node_t *p_node )
{
assert( s->p_source != NULL );
- return stream_ReadDir( s->p_source );
+ return stream_ReadDir( s->p_source, p_node );
}
diff --git a/src/libvlccore.sym b/src/libvlccore.sym
index 32dbaad..bb108d5 100644
--- a/src/libvlccore.sym
+++ b/src/libvlccore.sym
@@ -1,6 +1,9 @@
access_vaDirectoryControlHelper
vlc_access_NewMRL
vlc_access_Delete
+access_fsdir_init
+access_fsdir_finish
+access_fsdir_additem
AddMD5
aout_BitsPerSample
aout_ChannelExtract
--
2.8.1
More information about the vlc-devel
mailing list