queue: Begin code updates

So far I have renamed variables, changed a few functions, and updated
all the code that was affected.

Oh, I also started a new unit test.

Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
This commit is contained in:
Anna Schumaker 2014-04-13 12:26:32 -04:00
parent 44f62028c3
commit d939dcab20
10 changed files with 204 additions and 122 deletions

20
DESIGN
View File

@ -853,12 +853,11 @@ Queue:
- Sorting: - Sorting:
Sorting is done using std::stable_sort() to make sure that orders won't Sorting is done using std::stable_sort() to make sure that orders won't
change unexpectedly. The default sort order is (SORT_ARTIST, true), change unexpectedly.
(SORT_YEAR, true), (SORT_TRACK, true).
- Queue: - Queue:
class Queue { class Queue {
private: protected:
vector<Track *> _tracks; vector<Track *> _tracks;
list<sort_t> _sort_order; list<sort_t> _sort_order;
unsigned int _cur; unsigned int _cur;
@ -866,6 +865,7 @@ Queue:
unsigned int _length; unsigned int _length;
public: public:
Queue();
Queue(unsigned int); Queue(unsigned int);
void read(File &); void read(File &);
void write(File &); void write(File &);
@ -893,10 +893,13 @@ File Format:
File << flags << tracks.size() << tracks[0] << tracks[1] << ... << tracks[N]; File << flags << tracks.size() << tracks[0] << tracks[1] << ... << tracks[N];
- API - API
Queue :: Queue();
Initialize _flags = 0, _cur = -1, _length = 0, and empty sort
order.
Queue :: Queue(unsigned int flags); Queue :: Queue(unsigned int flags);
Initialize a new queue with the appropriate flags set and with Initialize _flags = flags, _cur = -1, _length = 0, and empty
default sorting. sort order.
Set _length = 0, _cur = 0.
void Queue :: read(File &f); void Queue :: read(File &f);
Read queue from file. Read queue from file.
@ -975,6 +978,11 @@ File Format:
- library queue should be set to the default sort order
The default sort order is (SORT_ARTIST, true),
(SORT_YEAR, true), (SORT_TRACK, true).
Library: (lib/library.cpp) Library: (lib/library.cpp)
The library manages databases containing track information added by the The library manages databases containing track information added by the
user. Ocarina 6 splits the library into multiple database tables for user. Ocarina 6 splits the library into multiple database tables for

View File

@ -19,7 +19,7 @@ namespace deck
unsigned int size(); unsigned int size();
void move(unsigned int, unsigned int); void move(unsigned int, unsigned int);
void move(Queue *, unsigned int); void move(Queue *, unsigned int);
unsigned int next(); Track *next();
Queue *get_library_pq(); Queue *get_library_pq();
#ifdef CONFIG_TEST #ifdef CONFIG_TEST

View File

@ -23,12 +23,12 @@ struct sort_info {
}; };
class Queue { class Queue {
private: protected:
std :: vector <unsigned int> tracks; std :: vector <Track *> _tracks;
std :: list <sort_info> sort_order; std :: list <sort_info> _sort_order;
unsigned int flags; unsigned int _cur;
unsigned int cur; unsigned int _flags;
unsigned int length; unsigned int _length;
unsigned int find_sorted_id(Track *); unsigned int find_sorted_id(Track *);
void _add_sort(sort_t, bool); void _add_sort(sort_t, bool);
@ -42,8 +42,8 @@ public:
void set_flag(queue_flags); void set_flag(queue_flags);
void unset_flag(queue_flags); void unset_flag(queue_flags);
const unsigned int get_flags(); bool has_flag(queue_flags);
unsigned int get_length();
std::string get_length_str(); std::string get_length_str();
unsigned int add(unsigned int); unsigned int add(unsigned int);
@ -58,8 +58,8 @@ public:
void force_clear_sort(); void force_clear_sort();
std::list <sort_info> &get_sort_order(); std::list <sort_info> &get_sort_order();
unsigned int operator[](unsigned int); Track *operator[](unsigned int);
unsigned int next(); Track *next();
void set_cur(unsigned int); void set_cur(unsigned int);
void path_selected(unsigned int); void path_selected(unsigned int);
#ifdef CONFIG_TEST #ifdef CONFIG_TEST

View File

@ -191,33 +191,27 @@ void audio :: seek_to(long pos)
void audio :: next() void audio :: next()
{ {
Track *track; Track *track;
unsigned int id;
track_loaded = false; track_loaded = false;
id = deck :: next(); track = deck :: next();
track = tagdb :: lookup(id);
load_song(track); load_song(track);
track_loaded = true; track_loaded = true;
cur_trackid = id; cur_trackid = track->id;
save_state(); save_state();
o_recently_played.del_track(id); o_recently_played.del_track(track->id);
o_recently_played.add_front(id); o_recently_played.add_front(track->id);
o_recently_played.set_cur(0); o_recently_played.set_cur(0);
} }
void audio :: previous() void audio :: previous()
{ {
Track *track; Track *track = o_recently_played.next();
unsigned int id; if (track->id == cur_trackid)
id = o_recently_played.next();
if (id == cur_trackid)
return; return;
track = tagdb :: lookup(id);
load_song(track); load_song(track);
cur_trackid = id; cur_trackid = track->id;
save_state(); save_state();
} }

View File

@ -92,7 +92,7 @@ void deck :: write()
/* Save library playqueue */ /* Save library playqueue */
sort_order = library_playqueue.get_sort_order(); sort_order = library_playqueue.get_sort_order();
deck_file << (library_playqueue.get_flags() & Q_RANDOM) << " "; deck_file << library_playqueue.has_flag(Q_RANDOM) << " ";
deck_file << sort_order.size() << " "; deck_file << sort_order.size() << " ";
for (st = sort_order.begin(); st != sort_order.end(); st++) for (st = sort_order.begin(); st != sort_order.end(); st++)
deck_file << st->field << " " << st->ascending << " "; deck_file << st->field << " " << st->ascending << " ";
@ -178,25 +178,25 @@ void deck :: move(Queue *pq, unsigned int new_pos)
playqueue_deck.splice(it_new, playqueue_deck, it_old); playqueue_deck.splice(it_new, playqueue_deck, it_old);
} }
unsigned int deck :: next() Track *deck :: next()
{ {
unsigned int id = 0; Track *track;
std::list<Queue>::iterator it; std::list<Queue>::iterator it;
for (it = playqueue_deck.begin(); it != playqueue_deck.end(); it++) { for (it = playqueue_deck.begin(); it != playqueue_deck.end(); it++) {
if (it->get_flags() & Q_ENABLED) { if (it->has_flag(Q_ENABLED)) {
if (it->size() == 0) { if (it->size() == 0) {
playqueue_deck.erase(it); playqueue_deck.erase(it);
get_callbacks()->on_pq_removed(&(*it)); get_callbacks()->on_pq_removed(&(*it));
} else { } else {
id = it->next(); track = it->next();
if (it->size() == 0) { if (it->size() == 0) {
playqueue_deck.erase(it); playqueue_deck.erase(it);
get_callbacks()->on_pq_removed(&(*it)); get_callbacks()->on_pq_removed(&(*it));
} }
} }
write(); write();
return id; return track;
} }
} }
@ -225,7 +225,7 @@ void deck :: print_info()
for (it = playqueue_deck.begin(); it != playqueue_deck.end(); it++) { for (it = playqueue_deck.begin(); it != playqueue_deck.end(); it++) {
print("deck[%u] = Queue { size = %u, flags = %u }\n", print("deck[%u] = Queue { size = %u, flags = %u }\n",
i, it->size(), it->get_flags()); i, it->size());
i++; i++;
} }
} }

View File

@ -14,12 +14,12 @@
#define O_DAYS (24 * O_HOURS) #define O_DAYS (24 * O_HOURS)
Queue :: Queue() Queue :: Queue()
: flags(0), cur(-1), length(0) : _cur(-1), _flags(0), _length(0)
{ {
} }
Queue :: Queue(queue_flags f) Queue :: Queue(queue_flags f)
: flags(f), cur(-1), length(0) : _cur(-1), _flags(f), _length(0)
{ {
} }
@ -29,40 +29,37 @@ Queue :: ~Queue()
void Queue :: write(File &f) void Queue :: write(File &f)
{ {
f << flags << " " << tracks.size(); f << _flags << " " << _tracks.size();
for (unsigned int i = 0; i < tracks.size(); i++) for (unsigned int i = 0; i < _tracks.size(); i++)
f << " " << tracks[i]; f << " " << _tracks[i];
} }
void Queue :: read(File &f) void Queue :: read(File &f)
{ {
unsigned int n; unsigned int n, id;
f >> flags >> n; f >> _flags >> n;
tracks.resize(n); _tracks.resize(n);
for (unsigned int i = 0; i < n; i++) for (unsigned int i = 0; i < n; i++) {
f >> tracks[i]; f >> id;
_tracks[i] = tagdb :: lookup(id);
}
} }
void Queue :: set_flag(queue_flags f) void Queue :: set_flag(queue_flags f)
{ {
flags |= f; _flags |= f;
get_callbacks()->on_queue_changed(); get_callbacks()->on_queue_changed();
} }
void Queue :: unset_flag(queue_flags f) void Queue :: unset_flag(queue_flags f)
{ {
flags &= ~f; _flags &= ~f;
get_callbacks()->on_queue_changed(); get_callbacks()->on_queue_changed();
} }
const unsigned int Queue :: get_flags() bool Queue :: has_flag(queue_flags f)
{ {
return flags; return (_flags & f) == (unsigned int)f;
}
unsigned int Queue :: get_length()
{
return length;
} }
static inline void add_duration(std::stringstream &ss, unsigned int dur, static inline void add_duration(std::stringstream &ss, unsigned int dur,
@ -80,7 +77,7 @@ static inline void add_duration(std::stringstream &ss, unsigned int dur,
std::string Queue :: get_length_str() std::string Queue :: get_length_str()
{ {
std::stringstream ss; std::stringstream ss;
unsigned int len = length; unsigned int len = _length;
unsigned int days = len / O_DAYS; unsigned int days = len / O_DAYS;
len -= days * O_DAYS; len -= days * O_DAYS;
@ -130,15 +127,15 @@ static bool track_less_than(Track *lhs, Track *rhs, std::list<sort_info> &order)
unsigned int Queue :: find_sorted_id(Track *rhs) unsigned int Queue :: find_sorted_id(Track *rhs)
{ {
Track *lhs; Track *lhs;
unsigned int begin = 0, end = (tracks.size() - 1), mid; unsigned int begin = 0, end = (_tracks.size() - 1), mid;
if (tracks.size() == 0) if (_tracks.size() == 0)
return 0; return 0;
while (end > begin) { while (end > begin) {
mid = begin + ((end - begin) / 2); mid = begin + ((end - begin) / 2);
lhs = tagdb :: lookup(tracks[mid]); lhs = _tracks[mid];
if (track_less_than(lhs, rhs, sort_order)) if (track_less_than(lhs, rhs, _sort_order))
begin = mid + 1; begin = mid + 1;
else { else {
if (mid == begin) if (mid == begin)
@ -148,37 +145,36 @@ unsigned int Queue :: find_sorted_id(Track *rhs)
} }
} }
lhs = tagdb :: lookup(tracks[begin]); lhs = _tracks[begin];
if (track_less_than(lhs, rhs, sort_order)) if (track_less_than(lhs, rhs, _sort_order))
return begin + 1; return begin + 1;
return begin; return begin;
} }
unsigned int Queue :: add(unsigned int track_id) unsigned int Queue :: add(unsigned int track_id)
{ {
unsigned int id = tracks.size(); unsigned int id = _tracks.size();
Track *track = tagdb :: lookup(track_id); Track *track = tagdb :: lookup(track_id);
if (sort_order.size() > 0) if (_sort_order.size() > 0)
id = find_sorted_id(track); id = find_sorted_id(track);
tracks.insert(tracks.begin() + id, track_id); _tracks.insert(_tracks.begin() + id, track);
length += track->length; _length += track->length;
get_callbacks()->on_queue_track_add(this, id); get_callbacks()->on_queue_track_add(this, id);
if (!(flags & Q_DISABLE_CHANGED_SIZE)) if (!(_flags & Q_DISABLE_CHANGED_SIZE))
get_callbacks()->on_queue_changed(); get_callbacks()->on_queue_changed();
return id; return id;
} }
unsigned int Queue :: add_front(unsigned int track_id) unsigned int Queue :: add_front(unsigned int track_id)
{ {
Track *track; Track *track = tagdb :: lookup(track_id);
tracks.insert(tracks.begin(), track_id); _tracks.insert(_tracks.begin(), track);
track = tagdb :: lookup(track_id); _length += track->length;
length += track->length;
get_callbacks()->on_queue_track_add(this, 0); get_callbacks()->on_queue_track_add(this, 0);
if (!(flags & Q_DISABLE_CHANGED_SIZE)) if (!(_flags & Q_DISABLE_CHANGED_SIZE))
get_callbacks()->on_queue_changed(); get_callbacks()->on_queue_changed();
return 0; return 0;
} }
@ -186,21 +182,21 @@ unsigned int Queue :: add_front(unsigned int track_id)
void Queue :: del(unsigned int plist_id) void Queue :: del(unsigned int plist_id)
{ {
Track *track; Track *track;
unsigned int track_id = tracks[plist_id]; unsigned int track_id = _tracks[plist_id]->id;
tracks.erase(tracks.begin() + plist_id); _tracks.erase(_tracks.begin() + plist_id);
track = tagdb :: lookup(track_id); track = tagdb :: lookup(track_id);
length -= track->length; _length -= track->length;
get_callbacks()->on_queue_track_del(this, plist_id); get_callbacks()->on_queue_track_del(this, plist_id);
if (!(flags & Q_DISABLE_CHANGED_SIZE)) if (!(_flags & Q_DISABLE_CHANGED_SIZE))
get_callbacks()->on_queue_changed(); get_callbacks()->on_queue_changed();
} }
void Queue :: del_track(unsigned int track_id) void Queue :: del_track(unsigned int track_id)
{ {
unsigned int i = 0; unsigned int i = 0;
while (i < tracks.size()) { while (i < _tracks.size()) {
if (tracks[i] == track_id) if (_tracks[i]->id == track_id)
del(i); del(i);
else else
i++; i++;
@ -209,15 +205,15 @@ void Queue :: del_track(unsigned int track_id)
void Queue :: track_updated(unsigned int track_id) void Queue :: track_updated(unsigned int track_id)
{ {
for (unsigned int i = 0; i < tracks.size(); i++) { for (unsigned int i = 0; i < _tracks.size(); i++) {
if (tracks[i] == track_id) if (_tracks[i]->id == track_id)
get_callbacks()->on_queue_track_changed(this, i); get_callbacks()->on_queue_track_changed(this, i);
} }
} }
unsigned int Queue :: size() unsigned int Queue :: size()
{ {
return tracks.size(); return _tracks.size();
} }
@ -227,10 +223,10 @@ private:
std::list<sort_info> fields; std::list<sort_info> fields;
public: public:
SortTracks(std::list<sort_info> f) : fields(f) {} SortTracks(std::list<sort_info> f) : fields(f) {}
bool operator()(unsigned int a, unsigned int b) bool operator()(Track *a, Track *b)
{ {
Track *lhs = tagdb :: lookup(a); Track *lhs = a;
Track *rhs = tagdb :: lookup(b); Track *rhs = b;
return track_less_than(lhs, rhs, fields); return track_less_than(lhs, rhs, fields);
} }
}; };
@ -241,7 +237,7 @@ void Queue :: _add_sort(sort_t field, bool ascending)
std::list<sort_info>::iterator it; std::list<sort_info>::iterator it;
/* Is field already in the sort_order? */ /* Is field already in the sort_order? */
for (it = sort_order.begin(); it != sort_order.end(); it++) { for (it = _sort_order.begin(); it != _sort_order.end(); it++) {
if (it->field == field) { if (it->field == field) {
it->ascending = !it->ascending; it->ascending = !it->ascending;
return; return;
@ -250,90 +246,90 @@ void Queue :: _add_sort(sort_t field, bool ascending)
info.field = field; info.field = field;
info.ascending = ascending; info.ascending = ascending;
sort_order.push_back(info); _sort_order.push_back(info);
if (sort_order.size() >= 4) if (_sort_order.size() >= 4)
sort_order.erase(sort_order.begin()); _sort_order.erase(_sort_order.begin());
} }
void Queue :: add_sort(sort_t field, bool ascending) void Queue :: add_sort(sort_t field, bool ascending)
{ {
if (flags & Q_NEVER_SORT) if (_flags & Q_NEVER_SORT)
return; return;
_add_sort(field, ascending); _add_sort(field, ascending);
std::stable_sort(tracks.begin(), tracks.end(), SortTracks(sort_order)); std::stable_sort(_tracks.begin(), _tracks.end(), SortTracks(_sort_order));
for (unsigned int i = 0; i < tracks.size(); i++) for (unsigned int i = 0; i < _tracks.size(); i++)
get_callbacks()->on_queue_track_changed(this, i); get_callbacks()->on_queue_track_changed(this, i);
get_callbacks()->on_queue_changed(); get_callbacks()->on_queue_changed();
} }
void Queue :: reset_sort(sort_t field, bool ascending) void Queue :: reset_sort(sort_t field, bool ascending)
{ {
if (flags & Q_NEVER_SORT) if (_flags & Q_NEVER_SORT)
return; return;
if (sort_order.front().field != field) if (_sort_order.front().field != field)
sort_order.clear(); _sort_order.clear();
add_sort(field, ascending); add_sort(field, ascending);
} }
void Queue :: force_clear_sort() void Queue :: force_clear_sort()
{ {
sort_order.clear(); _sort_order.clear();
} }
std::list<sort_info> &Queue :: get_sort_order() std::list<sort_info> &Queue :: get_sort_order()
{ {
return sort_order; return _sort_order;
} }
unsigned int Queue :: operator[](unsigned int i) Track *Queue :: operator[](unsigned int i)
{ {
return tracks[i]; return _tracks[i];
} }
unsigned int Queue :: next() Track *Queue :: next()
{ {
unsigned int res; Track *res;
if (tracks.size() == 0) if (_tracks.size() == 0)
throw -E_EXIST; return NULL;
else if (tracks.size() == 1) else if (_tracks.size() == 1)
cur = 0; _cur = 0;
else if (flags & Q_RANDOM) else if (_flags & Q_RANDOM)
cur += rand() % (tracks.size() / 2) + 1; _cur += rand() % (_tracks.size() / 2) + 1;
else else
cur++; _cur++;
if (cur >= tracks.size()) if (_cur >= _tracks.size())
cur -= tracks.size(); _cur -= _tracks.size();
res = tracks[cur]; res = _tracks[_cur];
if (!(flags & Q_REPEAT)) { if (!(_flags & Q_REPEAT)) {
del(cur); del(_cur);
cur--; _cur--;
} }
return res; return res;
} }
void Queue :: set_cur(unsigned int c) void Queue :: set_cur(unsigned int c)
{ {
cur = c; _cur = c;
} }
void Queue :: path_selected(unsigned int id) void Queue :: path_selected(unsigned int id)
{ {
cur = id; _cur = id;
if (!(flags &Q_REPEAT)) { if (!(_flags &Q_REPEAT)) {
del(cur); del(_cur);
cur--; _cur--;
} }
} }
#ifdef CONFIG_TEST #ifdef CONFIG_TEST
void Queue :: reset() void Queue :: reset()
{ {
tracks.clear(); _tracks.clear();
set_cur(0); set_cur(0);
} }
#endif /* CONFIG_TEST */ #endif /* CONFIG_TEST */

View File

@ -8,8 +8,9 @@ if sys.argv.count("tests") > 0:
src = SConscript("src/Sconscript") src = SConscript("src/Sconscript")
tests = [ "version", "file", "database", "index", "filter", "idle", "tag_db" ] tests = [ "version", "file", "database", "index", "filter", "idle", "tag_db",
#scripts = [ "playlist", "library", "playqueue", "deck", "audio", "gui" ] "queue" ]
#scripts = [ "playlist", "library", "deck", "audio", "gui" ]
prev = None prev = None

7
tests/queue Executable file
View File

@ -0,0 +1,7 @@
#!/bin/bash
# Copyright 2014 (c) Anna Schumaker.
. $(dirname $0)/_functions
echo "Queue test"
./src/queue.run

31
tests/src/queue.cpp Normal file
View File

@ -0,0 +1,31 @@
/*
* Copyright 2014 (c) Anna Schumaker.
*/
#include <queue.h>
#include "test.h"
class TestQueue : public Queue
{
public:
unsigned int get_cur() { return _cur; }
unsigned int get_flags() { return _flags; }
unsigned int get_length() { return _length; }
std::list <sort_info> get_sorder() { return _sort_order; };
};
void test_default()
{
TestQueue q;
test :: equal(q.get_cur(), (unsigned)-1);
test :: equal(q.get_flags(), (unsigned)0);
test :: equal(q.get_length(), (unsigned)0);
test :: equal(q.get_sorder().size(), (size_t)0);
test :: equal(q.next(), (Track *)NULL);
}
int main(int argc, char **argv)
{
test_default();
return 0;
}

45
tests/src/test.h Normal file
View File

@ -0,0 +1,45 @@
/*
* Copyright 2014 (c) Anna Schumaker.
*/
#include <iostream>
#include <stdlib.h>
namespace test
{
static unsigned int test_num;
void new_test(const std::string &name)
{
std::cout << name << std::endl;
test_num = 0;
}
void begin()
{
std::cout << " " << test_num << ": ";
test_num++;
}
template <class T>
void assert_equal(const T &lhs, const T &rhs)
{
if (lhs == rhs)
std::cout << "Success!" << std::endl;
else {
std::cout << "Failed! =(" << std::endl;
std::cout << " Actual: " << lhs << std::endl;
std::cout << " Expected: " << rhs << std::endl;
exit(1);
}
}
template <class T>
void equal(const T &lhs, const T &rhs)
{
begin();
assert_equal(lhs, rhs);
}
}