From: Patrick Hallen Date: Sat, 7 Mar 2009 15:23:56 +0000 (+0100) Subject: mpdclient: Fixes sorting of the filelist. X-Git-Tag: release-0.14~73 X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=d3cb26bf16733be694dd4f6a5bd2dacbbad3178c;p=ncmpc.git mpdclient: Fixes sorting of the filelist. 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. --- diff --git a/src/filelist.c b/src/filelist.c index 97636ee..92e6379 100644 --- a/src/filelist.c +++ b/src/filelist.c @@ -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 diff --git a/src/filelist.h b/src/filelist.h index d8db5a4..3ad6cc2 100644 --- a/src/filelist.h +++ b/src/filelist.h @@ -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); diff --git a/src/mpdclient.c b/src/mpdclient.c index f8f5ba7..a1766d9 100644 --- a/src/mpdclient.c +++ b/src/mpdclient.c @@ -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; } diff --git a/src/screen_search.c b/src/screen_search.c index f9b5145..f290e04 100644 --- a/src/screen_search.c +++ b/src/screen_search.c @@ -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)