diff --git a/core/playlists/artist.c b/core/playlists/artist.c index e1721b50..537dc59a 100644 --- a/core/playlists/artist.c +++ b/core/playlists/artist.c @@ -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; } diff --git a/core/playlists/generic.c b/core/playlists/generic.c index 0c47cbd8..6f796052 100644 --- a/core/playlists/generic.c +++ b/core/playlists/generic.c @@ -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) diff --git a/core/playlists/library.c b/core/playlists/library.c index 1892df51..9c0cc079 100644 --- a/core/playlists/library.c +++ b/core/playlists/library.c @@ -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; } diff --git a/core/playlists/system.c b/core/playlists/system.c index 6a861b45..f42e451a 100644 --- a/core/playlists/system.c +++ b/core/playlists/system.c @@ -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; } diff --git a/core/queue.c b/core/queue.c index 257d7702..0494d14a 100644 --- a/core/queue.c +++ b/core/queue.c @@ -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); -} diff --git a/gui/model.c b/gui/model.c index 7a451c44..e5e9e8aa 100644 --- a/gui/model.c +++ b/gui/model.c @@ -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) diff --git a/gui/playlist.c b/gui/playlist.c index ced41d70..3baf0ff5 100644 --- a/gui/playlist.c +++ b/gui/playlist.c @@ -76,6 +76,7 @@ struct queue_ops playlist_ops = { }; struct playlist_callbacks playlist_cb = { + .pl_cb_sorted = gui_model_update_all, }; diff --git a/include/core/playlists/generic.h b/include/core/playlists/generic.h index 742f5a8a..68a0fa45 100644 --- a/include/core/playlists/generic.h +++ b/include/core/playlists/generic.h @@ -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 *); diff --git a/include/core/queue.h b/include/core/queue.h index f2abf5d6..cfb59add 100644 --- a/include/core/queue.h +++ b/include/core/queue.h @@ -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 */ diff --git a/include/gui/model.h b/include/gui/model.h index 9a8e7857..e0aa8ea5 100644 --- a/include/gui/model.h +++ b/include/gui/model.h @@ -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 *); diff --git a/tests/core/playlist.c b/tests/core/playlist.c index 104d44f4..7450f8cc 100644 --- a/tests/core/playlist.c +++ b/tests/core/playlist.c @@ -6,10 +6,18 @@ #include #include +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"); diff --git a/tests/core/queue.c b/tests/core/queue.c index d728107f..aadb1023 100644 --- a/tests/core/queue.c +++ b/tests/core/queue.c @@ -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: diff --git a/tests/gui/model.c b/tests/gui/model.c index ef2399cc..f925e350 100644 --- a/tests/gui/model.c +++ b/tests/gui/model.c @@ -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));