Code

mpdclient: Fixes sorting of the filelist.
authorPatrick Hallen <patrick.hallen@rwth-aachen.de>
Sat, 7 Mar 2009 15:23:56 +0000 (16:23 +0100)
committerPatrick Hallen <patrick.hallen@rwth-aachen.de>
Sat, 7 Mar 2009 15:23:56 +0000 (16:23 +0100)
Sort the filelist with the correct linguastically rule for the current
locale, with directories first, after that songs and playlist files last.
This fixes bug 2092.

src/filelist.c
src/filelist.h
src/mpdclient.c
src/screen_search.c

index 97636eee6bf25edea67b625395c02a13eec3aae4..92e63792bee59f68fd5600e440c694b0cc6cfd8f 100644 (file)
@@ -110,12 +110,61 @@ filelist_compare_indirect(gconstpointer ap, gconstpointer bp, gpointer data)
        return compare_func(a, b);
 }
 
+/* Sorts the whole filelist, at the moment used by filelist_search */
 void
-filelist_sort(struct filelist *filelist, GCompareFunc compare_func)
+filelist_sort_all(struct filelist *filelist, GCompareFunc compare_func)
 {
        g_ptr_array_sort_with_data(filelist->entries,
-                                  filelist_compare_indirect,
-                                  compare_func);
+                       filelist_compare_indirect,
+                       compare_func);
+}
+
+
+/* Only sorts the directories and playlist files.
+ * The songs stay in the order it came from mpd. */
+void
+filelist_sort_dir_play(struct filelist *filelist, GCompareFunc compare_func)
+{
+       unsigned first, last;
+       const mpd_InfoEntity *iter;
+
+       assert(filelist && filelist->entries);
+
+       if (filelist->entries->len < 2)
+               return;
+       iter = ((struct filelist_entry*) g_ptr_array_index(filelist->entries, 0))->entity;
+       /* This can only happen at the beginning of the filelist,
+        * because NULL stands for "[..]" */
+       if (iter == NULL) {
+               iter = ((struct filelist_entry*) g_ptr_array_index(filelist->entries, 1))->entity;
+               first = 1;
+       }
+       else
+               first = 0;
+       /* find the last directory entry */
+       for (last = first+1; last < filelist->entries->len; last++) {
+               iter = ((struct filelist_entry*) g_ptr_array_index(filelist->entries, last))->entity;
+               if (iter->type != MPD_INFO_ENTITY_TYPE_DIRECTORY)
+                       break;
+       }
+       if (last == filelist->entries->len - 1)
+               last++;
+       /* sort the directories */
+       if (last - first > 1)
+               g_qsort_with_data(filelist->entries->pdata + first,
+                               last - first, sizeof(gpointer),
+                               filelist_compare_indirect, compare_func);
+       /* find the first playlist entry */
+       for (first = last; first < filelist->entries->len; first++) {
+               iter = ((struct filelist_entry*) g_ptr_array_index(filelist->entries, first))->entity;
+               if (iter->type == MPD_INFO_ENTITY_TYPE_PLAYLISTFILE)
+                       break;
+       }
+       /* sort the playlist entries */
+       if (filelist->entries->len - first > 1)
+               g_qsort_with_data(filelist->entries->pdata + first,
+                               filelist->entries->len - first, sizeof(gpointer),
+                               filelist_compare_indirect, compare_func);
 }
 
 int
index d8db5a46acf5715f072621e2f616243325502f93..3ad6cc2acbe72305d791a7b7121d3e819f9a6c30 100644 (file)
@@ -70,8 +70,14 @@ filelist_prepend(struct filelist *filelist, struct mpd_InfoEntity *entity);
 void
 filelist_move(struct filelist *filelist, struct filelist *from);
 
+/* Sorts the whole filelist, at the moment used by filelist_search */
 void
-filelist_sort(struct filelist *filelist, GCompareFunc compare_func);
+filelist_sort_all(struct filelist *filelist, GCompareFunc compare_func);
+
+/* Only sorts the directories and playlist files.
+ * The songs stay in the order it came from mpd. */
+void
+filelist_sort_dir_play(struct filelist *filelist, GCompareFunc compare_func);
 
 int
 filelist_find_song(struct filelist *flist, const struct mpd_song *song);
index f8f5ba72c42fff3c8f20503aaba206e07792b86f..a1766d9a47baf9e5beb5a668b9fb8de76c3496ac 100644 (file)
@@ -44,7 +44,7 @@ extern GList *string_list_free(GList *string_list);
 
 /* filelist sorting functions */
 static gint
-compare_filelistentry_dir(gconstpointer filelist_entry1,
+compare_filelistentry(gconstpointer filelist_entry1,
                          gconstpointer filelist_entry2)
 {
        const mpd_InfoEntity *e1, *e2;
@@ -53,12 +53,19 @@ compare_filelistentry_dir(gconstpointer filelist_entry1,
        e1 = ((const filelist_entry_t *)filelist_entry1)->entity;
        e2 = ((const filelist_entry_t *)filelist_entry2)->entity;
 
-       if (e1 && e2 &&
-           e1->type == MPD_INFO_ENTITY_TYPE_DIRECTORY &&
-           e2->type == MPD_INFO_ENTITY_TYPE_DIRECTORY)
-               n = g_utf8_collate(e1->info.directory->path,
-                                  e2->info.directory->path);
-
+       if (e1 && e2 && e1->type == e2->type) {
+               switch (e1->type) {
+               case MPD_INFO_ENTITY_TYPE_DIRECTORY:
+                       n = g_utf8_collate(e1->info.directory->path,
+                                       e2->info.directory->path);
+                       break;
+               case MPD_INFO_ENTITY_TYPE_SONG:
+                       break;
+               case MPD_INFO_ENTITY_TYPE_PLAYLISTFILE:
+                       n = g_utf8_collate(e1->info.playlistFile->path,
+                                       e2->info.playlistFile->path);
+               }
+       }
        return n;
 }
 
@@ -707,7 +714,6 @@ mpdclient_filelist_get(mpdclient_t *c, const gchar *path)
 {
        mpdclient_filelist_t *filelist;
        mpd_InfoEntity *entity;
-       gboolean has_dirs_only = TRUE;
 
        mpd_sendLsInfoCommand(c->connection, path);
        filelist = filelist_new(path);
@@ -717,18 +723,12 @@ mpdclient_filelist_get(mpdclient_t *c, const gchar *path)
 
        while ((entity=mpd_getNextInfoEntity(c->connection))) {
                filelist_append(filelist, entity);
-
-               if (has_dirs_only && entity->type != MPD_INFO_ENTITY_TYPE_DIRECTORY) {
-                       has_dirs_only = FALSE;
-               }
        }
 
        /* If there's an error, ignore it.  We'll return an empty filelist. */
        mpdclient_finish_command(c);
 
-       // If there are only directory entities in the filelist, we sort it
-       if (has_dirs_only)
-               filelist_sort(filelist, compare_filelistentry_dir);
+       filelist_sort_dir_play(filelist, compare_filelistentry);
 
        return filelist;
 }
index f9b51450b662fbc8b858ff4baf2df1e0f1f60189..f290e04d38a0d80af2e4f88296a37d78dd5165b9 100644 (file)
@@ -193,7 +193,7 @@ filelist_search(mpdclient_t *c, G_GNUC_UNUSED int exact_match, int table,
                        filelist_free(list2);
                }
 
-               filelist_sort(list, compare_filelistentry_format);
+               filelist_sort_all(list, compare_filelistentry_format);
        } else {
                list = mpdclient_filelist_search(c, FALSE, table, filter_utf8);
                if (list == NULL)