[vlc-devel] [PATCH 05/12] move directory-sort option from directory access to directory demux

Thomas Guillem thomas at gllm.fr
Tue May 19 10:27:45 CEST 2015


All readdir access that are used from demux directory can now be sorted like
the directory access.
---
 include/vlc_input_item.h           |  9 +++++
 modules/access/directory.c         | 28 +-------------
 modules/access/fs.c                | 12 ------
 modules/demux/playlist/directory.c | 76 ++++++++++++++++++++++++++++++++++----
 modules/demux/playlist/playlist.c  | 12 ++++++
 src/input/item.c                   | 45 +++++++++++++++++-----
 src/libvlccore.sym                 |  1 +
 7 files changed, 127 insertions(+), 56 deletions(-)

diff --git a/include/vlc_input_item.h b/include/vlc_input_item.h
index 48dcd32..4a07984 100644
--- a/include/vlc_input_item.h
+++ b/include/vlc_input_item.h
@@ -121,6 +121,8 @@ struct input_item_node_t
     input_item_node_t      *p_parent;
 };
 
+typedef int (*input_item_compar_cb)( input_item_t *, input_item_t * );
+
 VLC_API void input_item_CopyOptions( input_item_t *p_parent, input_item_t *p_child );
 VLC_API void input_item_SetName( input_item_t *p_item, const char *psz_name );
 
@@ -149,6 +151,13 @@ VLC_API input_item_node_t * input_item_node_Create( input_item_t *p_input ) VLC_
 VLC_API input_item_node_t * input_item_node_AppendItem( input_item_node_t *p_node, input_item_t *p_item );
 
 /**
+ * Add a new child node to this parent node that will point to this subitem.
+ */
+VLC_API input_item_node_t *input_item_node_AppendItemSorted( input_item_node_t *p_node,
+                                                             input_item_t *p_item,
+                                                             input_item_compar_cb compar_cb );
+
+/**
  * Add an already created node to children of this parent node.
  */
 VLC_API void input_item_node_AppendNode( input_item_node_t *p_parent, input_item_node_t *p_child );
diff --git a/modules/access/directory.c b/modules/access/directory.c
index 270e04f..4728fa4 100644
--- a/modules/access/directory.c
+++ b/modules/access/directory.c
@@ -82,7 +82,6 @@ struct access_sys_t
     directory *current;
     char      *ignored_exts;
     char       mode;
-    int        (*compar) (const char **a, const char **b);
 };
 
 /* Select non-hidden files only */
@@ -91,20 +90,6 @@ static int visible (const char *name)
     return name[0] != '.';
 }
 
-static int collate (const char **a, const char **b)
-{
-#ifdef HAVE_STRCOLL
-    return strcoll (*a, *b);
-#else
-    return strcmp  (*a, *b);
-#endif
-}
-
-static int version (const char **a, const char **b)
-{
-    return strverscmp (*a, *b);
-}
-
 /**
  * Does the provided URI/path/stuff has one of the extension provided ?
  *
@@ -212,7 +197,7 @@ static bool directory_push (access_sys_t *p_sys, DIR *handle, char *psz_uri)
     p_dir->parent = p_sys->current;
     p_dir->handle = handle;
     p_dir->uri = psz_uri;
-    p_dir->filec = vlc_loaddir (handle, &p_dir->filev, visible, p_sys->compar);
+    p_dir->filec = vlc_loaddir (handle, &p_dir->filev, visible, NULL);
     if (p_dir->filec < 0)
         p_dir->filev = NULL;
     p_dir->i = 0;
@@ -289,17 +274,6 @@ int DirInit (access_t *p_access, DIR *handle)
     if (unlikely (p_sys == NULL))
         goto error;
 
-    char *psz_sort = var_InheritString (p_access, "directory-sort");
-    if (!psz_sort)
-        p_sys->compar = collate;
-    else if (!strcasecmp ( psz_sort, "version"))
-        p_sys->compar = version;
-    else if (!strcasecmp (psz_sort, "none"))
-        p_sys->compar = NULL;
-    else
-        p_sys->compar = collate;
-    free(psz_sort);
-
     char *uri;
     if (!strcmp (p_access->psz_access, "fd"))
     {
diff --git a/modules/access/fs.c b/modules/access/fs.c
index 43714ea..ec19c21 100644
--- a/modules/access/fs.c
+++ b/modules/access/fs.c
@@ -37,16 +37,6 @@
         "This is useful if you add directories that contain playlist files " \
         "for instance. Use a comma-separated list of extensions." )
 
-static const char *const psz_sort_list[] = { "collate", "version", "none" };
-static const char *const psz_sort_list_text[] = {
-    N_("Sort alphabetically according to the current language's collation rules."),
-    N_("Sort items in a natural order (for example: 1.ogg 2.ogg 10.ogg). This method does not take the current language's collation rules into account."),
-    N_("Do not sort the items.") };
-
-#define SORT_TEXT N_("Directory sort order")
-#define SORT_LONGTEXT N_( \
-    "Define the sort algorithm used when adding items from a directory." )
-
 vlc_module_begin ()
     set_description( N_("File input") )
     set_shortname( N_("File") )
@@ -62,8 +52,6 @@ vlc_module_begin ()
     set_capability( "access", 55 )
     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 )
-      change_string_list( psz_sort_list, psz_sort_list_text )
 #ifndef HAVE_FDOPENDIR
     add_shortcut( "file", "directory", "dir" )
 #else
diff --git a/modules/demux/playlist/directory.c b/modules/demux/playlist/directory.c
index 30b2bfa..c56e29e 100644
--- a/modules/demux/playlist/directory.c
+++ b/modules/demux/playlist/directory.c
@@ -33,6 +33,11 @@
 
 #include "playlist.h"
 
+struct demux_sys_t
+{
+    bool b_dir_sorted;
+};
+
 /*****************************************************************************
  * Local prototypes
  *****************************************************************************/
@@ -44,32 +49,87 @@ int Import_Dir ( vlc_object_t *p_this)
     demux_t  *p_demux = (demux_t *)p_this;
 
     bool b_is_dir = false;
+    bool b_dir_sorted = false;
     int i_err = stream_Control( p_demux->s, STREAM_IS_DIRECTORY, &b_is_dir,
-                                NULL, NULL );
+                                &b_dir_sorted, NULL );
 
     if ( !( i_err == VLC_SUCCESS && b_is_dir ) )
         return VLC_EGENERIC;
 
-    p_demux->pf_control = Control;
-    p_demux->pf_demux = Demux;
-    msg_Dbg( p_demux, "reading directory content" );
+    STANDARD_DEMUX_INIT_MSG( "reading directory content" );
+    p_demux->p_sys->b_dir_sorted = b_dir_sorted;
 
     return VLC_SUCCESS;
 }
 
 void Close_Dir ( vlc_object_t *p_this )
 {
-    VLC_UNUSED(p_this);
+    demux_t *p_demux = (demux_t *)p_this;
+    free( p_demux->p_sys );
+}
+
+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
+    return strcoll( p1->psz_name, p2->psz_name );
+#else
+    return strcmp( 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 = GetCurrentItem(p_demux);
-    input_item_node_t *p_node = input_item_node_Create( p_input );
+    input_item_t *p_input;
+    input_item_node_t *p_node;
     input_item_t *p_item;
+    input_item_compar_cb compar_cb = NULL;
+
+    p_input = GetCurrentItem( p_demux );
+    p_node = input_item_node_Create( p_input );
     input_item_Release(p_input);
 
+    if( !p_demux->p_sys->b_dir_sorted )
+    {
+        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 );
+    }
+
     while( !i_ret && ( p_item = stream_ReadDir( p_demux->s ) ) )
     {
         int i_name_len = p_item->psz_name ? strlen( p_item->psz_name ) : 0;
@@ -81,7 +141,7 @@ static int Demux( demux_t *p_demux )
             goto skip_item;
 
         input_item_CopyOptions( p_node->p_item, p_item );
-        if( !input_item_node_AppendItem( p_node, p_item ) )
+        if( !input_item_node_AppendItemSorted( p_node, p_item, compar_cb ) )
             i_ret = VLC_ENOMEM;
 skip_item:
         input_item_Release( p_item );
diff --git a/modules/demux/playlist/playlist.c b/modules/demux/playlist/playlist.c
index 07e47e1..04eb90d 100644
--- a/modules/demux/playlist/playlist.c
+++ b/modules/demux/playlist/playlist.c
@@ -51,6 +51,16 @@
 #define SKIP_ADS_LONGTEXT N_( "Use playlist options usually used to prevent " \
     "ads skipping to detect ads and prevent adding them to the playlist." )
 
+static const char *const psz_sort_list[] = { "collate", "version", "none" };
+static const char *const psz_sort_list_text[] = {
+    N_("Sort alphabetically according to the current language's collation rules."),
+    N_("Sort items in a natural order (for example: 1.ogg 2.ogg 10.ogg). This method does not take the current language's collation rules into account."),
+    N_("Do not sort the items.") };
+
+#define SORT_TEXT N_("Directory sort order")
+#define SORT_LONGTEXT N_( \
+    "Define the sort algorithm used when adding items from a directory." )
+
 vlc_module_begin ()
     add_shortcut( "playlist" )
     set_category( CAT_INPUT )
@@ -145,6 +155,8 @@ vlc_module_begin ()
         add_shortcut( "playlist", "directory" )
         set_capability( "demux", 10 )
         set_callbacks( Import_Dir, Close_Dir )
+        add_string( "directory-sort", "collate", SORT_TEXT, SORT_LONGTEXT, false )
+          change_string_list( psz_sort_list, psz_sort_list_text )
 vlc_module_end ()
 
 int Control(demux_t *demux, int query, va_list args)
diff --git a/src/input/item.c b/src/input/item.c
index d357c25..5912768 100644
--- a/src/input/item.c
+++ b/src/input/item.c
@@ -1131,7 +1131,39 @@ void input_item_node_Delete( input_item_node_t *p_node )
     RecursiveNodeDelete( p_node );
 }
 
-input_item_node_t *input_item_node_AppendItem( input_item_node_t *p_node, input_item_t *p_item )
+static void input_item_node_AppendNodeSorted( input_item_node_t *p_parent,
+                                              input_item_node_t *p_child,
+                                              input_item_compar_cb compar_cb )
+{
+    assert( p_parent && p_child && p_child->p_parent == NULL );
+    int i_pos;
+
+    if( compar_cb )
+    {
+        for( i_pos = 0; i_pos < p_parent->i_children; ++i_pos )
+        {
+            if( compar_cb( p_parent->pp_children[i_pos]->p_item,
+                           p_child->p_item ) > 0 )
+                break;
+        }
+    } else
+        i_pos = p_parent->i_children;
+
+    INSERT_ELEM( p_parent->pp_children,
+                 p_parent->i_children,
+                 i_pos,
+                 p_child );
+    p_child->p_parent = p_parent;
+}
+
+void input_item_node_AppendNode( input_item_node_t *p_parent, input_item_node_t *p_child )
+{
+    input_item_node_AppendNodeSorted( p_parent, p_child, NULL );
+}
+
+input_item_node_t *input_item_node_AppendItemSorted( input_item_node_t *p_node,
+                                                     input_item_t *p_item,
+                                                     input_item_compar_cb compar_cb )
 {
     int i_preparse_depth;
     input_item_node_t *p_new_child = input_item_node_Create( p_item );
@@ -1146,18 +1178,13 @@ input_item_node_t *input_item_node_AppendItem( input_item_node_t *p_node, input_
     vlc_mutex_unlock( &p_item->lock );
     vlc_mutex_unlock( &p_node->p_item->lock );
 
-    input_item_node_AppendNode( p_node, p_new_child );
+    input_item_node_AppendNodeSorted( p_node, p_new_child, compar_cb );
     return p_new_child;
 }
 
-void input_item_node_AppendNode( input_item_node_t *p_parent, input_item_node_t *p_child )
+input_item_node_t *input_item_node_AppendItem( input_item_node_t *p_node, input_item_t *p_item )
 {
-    assert( p_parent && p_child && p_child->p_parent == NULL );
-    INSERT_ELEM( p_parent->pp_children,
-                 p_parent->i_children,
-                 p_parent->i_children,
-                 p_child );
-    p_child->p_parent = p_parent;
+    return input_item_node_AppendItemSorted( p_node, p_item, NULL );
 }
 
 void input_item_node_PostAndDelete( input_item_node_t *p_root )
diff --git a/src/libvlccore.sym b/src/libvlccore.sym
index 5350f96..95d0e61 100644
--- a/src/libvlccore.sym
+++ b/src/libvlccore.sym
@@ -204,6 +204,7 @@ input_item_NewWithTypeExt
 input_item_Hold
 input_item_Release
 input_item_node_AppendItem
+input_item_node_AppendItemSorted
 input_item_node_AppendNode
 input_item_node_Create
 input_item_node_Delete
-- 
2.1.4




More information about the vlc-devel mailing list