diff --git a/design/playqueue.txt b/design/playqueue.txt index d5fc1c30..28b18aa1 100644 --- a/design/playqueue.txt +++ b/design/playqueue.txt @@ -19,33 +19,24 @@ Playqueue: (lib/playqueue.cpp) - Sort order: enum sort_t { - SORT_ARTIST_ASC = 1, - SORT_ARTIST_DESC = 2, - SORT_ALBUM_ASC = 3, - SORT_ALBUM_DESC = 4, - SORT_COUNT_ASC = 5, - SORT_COUNT_DESC = 6, - SORT_GENRE_ASC = 7, - SORT_GENRE_DESC = 8, - SORT_LENGTH_ASC = 9, - SORT_LENGTH_DESC = 10, - SORT_PLAYED_ASC = 11, - SORT_PLAYED_DESC = 12, - SORT_TITLE_ASC = 13, - SORT_TITLE_DESC = 14, - SORT_TRACK_ASC = 15, - SORT_TRACK_DESC = 16, - SORT_YEAR_ASC = 17, - SORT_YEAR_DESC = 18, + SORT_ARTIST = 1, + SORT_ALBUM = 2, + SORT_COUNT = 3, + SORT_GENRE = 4, + SORT_LENGTH = 5, + SORT_PLAYED = 6, + SORT_TITLE = 7, + SORT_TRACK = 8, + SORT_YEAR = 9, }; - Playqueue: class Playqueue { private: vector tracks; - list sort_order; /* default = { SORT_ARTIST_ASC, - SORT_YEAR_ASC, - SORT_TRACK_ASC }; + list sort_order; /* default = { SORT_ARTIST, + SORT_YEAR, + SORT_TRACK }; unsigned int cur; unsigned int flags; unsigned int length; @@ -64,15 +55,15 @@ Playqueue: (lib/playqueue.cpp) void del(playqueue_id); unsigned int size(); - void reset_sort(); - void add_sort(sort_t, bool); - void sort(); + void clear_sort(); + void add_sort(sort_t); unsigned int next(); void reset_cur(); } - File << flags << tracks.size() << tracks[0] << tracks[1] << ... << tracks[N]; + File << flags << sort_order.size() << sort_order[0] << ... << sort_order[1]; + File << tracks.size() << tracks[0] << tracks[1] << ... << tracks[N]; - API Playqueue :: Playlist(unsigned int flags); diff --git a/include/playqueue.h b/include/playqueue.h index ffb13d8f..378c1965 100644 --- a/include/playqueue.h +++ b/include/playqueue.h @@ -7,18 +7,31 @@ #include #include #include +#include enum playqueue_flags { PQ_ENABLED = (1 << 0), PQ_RANDOM = (1 << 1), PQ_REPEAT = (1 << 2), - PQ_SORTED = (1 << 3), PQ_DISABLE_CHANGED_SIZE = (1 << 3), }; +enum sort_t { + SORT_ARTIST, + SORT_ALBUM, + SORT_COUNT, + SORT_GENRE, + SORT_LENGTH, + SORT_PLAYED, + SORT_TITLE, + SORT_TRACK, + SORT_YEAR, +}; + class Playqueue { private: std :: vector tracks; + std :: list sort_order; unsigned int flags; unsigned int cur; unsigned int length; @@ -43,8 +56,11 @@ public: void del(unsigned int); void del_track(unsigned int); unsigned int size(); - unsigned int operator[](unsigned int); + void add_sort(sort_t); + void reset_sort(sort_t); + + unsigned int operator[](unsigned int); unsigned int next(); void reset_cur(); #ifdef CONFIG_TEST diff --git a/lib/deck.cpp b/lib/deck.cpp index b633cced..2762b7da 100644 --- a/lib/deck.cpp +++ b/lib/deck.cpp @@ -26,8 +26,10 @@ static void del_library_track(unsigned int id) void deck :: init() { library_playqueue.set_flag(PQ_REPEAT); - library_playqueue.set_flag(PQ_SORTED); library_playqueue.set_flag(PQ_DISABLE_CHANGED_SIZE); + library_playqueue.add_sort(SORT_ARTIST); + library_playqueue.add_sort(SORT_YEAR); + library_playqueue.add_sort(SORT_TRACK); read(); get_callbacks()->on_library_track_add = add_library_track; diff --git a/lib/playqueue.cpp b/lib/playqueue.cpp index 71481a21..f4a9f005 100644 --- a/lib/playqueue.cpp +++ b/lib/playqueue.cpp @@ -96,24 +96,64 @@ std::string Playqueue :: get_length_str() return ss.str(); } +/* + * Returns: + * 0: lhs == rhs + * < 0: lhs < rhs + * > 0: lhs > rhs + */ +static inline int compare_uint(unsigned int a, unsigned int b) +{ + if (a == b) + return 0; + if (a < b) + return -1; + return 1; +} + /* * std::string.compare() returns * 0: Strings are equal * < 0: a < b * > 0: a > b */ -static bool track_less_than(library :: Song &lhs, library :: Song &rhs) +static inline int track_compare(library :: Song &lhs, library :: Song &rhs, + sort_t field) { - int cmp_res; + switch (field) { + case SORT_ARTIST: + return lhs.artist->key_lower.compare(rhs.artist->key_lower); + case SORT_ALBUM: + return lhs.album->name_lower.compare(rhs.album->name_lower); + case SORT_COUNT: + return compare_uint(lhs.track->track, rhs.track->track); + case SORT_GENRE: + return lhs.genre->key_lower.compare(rhs.genre->key_lower); + case SORT_LENGTH: + return compare_uint(lhs.track->length, rhs.track->length); + case SORT_PLAYED: + return compare_uint(lhs.track->play_count, rhs.track->play_count); + case SORT_TITLE: + return lhs.track->title_lower.compare(rhs.track->title_lower); + case SORT_TRACK: + return compare_uint(lhs.track->track, rhs.track->track); + default: //case SORT_YEAR + return compare_uint(lhs.album->year, rhs.album->year); + } +} - cmp_res = lhs.artist->key_lower.compare(rhs.artist->key_lower); - if (cmp_res != 0) - return cmp_res < 0; +static bool track_less_than(library :: Song &lhs, library :: Song &rhs, + std::list &order) +{ + std::list::iterator it; + int res; - if (lhs.album->year != rhs.album->year) - return lhs.album->year < rhs.album->year; - - return lhs.track->track < rhs.track->track; + for (it = order.begin(); it != order.end(); it++) { + res = track_compare(lhs, rhs, *it); + if (res != 0) + return res < 0; + } + return res; } unsigned int Playqueue :: add_sorted(unsigned int track_id, library :: Song &rhs) @@ -129,7 +169,7 @@ unsigned int Playqueue :: add_sorted(unsigned int track_id, library :: Song &rhs while (start != end) { cur = start + ((end - start) / 2); library :: lookup(tracks[cur], &lhs); - if (track_less_than(lhs, rhs)) { + if (track_less_than(lhs, rhs, sort_order)) { if (end - start == 1) cur = end; start = cur; @@ -147,7 +187,7 @@ unsigned int Playqueue :: add(unsigned int track_id) library :: Song song; library :: lookup(track_id, &song); - if (flags & PQ_SORTED) + if (sort_order.size() > 0) add_sorted(track_id, song); else tracks.push_back(track_id); @@ -201,6 +241,20 @@ unsigned int Playqueue :: size() return tracks.size(); } +void Playqueue :: add_sort(sort_t field) +{ + sort_order.remove(field); + sort_order.push_back(field); + if (sort_order.size() >= 4) + sort_order.erase(sort_order.begin()); +} + +void Playqueue :: reset_sort(sort_t field) +{ + sort_order.clear(); + add_sort(field); +} + unsigned int Playqueue :: operator[](unsigned int i) { return tracks[i];