diff --git a/core/playlist.c b/core/playlist.c index 21cb5c40..d44aef96 100644 --- a/core/playlist.c +++ b/core/playlist.c @@ -208,6 +208,20 @@ bool playlist_sort(struct playlist *playlist, enum compare_t sort) return g_slist_length(playlist->pl_sort) > 0; } +bool playlist_rearrange(struct playlist *playlist, unsigned int old_pos, + unsigned int new_pos) +{ + bool ret; + + if (!playlist || !playlist->pl_ops->pl_rearrange) + return false; + + ret = playlist->pl_ops->pl_rearrange(playlist, old_pos, new_pos); + if (ret && playlist->pl_type < PL_MAX_TYPE) + playlist_types[playlist->pl_type]->pl_save(); + return ret; +} + void playlist_set_search(struct playlist *playlist, const gchar *text) { gchar **tokens = NULL; diff --git a/core/playlists/artist.c b/core/playlists/artist.c index 61f422d6..47677e92 100644 --- a/core/playlists/artist.c +++ b/core/playlists/artist.c @@ -11,6 +11,7 @@ static struct playlist_ops pl_artist_ops = { .pl_can_select = playlist_generic_can_select, .pl_set_random = playlist_generic_set_random, .pl_sort = playlist_generic_sort, + .pl_rearrange = playlist_generic_rearrange, }; diff --git a/core/playlists/generic.c b/core/playlists/generic.c index 0f5625ef..112fd7ed 100644 --- a/core/playlists/generic.c +++ b/core/playlists/generic.c @@ -280,6 +280,22 @@ void playlist_generic_resort(struct playlist *playlist) playlist_generic_update(playlist, NULL); } +bool playlist_generic_rearrange(struct playlist *playlist, unsigned int old_pos, + unsigned int new_pos) +{ + GList *nth; + + if (old_pos == new_pos || old_pos >= playlist_size(playlist) || + new_pos > playlist_size(playlist)) + return false; + + playlist_clear_sort(playlist); + nth = g_queue_pop_nth_link(&playlist->pl_tracks, old_pos); + g_queue_push_nth_link(&playlist->pl_tracks, new_pos, nth); + playlist_generic_update(playlist, NULL); + return true; +} + struct track *playlist_generic_next(struct playlist *playlist) { unsigned int pos, size = playlist_size(playlist); diff --git a/core/playlists/library.c b/core/playlists/library.c index 8bb38501..1c4996fc 100644 --- a/core/playlists/library.c +++ b/core/playlists/library.c @@ -181,6 +181,7 @@ static struct playlist_ops pl_library_ops = { .pl_delete = pl_library_delete, .pl_set_random = playlist_generic_set_random, .pl_sort = playlist_generic_sort, + .pl_rearrange = playlist_generic_rearrange, }; diff --git a/core/playlists/system.c b/core/playlists/system.c index d6d9967f..f8a6fdb0 100644 --- a/core/playlists/system.c +++ b/core/playlists/system.c @@ -82,6 +82,7 @@ static struct playlist_ops favorites_ops = { .pl_remove = playlist_generic_remove, .pl_set_random = playlist_generic_set_random, .pl_sort = playlist_generic_sort, + .pl_rearrange = playlist_generic_rearrange, }; @@ -132,6 +133,7 @@ static struct playlist_ops hidden_ops = { .pl_remove = sys_pl_hidden_remove, .pl_set_random = playlist_generic_set_random, .pl_sort = playlist_generic_sort, + .pl_rearrange = playlist_generic_rearrange, }; @@ -183,6 +185,7 @@ static struct playlist_ops queued_ops = { .pl_remove = sys_pl_queued_remove, .pl_set_random = playlist_generic_set_random, .pl_sort = playlist_generic_sort, + .pl_rearrange = playlist_generic_rearrange, }; @@ -207,6 +210,7 @@ static struct playlist_ops collection_ops = { .pl_remove = sys_pl_hidden_add, .pl_set_random = playlist_generic_set_random, .pl_sort = playlist_generic_sort, + .pl_rearrange = playlist_generic_rearrange, }; @@ -232,6 +236,7 @@ static struct playlist_ops dynamic_ops = { .pl_can_select = playlist_generic_can_select, .pl_set_random = playlist_generic_set_random, .pl_sort = playlist_generic_sort, + .pl_rearrange = playlist_generic_rearrange, }; diff --git a/core/playlists/user.c b/core/playlists/user.c index 50c18b2b..198d6797 100644 --- a/core/playlists/user.c +++ b/core/playlists/user.c @@ -82,6 +82,7 @@ static struct playlist_ops user_ops = { .pl_remove = playlist_generic_remove, .pl_set_random = playlist_generic_set_random, .pl_sort = playlist_generic_sort, + .pl_rearrange = playlist_generic_rearrange, }; diff --git a/include/core/playlist.h b/include/core/playlist.h index 09e6eb1a..1d42244e 100644 --- a/include/core/playlist.h +++ b/include/core/playlist.h @@ -71,6 +71,9 @@ void playlist_set_random(struct playlist *, bool); /* Called to change the sort order of the playlist. */ bool playlist_sort(struct playlist *, enum compare_t); +/* Called to manually rearrange the order of the playlist. */ +bool playlist_rearrange(struct playlist *, unsigned int, unsigned int); + /* Called to set the playlist's search text */ void playlist_set_search(struct playlist *, const gchar *); diff --git a/include/core/playlists/generic.h b/include/core/playlists/generic.h index 8cfe8ad4..fde162a2 100644 --- a/include/core/playlists/generic.h +++ b/include/core/playlists/generic.h @@ -82,6 +82,9 @@ void playlist_generic_set_random(struct playlist *, bool); void playlist_generic_sort(struct playlist *, enum compare_t); void playlist_generic_resort(struct playlist *); +/* Generic playlist rearranging operation. */ +bool playlist_generic_rearrange(struct playlist *, unsigned int, unsigned int); + /* Generic playlist next track operation. */ struct track *playlist_generic_next(struct playlist *); diff --git a/include/core/playlists/playlist.h b/include/core/playlists/playlist.h index 23d7af5e..542db96d 100644 --- a/include/core/playlists/playlist.h +++ b/include/core/playlists/playlist.h @@ -39,6 +39,9 @@ struct playlist_ops { /* Called to sort the playlist. */ void (*pl_sort)(struct playlist *, enum compare_t); + + /* Called to rearrange the playlist. */ + bool (*pl_rearrange)(struct playlist *, unsigned int, unsigned int); }; diff --git a/tests/core/playlist.c b/tests/core/playlist.c index 70fd03cb..90d93f68 100644 --- a/tests/core/playlist.c +++ b/tests/core/playlist.c @@ -34,6 +34,7 @@ static struct playlist_ops test_ops = { .pl_remove = playlist_generic_remove, .pl_set_random = playlist_generic_set_random, .pl_sort = playlist_generic_sort, + .pl_rearrange = playlist_generic_rearrange, }; static struct playlist_callbacks test_cb = { .pl_cb_alloc = test_pl_alloc, @@ -76,6 +77,7 @@ static void test_null() g_assert_false(playlist_sort(NULL, COMPARE_TRACK)); playlist_generic_resort(NULL); playlist_clear_sort(NULL); + g_assert_false(playlist_rearrange(NULL, 0, 0)); playlist_set_search(NULL, NULL); @@ -280,6 +282,43 @@ static void test_sorting() g_assert_null(p.pl_sort); } +static void test_rearranging() +{ + struct playlist p = DEFINE_PLAYLIST(PL_MAX_TYPE, "Test", 0, &test_ops); + struct track *track; + unsigned int i; + + playlist_generic_init(&p, 4, COMPARE_ARTIST, COMPARE_YEAR, + COMPARE_ALBUM, COMPARE_TRACK); + g_assert_cmpuint(g_slist_length(p.pl_sort), ==, 4); + + for (i = 0; i < 13; i++) + playlist_add(&p, track_get(i)); + + g_assert_false(playlist_rearrange(&p, 42, 4)); + g_assert_cmpuint(g_slist_length(p.pl_sort), ==, 4); + g_assert_false(playlist_rearrange(&p, 4, 42)); + g_assert_cmpuint(g_slist_length(p.pl_sort), ==, 4); + g_assert_false(playlist_rearrange(&p, 4, 4)); + g_assert_cmpuint(g_slist_length(p.pl_sort), ==, 4); + g_assert_true(playlist_rearrange(&p, 12, 0)); + g_assert_cmpuint(g_slist_length(p.pl_sort), ==, 0); + g_assert_true(playlist_rearrange(&p, 1, 12)); + g_assert_cmpuint(g_slist_length(p.pl_sort), ==, 0); + + for (i = 0; i < 13; i++) { + track = playlist_at(&p, i); + if (i == 0) + g_assert_cmpuint(track->tr_track, ==, 13); + else if (i == 12) + g_assert_cmpuint(track->tr_track, ==, 1); + else + g_assert_cmpuint(track->tr_track, ==, i + 1); + } + + playlist_generic_deinit(&p); +} + static void test_next() { struct playlist p = DEFINE_PLAYLIST(PL_MAX_TYPE, "Test", 0, &test_ops); @@ -404,6 +443,7 @@ int main(int argc, char **argv) g_test_add_func("/Core/Playlist/NULL", test_null); g_test_add_func("/Core/Playlists/General", test_playlist); g_test_add_func("/Core/Playlists/Sorting", test_sorting); + g_test_add_func("/Core/Playlists/Rearranging", test_rearranging); g_test_add_func("/Core/Playlists/Next Track", test_next); g_test_add_func("/Core/Playlist/Save and Load", test_save_load); ret = g_test_run(); diff --git a/tests/core/playlists/library.c b/tests/core/playlists/library.c index c9f7230f..1fec64ab 100644 --- a/tests/core/playlists/library.c +++ b/tests/core/playlists/library.c @@ -76,7 +76,7 @@ void test_library() g_assert_false(playlist->pl_random); g_assert_cmpuint(g_slist_length(playlist->pl_sort), ==, 4); - playlist_clear_sort(playlist); + g_assert_true(playlist_rearrange(playlist, 15, 20)); g_assert_cmpuint(g_slist_length(playlist->pl_sort), ==, 0); g_assert_true(playlist_sort(playlist, COMPARE_ARTIST)); g_assert_cmpuint(g_slist_length(playlist->pl_sort), ==, 1);