diff --git a/DESIGN b/DESIGN index ef355013..ad1e9f09 100644 --- a/DESIGN +++ b/DESIGN @@ -853,12 +853,11 @@ Queue: - Sorting: Sorting is done using std::stable_sort() to make sure that orders won't - change unexpectedly. The default sort order is (SORT_ARTIST, true), - (SORT_YEAR, true), (SORT_TRACK, true). + change unexpectedly. - Queue: class Queue { - private: + protected: vector _tracks; list _sort_order; unsigned int _cur; @@ -866,6 +865,7 @@ Queue: unsigned int _length; public: + Queue(); Queue(unsigned int); void read(File &); void write(File &); @@ -893,10 +893,13 @@ File Format: File << flags << tracks.size() << tracks[0] << tracks[1] << ... << tracks[N]; - API + Queue :: Queue(); + Initialize _flags = 0, _cur = -1, _length = 0, and empty sort + order. + Queue :: Queue(unsigned int flags); - Initialize a new queue with the appropriate flags set and with - default sorting. - Set _length = 0, _cur = 0. + Initialize _flags = flags, _cur = -1, _length = 0, and empty + sort order. void Queue :: read(File &f); 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) The library manages databases containing track information added by the user. Ocarina 6 splits the library into multiple database tables for diff --git a/include/deck.h b/include/deck.h index 4ef8a10a..5c776b83 100644 --- a/include/deck.h +++ b/include/deck.h @@ -19,7 +19,7 @@ namespace deck unsigned int size(); void move(unsigned int, unsigned int); void move(Queue *, unsigned int); - unsigned int next(); + Track *next(); Queue *get_library_pq(); #ifdef CONFIG_TEST diff --git a/include/queue.h b/include/queue.h index b4d78bf6..66303f7d 100644 --- a/include/queue.h +++ b/include/queue.h @@ -23,12 +23,12 @@ struct sort_info { }; class Queue { -private: - std :: vector tracks; - std :: list sort_order; - unsigned int flags; - unsigned int cur; - unsigned int length; +protected: + std :: vector _tracks; + std :: list _sort_order; + unsigned int _cur; + unsigned int _flags; + unsigned int _length; unsigned int find_sorted_id(Track *); void _add_sort(sort_t, bool); @@ -42,8 +42,8 @@ public: void set_flag(queue_flags); void unset_flag(queue_flags); - const unsigned int get_flags(); - unsigned int get_length(); + bool has_flag(queue_flags); + std::string get_length_str(); unsigned int add(unsigned int); @@ -58,8 +58,8 @@ public: void force_clear_sort(); std::list &get_sort_order(); - unsigned int operator[](unsigned int); - unsigned int next(); + Track *operator[](unsigned int); + Track *next(); void set_cur(unsigned int); void path_selected(unsigned int); #ifdef CONFIG_TEST diff --git a/lib/audio.cpp b/lib/audio.cpp index 039bdd8c..9557b4a0 100644 --- a/lib/audio.cpp +++ b/lib/audio.cpp @@ -191,33 +191,27 @@ void audio :: seek_to(long pos) void audio :: next() { Track *track; - unsigned int id; track_loaded = false; - id = deck :: next(); - track = tagdb :: lookup(id); + track = deck :: next(); load_song(track); track_loaded = true; - cur_trackid = id; + cur_trackid = track->id; save_state(); - o_recently_played.del_track(id); - o_recently_played.add_front(id); + o_recently_played.del_track(track->id); + o_recently_played.add_front(track->id); o_recently_played.set_cur(0); } void audio :: previous() { - Track *track; - unsigned int id; - - id = o_recently_played.next(); - if (id == cur_trackid) + Track *track = o_recently_played.next(); + if (track->id == cur_trackid) return; - track = tagdb :: lookup(id); load_song(track); - cur_trackid = id; + cur_trackid = track->id; save_state(); } diff --git a/lib/deck.cpp b/lib/deck.cpp index 384801b4..3631be74 100644 --- a/lib/deck.cpp +++ b/lib/deck.cpp @@ -92,7 +92,7 @@ void deck :: write() /* Save library playqueue */ 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() << " "; for (st = sort_order.begin(); st != sort_order.end(); st++) 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); } -unsigned int deck :: next() +Track *deck :: next() { - unsigned int id = 0; + Track *track; std::list::iterator 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) { playqueue_deck.erase(it); get_callbacks()->on_pq_removed(&(*it)); } else { - id = it->next(); + track = it->next(); if (it->size() == 0) { playqueue_deck.erase(it); get_callbacks()->on_pq_removed(&(*it)); } } write(); - return id; + return track; } } @@ -225,7 +225,7 @@ void deck :: print_info() for (it = playqueue_deck.begin(); it != playqueue_deck.end(); it++) { print("deck[%u] = Queue { size = %u, flags = %u }\n", - i, it->size(), it->get_flags()); + i, it->size()); i++; } } diff --git a/lib/queue.cpp b/lib/queue.cpp index c07d7d36..186cb520 100644 --- a/lib/queue.cpp +++ b/lib/queue.cpp @@ -14,12 +14,12 @@ #define O_DAYS (24 * O_HOURS) Queue :: Queue() - : flags(0), cur(-1), length(0) + : _cur(-1), _flags(0), _length(0) { } 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) { - f << flags << " " << tracks.size(); - for (unsigned int i = 0; i < tracks.size(); i++) - f << " " << tracks[i]; + f << _flags << " " << _tracks.size(); + for (unsigned int i = 0; i < _tracks.size(); i++) + f << " " << _tracks[i]; } void Queue :: read(File &f) { - unsigned int n; - f >> flags >> n; - tracks.resize(n); - for (unsigned int i = 0; i < n; i++) - f >> tracks[i]; + unsigned int n, id; + f >> _flags >> n; + _tracks.resize(n); + for (unsigned int i = 0; i < n; i++) { + f >> id; + _tracks[i] = tagdb :: lookup(id); + } } void Queue :: set_flag(queue_flags f) { - flags |= f; + _flags |= f; get_callbacks()->on_queue_changed(); } void Queue :: unset_flag(queue_flags f) { - flags &= ~f; + _flags &= ~f; get_callbacks()->on_queue_changed(); } -const unsigned int Queue :: get_flags() +bool Queue :: has_flag(queue_flags f) { - return flags; -} - -unsigned int Queue :: get_length() -{ - return length; + return (_flags & f) == (unsigned int)f; } 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::stringstream ss; - unsigned int len = length; + unsigned int len = _length; unsigned int days = len / O_DAYS; len -= days * O_DAYS; @@ -130,15 +127,15 @@ static bool track_less_than(Track *lhs, Track *rhs, std::list &order) unsigned int Queue :: find_sorted_id(Track *rhs) { 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; while (end > begin) { mid = begin + ((end - begin) / 2); - lhs = tagdb :: lookup(tracks[mid]); - if (track_less_than(lhs, rhs, sort_order)) + lhs = _tracks[mid]; + if (track_less_than(lhs, rhs, _sort_order)) begin = mid + 1; else { if (mid == begin) @@ -148,37 +145,36 @@ unsigned int Queue :: find_sorted_id(Track *rhs) } } - lhs = tagdb :: lookup(tracks[begin]); - if (track_less_than(lhs, rhs, sort_order)) + lhs = _tracks[begin]; + if (track_less_than(lhs, rhs, _sort_order)) return begin + 1; return begin; } unsigned int Queue :: add(unsigned int track_id) { - unsigned int id = tracks.size(); + unsigned int id = _tracks.size(); Track *track = tagdb :: lookup(track_id); - if (sort_order.size() > 0) + if (_sort_order.size() > 0) id = find_sorted_id(track); - tracks.insert(tracks.begin() + id, track_id); - length += track->length; + _tracks.insert(_tracks.begin() + id, track); + _length += track->length; 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(); return id; } unsigned int Queue :: add_front(unsigned int track_id) { - Track *track; - tracks.insert(tracks.begin(), track_id); + Track *track = tagdb :: lookup(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); - if (!(flags & Q_DISABLE_CHANGED_SIZE)) + if (!(_flags & Q_DISABLE_CHANGED_SIZE)) get_callbacks()->on_queue_changed(); return 0; } @@ -186,21 +182,21 @@ unsigned int Queue :: add_front(unsigned int track_id) void Queue :: del(unsigned int plist_id) { 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); - length -= track->length; + _length -= track->length; 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(); } void Queue :: del_track(unsigned int track_id) { unsigned int i = 0; - while (i < tracks.size()) { - if (tracks[i] == track_id) + while (i < _tracks.size()) { + if (_tracks[i]->id == track_id) del(i); else i++; @@ -209,15 +205,15 @@ void Queue :: del_track(unsigned int track_id) void Queue :: track_updated(unsigned int track_id) { - for (unsigned int i = 0; i < tracks.size(); i++) { - if (tracks[i] == track_id) + for (unsigned int i = 0; i < _tracks.size(); i++) { + if (_tracks[i]->id == track_id) get_callbacks()->on_queue_track_changed(this, i); } } unsigned int Queue :: size() { - return tracks.size(); + return _tracks.size(); } @@ -227,10 +223,10 @@ private: std::list fields; public: SortTracks(std::list f) : fields(f) {} - bool operator()(unsigned int a, unsigned int b) + bool operator()(Track *a, Track *b) { - Track *lhs = tagdb :: lookup(a); - Track *rhs = tagdb :: lookup(b); + Track *lhs = a; + Track *rhs = b; return track_less_than(lhs, rhs, fields); } }; @@ -241,7 +237,7 @@ void Queue :: _add_sort(sort_t field, bool ascending) std::list::iterator it; /* 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) { it->ascending = !it->ascending; return; @@ -250,90 +246,90 @@ void Queue :: _add_sort(sort_t field, bool ascending) info.field = field; info.ascending = ascending; - sort_order.push_back(info); - if (sort_order.size() >= 4) - sort_order.erase(sort_order.begin()); + _sort_order.push_back(info); + if (_sort_order.size() >= 4) + _sort_order.erase(_sort_order.begin()); } void Queue :: add_sort(sort_t field, bool ascending) { - if (flags & Q_NEVER_SORT) + if (_flags & Q_NEVER_SORT) return; _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_changed(); } void Queue :: reset_sort(sort_t field, bool ascending) { - if (flags & Q_NEVER_SORT) + if (_flags & Q_NEVER_SORT) return; - if (sort_order.front().field != field) - sort_order.clear(); + if (_sort_order.front().field != field) + _sort_order.clear(); add_sort(field, ascending); } void Queue :: force_clear_sort() { - sort_order.clear(); + _sort_order.clear(); } std::list &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) - throw -E_EXIST; - else if (tracks.size() == 1) - cur = 0; - else if (flags & Q_RANDOM) - cur += rand() % (tracks.size() / 2) + 1; + if (_tracks.size() == 0) + return NULL; + else if (_tracks.size() == 1) + _cur = 0; + else if (_flags & Q_RANDOM) + _cur += rand() % (_tracks.size() / 2) + 1; else - cur++; + _cur++; - if (cur >= tracks.size()) - cur -= tracks.size(); + if (_cur >= _tracks.size()) + _cur -= _tracks.size(); - res = tracks[cur]; - if (!(flags & Q_REPEAT)) { - del(cur); - cur--; + res = _tracks[_cur]; + if (!(_flags & Q_REPEAT)) { + del(_cur); + _cur--; } return res; } void Queue :: set_cur(unsigned int c) { - cur = c; + _cur = c; } void Queue :: path_selected(unsigned int id) { - cur = id; - if (!(flags &Q_REPEAT)) { - del(cur); - cur--; + _cur = id; + if (!(_flags &Q_REPEAT)) { + del(_cur); + _cur--; } } #ifdef CONFIG_TEST void Queue :: reset() { - tracks.clear(); + _tracks.clear(); set_cur(0); } #endif /* CONFIG_TEST */ diff --git a/tests/Sconscript b/tests/Sconscript index 011f97a5..a99f8a91 100644 --- a/tests/Sconscript +++ b/tests/Sconscript @@ -8,8 +8,9 @@ if sys.argv.count("tests") > 0: src = SConscript("src/Sconscript") -tests = [ "version", "file", "database", "index", "filter", "idle", "tag_db" ] -#scripts = [ "playlist", "library", "playqueue", "deck", "audio", "gui" ] +tests = [ "version", "file", "database", "index", "filter", "idle", "tag_db", + "queue" ] +#scripts = [ "playlist", "library", "deck", "audio", "gui" ] prev = None diff --git a/tests/queue b/tests/queue new file mode 100755 index 00000000..fe39791d --- /dev/null +++ b/tests/queue @@ -0,0 +1,7 @@ +#!/bin/bash +# Copyright 2014 (c) Anna Schumaker. + +. $(dirname $0)/_functions + +echo "Queue test" +./src/queue.run diff --git a/tests/src/queue.cpp b/tests/src/queue.cpp new file mode 100644 index 00000000..31cbca59 --- /dev/null +++ b/tests/src/queue.cpp @@ -0,0 +1,31 @@ +/* + * Copyright 2014 (c) Anna Schumaker. + */ +#include +#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 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; +} diff --git a/tests/src/test.h b/tests/src/test.h new file mode 100644 index 00000000..3f74dee5 --- /dev/null +++ b/tests/src/test.h @@ -0,0 +1,45 @@ +/* + * Copyright 2014 (c) Anna Schumaker. + */ + +#include +#include + +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 + 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 + void equal(const T &lhs, const T &rhs) + { + begin(); + assert_equal(lhs, rhs); + } +}