diff --git a/core/deck.cpp b/core/deck.cpp index 3b4c86dc..ef9f916a 100644 --- a/core/deck.cpp +++ b/core/deck.cpp @@ -9,8 +9,6 @@ class RecentQueue : public queue { public: - RecentQueue() : queue(Q_ENABLED | Q_REPEAT | Q_NO_SORT) {} - unsigned int add(struct track *track) { del(track); @@ -25,9 +23,16 @@ static RecentQueue recent_queue; static struct file deck_file; -TempQueue :: TempQueue() {} +TempQueue :: TempQueue() +{ + queue_init(this, 0, NULL); +} + TempQueue :: TempQueue(bool random) - : queue(Q_ENABLED | (random ? Q_RANDOM : 0)) {} +{ + queue_init(this, Q_ENABLED | (random ? Q_RANDOM : 0), NULL); +} + void TempQueue :: set_flag(queue_flags flag) { @@ -91,7 +96,9 @@ void deck :: init() bool upgraded = false; std::list::iterator it; + queue_init(&recent_queue, Q_ENABLED | Q_REPEAT | Q_NO_SORT, NULL); file_init(&deck_file, "deck", 1); + if (!file_open(&deck_file, OPEN_READ)) return; diff --git a/core/library.cpp b/core/library.cpp index d80ee594..589db613 100644 --- a/core/library.cpp +++ b/core/library.cpp @@ -16,12 +16,9 @@ private: public: - LibraryQueue() : queue(Q_ENABLED | Q_REPEAT) + LibraryQueue() { file_init(&f, "library.q", 0); - queue :: sort(COMPARE_ARTIST, true); - queue :: sort(COMPARE_YEAR, false); - queue :: sort(COMPARE_TRACK, false); } void save() @@ -154,12 +151,19 @@ void collection :: init() { struct db_entry *track, *next; - library_q.load(); + queue_init(&library_q, Q_ENABLED | Q_REPEAT, NULL); db_for_each(track, next, track_db_get()) { if (TRACK(track)->tr_library->li_enabled) library_q.add(TRACK(track)); } + + library_q.load(); + if (library_q.q_sort.size() == 0) { + library_q.sort(COMPARE_ARTIST, true); + library_q.sort(COMPARE_YEAR, false); + library_q.sort(COMPARE_TRACK, false); + } } struct library *collection :: add(const std::string &dir) diff --git a/core/playlist.cpp b/core/playlist.cpp index 49f5c4a5..715bde8d 100644 --- a/core/playlist.cpp +++ b/core/playlist.cpp @@ -8,14 +8,6 @@ class PlaylistQueue : public queue { public: - PlaylistQueue() : queue(Q_ENABLED | Q_REPEAT) - { - sort(COMPARE_ARTIST, true); - sort(COMPARE_YEAR, false); - sort(COMPARE_TRACK, false); - set_flag(Q_NO_SORT); - } - void clear() { while (queue_size(this) > 0) @@ -81,6 +73,12 @@ void playlist :: init() { struct set_iter it; + queue_init(&playlist_q, Q_ENABLED | Q_REPEAT, NULL); + playlist_q.sort(COMPARE_ARTIST, true); + playlist_q.sort(COMPARE_YEAR, false); + playlist_q.sort(COMPARE_TRACK, false); + playlist_q.set_flag(Q_NO_SORT); + index_init(&playlist_db, "playlist.db", true); db_load(&playlist_db); @@ -94,6 +92,8 @@ void playlist :: init() bool playlist :: has(struct track *track, const std::string &name) { + if (playlist_db.db_size == 0) + return false; return index_has(&playlist_db, name.c_str(), track->tr_dbe.dbe_index); } diff --git a/core/queue.cpp b/core/queue.cpp index ddda9a2c..ebcdbde7 100644 --- a/core/queue.cpp +++ b/core/queue.cpp @@ -20,13 +20,21 @@ public: } def_notify; -queue :: queue(unsigned int flags) - : q_cur(-1), q_flags(flags), q_length(0), q_notify(&def_notify) -{} +static inline void __queue_save(struct queue *queue, enum queue_flags flag) +{ + if (queue->q_ops && queue_has_flag(queue, flag)) + queue->q_ops->qop_save(queue, flag); +} -queue :: queue() - : q_cur(-1), q_flags(0), q_length(0), q_notify(&def_notify) -{} +void queue_init(struct queue *queue, unsigned int flags, + const struct queue_ops *ops) +{ + queue->q_cur = -1; + queue->q_flags = flags; + queue->q_length = 0; + queue->q_notify = &def_notify; + queue->q_ops = ops; +} queue :: ~queue() {} @@ -53,11 +61,13 @@ void queue :: read(file &file) void queue :: set_flag(queue_flags flag) { q_flags |= flag; + __queue_save(this, Q_SAVE_FLAGS); } void queue :: unset_flag(queue_flags flag) { q_flags &= ~flag; + __queue_save(this, Q_SAVE_FLAGS); } static bool track_less_than(struct track *lhs, struct track *rhs, @@ -210,4 +220,5 @@ void queue :: sort(compare_t field, bool reset) for (unsigned int i = 0; i < q_tracks.size(); i++) q_notify->on_track_updated(i); + __queue_save(this, Q_SAVE_SORT); } diff --git a/gui/ocarina.cpp b/gui/ocarina.cpp index 29de8412..684d7935 100644 --- a/gui/ocarina.cpp +++ b/gui/ocarina.cpp @@ -46,10 +46,10 @@ int main(int argc, char **argv) exit(1); gst :: init(&argc, &argv); - plist :: init(); core :: init(); + plist :: init(); manager :: init(); init_tabs(); window = window_init(); diff --git a/gui/playlist.cpp b/gui/playlist.cpp index 294baa13..e9ca2669 100644 --- a/gui/playlist.cpp +++ b/gui/playlist.cpp @@ -147,8 +147,10 @@ static void on_favorite() void plist :: track_loaded(struct track *track) { - o_ban->set_active(playlist :: has(track, "Banned")); - o_fav->set_active(playlist :: has(track, "Favorites")); + if (p_tab) { + o_ban->set_active(playlist :: has(track, "Banned")); + o_fav->set_active(playlist :: has(track, "Favorites")); + } } void plist :: init() @@ -158,6 +160,8 @@ void plist :: init() o_ban = gui :: get_widget("o_ban"); o_fav = gui :: get_widget("o_favorite"); + track_loaded(audio :: current_track()); + o_ban->signal_toggled().connect(sigc::ptr_fun(on_ban)); o_fav->signal_toggled().connect(sigc::ptr_fun(on_favorite)); } diff --git a/include/core/queue.h b/include/core/queue.h index 9cd68263..51555042 100644 --- a/include/core/queue.h +++ b/include/core/queue.h @@ -17,10 +17,12 @@ extern "C" { * Enum defining flags that effect a Queue's behavior. */ enum queue_flags { - Q_ENABLED = (1 << 0), /**< Queue is enabled. */ - Q_RANDOM = (1 << 1), /**< Queue will pick songs randomly. */ - Q_REPEAT = (1 << 2), /**< Queue will not remove songs when picked. */ - Q_NO_SORT = (1 << 3), /**< Queue will not be sorted. */ + Q_ENABLED = (1 << 0), /* Queue is enabled. */ + Q_RANDOM = (1 << 1), /* Queue will pick songs randomly. */ + Q_REPEAT = (1 << 2), /* Queue will not remove songs when picked. */ + Q_NO_SORT = (1 << 3), /* Queue will not be sorted. */ + Q_SAVE_FLAGS = (1 << 4), /* Queue will be saved when flags change. */ + Q_SAVE_SORT = (1 << 5), /* Queue will be saved when sorted. */ }; @@ -54,6 +56,12 @@ public: }; +struct queue_ops { + /* Called to have a higher layer save the queue. */ + void (*qop_save)(struct queue *, enum queue_flags); +}; + + /** * Struct for passing sort parameters. */ @@ -81,18 +89,12 @@ struct queue { std :: vector q_tracks; /* The queue's list of tracks. */ std :: vector q_sort; /* The queue's sort settings. */ + const struct queue_ops *q_ops; /* The queue's operations vector. */ + unsigned int find_sorted_id(struct track *); unsigned int _add_at(struct track *, unsigned int); - /** - * Alternate queue constructor. - * - * @param flags Create a queue with _flags set to flags. - */ - queue(unsigned int); - - queue(); /**< Default queue constructor. */ virtual ~queue(); /**< Queue destructor. */ /** @@ -163,6 +165,10 @@ struct queue { }; +/* Called to initialize a queue. */ +void queue_init(struct queue *, unsigned int, const struct queue_ops *); + + /* Called to check if the queue has a specific flag set. */ static inline bool queue_has_flag(struct queue *queue, enum queue_flags flag) { diff --git a/tests/core/audio.cpp b/tests/core/audio.cpp index 07f8f138..81b89d2f 100644 --- a/tests/core/audio.cpp +++ b/tests/core/audio.cpp @@ -6,6 +6,7 @@ extern "C" { #include #include } +#include #include #include "test.h" @@ -88,6 +89,7 @@ void test_init() filter_init(); tags_init(); collection :: init(); + deck :: init(); audio :: init(); track = audio :: current_track(); diff --git a/tests/core/deck.cpp b/tests/core/deck.cpp index 28b2970d..018cbc4e 100644 --- a/tests/core/deck.cpp +++ b/tests/core/deck.cpp @@ -113,9 +113,10 @@ static void test_next_prev() { std::list::iterator it = deck :: get_queues().begin(); queue *q = deck :: get_queue(); - queue *q0 = &(*it++); - queue *q1 = &(*it++); + queue *q0 = deck :: get(0); + queue *q1 = deck :: get(1); + q0->q_notify = &test_notifier; q0->unset_flag(Q_RANDOM); for (unsigned int i = 0; i < 4; i++) q0->add(track_get(i)); diff --git a/tests/core/library.cpp b/tests/core/library.cpp index 0c8f654f..b6163bb6 100644 --- a/tests/core/library.cpp +++ b/tests/core/library.cpp @@ -16,15 +16,14 @@ static void test_init() { queue *q = collection :: get_queue(); - test_not_equal(q, Q_NULL); - test_equal(queue_has_flag(q, Q_ENABLED), true); - test_equal(queue_has_flag(q, Q_REPEAT), true); - test_cp_data_dir(); filter_init(); tags_init(); collection :: init(); + test_not_equal(q, Q_NULL); + test_equal(queue_has_flag(q, Q_ENABLED), true); + test_equal(queue_has_flag(q, Q_REPEAT), true); test_equal(queue_size(q), (unsigned)24); } diff --git a/tests/core/playlist.cpp b/tests/core/playlist.cpp index 4a93fbbd..449d696f 100644 --- a/tests/core/playlist.cpp +++ b/tests/core/playlist.cpp @@ -17,20 +17,17 @@ static void test_init() index_entry *ent; queue *q = playlist :: get_queue(); - test_not_equal(q, Q_NULL); - test_equal(queue_has_flag(q, Q_ENABLED), true); - test_equal(queue_has_flag(q, Q_REPEAT), true); - test_equal(queue_has_flag(q, Q_NO_SORT), true); - - /* init should work even if playlist.db doesn't exist! */ - playlist :: init(); - test_cp_data_dir(); filter_init(); tags_init(); collection :: init(); playlist :: init(); + test_not_equal(q, Q_NULL); + test_equal(queue_has_flag(q, Q_ENABLED), true); + test_equal(queue_has_flag(q, Q_REPEAT), true); + test_equal(queue_has_flag(q, Q_NO_SORT), true); + ent = playlist :: get_tracks("Banned"); test_equal(set_size(&ent->ie_set), (size_t)4); test_equal(queue_size(collection :: get_queue()), (unsigned)20); diff --git a/tests/core/queue.cpp b/tests/core/queue.cpp index 41c7a6ef..cb14c663 100644 --- a/tests/core/queue.cpp +++ b/tests/core/queue.cpp @@ -10,8 +10,10 @@ extern "C" { #include "test.h" -unsigned int count_added = 0; +unsigned int count_added = 0; unsigned int count_deleted = 0; +unsigned int count_flags = 0; +unsigned int count_sort = 0; unsigned int count_updated = 0; @@ -24,6 +26,20 @@ public: } test_notifier; +static void queue_op_save(struct queue *queue, enum queue_flags flag) +{ + if (flag == Q_SAVE_FLAGS) + count_flags++; + else if (flag == Q_SAVE_SORT) + count_sort++; +} + + +static const struct queue_ops test_ops = { + queue_op_save, +}; + + static void __test_init_core() { struct library *library; @@ -60,48 +76,65 @@ static void test_init() __test_init_core(); + queue_init(&q, 0, NULL); test_equal(q.q_cur, (unsigned int)-1); test_equal(q.q_flags, 0); test_equal(q.q_length, 0); test_equal(q.q_sort.size(), (size_t)0); + test_equal(q.q_ops, NULL); test_equal(queue_next(&q), (struct track *)NULL); test_not_equal(q.q_notify, NULL); - q = queue(Q_ENABLED | Q_RANDOM); + queue_init(&q, Q_ENABLED | Q_RANDOM, &test_ops); q.q_notify = &test_notifier; test_equal(q.q_cur, (unsigned int )-1); test_equal(q.q_flags, Q_ENABLED | Q_RANDOM); test_equal(q.q_length, 0); test_equal(q.q_sort.size(), 0); + test_equal(q.q_ops, &test_ops); test_equal(queue_next(&q), (struct track *)NULL); test_equal(q.q_notify, &test_notifier); } static void test_flags() { - struct queue q(0); + struct queue q; + queue_init(&q, 0, &test_ops); test_equal(q.q_flags, 0); - test_equal(queue_has_flag(&q, Q_ENABLED), false); - test_equal(queue_has_flag(&q, Q_RANDOM), false); - test_equal(queue_has_flag(&q, Q_REPEAT), false); - test_equal(queue_has_flag(&q, Q_NO_SORT), false); + test_equal(queue_has_flag(&q, Q_ENABLED), false); + test_equal(queue_has_flag(&q, Q_RANDOM), false); + test_equal(queue_has_flag(&q, Q_REPEAT), false); + test_equal(queue_has_flag(&q, Q_NO_SORT), false); + test_equal(queue_has_flag(&q, Q_SAVE_FLAGS), false); + test_equal(queue_has_flag(&q, Q_SAVE_SORT), false); q.set_flag(Q_ENABLED); - test_equal(q.q_flags, Q_ENABLED); + test_equal(q.q_flags, Q_ENABLED); + test_equal(count_flags, 0); q.unset_flag(Q_ENABLED); - test_equal(q.q_flags, 0); + test_equal(q.q_flags, 0); + test_equal(count_flags, 0); + q.set_flag(Q_SAVE_FLAGS); q.set_flag(Q_ENABLED); q.set_flag(Q_RANDOM); q.set_flag(Q_REPEAT); q.set_flag(Q_NO_SORT); - test_equal(queue_has_flag(&q, Q_ENABLED), true); - test_equal(queue_has_flag(&q, Q_RANDOM), true); - test_equal(queue_has_flag(&q, Q_REPEAT), true); - test_equal(queue_has_flag(&q, Q_NO_SORT), true); + test_equal(queue_has_flag(&q, Q_ENABLED), true); + test_equal(queue_has_flag(&q, Q_RANDOM), true); + test_equal(queue_has_flag(&q, Q_REPEAT), true); + test_equal(queue_has_flag(&q, Q_NO_SORT), true); + test_equal(queue_has_flag(&q, Q_SAVE_FLAGS), true); + test_equal(count_flags, 5); + + q.unset_flag(Q_ENABLED); + q.unset_flag(Q_RANDOM); + q.unset_flag(Q_REPEAT); + q.unset_flag(Q_NO_SORT); + test_equal(count_flags, 9); } static void test_stress(unsigned int N) @@ -109,12 +142,14 @@ static void test_stress(unsigned int N) unsigned int ex_length = 0; unsigned int ex_size = N; struct track *track; - struct queue q(0); unsigned int i; + struct queue q; count_added = 0; count_deleted = 0; count_updated = 0; + + queue_init(&q, 0, &test_ops); q.q_notify = &test_notifier; /* Queue :: add() */ @@ -180,10 +215,11 @@ static void test_stress_100K() { test_stress(100009); } static void test_rand_select() { - struct queue q(Q_ENABLED | Q_RANDOM); unsigned int i; + struct queue q; random_seed(0); + queue_init(&q, Q_ENABLED | Q_RANDOM, &test_ops); /* Call next() on an empty queue. */ for (i = 0; i < 13; i++) { @@ -256,9 +292,10 @@ static void test_sorting() unsigned int ex_title[] = { 6, 9, 8, 3, 2, 5, 1, 4, 11, 10, 12, 0, 7 }; unsigned int ex_co_ti[] = { 3, 2, 5, 1, 4, 0, 6, 9, 8, 11, 10, 12, 7 }; struct track *track; - struct queue q(0); unsigned int i; + struct queue q; + queue_init(&q, Q_SAVE_SORT, &test_ops); for (i = 0; i < 13; i++) { track = track_get(i); track->tr_count = (i < 6) ? 4 : 2; @@ -271,6 +308,7 @@ static void test_sorting() test_loop_not_equal(track, NULL, i); test_loop_equal(track->tr_dbe.dbe_index, ex_count[i], i); } test_loop_passed(); + test_equal(count_sort, 1); q.set_flag(Q_NO_SORT); q.sort(COMPARE_TITLE, true); @@ -287,6 +325,7 @@ static void test_sorting() test_loop_not_equal(track, NULL, i); test_loop_equal(track->tr_dbe.dbe_index, ex_title[i], i); } test_loop_passed(); + test_equal(count_sort, 2); q.sort(COMPARE_COUNT, true); q.sort(COMPARE_TITLE, false); @@ -296,7 +335,9 @@ static void test_sorting() test_loop_not_equal(track, NULL, i); test_loop_equal(track->tr_dbe.dbe_index, ex_co_ti[i], i); } test_loop_passed(); + test_equal(count_sort, 5); + q.unset_flag(Q_SAVE_SORT); q.sort(COMPARE_ARTIST, true); q.sort(COMPARE_ALBUM, false); q.sort(COMPARE_TRACK, false); @@ -306,15 +347,19 @@ static void test_sorting() test_loop_not_equal(track, NULL, i); test_loop_equal(track->tr_dbe.dbe_index, 12 - i, i); } test_loop_passed(); + test_equal(count_sort, 5); } static void test_save_load() { - struct queue q(Q_RANDOM), r(0); struct track *track; + struct queue q, r; unsigned int i; struct file f; + queue_init(&q, Q_RANDOM, &test_ops); + queue_init(&r, 0, &test_ops); + for (i = 0; i < 13; i++) q.add(track_get(i)); q.sort(COMPARE_TRACK, true);