[vlc-devel] [RFC PATCH 7/7] input: handle recursive parsing in preparser

Thomas Guillem thomas at gllm.fr
Fri Mar 20 17:38:38 CET 2015


Add i_preparse_depth in input_item to handle how many level of sub items can be
parsed.

The "recursive" option is now moved from access/file to the playlist category.

You can now abort a long local directory opening.

NET items won't be parsed recursively since playlist_preparser_Push is not
called with the META_REQUEST_OPTION_SCOPE_NETWORK argument.

Fixes #13850
Fixes #11921
Fixes #13872
---
 include/vlc_input_item.h   |  3 +++
 modules/access/directory.c | 24 +-----------------------
 modules/access/fs.c        | 14 --------------
 src/input/input.c          | 23 ++++++++++++++++++++++-
 src/input/item.c           | 22 ++++++++++++++++++++++
 src/input/item.h           |  1 +
 src/libvlc-module.c        | 15 +++++++++++++++
 7 files changed, 64 insertions(+), 38 deletions(-)

diff --git a/include/vlc_input_item.h b/include/vlc_input_item.h
index 2a9b13f..874df00 100644
--- a/include/vlc_input_item.h
+++ b/include/vlc_input_item.h
@@ -87,6 +87,9 @@ struct input_item_t
     uint8_t     i_type;              /**< Type (file, disc, ... see input_item_type_e) */
     uint8_t     i_browsable;         /**< Browsable (see input_item_browsable_e) */
     bool        b_error_when_reading;/**< Error When Reading */
+
+    int         i_preparse_depth;    /**< How many level of sub items can be preparsed:
+                                          -1: recursive, 0: none, >0: n levels */
 };
 
 TYPEDEF_ARRAY(input_item_t*, input_item_array_t)
diff --git a/modules/access/directory.c b/modules/access/directory.c
index 5c471a2..7209978 100644
--- a/modules/access/directory.c
+++ b/modules/access/directory.c
@@ -326,17 +326,6 @@ int DirInit (access_t *p_access, DIR *handle)
     p_access->p_sys = p_sys;
     p_sys->ignored_exts = var_InheritString (p_access, "ignore-filetypes");
 
-
-    /* Handle mode */
-    char *psz_rec = var_InheritString (p_access, "recursive");
-    if (psz_rec == NULL || !strcasecmp (psz_rec, "none"))
-        p_sys->mode = MODE_NONE;
-    else if (!strcasecmp (psz_rec, "collapse"))
-        p_sys->mode = MODE_COLLAPSE;
-    else
-        p_sys->mode = MODE_EXPAND;
-    free (psz_rec);
-
     p_access->pf_readdir = DirRead;
     p_access->pf_control = DirControl;
 
@@ -392,7 +381,6 @@ int DirRead (access_t *p_access, input_item_node_t *p_current_node)
         i_res = directory_open (p_current, psz_entry, &handle);
 
         if (i_res == ENTRY_EACCESS
-            || (i_res == ENTRY_DIR && p_sys->mode == MODE_NONE)
             || (i_res == ENTRY_ENOTDIR && has_ext (p_sys->ignored_exts, psz_entry)))
             continue;
 
@@ -421,17 +409,7 @@ int DirRead (access_t *p_access, input_item_node_t *p_current_node)
         }
 
         input_item_CopyOptions (p_current_node->p_item, p_new);
-        input_item_node_t *p_new_node = input_item_node_AppendItem (p_current_node, p_new);
-
-        /* Handle directory flags and recursion if in EXPAND mode  */
-        if (i_res == ENTRY_DIR)
-        {
-            if (p_sys->mode == MODE_EXPAND
-                && directory_push (p_sys, handle, psz_full_uri))
-            {
-                p_current_node = p_new_node;
-            }
-        }
+        input_item_node_AppendItem (p_current_node, p_new);
 
         free (psz_full_uri);
         input_item_Release (p_new);
diff --git a/modules/access/fs.c b/modules/access/fs.c
index 175c549..43714ea 100644
--- a/modules/access/fs.c
+++ b/modules/access/fs.c
@@ -30,17 +30,6 @@
 #include "fs.h"
 #include <vlc_plugin.h>
 
-#define RECURSIVE_TEXT N_("Subdirectory behavior")
-#define RECURSIVE_LONGTEXT N_( \
-        "Select whether subdirectories must be expanded.\n" \
-        "none: subdirectories do not appear in the playlist.\n" \
-        "collapse: subdirectories appear but are expanded on first play.\n" \
-        "expand: all subdirectories are expanded.\n" )
-
-static const char *const psz_recursive_list[] = { "none", "collapse", "expand" };
-static const char *const psz_recursive_list_text[] = {
-    N_("None"), N_("Collapse"), N_("Expand") };
-
 #define IGNORE_TEXT N_("Ignored extensions")
 #define IGNORE_LONGTEXT N_( \
         "Files with these extensions will not be added to playlist when " \
@@ -71,9 +60,6 @@ vlc_module_begin ()
     add_submodule()
     set_section( N_("Directory" ), NULL )
     set_capability( "access", 55 )
-    add_string( "recursive", "expand" , RECURSIVE_TEXT,
-                RECURSIVE_LONGTEXT, false )
-      change_string_list( psz_recursive_list, psz_recursive_list_text )
     add_string( "ignore-filetypes", "m3u,db,nfo,ini,jpg,jpeg,ljpg,gif,png,pgm,pgmyuv,pbm,pam,tga,bmp,pnm,xpm,xcf,pcx,tif,tiff,lbm,sfv,txt,sub,idx,srt,cue,ssa",
                 IGNORE_TEXT, IGNORE_LONGTEXT, false )
     add_string( "directory-sort", "collate", SORT_TEXT, SORT_LONGTEXT, false )
diff --git a/src/input/input.c b/src/input/input.c
index 98f3567..1afeebb 100644
--- a/src/input/input.c
+++ b/src/input/input.c
@@ -197,7 +197,8 @@ int input_Preparse( vlc_object_t *p_parent, input_item_t *p_item )
          * demux_Demux in order to fetch sub items */
         bool b_is_playlist = false;
 
-        if ( demux_Control( p_input->p->input.p_demux,
+        if ( input_item_ShouldPreparseSubItems( p_item )
+          && demux_Control( p_input->p->input.p_demux,
                             DEMUX_IS_PLAYLIST,
                             &b_is_playlist ) )
             b_is_playlist = false;
@@ -370,6 +371,26 @@ static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item,
 
     if( !p_item->p_stats )
         p_item->p_stats = stats_NewInputStats( p_input );
+
+    /* setup the preparse depth of the item
+     * if we are preparsing, use the i_preparse_depth of the parent item */
+    if( !p_input->b_preparsing )
+    {
+        char *psz_rec = var_InheritString( p_parent, "recursive" );
+
+        if( psz_rec != NULL )
+        {
+            if ( !strcasecmp( psz_rec, "none" ) )
+                p_item->i_preparse_depth = 0;
+            else if ( !strcasecmp( psz_rec, "collapse" ) )
+                p_item->i_preparse_depth = 1;
+            else
+                p_item->i_preparse_depth = -1; /* default is expand */
+            free (psz_rec);
+        } else
+            p_item->i_preparse_depth = -1;
+    }
+
     vlc_mutex_unlock( &p_item->lock );
 
     /* No slave */
diff --git a/src/input/item.c b/src/input/item.c
index c3c3de8..30d04d5 100644
--- a/src/input/item.c
+++ b/src/input/item.c
@@ -423,6 +423,17 @@ bool input_item_IsArtFetched( input_item_t *p_item )
     return b_fetched;
 }
 
+bool input_item_ShouldPreparseSubItems( input_item_t *p_item )
+{
+    bool b_ret;
+
+    vlc_mutex_lock( &p_item->lock );
+    b_ret = p_item->i_preparse_depth == -1 ? true : p_item->i_preparse_depth > 0;
+    vlc_mutex_unlock( &p_item->lock );
+
+    return b_ret;
+}
+
 input_item_t *input_item_Hold( input_item_t *p_item )
 {
     input_item_owner_t *owner = item_owner(p_item);
@@ -1067,8 +1078,19 @@ void input_item_node_Delete( input_item_node_t *p_node )
 
 input_item_node_t *input_item_node_AppendItem( input_item_node_t *p_node, input_item_t *p_item )
 {
+    int i_preparse_depth;
     input_item_node_t *p_new_child = input_item_node_Create( p_item );
     if( !p_new_child ) return NULL;
+
+    vlc_mutex_lock( &p_node->p_item->lock );
+    vlc_mutex_lock( &p_item->lock );
+    i_preparse_depth = p_node->p_item->i_preparse_depth;
+    p_item->i_preparse_depth = i_preparse_depth > 0 ?
+                               i_preparse_depth -1 :
+                               i_preparse_depth;
+    vlc_mutex_unlock( &p_item->lock );
+    vlc_mutex_unlock( &p_node->p_item->lock );
+
     input_item_node_AppendNode( p_node, p_new_child );
     return p_new_child;
 }
diff --git a/src/input/item.h b/src/input/item.h
index aa31d05..f4b89a4 100644
--- a/src/input/item.h
+++ b/src/input/item.h
@@ -29,6 +29,7 @@
 
 void input_item_SetErrorWhenReading( input_item_t *p_i, bool b_error );
 void input_item_UpdateTracksInfo( input_item_t *item, const es_format_t *fmt );
+bool input_item_ShouldPreparseSubItems( input_item_t *p_i );
 
 typedef struct input_item_owner
 {
diff --git a/src/libvlc-module.c b/src/libvlc-module.c
index 31037b4..a2474cb 100644
--- a/src/libvlc-module.c
+++ b/src/libvlc-module.c
@@ -1091,6 +1091,17 @@ static const char *const ppsz_prefres[] = {
     "Automatically preparse files added to the playlist " \
     "(to retrieve some metadata)." )
 
+#define RECURSIVE_TEXT N_("Subdirectory behavior")
+#define RECURSIVE_LONGTEXT N_( \
+        "Select whether subdirectories must be expanded.\n" \
+        "none: subdirectories do not appear in the playlist.\n" \
+        "collapse: subdirectories appear but are expanded on first play.\n" \
+        "expand: all subdirectories are expanded.\n" )
+
+static const char *const psz_recursive_list[] = { "none", "collapse", "expand" };
+static const char *const psz_recursive_list_text[] = {
+    N_("None"), N_("Collapse"), N_("Expand"), N_("Expand distant files") };
+
 #define METADATA_NETWORK_TEXT N_( "Allow metadata network access" )
 
 #define SD_TEXT N_( "Services discovery modules")
@@ -2006,6 +2017,10 @@ vlc_module_begin ()
     add_bool( "auto-preparse", true, PREPARSE_TEXT,
               PREPARSE_LONGTEXT, false )
 
+    add_string( "recursive", "collapse" , RECURSIVE_TEXT,
+                RECURSIVE_LONGTEXT, false )
+      change_string_list( psz_recursive_list, psz_recursive_list_text )
+
     add_obsolete_integer( "album-art" )
     add_bool( "metadata-network-access", false, METADATA_NETWORK_TEXT,
                  METADATA_NETWORK_TEXT, false )
-- 
2.1.3




More information about the vlc-devel mailing list