diff --git a/core/queue.c b/core/queue.c index b594a1d2..20deb193 100644 --- a/core/queue.c +++ b/core/queue.c @@ -52,6 +52,15 @@ static inline unsigned int __queue_added(struct queue *queue, return pos; } +static inline bool __queue_erase(struct queue *queue, struct _q_iter *it) +{ + struct track *track = (struct track *)_q_iter_val(it); + + if (queue->q_ops) + return queue->q_ops->qop_erase(queue, track); + return true; +} + static inline void __queue_remove(struct queue *queue, struct _q_iter *it) { unsigned int pos = it->it_pos; @@ -142,6 +151,15 @@ unsigned int queue_add(struct queue *queue, struct track *track) return __queue_added(queue, track, pos); } +void queue_erase(struct queue *queue, unsigned int index) +{ + struct _q_iter it; + + _q_iter_set(&queue->q_tracks, &it, index); + if (__queue_erase(queue, &it)) + __queue_remove(queue, &it); +} + void queue_remove(struct queue *queue, unsigned int index) { struct _q_iter it; diff --git a/gui/collection_tab.cpp b/gui/collection_tab.cpp index 5c46c5d9..b9f9e2c3 100644 --- a/gui/collection_tab.cpp +++ b/gui/collection_tab.cpp @@ -65,6 +65,11 @@ static void collection_added(struct queue *queue, unsigned int pos) gui_queue_added(queue, pos); } +static bool collection_erase(struct queue *queue, struct track *track) +{ + return false; +} + static void collection_removed(struct queue *queue, unsigned int pos) { if (collection_tab) @@ -76,6 +81,7 @@ struct queue_ops collection_ops = { collection_init, gui_queue_free, collection_added, + collection_erase, collection_removed, gui_queue_cleared, collection_save, diff --git a/gui/history.cpp b/gui/history.cpp index 36d045e7..2f54afd9 100644 --- a/gui/history.cpp +++ b/gui/history.cpp @@ -50,6 +50,11 @@ static void history_added(struct queue *queue, unsigned int pos) gui_queue_added(queue, pos); } +static bool history_erase(struct queue *queue, struct track *track) +{ + return false; +} + static void history_removed(struct queue *queue, unsigned int pos) { history_tab->on_track_removed(pos); @@ -60,6 +65,7 @@ struct queue_ops history_ops = { history_init, gui_queue_free, history_added, + history_erase, history_removed, gui_queue_cleared, NULL, diff --git a/gui/playlist_tab.cpp b/gui/playlist_tab.cpp index 20da15ce..d0d60675 100644 --- a/gui/playlist_tab.cpp +++ b/gui/playlist_tab.cpp @@ -95,6 +95,11 @@ static void playlist_added(struct queue *queue, unsigned int pos) gui_queue_added(queue, pos); } +static bool playlist_erase(struct queue *queue, struct track *track) +{ + return false; +} + static void playlist_removed(struct queue *queue, unsigned int pos) { p_tab->on_track_removed(pos); @@ -105,6 +110,7 @@ struct queue_ops playlist_ops = { playlist_init, gui_queue_free, playlist_added, + playlist_erase, playlist_removed, gui_queue_cleared, NULL, diff --git a/gui/tabs.cpp b/gui/tabs.cpp index c340d4ff..ba5be371 100644 --- a/gui/tabs.cpp +++ b/gui/tabs.cpp @@ -40,6 +40,11 @@ static void tempq_added(struct queue *queue, unsigned int pos) gui_queue_added(queue, pos); } +static bool tempq_erase(struct queue *queue, struct track *track) +{ + return false; +} + static void tempq_removed(struct queue *queue, unsigned int pos) { find_tab(queue)->on_track_removed(pos); @@ -51,6 +56,7 @@ struct queue_ops tempq_ops = { tempq_init, gui_queue_free, tempq_added, + tempq_erase, tempq_removed, gui_queue_cleared, tempq_save, diff --git a/include/core/queue.h b/include/core/queue.h index 7f6d10f8..cbc36786 100644 --- a/include/core/queue.h +++ b/include/core/queue.h @@ -36,6 +36,9 @@ struct queue_ops { /* Called to tell a higher layer that a track has been added. */ void (*qop_added)(struct queue *, unsigned int); + /* Called to ask a higher layer if a track can be erased. */ + bool (*qop_erase)(struct queue *, struct track *); + /* Called to tell a higher layer that a track has been removed. */ void (*qop_removed)(struct queue *, unsigned int); @@ -45,7 +48,7 @@ struct queue_ops { /* Called to have a higher layer save the queue. */ void (*qop_save)(struct queue *, enum queue_flags); - /* Called to hell a higher layer that a track has been updated. */ + /* Called to tell a higher layer that a track has been updated. */ void (*qop_updated)(struct queue *, unsigned int); }; @@ -97,6 +100,12 @@ static inline struct track *queue_at(struct queue *queue, unsigned int index) /* Called to add a track to the queue. */ unsigned int queue_add(struct queue *, struct track *); +/* + * Called to erase a track from the queue by index. + * This can be prevented if qop_erase() returns "false". + */ +void queue_erase(struct queue *, unsigned int); + /* Called to remove a track from the queue by index. */ void queue_remove(struct queue *, unsigned int); diff --git a/tests/core/queue.c b/tests/core/queue.c index 00e1c737..5bc79030 100644 --- a/tests/core/queue.c +++ b/tests/core/queue.c @@ -11,12 +11,15 @@ unsigned int count_init = 0; unsigned int count_deinit = 0; unsigned int count_added = 0; +unsigned int count_erase = 0; unsigned int count_deleted = 0; unsigned int count_cleared = 0; unsigned int count_flags = 0; unsigned int count_sort = 0; unsigned int count_updated = 0; +bool can_erase = true; + static void *queue_op_init(struct queue *queue) { @@ -34,6 +37,12 @@ static void queue_op_added(struct queue *queue, unsigned int pos) count_added++; } +static bool queue_op_erase(struct queue *queue, struct track *track) +{ + count_erase++; + return can_erase; +} + static void queue_op_removed(struct queue *queue, unsigned int pos) { count_deleted++; @@ -62,6 +71,7 @@ static const struct queue_ops test_ops = { .qop_init = queue_op_init, .qop_deinit = queue_op_deinit, .qop_added = queue_op_added, + .qop_erase = queue_op_erase, .qop_removed = queue_op_removed, .qop_cleared = queue_op_cleared, .qop_save = queue_op_save, @@ -213,13 +223,25 @@ static void test_stress(unsigned int N) test_equal(q.q_length, ex_length); test_equal(queue_size(&q), ex_size); - /* queue_remove() */ + /* queue_erase() = false */ + can_erase = false; + for (i = 0; i < ex_size; i += 11) { + queue_erase(&q, i); + test_loop_equal(q.q_length, ex_length, i); + test_loop_equal(queue_size(&q), ex_size, i); + } test_loop_passed(); + + /* queue_remove() and queue_erase() == true */ + can_erase = true; track = track_get(1); ex_length -= track->tr_length * (N / 13); ex_size -= (N / 13); for (i = 0; i < ex_size; i += 11) { test_loop_equal((void *)queue_at(&q, i), (void *)track, i); - queue_remove(&q, i); + if (i % 2 == 0) + queue_remove(&q, i); + else + queue_erase(&q, i); } test_loop_passed(); test_equal(q.q_length, ex_length); test_equal(queue_size(&q), ex_size);