core/playlist: Implement sorting directly

Rather than passing through to queue_sort().  Additionally, I remove the
queue_sort() function.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
This commit is contained in:
Anna Schumaker 2016-09-16 16:43:13 -04:00
parent 793a8a5817
commit e74c1c053c
6 changed files with 78 additions and 115 deletions

View File

@ -215,6 +215,7 @@ bool playlist_sort(struct playlist *playlist, enum compare_t sort)
return false;
playlist->pl_ops->pl_sort(playlist, sort);
playlist_types[playlist->pl_type]->pl_save();
if (playlist->pl_type < PL_MAX_TYPE)
playlist_types[playlist->pl_type]->pl_save();
return g_slist_length(playlist->pl_queue.q_sort) > 0;
}

View File

@ -8,6 +8,12 @@
static struct playlist_callbacks *callbacks = NULL;
static int __playlist_generic_find_sort(gconstpointer a, gconstpointer b)
{
return abs(GPOINTER_TO_INT(a)) - abs(GPOINTER_TO_INT(b));
}
void playlist_generic_set_callbacks(struct playlist_callbacks *cb)
{
callbacks = cb;
@ -17,9 +23,9 @@ void playlist_generic_init(struct playlist *playlist, unsigned int flags,
struct queue_ops *ops)
{
queue_init(&playlist->pl_queue, flags, ops, playlist);
queue_sort(&playlist->pl_queue, COMPARE_ARTIST);
queue_sort(&playlist->pl_queue, COMPARE_YEAR);
queue_sort(&playlist->pl_queue, COMPARE_TRACK);
playlist_generic_sort(playlist, COMPARE_ARTIST);
playlist_generic_sort(playlist, COMPARE_YEAR);
playlist_generic_sort(playlist, COMPARE_TRACK);
playlist->pl_private = NULL;
}
@ -143,7 +149,17 @@ void playlist_generic_set_flag(struct playlist *playlist,
void playlist_generic_sort(struct playlist *playlist, enum compare_t sort)
{
queue_sort(&playlist->pl_queue, sort);
GSList *found = g_slist_find_custom(playlist->pl_queue.q_sort,
GINT_TO_POINTER(sort),
__playlist_generic_find_sort);
if (found)
found->data = GINT_TO_POINTER(-GPOINTER_TO_INT(found->data));
else
playlist->pl_queue.q_sort = g_slist_append(playlist->pl_queue.q_sort,
GINT_TO_POINTER(sort));
queue_resort(&playlist->pl_queue);
}
struct track *playlist_generic_next(struct playlist *playlist)

View File

@ -255,24 +255,3 @@ void queue_resort(struct queue *queue)
for (unsigned int i = 0; i < queue_size(queue); i++)
__queue_updated(queue, i);
}
void queue_sort(struct queue *queue, enum compare_t sort)
{
GSList *cur = NULL;
int field;
cur = queue->q_sort;
while (cur) {
field = GPOINTER_TO_INT(cur->data);
if (abs(field) == sort) {
cur->data = GINT_TO_POINTER(-field);
goto out_sort;
}
cur = g_slist_next(cur);
}
queue->q_sort = g_slist_append(queue->q_sort, GINT_TO_POINTER(sort));
out_sort:
queue_resort(queue);
}

View File

@ -170,7 +170,4 @@ struct track *queue_next(struct queue *);
/* Called to sort the queue without changing sort order. */
void queue_resort(struct queue *);
/* Called to change the sort order and resort the queue. */
void queue_sort(struct queue *, enum compare_t);
#endif /* OCARINA_CORE_QUEUE_H */

View File

@ -6,6 +6,11 @@
#include <core/settings.h>
#include <core/tags/tags.h>
static struct playlist_ops test_noop;
static struct playlist_ops test_ops = {
.pl_sort = playlist_generic_sort,
};
static void test_null()
{
g_assert_null(playlist_new(PL_MAX_TYPE, "NULL"));
@ -42,19 +47,64 @@ static void test_null()
static void test_sorting()
{
struct playlist p = DEFINE_PLAYLIST(PL_MAX_TYPE, "Test", 0, NULL);
struct playlist p = DEFINE_PLAYLIST(PL_MAX_TYPE, "Test", 0, &test_ops);
struct track *track;
unsigned int i;
playlist_generic_init(&p, 0, NULL);
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);
for (i = 0; i < 13; i++) {
track = track_get(i);
track->tr_count = (track->tr_track % 2) ? 4 : 2;
playlist_generic_add_track_front(&p, track);
}
p.pl_ops = &test_noop;
g_assert_false(playlist_sort(&p, COMPARE_TRACK));
p.pl_ops = &test_ops;
g_assert_true(playlist_sort(&p, COMPARE_TRACK));
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);
g_assert_true(playlist_sort(&p, COMPARE_COUNT));
for (i = 0; i < 13; i++) {
track = queue_at(&p.pl_queue, i);
g_assert_cmpuint(track->tr_count, ==, (i < 6) ? 2 : 4);
}
g_assert_true(playlist_sort(&p, COMPARE_TRACK));
for (i = 0; i < 13; i++) {
track = queue_at(&p.pl_queue, i);
g_assert_cmpuint(track->tr_count, ==, (i < 6) ? 2 : 4);
if (i < 6)
g_assert_cmpuint(track->tr_track, ==, (i + 1) * 2);
else
g_assert_cmpuint(track->tr_track, ==, (2 * i) - 11);
}
g_assert_true(playlist_sort(&p, COMPARE_COUNT));
for (i = 0; i < 13; i++) {
track = queue_at(&p.pl_queue, i);
g_assert_cmpuint(track->tr_count, ==, (i < 7) ? 4 : 2);
if (i < 7)
g_assert_cmpuint(track->tr_track, ==, (2 * i) + 1);
else
g_assert_cmpuint(track->tr_track, ==, (2 * i) - 12);
}
}
static void test_save_load()
{
struct playlist p = DEFINE_PLAYLIST(PL_MAX_TYPE, "Test", 0, NULL);
struct playlist p = DEFINE_PLAYLIST(PL_MAX_TYPE, "Test", 0, &test_ops);
struct playlist q = DEFINE_PLAYLIST(PL_MAX_TYPE, "Test 2", 0, NULL);
struct playlist r = DEFINE_PLAYLIST(PL_MAX_TYPE, "Test", 0, NULL);
struct playlist r = DEFINE_PLAYLIST(PL_MAX_TYPE, "Test", 0, &test_ops);
struct playlist s = DEFINE_PLAYLIST(PL_MAX_TYPE, "Test 2", 0, NULL);
struct file f = FILE_INIT("test.playlist", 0);
unsigned int i;
@ -65,7 +115,7 @@ static void test_save_load()
}
queue_set_flag(&p.pl_queue, Q_RANDOM);
playlist_clear_sort(&p);
queue_sort(&p.pl_queue, COMPARE_TRACK);
playlist_sort(&p, COMPARE_TRACK);
p.pl_queue.q_cur.it_pos = 3;
q.pl_queue.q_cur.it_pos = 4;

View File

@ -224,9 +224,8 @@ static void test_rand_select()
for (i = 0; i < 13; i++)
queue_add(&q, track_get(i));
g_slist_free(q.q_sort);
q.q_sort = NULL;
queue_sort(&q, COMPARE_TRACK);
q.q_sort = g_slist_append(q.q_sort, GINT_TO_POINTER(COMPARE_TRACK));
queue_resort(&q);
/*
* The comments below use the following notation:
@ -257,84 +256,6 @@ static void test_rand_select()
queue_deinit(&q);
}
static void test_sorting()
{
unsigned int ex_count[] = { 7, 8, 9, 10, 11, 12, 13, 1, 2, 3, 4, 5, 6 };
unsigned int ex_title[] = { 7, 10, 9, 4, 3, 6, 2, 5, 12, 11, 13, 1, 8 };
unsigned int ex_co_ti[] = { 4, 3, 6, 2, 5, 1, 7, 10, 9, 12, 11, 13, 8 };
struct track *track;
unsigned int i;
struct queue q;
queue_init(&q, 0, &test_ops, NULL);
for (i = 0; i < 13; i++) {
track = track_get(i);
track->tr_count = (track->tr_track <= 6) ? 4 : 2;
queue_add_front(&q, track);
}
for (i = 0; i < 13; i++) {
track = queue_at(&q, i);
g_assert_nonnull(track);
g_assert_cmpuint(track->tr_dbe.dbe_index, ==, 12 - i);
}
g_slist_free(q.q_sort);
q.q_sort = NULL;
queue_sort(&q, COMPARE_TRACK);
for (i = 0; i < 13; i++) {
track = queue_at(&q, i);
g_assert_nonnull(track);
g_assert_cmpuint(track->tr_track, ==, i + 1);
}
g_slist_free(q.q_sort);
q.q_sort = NULL;
queue_sort(&q, COMPARE_COUNT);
for (i = 0; i < 13; i++) {
track = queue_at(&q, i);
g_assert_nonnull(track);
g_assert_cmpuint(track->tr_track, ==, ex_count[i]);
}
g_slist_free(q.q_sort);
q.q_sort = NULL;
queue_sort(&q, COMPARE_TITLE);
for (i = 0; i < 13; i++) {
track = queue_at(&q, i);
g_assert_nonnull(track);
g_assert_cmpuint(track->tr_track, ==, ex_title[i]);
}
g_slist_free(q.q_sort);
q.q_sort = NULL;
queue_sort(&q, COMPARE_COUNT);
queue_sort(&q, COMPARE_TITLE);
queue_sort(&q, COMPARE_COUNT);
for (i = 0; i < 13; i++) {
track = queue_at(&q, i);
g_assert_nonnull(track);
g_assert_cmpuint(track->tr_track, ==, ex_co_ti[i]);
}
g_slist_free(q.q_sort);
q.q_sort = NULL;
queue_sort(&q, COMPARE_ARTIST);
queue_sort(&q, COMPARE_ALBUM);
queue_sort(&q, COMPARE_TRACK);
queue_sort(&q, COMPARE_TRACK);
for (i = 0; i < 13; i++) {
track = queue_at(&q, i);
g_assert_nonnull(track);
g_assert_cmpuint(track->tr_track, ==, 13 - i);
}
queue_deinit(&q);
g_assert_cmpuint(q.q_length, ==, 0);
g_assert_cmpuint(queue_size(&q),==, 0);
g_assert_null(q.q_sort);
}
int main(int argc, char **argv)
{
struct library *library;
@ -367,7 +288,6 @@ int main(int argc, char **argv)
g_test_add_data_func("/Core/Queue/n = 13", GUINT_TO_POINTER( 13), test_queue);
g_test_add_data_func("/Core/Queue/n = 100,009)", GUINT_TO_POINTER(100009), test_queue);
g_test_add_func("/Core/Queue/Random Next and Selection", test_rand_select);
g_test_add_func("/Core/Queue/Sorting", test_sorting);
ret = g_test_run();
tags_deinit();