playqueue: Sort by a generic list of fields
Eventually I'll be able to click on column headers to change the sort value. Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
This commit is contained in:
parent
ddbbf0ea49
commit
d434b7ebbb
|
@ -19,33 +19,24 @@ Playqueue: (lib/playqueue.cpp)
|
||||||
|
|
||||||
- Sort order:
|
- Sort order:
|
||||||
enum sort_t {
|
enum sort_t {
|
||||||
SORT_ARTIST_ASC = 1,
|
SORT_ARTIST = 1,
|
||||||
SORT_ARTIST_DESC = 2,
|
SORT_ALBUM = 2,
|
||||||
SORT_ALBUM_ASC = 3,
|
SORT_COUNT = 3,
|
||||||
SORT_ALBUM_DESC = 4,
|
SORT_GENRE = 4,
|
||||||
SORT_COUNT_ASC = 5,
|
SORT_LENGTH = 5,
|
||||||
SORT_COUNT_DESC = 6,
|
SORT_PLAYED = 6,
|
||||||
SORT_GENRE_ASC = 7,
|
SORT_TITLE = 7,
|
||||||
SORT_GENRE_DESC = 8,
|
SORT_TRACK = 8,
|
||||||
SORT_LENGTH_ASC = 9,
|
SORT_YEAR = 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,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
- Playqueue:
|
- Playqueue:
|
||||||
class Playqueue {
|
class Playqueue {
|
||||||
private:
|
private:
|
||||||
vector<track_id> tracks;
|
vector<track_id> tracks;
|
||||||
list<sort_t> sort_order; /* default = { SORT_ARTIST_ASC,
|
list<sort_t> sort_order; /* default = { SORT_ARTIST,
|
||||||
SORT_YEAR_ASC,
|
SORT_YEAR,
|
||||||
SORT_TRACK_ASC };
|
SORT_TRACK };
|
||||||
unsigned int cur;
|
unsigned int cur;
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
unsigned int length;
|
unsigned int length;
|
||||||
|
@ -64,15 +55,15 @@ Playqueue: (lib/playqueue.cpp)
|
||||||
void del(playqueue_id);
|
void del(playqueue_id);
|
||||||
unsigned int size();
|
unsigned int size();
|
||||||
|
|
||||||
void reset_sort();
|
void clear_sort();
|
||||||
void add_sort(sort_t, bool);
|
void add_sort(sort_t);
|
||||||
void sort();
|
|
||||||
|
|
||||||
unsigned int next();
|
unsigned int next();
|
||||||
void reset_cur();
|
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
|
- API
|
||||||
Playqueue :: Playlist(unsigned int flags);
|
Playqueue :: Playlist(unsigned int flags);
|
||||||
|
|
|
@ -7,18 +7,31 @@
|
||||||
#include <file.h>
|
#include <file.h>
|
||||||
#include <library.h>
|
#include <library.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
enum playqueue_flags {
|
enum playqueue_flags {
|
||||||
PQ_ENABLED = (1 << 0),
|
PQ_ENABLED = (1 << 0),
|
||||||
PQ_RANDOM = (1 << 1),
|
PQ_RANDOM = (1 << 1),
|
||||||
PQ_REPEAT = (1 << 2),
|
PQ_REPEAT = (1 << 2),
|
||||||
PQ_SORTED = (1 << 3),
|
|
||||||
PQ_DISABLE_CHANGED_SIZE = (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 {
|
class Playqueue {
|
||||||
private:
|
private:
|
||||||
std :: vector <unsigned int> tracks;
|
std :: vector <unsigned int> tracks;
|
||||||
|
std :: list <sort_t> sort_order;
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
unsigned int cur;
|
unsigned int cur;
|
||||||
unsigned int length;
|
unsigned int length;
|
||||||
|
@ -43,8 +56,11 @@ public:
|
||||||
void del(unsigned int);
|
void del(unsigned int);
|
||||||
void del_track(unsigned int);
|
void del_track(unsigned int);
|
||||||
unsigned int size();
|
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();
|
unsigned int next();
|
||||||
void reset_cur();
|
void reset_cur();
|
||||||
#ifdef CONFIG_TEST
|
#ifdef CONFIG_TEST
|
||||||
|
|
|
@ -26,8 +26,10 @@ static void del_library_track(unsigned int id)
|
||||||
void deck :: init()
|
void deck :: init()
|
||||||
{
|
{
|
||||||
library_playqueue.set_flag(PQ_REPEAT);
|
library_playqueue.set_flag(PQ_REPEAT);
|
||||||
library_playqueue.set_flag(PQ_SORTED);
|
|
||||||
library_playqueue.set_flag(PQ_DISABLE_CHANGED_SIZE);
|
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();
|
read();
|
||||||
|
|
||||||
get_callbacks()->on_library_track_add = add_library_track;
|
get_callbacks()->on_library_track_add = add_library_track;
|
||||||
|
|
|
@ -96,24 +96,64 @@ std::string Playqueue :: get_length_str()
|
||||||
return ss.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
|
* std::string.compare() returns
|
||||||
* 0: Strings are equal
|
* 0: Strings are equal
|
||||||
* < 0: a < b
|
* < 0: a < b
|
||||||
* > 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);
|
static bool track_less_than(library :: Song &lhs, library :: Song &rhs,
|
||||||
if (cmp_res != 0)
|
std::list<sort_t> &order)
|
||||||
return cmp_res < 0;
|
{
|
||||||
|
std::list<sort_t>::iterator it;
|
||||||
|
int res;
|
||||||
|
|
||||||
if (lhs.album->year != rhs.album->year)
|
for (it = order.begin(); it != order.end(); it++) {
|
||||||
return lhs.album->year < rhs.album->year;
|
res = track_compare(lhs, rhs, *it);
|
||||||
|
if (res != 0)
|
||||||
return lhs.track->track < rhs.track->track;
|
return res < 0;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int Playqueue :: add_sorted(unsigned int track_id, library :: Song &rhs)
|
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) {
|
while (start != end) {
|
||||||
cur = start + ((end - start) / 2);
|
cur = start + ((end - start) / 2);
|
||||||
library :: lookup(tracks[cur], &lhs);
|
library :: lookup(tracks[cur], &lhs);
|
||||||
if (track_less_than(lhs, rhs)) {
|
if (track_less_than(lhs, rhs, sort_order)) {
|
||||||
if (end - start == 1)
|
if (end - start == 1)
|
||||||
cur = end;
|
cur = end;
|
||||||
start = cur;
|
start = cur;
|
||||||
|
@ -147,7 +187,7 @@ unsigned int Playqueue :: add(unsigned int track_id)
|
||||||
library :: Song song;
|
library :: Song song;
|
||||||
library :: lookup(track_id, &song);
|
library :: lookup(track_id, &song);
|
||||||
|
|
||||||
if (flags & PQ_SORTED)
|
if (sort_order.size() > 0)
|
||||||
add_sorted(track_id, song);
|
add_sorted(track_id, song);
|
||||||
else
|
else
|
||||||
tracks.push_back(track_id);
|
tracks.push_back(track_id);
|
||||||
|
@ -201,6 +241,20 @@ unsigned int Playqueue :: size()
|
||||||
return tracks.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)
|
unsigned int Playqueue :: operator[](unsigned int i)
|
||||||
{
|
{
|
||||||
return tracks[i];
|
return tracks[i];
|
||||||
|
|
Loading…
Reference in New Issue