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 <Anna@NoWheyCreamery.com>
This commit is contained in:
parent
f25bdab367
commit
18f1bfe801
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
*/
|
||||
#ifndef OCARINA_CORE_PLAYLISTS_GENERIC_H
|
||||
#define OCARINA_CORE_PLAYLISTS_GENERIC_H
|
||||
#include <core/playlists/iterator.h>
|
||||
#include <core/playlists/playlist.h>
|
||||
|
||||
enum playlist_save_flags {
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* Copyright 2016 (c) Anna Schumaker.
|
||||
*/
|
||||
#ifndef OCARINA_CORE_PLAYLISTS_ITERATOR_H
|
||||
#define OCARINA_CORE_PLAYLISTS_ITERATOR_H
|
||||
#include <core/playlists/playlist.h>
|
||||
#include <core/queue.h>
|
||||
|
||||
/* 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 */
|
|
@ -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 *);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue