diff --git a/NEWS b/NEWS index 082e456db..edd06edda 100644 --- a/NEWS +++ b/NEWS @@ -46,6 +46,7 @@ ver 0.16 (20??/??/??) * update: - automatically update the database with Linux inotify - support .mpdignore files in the music directory + - sort songs by album name first, then disc/track number * log unused/unknown block parameters * removed the deprecated "error_file" option * save state when stopped diff --git a/src/songvec.c b/src/songvec.c index 49486bb54..f8f83e6e8 100644 --- a/src/songvec.c +++ b/src/songvec.c @@ -37,6 +37,30 @@ tag_get_value_checked(const struct tag *tag, enum tag_type type) : NULL; } +static int +compare_utf8_string(const char *a, const char *b) +{ + if (a == NULL) + return b == NULL ? 0 : -1; + + if (b == NULL) + return 1; + + return g_utf8_collate(a, b); +} + +/** + * Compare two string tag values, ignoring case. Either one may be + * NULL. + */ +static int +compare_string_tag_item(const struct tag *a, const struct tag *b, + enum tag_type type) +{ + return compare_utf8_string(tag_get_value_checked(a, type), + tag_get_value_checked(b, type)); +} + /** * Compare two tag values which should contain an integer value * (e.g. disc or track number). Either one may be NULL. @@ -70,7 +94,12 @@ static int songvec_cmp(const void *s1, const void *s2) const struct song *b = ((const struct song * const *)s2)[0]; int ret; - /* first sort by disc */ + /* first sort by album */ + ret = compare_string_tag_item(a->tag, b->tag, TAG_ALBUM); + if (ret != 0) + return ret; + + /* then sort by disc */ ret = compare_tag_item(a->tag, b->tag, TAG_DISC); if (ret != 0) return ret;