From 18f1bfe80128a34b16a60aacd38399b25ae71b3a Mon Sep 17 00:00:00 2001 From: Anna Schumaker Date: Thu, 22 Sep 2016 10:00:55 -0400 Subject: [PATCH] core/playlist: Move playlist iterator functions into the playlist layer I also take this chance to add extra functions for directly manipulating the current track, since this is something we do fairly often. Signed-off-by: Anna Schumaker --- core/playlists/generic.c | 24 ++++------ core/playlists/library.c | 8 ++-- core/playlists/system.c | 3 +- core/queue.c | 5 +- gui/filter.c | 3 +- include/core/playlists/generic.h | 1 + include/core/playlists/iterator.h | 76 +++++++++++++++++++++++++++++++ include/core/queue.h | 41 ----------------- tests/core/playlist.c | 24 +++++++--- tests/core/queue.c | 6 --- 10 files changed, 113 insertions(+), 78 deletions(-) create mode 100644 include/core/playlists/iterator.h diff --git a/core/playlists/generic.c b/core/playlists/generic.c index 3bc5d82b..4a6865c7 100644 --- a/core/playlists/generic.c +++ b/core/playlists/generic.c @@ -84,8 +84,9 @@ void playlist_generic_save(struct playlist *playlist, struct file *file, if (flags & PL_SAVE_TRACKS) { file_writef(file, "%u", playlist_size(playlist)); - queue_for_each(&playlist->pl_queue, &it) - file_writef(file, " %u", track_index(queue_iter_val(&it))); + playlist_for_each(playlist, &it) + file_writef(file, " %u", + track_index(playlist_iter_track(&it))); file_writef(file, "\n"); } } @@ -131,7 +132,7 @@ void playlist_generic_load(struct playlist *playlist, struct file *file, } playlist_generic_set_random(playlist, f == PL_RANDOM); - queue_iter_set(&playlist->pl_queue, &playlist->pl_queue.q_cur, it); + playlist_current_set(playlist, it); } bool playlist_generic_can_select(struct playlist *playlist) @@ -194,8 +195,8 @@ bool playlist_generic_remove(struct playlist *playlist, struct track *track) if (!playlist || !track) return false; - while (queue_iter_val(&playlist->pl_queue.q_cur) == track) - queue_iter_prev(&playlist->pl_queue.q_cur); + while (playlist_current_track(playlist) == track) + playlist_current_previous(playlist); count = g_queue_remove_all(&playlist->pl_queue.q_tracks, track); playlist->pl_length -= (count * track->tr_length); @@ -253,14 +254,9 @@ struct track *playlist_generic_next(struct playlist *playlist) else if (playlist->pl_random) { pos = g_random_int_range(1, size); pos += playlist->pl_queue.q_cur.it_pos; - queue_iter_set(&playlist->pl_queue, - &playlist->pl_queue.q_cur, pos % size); - } else { - queue_iter_next(&playlist->pl_queue.q_cur); - if (!playlist->pl_queue.q_cur.it_iter) - queue_iter_set(&playlist->pl_queue, - &playlist->pl_queue.q_cur, 0); - } + playlist_current_set(playlist, pos % size); + } else if (!playlist_current_next(playlist)) + playlist_current_set(playlist, 0); - return queue_iter_val(&playlist->pl_queue.q_cur); + return playlist_current_track(playlist); } diff --git a/core/playlists/library.c b/core/playlists/library.c index f5e2f220..50907e1a 100644 --- a/core/playlists/library.c +++ b/core/playlists/library.c @@ -177,10 +177,10 @@ static bool pl_library_delete(struct playlist *playlist) if (!library) return false; - queue_for_each(&playlist->pl_queue, &it) { - pl_system_delete_track(queue_iter_val(&it)); - pl_artist_delete_track(queue_iter_val(&it)); - pl_user_delete_track(queue_iter_val(&it)); + playlist_for_each(playlist, &it) { + pl_system_delete_track(playlist_iter_track(&it)); + pl_artist_delete_track(playlist_iter_track(&it)); + pl_user_delete_track(playlist_iter_track(&it)); } __lib_pl_free(playlist); diff --git a/core/playlists/system.c b/core/playlists/system.c index c2f3adb9..37dfdd5e 100644 --- a/core/playlists/system.c +++ b/core/playlists/system.c @@ -201,7 +201,7 @@ static struct playlist_ops collection_ops = { static bool sys_pl_history_add(struct playlist *playlist, struct track *track) { playlist_generic_add_front(playlist, track); - queue_iter_set(&playlist->pl_queue, &playlist->pl_queue.q_cur, 0); + playlist_current_set(playlist, 0); return true; } @@ -370,7 +370,6 @@ static void pl_system_selected(struct track *track) { unsigned int i; - queue_iter_prev(&pl_system_get(SYS_PL_QUEUED)->pl_queue.q_cur); playlist_generic_remove(pl_system_get(SYS_PL_QUEUED), track); for (i = 0; i < SYS_PL_NUM_PLAYLISTS; i++) playlist_generic_update(pl_system_get(i), track); diff --git a/core/queue.c b/core/queue.c index 277ce1ad..eb6622ad 100644 --- a/core/queue.c +++ b/core/queue.c @@ -22,10 +22,9 @@ static inline void __queue_deinit(struct queue *queue) void queue_init(struct queue *queue, const struct queue_ops *ops, void *data) { queue->q_ops = ops; - g_queue_init(&queue->q_tracks); - queue_iter_init(queue, &queue->q_cur); - + queue->q_cur.it_iter = NULL; + queue->q_cur.it_pos = -1; queue->q_private = __queue_init(queue, data); } diff --git a/gui/filter.c b/gui/filter.c index e7d9bb04..b9ac11d1 100644 --- a/gui/filter.c +++ b/gui/filter.c @@ -131,8 +131,7 @@ void gui_filter_path_load_track(GtkTreePath *path) unsigned int index = gtk_tree_path_get_indices(path)[0]; audio_load(track); - queue_iter_set(&gui_model_get_playlist()->pl_queue, - &gui_model_get_playlist()->pl_queue.q_cur, index); + playlist_current_set(gui_model_get_playlist(), index); } unsigned int gui_filter_path_get_index(GtkTreePath *path) diff --git a/include/core/playlists/generic.h b/include/core/playlists/generic.h index d7e299b7..aed8ac38 100644 --- a/include/core/playlists/generic.h +++ b/include/core/playlists/generic.h @@ -3,6 +3,7 @@ */ #ifndef OCARINA_CORE_PLAYLISTS_GENERIC_H #define OCARINA_CORE_PLAYLISTS_GENERIC_H +#include #include enum playlist_save_flags { diff --git a/include/core/playlists/iterator.h b/include/core/playlists/iterator.h new file mode 100644 index 00000000..3ae41bfd --- /dev/null +++ b/include/core/playlists/iterator.h @@ -0,0 +1,76 @@ +/* + * Copyright 2016 (c) Anna Schumaker. + */ +#ifndef OCARINA_CORE_PLAYLISTS_ITERATOR_H +#define OCARINA_CORE_PLAYLISTS_ITERATOR_H +#include +#include + +/* Called to set the playlist iterator to a specific position. */ +static inline bool playlist_iter_set(struct playlist *playlist, + struct queue_iter *iter, + unsigned int n) +{ + if (!playlist || !iter) + return false; + iter->it_iter = g_queue_peek_nth_link(&playlist->pl_queue.q_tracks, n); + iter->it_pos = n; + return iter->it_iter != NULL; +} + +/* Called to advance the requested playlist iterator. */ +static inline bool playlist_iter_next(struct queue_iter *iter) +{ + if (!iter) + return false; + iter->it_iter = g_list_next(iter->it_iter); + iter->it_pos++; + return iter->it_iter != NULL; +} + +/* Called to get a pointer to the track at the requested iterator. */ +static inline struct track *playlist_iter_track(struct queue_iter *iter) +{ + return (iter && iter->it_iter) ? iter->it_iter->data : NULL; +} + +/* Called to iterate over the entire playlist. */ +#define playlist_for_each(playlist, it) \ + for (playlist_iter_set(playlist, it, 0); (it)->it_iter; \ + playlist_iter_next(it)) + + +/* Called to set the index of the current track. */ +static inline bool playlist_current_set(struct playlist *playlist, + unsigned int n) +{ + if (!playlist) + return false; + return playlist_iter_set(playlist, &playlist->pl_queue.q_cur, n); +} + +/* Called to advance the current track. */ +static inline bool playlist_current_next(struct playlist *playlist) +{ + if (!playlist) + return false; + return playlist_iter_next(&playlist->pl_queue.q_cur); +} + +/* Called to rewind the current track. */ +static inline bool playlist_current_previous(struct playlist *playlist) +{ + if (!playlist) + return false; + playlist->pl_queue.q_cur.it_iter = g_list_previous(playlist->pl_queue.q_cur.it_iter); + playlist->pl_queue.q_cur.it_pos--; + return playlist->pl_queue.q_cur.it_iter != NULL; +} + +/* Called to get a pointer to the current track. */ +static inline struct track *playlist_current_track(struct playlist *playlist) +{ + return playlist ? playlist_iter_track(&playlist->pl_queue.q_cur) : NULL; +} + +#endif /* OCARINA_CORE_PLAYLISTS_ITERATOR_H */ diff --git a/include/core/queue.h b/include/core/queue.h index 64000a63..f90d96dc 100644 --- a/include/core/queue.h +++ b/include/core/queue.h @@ -38,47 +38,6 @@ struct queue { }; - -/* Called to initialize a queue iterator. */ -static inline void queue_iter_init(struct queue *queue, struct queue_iter *it) -{ - it->it_iter = g_queue_peek_head_link(&queue->q_tracks); - it->it_pos = g_queue_link_index(&queue->q_tracks, it->it_iter); -} - -/* Called to advance a queue iterator by one step. */ -static inline void queue_iter_next(struct queue_iter *it) -{ - it->it_iter = g_list_next(it->it_iter); - it->it_pos++; -} - -/* Called to rewind a queue iterator by one step. */ -static inline void queue_iter_prev(struct queue_iter *it) -{ - it->it_iter = g_list_previous(it->it_iter); - it->it_pos--; -} - -/* Called to set a queue iterator to a specific position. */ -static inline void queue_iter_set(struct queue *queue, struct queue_iter *it, - unsigned int pos) -{ - it->it_iter = g_queue_peek_nth_link(&queue->q_tracks, pos); - it->it_pos = pos; -} - -/* Called to access the value of a queue iterator. */ -static inline struct track *queue_iter_val(struct queue_iter *it) -{ - return (it->it_iter) ? it->it_iter->data : NULL; -} - -#define queue_for_each(queue, it) \ - for (queue_iter_init(queue, it); (it)->it_iter; queue_iter_next(it)) - - - /* Called to initialize a queue. */ void queue_init(struct queue *, const struct queue_ops *, void *); diff --git a/tests/core/playlist.c b/tests/core/playlist.c index f81f68d2..4b1ad924 100644 --- a/tests/core/playlist.c +++ b/tests/core/playlist.c @@ -77,12 +77,22 @@ static void test_null() playlist_generic_save(NULL, NULL, PL_SAVE_ALL); playlist_generic_load(NULL, NULL, PL_SAVE_ALL); + + g_assert_false(playlist_iter_set(NULL, NULL, 0)); + g_assert_false(playlist_iter_next(NULL)); + g_assert_null(playlist_iter_track(NULL)); + + g_assert_false(playlist_current_set(NULL, 0)); + g_assert_false(playlist_current_next(NULL)); + g_assert_false(playlist_current_previous(NULL)); + g_assert_null(playlist_current_track(NULL)); } static void test_playlist() { struct playlist p = DEFINE_PLAYLIST(PL_MAX_TYPE, "Test", 0, &test_ops); unsigned int ex_length = 0; + struct queue_iter it; unsigned int i; g_assert_cmpuint(playlist_size(&p), ==, 0); @@ -102,17 +112,19 @@ static void test_playlist() g_assert_false(playlist_generic_add_front(&p, NULL)); /* Trigger an update for each track. */ - for (i = 0; i < 13; i++) { - playlist_generic_update(&p, track_get(i)); + i = 13; + playlist_for_each(&p, &it) { + g_assert_cmpuint(playlist_iter_track(&it)->tr_track, ==, i--); + playlist_generic_update(&p, playlist_iter_track(&it)); g_assert(cb_playlist == &p); - g_assert(cb_track == track_get(i)); + g_assert(cb_track == playlist_iter_track(&it)); } playlist_generic_update(&p, NULL); g_assert(cb_playlist == &p); g_assert_null(cb_track); /* Remove all tracks. */ - queue_iter_set(&p.pl_queue, &p.pl_queue.q_cur, 12); + playlist_current_set(&p, 12); for (i = 0; i < 13; i++) { ex_length -= track_get(i)->tr_length; g_assert_true(playlist_remove(&p, track_get(i))); @@ -148,7 +160,7 @@ static void test_playlist() g_assert_cmpuint(p.pl_length, ==, ex_length); /* Now clear the playlist. */ - queue_iter_set(&p.pl_queue, &p.pl_queue.q_cur, 12); + playlist_current_set(&p, 12); playlist_generic_clear(&p); g_assert_cmpuint(playlist_size(&p), ==, 0); g_assert_cmpuint(p.pl_length, ==, 0); @@ -332,7 +344,7 @@ static void test_save_load() g_assert_false(s.pl_random); g_assert_cmpuint(s.pl_queue.q_cur.it_pos, ==, 4); - g_assert(queue_iter_val(&s.pl_queue.q_cur) == queue_at(&q.pl_queue, 4)); + g_assert(playlist_current_track(&s) == queue_at(&q.pl_queue, 4)); g_assert_cmpuint(g_slist_length(s.pl_sort), ==, 0); g_assert_cmpuint(playlist_size(&s), ==, 13); diff --git a/tests/core/queue.c b/tests/core/queue.c index 44fd790c..f748ab5d 100644 --- a/tests/core/queue.c +++ b/tests/core/queue.c @@ -32,7 +32,6 @@ static const struct queue_ops test_ops = { static void test_init() { struct queue q; - struct queue_iter it; queue_init(&q, NULL, NULL); g_assert_cmpuint(count_init, ==, 0); @@ -41,11 +40,6 @@ static void test_init() g_assert_cmpuint(q.q_cur.it_pos, ==, (unsigned int)-1); g_assert_null(q.q_ops); - queue_iter_init(&q, &it); - g_assert_null(it.it_iter); - g_assert_cmpuint(it.it_pos, ==, (unsigned int)-1); - g_assert_null(queue_iter_val(&it)); - queue_deinit(&q); g_assert_cmpuint(count_deinit, ==, 0);