core/playlist: Add a playlist_generic_resort() function

This function is called to force-sort the playlist.  Additionally, we
trigger the "playlist-sorted" callback to to notify the gui that
playlist rows need to be updated.

Additionally, I implement the gui_model_update_all() function to loop
over the model and update all rows of the current playlist.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
This commit is contained in:
Anna Schumaker 2016-09-17 10:33:09 -04:00
parent e74c1c053c
commit 07bf09c2ad
13 changed files with 81 additions and 23 deletions

View File

@ -48,7 +48,7 @@ static bool __artist_pl_add(void *data)
queue_add_front(&playlist->pl_queue, TRACK(dbe));
}
queue_resort(&playlist->pl_queue);
playlist_generic_resort(playlist);
return true;
}

View File

@ -13,6 +13,25 @@ static int __playlist_generic_find_sort(gconstpointer a, gconstpointer b)
return abs(GPOINTER_TO_INT(a)) - abs(GPOINTER_TO_INT(b));
}
static int __playlist_generic_less_than(gconstpointer a, gconstpointer b,
gpointer data)
{
struct track *lhs = (struct track *)a;
struct track *rhs = (struct track *)b;
GSList *cur = (GSList *)data;
int res, field;
while (cur) {
field = GPOINTER_TO_INT(cur->data);
res = track_compare(lhs, rhs, abs(field));
if (res != 0)
break;
cur = g_slist_next(cur);
};
return (field > 0) ? res : -res;
}
void playlist_generic_set_callbacks(struct playlist_callbacks *cb)
{
@ -87,7 +106,7 @@ void playlist_generic_load(struct playlist *playlist, struct file *file,
}
playlist_clear_sort(playlist);
playlist->pl_queue.q_sort = sort;
queue_resort(&playlist->pl_queue);
playlist_generic_resort(playlist);
if (file_readf(file, "%m\n", &line))
g_free(line);
@ -159,7 +178,19 @@ void playlist_generic_sort(struct playlist *playlist, enum compare_t sort)
playlist->pl_queue.q_sort = g_slist_append(playlist->pl_queue.q_sort,
GINT_TO_POINTER(sort));
queue_resort(&playlist->pl_queue);
playlist_generic_resort(playlist);
}
void playlist_generic_resort(struct playlist *playlist)
{
if (!playlist || !playlist->pl_queue.q_sort)
return;
g_queue_sort(&playlist->pl_queue.q_tracks, __playlist_generic_less_than,
playlist->pl_queue.q_sort);
if (callbacks)
callbacks->pl_cb_sorted(playlist);
}
struct track *playlist_generic_next(struct playlist *playlist)

View File

@ -52,7 +52,7 @@ static bool __lib_pl_add(void *data)
queue_add_front(&playlist->pl_queue, TRACK(dbe));
}
queue_resort(&playlist->pl_queue);
playlist_generic_resort(playlist);
return true;
}

View File

@ -54,7 +54,7 @@ static bool sys_pl_update_func(void *data)
playlist_generic_remove_track(playlist, track);
}
queue_resort(&playlist->pl_queue);
playlist_generic_resort(playlist);
return true;
}

View File

@ -246,12 +246,3 @@ struct track *queue_next(struct queue *queue)
return __queue_selected(queue, queue->q_cur.it_pos);
}
void queue_resort(struct queue *queue)
{
g_queue_sort(&queue->q_tracks, track_less_than, queue->q_sort);
queue_iter_set(queue, &queue->q_cur, queue->q_cur.it_pos);
for (unsigned int i = 0; i < queue_size(queue); i++)
__queue_updated(queue, i);
}

View File

@ -257,6 +257,13 @@ static void __gui_model_set_runtime(void)
g_free(len);
}
static gboolean __gui_model_foreach_changed(GtkTreeModel *model, GtkTreePath *path,
GtkTreeIter *iter, gpointer data)
{
gtk_tree_model_row_changed(model, path, iter);
return FALSE;
}
GuiModel *gui_model_get(void)
{
return gui_model;
@ -328,6 +335,13 @@ void gui_model_update(struct playlist *playlist, unsigned int row)
gtk_tree_path_free(path);
}
void gui_model_update_all(struct playlist *playlist)
{
if (cur_playlist == playlist)
gtk_tree_model_foreach(GTK_TREE_MODEL(gui_model),
__gui_model_foreach_changed, NULL);
}
void gui_model_set_playlist(struct playlist *playlist)
{
if (cur_playlist)

View File

@ -76,6 +76,7 @@ struct queue_ops playlist_ops = {
};
struct playlist_callbacks playlist_cb = {
.pl_cb_sorted = gui_model_update_all,
};

View File

@ -14,6 +14,8 @@ enum playlist_save_flags {
#define PL_SAVE_ALL (PL_SAVE_TRACKS | PL_SAVE_METADATA)
struct playlist_callbacks {
/* Called to notify that a playlist has been sorted. */
void (*pl_cb_sorted)(struct playlist *);
};
@ -45,8 +47,9 @@ bool playlist_generic_remove_track(struct playlist *, struct track *);
/* Generic playlist set_flag operation. */
void playlist_generic_set_flag(struct playlist *, enum queue_flags, bool);
/* Generic playlist sorting operation. */
/* Generic playlist sorting operations. */
void playlist_generic_sort(struct playlist *, enum compare_t);
void playlist_generic_resort(struct playlist *);
/* Generic playlist next track operation. */
struct track *playlist_generic_next(struct playlist *);

View File

@ -167,7 +167,4 @@ struct track *queue_selected(struct queue *, unsigned int);
/* Called to pick the next track from the queue. */
struct track *queue_next(struct queue *);
/* Called to sort the queue without changing sort order. */
void queue_resort(struct queue *);
#endif /* OCARINA_CORE_QUEUE_H */

View File

@ -63,6 +63,9 @@ void gui_model_clear(struct playlist *, unsigned int);
/* Called to update a row in the model */
void gui_model_update(struct playlist *, unsigned int);
/* Called to update all rows in the model */
void gui_model_update_all(struct playlist *);
/* Called to change the queue represented by the model. */
void gui_model_set_playlist(struct playlist *);

View File

@ -6,10 +6,18 @@
#include <core/settings.h>
#include <core/tags/tags.h>
static struct playlist *last_sort = NULL;
static void test_pl_sorted(struct playlist *playlist)
{ last_sort = playlist; }
static struct playlist_ops test_noop;
static struct playlist_ops test_ops = {
.pl_sort = playlist_generic_sort,
};
static struct playlist_callbacks test_cb = {
.pl_cb_sorted = test_pl_sorted,
};
static void test_null()
{
@ -39,6 +47,7 @@ static void test_null()
g_assert_false(playlist_sort(NULL, COMPARE_TRACK));
g_assert_false(playlist_sort(NULL, COMPARE_TRACK));
playlist_generic_resort(NULL);
playlist_clear_sort(NULL);
playlist_generic_save(NULL, NULL, PL_SAVE_ALL);
@ -55,6 +64,7 @@ static void test_sorting()
g_assert_cmpuint(g_slist_length(p.pl_queue.q_sort), ==, 3);
playlist_clear_sort(&p);
g_assert_cmpuint(g_slist_length(p.pl_queue.q_sort), ==, 0);
last_sort = NULL;
for (i = 0; i < 13; i++) {
track = track_get(i);
@ -64,15 +74,19 @@ static void test_sorting()
p.pl_ops = &test_noop;
g_assert_false(playlist_sort(&p, COMPARE_TRACK));
g_assert_null(last_sort);
p.pl_ops = &test_ops;
g_assert_true(playlist_sort(&p, COMPARE_TRACK));
g_assert(last_sort == &p);
for (i = 0; i < 13; i++) {
track = queue_at(&p.pl_queue, i);
g_assert_cmpuint(track->tr_track, ==, i + 1);
}
playlist_clear_sort(&p);
playlist_generic_resort(&p);
g_assert_true(playlist_sort(&p, COMPARE_COUNT));
for (i = 0; i < 13; i++) {
track = queue_at(&p.pl_queue, i);
@ -152,7 +166,7 @@ int main(int argc, char **argv)
idle_init_sync();
settings_init();
tags_init();
playlist_init(NULL, NULL);
playlist_init(NULL, &test_cb);
while (idle_run_task()) {};
library = library_find("tests/Music");

View File

@ -222,10 +222,9 @@ static void test_rand_select()
g_assert_cmpuint(queue_size(&q), ==, 0);
}
q.q_sort = g_slist_append(q.q_sort, GINT_TO_POINTER(COMPARE_TRACK));
for (i = 0; i < 13; i++)
queue_add(&q, track_get(i));
q.q_sort = g_slist_append(q.q_sort, GINT_TO_POINTER(COMPARE_TRACK));
queue_resort(&q);
/*
* The comments below use the following notation:

View File

@ -48,6 +48,10 @@ struct queue_ops test_ops = {
.qop_updated = test_queue_update,
};
struct playlist_callbacks test_cb = {
.pl_cb_sorted = gui_model_update_all,
};
struct audio_ops test_audio_ops = {
.on_load = test_on_load,
.on_state_change = test_on_state_change,
@ -55,8 +59,9 @@ struct audio_ops test_audio_ops = {
};
struct core_init_data init_data = {
.playlist_cb = &test_cb,
.playlist_ops = &test_ops,
.audio_ops = &test_audio_ops,
.audio_ops = &test_audio_ops,
};
static void test_init()
@ -186,7 +191,7 @@ static void test_model()
while (idle_run_task() == true) {}
g_assert_cmpuint(playlist_size(collection), ==, 13);
g_assert_cmpuint(count_insert, ==, 13);
queue_resort(&playlist_lookup(PL_SYSTEM, "Collection")->pl_queue);
playlist_generic_resort(playlist_lookup(PL_SYSTEM, "Collection"));
g_assert_cmpuint(count_update, ==, 13);
playlist_add(playlist_lookup(PL_SYSTEM, "Favorites"), track_get(0));
playlist_add(playlist_lookup(PL_SYSTEM, "Favorites"), track_get(1));