queue: convert all functions to methods

This commit is contained in:
Max Kellermann 2013-01-06 21:33:58 +01:00
parent 70652abf97
commit 108242042e
12 changed files with 700 additions and 786 deletions

View File

@ -36,7 +36,7 @@ extern "C" {
void void
playlist_increment_version_all(struct playlist *playlist) playlist_increment_version_all(struct playlist *playlist)
{ {
queue_modify_all(&playlist->queue); playlist->queue.ModifyAll();
idle_add(IDLE_PLAYLIST); idle_add(IDLE_PLAYLIST);
} }
@ -48,7 +48,7 @@ playlist_tag_changed(struct playlist *playlist)
assert(playlist->current >= 0); assert(playlist->current >= 0);
queue_modify(&playlist->queue, playlist->current); playlist->queue.ModifyAtOrder(playlist->current);
idle_add(IDLE_PLAYLIST); idle_add(IDLE_PLAYLIST);
} }
@ -61,12 +61,12 @@ playlist_queue_song_order(struct playlist *playlist, struct player_control *pc,
{ {
char *uri; char *uri;
assert(queue_valid_order(&playlist->queue, order)); assert(playlist->queue.IsValidOrder(order));
playlist->queued = order; playlist->queued = order;
struct song *song = struct song *song =
song_dup_detached(queue_get_order(&playlist->queue, order)); song_dup_detached(playlist->queue.GetOrder(order));
uri = song_get_uri(song); uri = song_get_uri(song);
g_debug("queue song %i:\"%s\"", playlist->queued, uri); g_debug("queue song %i:\"%s\"", playlist->queued, uri);
@ -93,8 +93,7 @@ playlist_song_started(struct playlist *playlist, struct player_control *pc)
if(playlist->queue.consume) if(playlist->queue.consume)
playlist_delete(playlist, pc, playlist_delete(playlist, pc,
queue_order_to_position(&playlist->queue, playlist->queue.OrderToPosition(current));
current));
idle_add(IDLE_PLAYER); idle_add(IDLE_PLAYER);
} }
@ -105,7 +104,7 @@ playlist_get_queued_song(struct playlist *playlist)
if (!playlist->playing || playlist->queued < 0) if (!playlist->playing || playlist->queued < 0)
return NULL; return NULL;
return queue_get_order(&playlist->queue, playlist->queued); return playlist->queue.GetOrder(playlist->queued);
} }
void void
@ -119,11 +118,11 @@ playlist_update_queued_song(struct playlist *playlist,
if (!playlist->playing) if (!playlist->playing)
return; return;
assert(!queue_is_empty(&playlist->queue)); assert(!playlist->queue.IsEmpty());
assert((playlist->queued < 0) == (prev == NULL)); assert((playlist->queued < 0) == (prev == NULL));
next_order = playlist->current >= 0 next_order = playlist->current >= 0
? queue_next_order(&playlist->queue, playlist->current) ? playlist->queue.GetNextOrder(playlist->current)
: 0; : 0;
if (next_order == 0 && playlist->queue.random && if (next_order == 0 && playlist->queue.random &&
@ -132,21 +131,19 @@ playlist_update_queued_song(struct playlist *playlist,
order each time the playlist is played order each time the playlist is played
completely */ completely */
unsigned current_position = unsigned current_position =
queue_order_to_position(&playlist->queue, playlist->queue.OrderToPosition(playlist->current);
playlist->current);
queue_shuffle_order(&playlist->queue); playlist->queue.ShuffleOrder();
/* make sure that the playlist->current still points to /* make sure that the playlist->current still points to
the current song, after the song order has been the current song, after the song order has been
shuffled */ shuffled */
playlist->current = playlist->current =
queue_position_to_order(&playlist->queue, playlist->queue.PositionToOrder(current_position);
current_position);
} }
if (next_order >= 0) if (next_order >= 0)
next_song = queue_get_order(&playlist->queue, next_order); next_song = playlist->queue.GetOrder(next_order);
else else
next_song = NULL; next_song = NULL;
@ -174,7 +171,7 @@ playlist_play_order(struct playlist *playlist, struct player_control *pc,
playlist->queued = -1; playlist->queued = -1;
struct song *song = struct song *song =
song_dup_detached(queue_get_order(&playlist->queue, orderNum)); song_dup_detached(playlist->queue.GetOrder(orderNum));
uri = song_get_uri(song); uri = song_get_uri(song);
g_debug("play %i:\"%s\"", orderNum, uri); g_debug("play %i:\"%s\"", orderNum, uri);
@ -247,7 +244,7 @@ playlist_resume_playback(struct playlist *playlist, struct player_control *pc)
if ((playlist->stop_on_error && error != PLAYER_ERROR_NONE) || if ((playlist->stop_on_error && error != PLAYER_ERROR_NONE) ||
error == PLAYER_ERROR_OUTPUT || error == PLAYER_ERROR_OUTPUT ||
playlist->error_count >= queue_length(&playlist->queue)) playlist->error_count >= playlist->queue.GetLength())
/* too many errors, or critical error: stop /* too many errors, or critical error: stop
playback */ playback */
playlist_stop(playlist, pc); playlist_stop(playlist, pc);
@ -306,10 +303,9 @@ playlist_order(struct playlist *playlist)
{ {
if (playlist->current >= 0) if (playlist->current >= 0)
/* update playlist.current, order==position now */ /* update playlist.current, order==position now */
playlist->current = queue_order_to_position(&playlist->queue, playlist->current = playlist->queue.OrderToPosition(playlist->current);
playlist->current);
queue_restore_order(&playlist->queue); playlist->queue.RestoreOrder();
} }
void void
@ -362,20 +358,18 @@ playlist_set_random(struct playlist *playlist, struct player_control *pc,
int current_position = int current_position =
playlist->playing && playlist->current >= 0 playlist->playing && playlist->current >= 0
? (int)queue_order_to_position(&playlist->queue, ? (int)playlist->queue.OrderToPosition(playlist->current)
playlist->current)
: -1; : -1;
queue_shuffle_order(&playlist->queue); playlist->queue.ShuffleOrder();
if (current_position >= 0) { if (current_position >= 0) {
/* make sure the current song is the first in /* make sure the current song is the first in
the order list, so the whole rest of the the order list, so the whole rest of the
playlist is played after that */ playlist is played after that */
unsigned current_order = unsigned current_order =
queue_position_to_order(&playlist->queue, playlist->queue.PositionToOrder(current_position);
current_position); playlist->queue.SwapOrders(0, current_order);
queue_swap_order(&playlist->queue, 0, current_order);
playlist->current = 0; playlist->current = 0;
} else } else
playlist->current = -1; playlist->current = -1;
@ -391,8 +385,7 @@ int
playlist_get_current_song(const struct playlist *playlist) playlist_get_current_song(const struct playlist *playlist)
{ {
if (playlist->current >= 0) if (playlist->current >= 0)
return queue_order_to_position(&playlist->queue, return playlist->queue.OrderToPosition(playlist->current);
playlist->current);
return -1; return -1;
} }
@ -403,13 +396,11 @@ playlist_get_next_song(const struct playlist *playlist)
if (playlist->current >= 0) if (playlist->current >= 0)
{ {
if (playlist->queue.single == 1 && playlist->queue.repeat == 1) if (playlist->queue.single == 1 && playlist->queue.repeat == 1)
return queue_order_to_position(&playlist->queue, return playlist->queue.OrderToPosition(playlist->current);
playlist->current); else if (playlist->current + 1 < (int)playlist->queue.GetLength())
else if (playlist->current + 1 < (int)queue_length(&playlist->queue)) return playlist->queue.OrderToPosition(playlist->current + 1);
return queue_order_to_position(&playlist->queue,
playlist->current + 1);
else if (playlist->queue.repeat == 1) else if (playlist->queue.repeat == 1)
return queue_order_to_position(&playlist->queue, 0); return playlist->queue.OrderToPosition(0);
} }
return -1; return -1;
@ -424,11 +415,11 @@ playlist_get_version(const struct playlist *playlist)
int int
playlist_get_length(const struct playlist *playlist) playlist_get_length(const struct playlist *playlist)
{ {
return queue_length(&playlist->queue); return playlist->queue.GetLength();
} }
unsigned unsigned
playlist_get_song_id(const struct playlist *playlist, unsigned song) playlist_get_song_id(const struct playlist *playlist, unsigned song)
{ {
return queue_position_to_id(&playlist->queue, song); return playlist->queue.PositionToId(song);
} }

View File

@ -50,16 +50,14 @@ playlist_stop(struct playlist *playlist, struct player_control *pc)
result in a new random order */ result in a new random order */
unsigned current_position = unsigned current_position =
queue_order_to_position(&playlist->queue, playlist->queue.OrderToPosition(playlist->current);
playlist->current);
queue_shuffle_order(&playlist->queue); playlist->queue.ShuffleOrder();
/* make sure that "current" stays valid, and the next /* make sure that "current" stays valid, and the next
"play" command plays the same song again */ "play" command plays the same song again */
playlist->current = playlist->current =
queue_position_to_order(&playlist->queue, playlist->queue.PositionToOrder(current_position);
current_position);
} }
} }
@ -74,7 +72,7 @@ playlist_play(struct playlist *playlist, struct player_control *pc,
if (song == -1) { if (song == -1) {
/* play any song ("current" song, or the first song */ /* play any song ("current" song, or the first song */
if (queue_is_empty(&playlist->queue)) if (playlist->queue.IsEmpty())
return PLAYLIST_RESULT_SUCCESS; return PLAYLIST_RESULT_SUCCESS;
if (playlist->playing) { if (playlist->playing) {
@ -88,7 +86,7 @@ playlist_play(struct playlist *playlist, struct player_control *pc,
i = playlist->current >= 0 i = playlist->current >= 0
? playlist->current ? playlist->current
: 0; : 0;
} else if (!queue_valid_position(&playlist->queue, song)) } else if (!playlist->queue.IsValidPosition(song))
return PLAYLIST_RESULT_BAD_RANGE; return PLAYLIST_RESULT_BAD_RANGE;
if (playlist->queue.random) { if (playlist->queue.random) {
@ -97,15 +95,14 @@ playlist_play(struct playlist *playlist, struct player_control *pc,
would be equal to the order number in would be equal to the order number in
no-random mode); convert it to a order no-random mode); convert it to a order
number, because random mode is enabled */ number, because random mode is enabled */
i = queue_position_to_order(&playlist->queue, song); i = playlist->queue.PositionToOrder(song);
if (!playlist->playing) if (!playlist->playing)
playlist->current = 0; playlist->current = 0;
/* swap the new song with the previous "current" one, /* swap the new song with the previous "current" one,
so playback continues as planned */ so playback continues as planned */
queue_swap_order(&playlist->queue, playlist->queue.SwapOrders(i, playlist->current);
i, playlist->current);
i = playlist->current; i = playlist->current;
} }
@ -126,7 +123,7 @@ playlist_play_id(struct playlist *playlist, struct player_control *pc,
return playlist_play(playlist, pc, id); return playlist_play(playlist, pc, id);
} }
song = queue_id_to_position(&playlist->queue, id); song = playlist->queue.IdToPosition(id);
if (song < 0) if (song < 0)
return PLAYLIST_RESULT_NO_SUCH_SONG; return PLAYLIST_RESULT_NO_SUCH_SONG;
@ -142,15 +139,15 @@ playlist_next(struct playlist *playlist, struct player_control *pc)
if (!playlist->playing) if (!playlist->playing)
return; return;
assert(!queue_is_empty(&playlist->queue)); assert(!playlist->queue.IsEmpty());
assert(queue_valid_order(&playlist->queue, playlist->current)); assert(playlist->queue.IsValidOrder(playlist->current));
current = playlist->current; current = playlist->current;
playlist->stop_on_error = false; playlist->stop_on_error = false;
/* determine the next song from the queue's order list */ /* determine the next song from the queue's order list */
next_order = queue_next_order(&playlist->queue, playlist->current); next_order = playlist->queue.GetNextOrder(playlist->current);
if (next_order < 0) { if (next_order < 0) {
/* no song after this one: stop playback */ /* no song after this one: stop playback */
playlist_stop(playlist, pc); playlist_stop(playlist, pc);
@ -167,7 +164,7 @@ playlist_next(struct playlist *playlist, struct player_control *pc)
songs in a different than before */ songs in a different than before */
assert(playlist->queue.repeat); assert(playlist->queue.repeat);
queue_shuffle_order(&playlist->queue); playlist->queue.ShuffleOrder();
/* note that playlist->current and playlist->queued are /* note that playlist->current and playlist->queued are
now invalid, but playlist_play_order() will now invalid, but playlist_play_order() will
@ -180,8 +177,7 @@ playlist_next(struct playlist *playlist, struct player_control *pc)
/* Consume mode removes each played songs. */ /* Consume mode removes each played songs. */
if(playlist->queue.consume) if(playlist->queue.consume)
playlist_delete(playlist, pc, playlist_delete(playlist, pc,
queue_order_to_position(&playlist->queue, playlist->queue.OrderToPosition(current));
current));
} }
void void
@ -190,7 +186,7 @@ playlist_previous(struct playlist *playlist, struct player_control *pc)
if (!playlist->playing) if (!playlist->playing)
return; return;
assert(queue_length(&playlist->queue) > 0); assert(playlist->queue.GetLength() > 0);
if (playlist->current > 0) { if (playlist->current > 0) {
/* play the preceding song */ /* play the preceding song */
@ -199,7 +195,7 @@ playlist_previous(struct playlist *playlist, struct player_control *pc)
} else if (playlist->queue.repeat) { } else if (playlist->queue.repeat) {
/* play the last song in "repeat" mode */ /* play the last song in "repeat" mode */
playlist_play_order(playlist, pc, playlist_play_order(playlist, pc,
queue_length(&playlist->queue) - 1); playlist->queue.GetLength() - 1);
} else { } else {
/* re-start playing the current song if it's /* re-start playing the current song if it's
the first one */ the first one */
@ -215,13 +211,13 @@ playlist_seek_song(struct playlist *playlist, struct player_control *pc,
unsigned i; unsigned i;
bool success; bool success;
if (!queue_valid_position(&playlist->queue, song)) if (!playlist->queue.IsValidPosition(song))
return PLAYLIST_RESULT_BAD_RANGE; return PLAYLIST_RESULT_BAD_RANGE;
queued = playlist_get_queued_song(playlist); queued = playlist_get_queued_song(playlist);
if (playlist->queue.random) if (playlist->queue.random)
i = queue_position_to_order(&playlist->queue, song); i = playlist->queue.PositionToOrder(song);
else else
i = song; i = song;
@ -240,7 +236,7 @@ playlist_seek_song(struct playlist *playlist, struct player_control *pc,
} }
struct song *the_song = struct song *the_song =
song_dup_detached(queue_get_order(&playlist->queue, i)); song_dup_detached(playlist->queue.GetOrder(i));
success = pc_seek(pc, the_song, seek_time); success = pc_seek(pc, the_song, seek_time);
if (!success) { if (!success) {
playlist_update_queued_song(playlist, pc, queued); playlist_update_queued_song(playlist, pc, queued);
@ -258,7 +254,7 @@ enum playlist_result
playlist_seek_song_id(struct playlist *playlist, struct player_control *pc, playlist_seek_song_id(struct playlist *playlist, struct player_control *pc,
unsigned id, float seek_time) unsigned id, float seek_time)
{ {
int song = queue_id_to_position(&playlist->queue, id); int song = playlist->queue.IdToPosition(id);
if (song < 0) if (song < 0)
return PLAYLIST_RESULT_NO_SUCH_SONG; return PLAYLIST_RESULT_NO_SUCH_SONG;

View File

@ -40,7 +40,7 @@ extern "C" {
static void playlist_increment_version(struct playlist *playlist) static void playlist_increment_version(struct playlist *playlist)
{ {
queue_increment_version(&playlist->queue); playlist->queue.IncrementVersion();
idle_add(IDLE_PLAYLIST); idle_add(IDLE_PLAYLIST);
} }
@ -50,7 +50,7 @@ playlist_clear(struct playlist *playlist, struct player_control *pc)
{ {
playlist_stop(playlist, pc); playlist_stop(playlist, pc);
queue_clear(&playlist->queue); playlist->queue.Clear();
playlist->current = -1; playlist->current = -1;
@ -75,12 +75,12 @@ playlist_append_song(struct playlist *playlist, struct player_control *pc,
const struct song *queued; const struct song *queued;
unsigned id; unsigned id;
if (queue_is_full(&playlist->queue)) if (playlist->queue.IsFull())
return PLAYLIST_RESULT_TOO_LARGE; return PLAYLIST_RESULT_TOO_LARGE;
queued = playlist_get_queued_song(playlist); queued = playlist_get_queued_song(playlist);
id = queue_append(&playlist->queue, song, 0); id = playlist->queue.Append(song, 0);
if (playlist->queue.random) { if (playlist->queue.random) {
/* shuffle the new song into the list of remaining /* shuffle the new song into the list of remaining
@ -91,9 +91,9 @@ playlist_append_song(struct playlist *playlist, struct player_control *pc,
start = playlist->queued + 1; start = playlist->queued + 1;
else else
start = playlist->current + 1; start = playlist->current + 1;
if (start < queue_length(&playlist->queue)) if (start < playlist->queue.GetLength())
queue_shuffle_order_last(&playlist->queue, start, playlist->queue.ShuffleOrderLast(start,
queue_length(&playlist->queue)); playlist->queue.GetLength());
} }
playlist_increment_version(playlist); playlist_increment_version(playlist);
@ -140,23 +140,20 @@ playlist_swap_songs(struct playlist *playlist, struct player_control *pc,
{ {
const struct song *queued; const struct song *queued;
if (!queue_valid_position(&playlist->queue, song1) || if (!playlist->queue.IsValidPosition(song1) ||
!queue_valid_position(&playlist->queue, song2)) !playlist->queue.IsValidPosition(song2))
return PLAYLIST_RESULT_BAD_RANGE; return PLAYLIST_RESULT_BAD_RANGE;
queued = playlist_get_queued_song(playlist); queued = playlist_get_queued_song(playlist);
queue_swap(&playlist->queue, song1, song2); playlist->queue.SwapPositions(song1, song2);
if (playlist->queue.random) { if (playlist->queue.random) {
/* update the queue order, so that playlist->current /* update the queue order, so that playlist->current
still points to the current song order */ still points to the current song order */
queue_swap_order(&playlist->queue, playlist->queue.SwapOrders(playlist->queue.PositionToOrder(song1),
queue_position_to_order(&playlist->queue, playlist->queue.PositionToOrder(song2));
song1),
queue_position_to_order(&playlist->queue,
song2));
} else { } else {
/* correct the "current" song order */ /* correct the "current" song order */
@ -177,8 +174,8 @@ enum playlist_result
playlist_swap_songs_id(struct playlist *playlist, struct player_control *pc, playlist_swap_songs_id(struct playlist *playlist, struct player_control *pc,
unsigned id1, unsigned id2) unsigned id1, unsigned id2)
{ {
int song1 = queue_id_to_position(&playlist->queue, id1); int song1 = playlist->queue.IdToPosition(id1);
int song2 = queue_id_to_position(&playlist->queue, id2); int song2 = playlist->queue.IdToPosition(id2);
if (song1 < 0 || song2 < 0) if (song1 < 0 || song2 < 0)
return PLAYLIST_RESULT_NO_SUCH_SONG; return PLAYLIST_RESULT_NO_SUCH_SONG;
@ -191,11 +188,11 @@ playlist_set_priority(struct playlist *playlist, struct player_control *pc,
unsigned start, unsigned end, unsigned start, unsigned end,
uint8_t priority) uint8_t priority)
{ {
if (start >= queue_length(&playlist->queue)) if (start >= playlist->queue.GetLength())
return PLAYLIST_RESULT_BAD_RANGE; return PLAYLIST_RESULT_BAD_RANGE;
if (end > queue_length(&playlist->queue)) if (end > playlist->queue.GetLength())
end = queue_length(&playlist->queue); end = playlist->queue.GetLength();
if (start >= end) if (start >= end)
return PLAYLIST_RESULT_SUCCESS; return PLAYLIST_RESULT_SUCCESS;
@ -203,24 +200,22 @@ playlist_set_priority(struct playlist *playlist, struct player_control *pc,
/* remember "current" and "queued" */ /* remember "current" and "queued" */
int current_position = playlist->current >= 0 int current_position = playlist->current >= 0
? (int)queue_order_to_position(&playlist->queue, ? (int)playlist->queue.OrderToPosition(playlist->current)
playlist->current)
: -1; : -1;
const struct song *queued = playlist_get_queued_song(playlist); const struct song *queued = playlist_get_queued_song(playlist);
/* apply the priority changes */ /* apply the priority changes */
queue_set_priority_range(&playlist->queue, start, end, priority, playlist->queue.SetPriorityRange(start, end, priority,
playlist->current); playlist->current);
playlist_increment_version(playlist); playlist_increment_version(playlist);
/* restore "current" and choose a new "queued" */ /* restore "current" and choose a new "queued" */
if (current_position >= 0) if (current_position >= 0)
playlist->current = queue_position_to_order(&playlist->queue, playlist->current = playlist->queue.PositionToOrder(current_position);
current_position);
playlist_update_queued_song(playlist, pc, queued); playlist_update_queued_song(playlist, pc, queued);
@ -231,7 +226,7 @@ enum playlist_result
playlist_set_priority_id(struct playlist *playlist, struct player_control *pc, playlist_set_priority_id(struct playlist *playlist, struct player_control *pc,
unsigned song_id, uint8_t priority) unsigned song_id, uint8_t priority)
{ {
int song_position = queue_id_to_position(&playlist->queue, song_id); int song_position = playlist->queue.IdToPosition(song_id);
if (song_position < 0) if (song_position < 0)
return PLAYLIST_RESULT_NO_SUCH_SONG; return PLAYLIST_RESULT_NO_SUCH_SONG;
@ -247,9 +242,9 @@ playlist_delete_internal(struct playlist *playlist, struct player_control *pc,
{ {
unsigned songOrder; unsigned songOrder;
assert(song < queue_length(&playlist->queue)); assert(song < playlist->queue.GetLength());
songOrder = queue_position_to_order(&playlist->queue, song); songOrder = playlist->queue.PositionToOrder(song);
if (playlist->playing && playlist->current == (int)songOrder) { if (playlist->playing && playlist->current == (int)songOrder) {
bool paused = pc_get_state(pc) == PLAYER_STATE_PAUSE; bool paused = pc_get_state(pc) == PLAYER_STATE_PAUSE;
@ -261,8 +256,7 @@ playlist_delete_internal(struct playlist *playlist, struct player_control *pc,
/* see which song is going to be played instead */ /* see which song is going to be played instead */
playlist->current = queue_next_order(&playlist->queue, playlist->current = playlist->queue.GetNextOrder(playlist->current);
playlist->current);
if (playlist->current == (int)songOrder) if (playlist->current == (int)songOrder)
playlist->current = -1; playlist->current = -1;
@ -282,7 +276,7 @@ playlist_delete_internal(struct playlist *playlist, struct player_control *pc,
/* now do it: remove the song */ /* now do it: remove the song */
queue_delete(&playlist->queue, song); playlist->queue.DeletePosition(song);
/* update the "current" and "queued" variables */ /* update the "current" and "queued" variables */
@ -297,7 +291,7 @@ playlist_delete(struct playlist *playlist, struct player_control *pc,
{ {
const struct song *queued; const struct song *queued;
if (song >= queue_length(&playlist->queue)) if (song >= playlist->queue.GetLength())
return PLAYLIST_RESULT_BAD_RANGE; return PLAYLIST_RESULT_BAD_RANGE;
queued = playlist_get_queued_song(playlist); queued = playlist_get_queued_song(playlist);
@ -316,11 +310,11 @@ playlist_delete_range(struct playlist *playlist, struct player_control *pc,
{ {
const struct song *queued; const struct song *queued;
if (start >= queue_length(&playlist->queue)) if (start >= playlist->queue.GetLength())
return PLAYLIST_RESULT_BAD_RANGE; return PLAYLIST_RESULT_BAD_RANGE;
if (end > queue_length(&playlist->queue)) if (end > playlist->queue.GetLength())
end = queue_length(&playlist->queue); end = playlist->queue.GetLength();
if (start >= end) if (start >= end)
return PLAYLIST_RESULT_SUCCESS; return PLAYLIST_RESULT_SUCCESS;
@ -341,7 +335,7 @@ enum playlist_result
playlist_delete_id(struct playlist *playlist, struct player_control *pc, playlist_delete_id(struct playlist *playlist, struct player_control *pc,
unsigned id) unsigned id)
{ {
int song = queue_id_to_position(&playlist->queue, id); int song = playlist->queue.IdToPosition(id);
if (song < 0) if (song < 0)
return PLAYLIST_RESULT_NO_SUCH_SONG; return PLAYLIST_RESULT_NO_SUCH_SONG;
@ -352,8 +346,8 @@ void
playlist_delete_song(struct playlist *playlist, struct player_control *pc, playlist_delete_song(struct playlist *playlist, struct player_control *pc,
const struct song *song) const struct song *song)
{ {
for (int i = queue_length(&playlist->queue) - 1; i >= 0; --i) for (int i = playlist->queue.GetLength() - 1; i >= 0; --i)
if (song == queue_get(&playlist->queue, i)) if (song == playlist->queue.Get(i))
playlist_delete(playlist, pc, i); playlist_delete(playlist, pc, i);
} }
@ -364,12 +358,12 @@ playlist_move_range(struct playlist *playlist, struct player_control *pc,
const struct song *queued; const struct song *queued;
int currentSong; int currentSong;
if (!queue_valid_position(&playlist->queue, start) || if (!playlist->queue.IsValidPosition(start) ||
!queue_valid_position(&playlist->queue, end - 1)) !playlist->queue.IsValidPosition(end - 1))
return PLAYLIST_RESULT_BAD_RANGE; return PLAYLIST_RESULT_BAD_RANGE;
if ((to >= 0 && to + end - start - 1 >= queue_length(&playlist->queue)) || if ((to >= 0 && to + end - start - 1 >= playlist->queue.GetLength()) ||
(to < 0 && abs(to) > (int)queue_length(&playlist->queue))) (to < 0 && abs(to) > (int)playlist->queue.GetLength()))
return PLAYLIST_RESULT_BAD_RANGE; return PLAYLIST_RESULT_BAD_RANGE;
if ((int)start == to) if ((int)start == to)
@ -383,19 +377,18 @@ playlist_move_range(struct playlist *playlist, struct player_control *pc,
* (-playlist.length == to) => move to position BEFORE current song * (-playlist.length == to) => move to position BEFORE current song
*/ */
currentSong = playlist->current >= 0 currentSong = playlist->current >= 0
? (int)queue_order_to_position(&playlist->queue, ? (int)playlist->queue.OrderToPosition(playlist->current)
playlist->current)
: -1; : -1;
if (to < 0 && playlist->current >= 0) { if (to < 0 && playlist->current >= 0) {
if (start <= (unsigned)currentSong && (unsigned)currentSong < end) if (start <= (unsigned)currentSong && (unsigned)currentSong < end)
/* no-op, can't be moved to offset of itself */ /* no-op, can't be moved to offset of itself */
return PLAYLIST_RESULT_SUCCESS; return PLAYLIST_RESULT_SUCCESS;
to = (currentSong + abs(to)) % queue_length(&playlist->queue); to = (currentSong + abs(to)) % playlist->queue.GetLength();
if (start < (unsigned)to) if (start < (unsigned)to)
to--; to--;
} }
queue_move_range(&playlist->queue, start, end, to); playlist->queue.MoveRange(start, end, to);
if (!playlist->queue.random) { if (!playlist->queue.random) {
/* update current/queued */ /* update current/queued */
@ -422,7 +415,7 @@ enum playlist_result
playlist_move_id(struct playlist *playlist, struct player_control *pc, playlist_move_id(struct playlist *playlist, struct player_control *pc,
unsigned id1, int to) unsigned id1, int to)
{ {
int song = queue_id_to_position(&playlist->queue, id1); int song = playlist->queue.IdToPosition(id1);
if (song < 0) if (song < 0)
return PLAYLIST_RESULT_NO_SUCH_SONG; return PLAYLIST_RESULT_NO_SUCH_SONG;
@ -435,9 +428,9 @@ playlist_shuffle(struct playlist *playlist, struct player_control *pc,
{ {
const struct song *queued; const struct song *queued;
if (end > queue_length(&playlist->queue)) if (end > playlist->queue.GetLength())
/* correct the "end" offset */ /* correct the "end" offset */
end = queue_length(&playlist->queue); end = playlist->queue.GetLength();
if ((start+1) >= end) if ((start+1) >= end)
/* needs at least two entries. */ /* needs at least two entries. */
@ -446,17 +439,16 @@ playlist_shuffle(struct playlist *playlist, struct player_control *pc,
queued = playlist_get_queued_song(playlist); queued = playlist_get_queued_song(playlist);
if (playlist->playing && playlist->current >= 0) { if (playlist->playing && playlist->current >= 0) {
unsigned current_position; unsigned current_position;
current_position = queue_order_to_position(&playlist->queue, current_position = playlist->queue.OrderToPosition(playlist->current);
playlist->current);
if (current_position >= start && current_position < end) if (current_position >= start && current_position < end)
{ {
/* put current playing song first */ /* put current playing song first */
queue_swap(&playlist->queue, start, current_position); playlist->queue.SwapPositions(start, current_position);
if (playlist->queue.random) { if (playlist->queue.random) {
playlist->current = playlist->current =
queue_position_to_order(&playlist->queue, start); playlist->queue.PositionToOrder(start);
} else } else
playlist->current = start; playlist->current = start;
@ -469,7 +461,7 @@ playlist_shuffle(struct playlist *playlist, struct player_control *pc,
playlist->current = -1; playlist->current = -1;
} }
queue_shuffle_range(&playlist->queue, start, end); playlist->queue.ShuffleRange(start, end);
playlist_increment_version(playlist); playlist_increment_version(playlist);

View File

@ -41,7 +41,7 @@ playlist_print_uris(Client *client, const struct playlist *playlist)
{ {
const struct queue *queue = &playlist->queue; const struct queue *queue = &playlist->queue;
queue_print_uris(client, queue, 0, queue_length(queue)); queue_print_uris(client, queue, 0, queue->GetLength());
} }
bool bool
@ -50,9 +50,9 @@ playlist_print_info(Client *client, const struct playlist *playlist,
{ {
const struct queue *queue = &playlist->queue; const struct queue *queue = &playlist->queue;
if (end > queue_length(queue)) if (end > queue->GetLength())
/* correct the "end" offset */ /* correct the "end" offset */
end = queue_length(queue); end = queue->GetLength();
if (start > end) if (start > end)
/* an invalid "start" offset is fatal */ /* an invalid "start" offset is fatal */
@ -69,7 +69,7 @@ playlist_print_id(Client *client, const struct playlist *playlist,
const struct queue *queue = &playlist->queue; const struct queue *queue = &playlist->queue;
int position; int position;
position = queue_id_to_position(queue, id); position = queue->IdToPosition(id);
if (position < 0) if (position < 0)
/* no such song */ /* no such song */
return false; return false;

View File

@ -98,8 +98,8 @@ spl_save_queue(const char *name_utf8, const struct queue *queue)
if (file == NULL) if (file == NULL)
return PLAYLIST_RESULT_ERRNO; return PLAYLIST_RESULT_ERRNO;
for (unsigned i = 0; i < queue_length(queue); i++) for (unsigned i = 0; i < queue->GetLength(); i++)
playlist_print_song(file, queue_get(queue, i)); playlist_print_song(file, queue->Get(i));
fclose(file); fclose(file);

View File

@ -74,8 +74,7 @@ playlist_state_save(FILE *fp, const struct playlist *playlist,
fputs(PLAYLIST_STATE_FILE_STATE_PLAY "\n", fp); fputs(PLAYLIST_STATE_FILE_STATE_PLAY "\n", fp);
} }
fprintf(fp, PLAYLIST_STATE_FILE_CURRENT "%i\n", fprintf(fp, PLAYLIST_STATE_FILE_CURRENT "%i\n",
queue_order_to_position(&playlist->queue, playlist->queue.OrderToPosition(playlist->current));
playlist->current));
fprintf(fp, PLAYLIST_STATE_FILE_TIME "%i\n", fprintf(fp, PLAYLIST_STATE_FILE_TIME "%i\n",
(int)player_status.elapsed_time); (int)player_status.elapsed_time);
} else { } else {
@ -83,8 +82,7 @@ playlist_state_save(FILE *fp, const struct playlist *playlist,
if (playlist->current >= 0) if (playlist->current >= 0)
fprintf(fp, PLAYLIST_STATE_FILE_CURRENT "%i\n", fprintf(fp, PLAYLIST_STATE_FILE_CURRENT "%i\n",
queue_order_to_position(&playlist->queue, playlist->queue.OrderToPosition(playlist->current));
playlist->current));
} }
fprintf(fp, PLAYLIST_STATE_FILE_RANDOM "%i\n", playlist->queue.random); fprintf(fp, PLAYLIST_STATE_FILE_RANDOM "%i\n", playlist->queue.random);
@ -123,7 +121,7 @@ playlist_state_load(TextFile &file, struct playlist *playlist)
} }
} }
queue_increment_version(&playlist->queue); playlist->queue.IncrementVersion();
} }
bool bool
@ -195,8 +193,8 @@ playlist_state_restore(const char *line, TextFile &file,
playlist_set_random(playlist, pc, random_mode); playlist_set_random(playlist, pc, random_mode);
if (!queue_is_empty(&playlist->queue)) { if (!playlist->queue.IsEmpty()) {
if (!queue_valid_position(&playlist->queue, current)) if (!playlist->queue.IsValidPosition(current))
current = 0; current = 0;
if (state == PLAYER_STATE_PLAY && if (state == PLAYER_STATE_PLAY &&
@ -239,8 +237,7 @@ playlist_state_get_hash(const struct playlist *playlist,
? ((int)player_status.elapsed_time << 8) ? ((int)player_status.elapsed_time << 8)
: 0) ^ : 0) ^
(playlist->current >= 0 (playlist->current >= 0
? (queue_order_to_position(&playlist->queue, ? (playlist->queue.OrderToPosition(playlist->current) << 16)
playlist->current) << 16)
: 0) ^ : 0) ^
((int)pc_get_cross_fade(pc) << 20) ^ ((int)pc_get_cross_fade(pc) << 20) ^
(player_status.state << 24) ^ (player_status.state << 24) ^

View File

@ -23,283 +23,6 @@
#include <stdlib.h> #include <stdlib.h>
/**
* Generate a non-existing id number.
*/
static unsigned
queue_generate_id(const struct queue *queue)
{
static unsigned cur = (unsigned)-1;
do {
cur++;
if (cur >= queue->max_length * QUEUE_HASH_MULT)
cur = 0;
} while (queue->id_to_position[cur] != -1);
return cur;
}
int
queue_next_order(const struct queue *queue, unsigned order)
{
assert(order < queue->length);
if (queue->single && queue->repeat && !queue->consume)
return order;
else if (order + 1 < queue->length)
return order + 1;
else if (queue->repeat && (order > 0 || !queue->consume))
/* restart at first song */
return 0;
else
/* end of queue */
return -1;
}
void
queue_increment_version(struct queue *queue)
{
static unsigned long max = ((uint32_t) 1 << 31) - 1;
queue->version++;
if (queue->version >= max) {
for (unsigned i = 0; i < queue->length; i++)
queue->items[i].version = 0;
queue->version = 1;
}
}
void
queue_modify(struct queue *queue, unsigned order)
{
unsigned position;
assert(order < queue->length);
position = queue->order[order];
queue->items[position].version = queue->version;
queue_increment_version(queue);
}
void
queue_modify_all(struct queue *queue)
{
for (unsigned i = 0; i < queue->length; i++)
queue->items[i].version = queue->version;
queue_increment_version(queue);
}
unsigned
queue_append(struct queue *queue, struct song *song, uint8_t priority)
{
unsigned id = queue_generate_id(queue);
assert(!queue_is_full(queue));
auto &item = queue->items[queue->length];
item.song = song_dup_detached(song);
item.id = id;
item.version = queue->version;
item.priority = priority;
queue->order[queue->length] = queue->length;
queue->id_to_position[id] = queue->length;
++queue->length;
return id;
}
void
queue_swap(struct queue *queue, unsigned position1, unsigned position2)
{
struct queue_item tmp;
unsigned id1 = queue->items[position1].id;
unsigned id2 = queue->items[position2].id;
tmp = queue->items[position1];
queue->items[position1] = queue->items[position2];
queue->items[position2] = tmp;
queue->items[position1].version = queue->version;
queue->items[position2].version = queue->version;
queue->id_to_position[id1] = position2;
queue->id_to_position[id2] = position1;
}
static void
queue_move_song_to(struct queue *queue, unsigned from, unsigned to)
{
unsigned from_id = queue->items[from].id;
queue->items[to] = queue->items[from];
queue->items[to].version = queue->version;
queue->id_to_position[from_id] = to;
}
void
queue_move(struct queue *queue, unsigned from, unsigned to)
{
struct queue_item item = queue->items[from];
/* move songs to one less in from->to */
for (unsigned i = from; i < to; i++)
queue_move_song_to(queue, i + 1, i);
/* move songs to one more in to->from */
for (unsigned i = from; i > to; i--)
queue_move_song_to(queue, i - 1, i);
/* put song at _to_ */
queue->id_to_position[item.id] = to;
queue->items[to] = item;
queue->items[to].version = queue->version;
/* now deal with order */
if (queue->random) {
for (unsigned i = 0; i < queue->length; i++) {
if (queue->order[i] > from && queue->order[i] <= to)
queue->order[i]--;
else if (queue->order[i] < from &&
queue->order[i] >= to)
queue->order[i]++;
else if (from == queue->order[i])
queue->order[i] = to;
}
}
}
void
queue_move_range(struct queue *queue, unsigned start, unsigned end, unsigned to)
{
struct queue_item items[end - start];
// Copy the original block [start,end-1]
for (unsigned i = start; i < end; i++)
items[i - start] = queue->items[i];
// If to > start, we need to move to-start items to start, starting from end
for (unsigned i = end; i < end + to - start; i++)
queue_move_song_to(queue, i, start + i - end);
// If to < start, we need to move start-to items to newend (= end + to - start), starting from to
// This is the same as moving items from start-1 to to (decreasing), with start-1 going to end-1
// We have to iterate in this order to avoid writing over something we haven't yet moved
for (unsigned i = start - 1; i >= to && i != G_MAXUINT; i--)
queue_move_song_to(queue, i, i + end - start);
// Copy the original block back in, starting at to.
for (unsigned i = start; i< end; i++)
{
queue->id_to_position[items[i-start].id] = to + i - start;
queue->items[to + i - start] = items[i-start];
queue->items[to + i - start].version = queue->version;
}
if (queue->random) {
// Update the positions in the queue.
// Note that the ranges for these cases are the same as the ranges of
// the loops above.
for (unsigned i = 0; i < queue->length; i++) {
if (queue->order[i] >= end && queue->order[i] < to + end - start)
queue->order[i] -= end - start;
else if (queue->order[i] < start &&
queue->order[i] >= to)
queue->order[i] += end - start;
else if (start <= queue->order[i] && queue->order[i] < end)
queue->order[i] += to - start;
}
}
}
/**
* Moves a song to a new position in the "order" list.
*/
static void
queue_move_order(struct queue *queue, unsigned from_order, unsigned to_order)
{
assert(queue != NULL);
assert(from_order < queue->length);
assert(to_order <= queue->length);
const unsigned from_position =
queue_order_to_position(queue, from_order);
if (from_order < to_order) {
for (unsigned i = from_order; i < to_order; ++i)
queue->order[i] = queue->order[i + 1];
} else {
for (unsigned i = from_order; i > to_order; --i)
queue->order[i] = queue->order[i - 1];
}
queue->order[to_order] = from_position;
}
void
queue_delete(struct queue *queue, unsigned position)
{
struct song *song;
unsigned id, order;
assert(position < queue->length);
song = queue_get(queue, position);
assert(!song_in_database(song) || song_is_detached(song));
song_free(song);
id = queue_position_to_id(queue, position);
order = queue_position_to_order(queue, position);
--queue->length;
/* release the song id */
queue->id_to_position[id] = -1;
/* delete song from songs array */
for (unsigned i = position; i < queue->length; i++)
queue_move_song_to(queue, i + 1, i);
/* delete the entry from the order array */
for (unsigned i = order; i < queue->length; i++)
queue->order[i] = queue->order[i + 1];
/* readjust values in the order array */
for (unsigned i = 0; i < queue->length; i++)
if (queue->order[i] > position)
--queue->order[i];
}
void
queue_clear(struct queue *queue)
{
for (unsigned i = 0; i < queue->length; i++) {
struct queue_item *item = &queue->items[i];
assert(!song_in_database(item->song) ||
song_is_detached(item->song));
song_free(item->song);
queue->id_to_position[item->id] = -1;
}
queue->length = 0;
}
queue::queue(unsigned _max_length) queue::queue(unsigned _max_length)
:max_length(_max_length), length(0), :max_length(_max_length), length(0),
version(1), version(1),
@ -319,7 +42,7 @@ queue::queue(unsigned _max_length)
queue::~queue() queue::~queue()
{ {
queue_clear(this); Clear();
g_free(items); g_free(items);
g_free(order); g_free(order);
@ -328,6 +51,277 @@ queue::~queue()
g_rand_free(rand); g_rand_free(rand);
} }
/**
* Generate a non-existing id number.
*/
static unsigned
queue_generate_id(const struct queue *queue)
{
static unsigned cur = (unsigned)-1;
do {
cur++;
if (cur >= queue->max_length * QUEUE_HASH_MULT)
cur = 0;
} while (queue->id_to_position[cur] != -1);
return cur;
}
int
queue::GetNextOrder(unsigned _order) const
{
assert(_order < length);
if (single && repeat && !consume)
return _order;
else if (_order + 1 < length)
return _order + 1;
else if (repeat && (_order > 0 || !consume))
/* restart at first song */
return 0;
else
/* end of queue */
return -1;
}
void
queue::IncrementVersion()
{
static unsigned long max = ((uint32_t) 1 << 31) - 1;
version++;
if (version >= max) {
for (unsigned i = 0; i < length; i++)
items[i].version = 0;
version = 1;
}
}
void
queue::ModifyAtOrder(unsigned _order)
{
assert(_order < length);
unsigned position = order[_order];
items[position].version = version;
IncrementVersion();
}
void
queue::ModifyAll()
{
for (unsigned i = 0; i < length; i++)
items[i].version = version;
IncrementVersion();
}
unsigned
queue::Append(struct song *song, uint8_t priority)
{
unsigned id = queue_generate_id(this);
assert(!IsFull());
auto &item = items[length];
item.song = song_dup_detached(song);
item.id = id;
item.version = version;
item.priority = priority;
order[length] = length;
id_to_position[id] = length;
++length;
return id;
}
void
queue::SwapPositions(unsigned position1, unsigned position2)
{
struct queue_item tmp;
unsigned id1 = items[position1].id;
unsigned id2 = items[position2].id;
tmp = items[position1];
items[position1] = items[position2];
items[position2] = tmp;
items[position1].version = version;
items[position2].version = version;
id_to_position[id1] = position2;
id_to_position[id2] = position1;
}
static void
queue_move_song_to(struct queue *queue, unsigned from, unsigned to)
{
unsigned from_id = queue->items[from].id;
queue->items[to] = queue->items[from];
queue->items[to].version = queue->version;
queue->id_to_position[from_id] = to;
}
void
queue::MovePostion(unsigned from, unsigned to)
{
struct queue_item item = items[from];
/* move songs to one less in from->to */
for (unsigned i = from; i < to; i++)
queue_move_song_to(this, i + 1, i);
/* move songs to one more in to->from */
for (unsigned i = from; i > to; i--)
queue_move_song_to(this, i - 1, i);
/* put song at _to_ */
id_to_position[item.id] = to;
items[to] = item;
items[to].version = version;
/* now deal with order */
if (random) {
for (unsigned i = 0; i < length; i++) {
if (order[i] > from && order[i] <= to)
order[i]--;
else if (order[i] < from &&
order[i] >= to)
order[i]++;
else if (from == order[i])
order[i] = to;
}
}
}
void
queue::MoveRange(unsigned start, unsigned end, unsigned to)
{
struct queue_item tmp[end - start];
// Copy the original block [start,end-1]
for (unsigned i = start; i < end; i++)
tmp[i - start] = items[i];
// If to > start, we need to move to-start items to start, starting from end
for (unsigned i = end; i < end + to - start; i++)
queue_move_song_to(this, i, start + i - end);
// If to < start, we need to move start-to items to newend (= end + to - start), starting from to
// This is the same as moving items from start-1 to to (decreasing), with start-1 going to end-1
// We have to iterate in this order to avoid writing over something we haven't yet moved
for (unsigned i = start - 1; i >= to && i != G_MAXUINT; i--)
queue_move_song_to(this, i, i + end - start);
// Copy the original block back in, starting at to.
for (unsigned i = start; i< end; i++)
{
id_to_position[tmp[i-start].id] = to + i - start;
items[to + i - start] = tmp[i-start];
items[to + i - start].version = version;
}
if (random) {
// Update the positions in the queue.
// Note that the ranges for these cases are the same as the ranges of
// the loops above.
for (unsigned i = 0; i < length; i++) {
if (order[i] >= end && order[i] < to + end - start)
order[i] -= end - start;
else if (order[i] < start &&
order[i] >= to)
order[i] += end - start;
else if (start <= order[i] && order[i] < end)
order[i] += to - start;
}
}
}
/**
* Moves a song to a new position in the "order" list.
*/
static void
queue_move_order(struct queue *queue, unsigned from_order, unsigned to_order)
{
assert(queue != NULL);
assert(from_order < queue->length);
assert(to_order <= queue->length);
const unsigned from_position = queue->OrderToPosition(from_order);
if (from_order < to_order) {
for (unsigned i = from_order; i < to_order; ++i)
queue->order[i] = queue->order[i + 1];
} else {
for (unsigned i = from_order; i > to_order; --i)
queue->order[i] = queue->order[i - 1];
}
queue->order[to_order] = from_position;
}
void
queue::DeletePosition(unsigned position)
{
assert(position < length);
struct song *song = Get(position);
assert(!song_in_database(song) || song_is_detached(song));
song_free(song);
const unsigned id = PositionToId(position);
const unsigned _order = PositionToOrder(position);
--length;
/* release the song id */
id_to_position[id] = -1;
/* delete song from songs array */
for (unsigned i = position; i < length; i++)
queue_move_song_to(this, i + 1, i);
/* delete the entry from the order array */
for (unsigned i = _order; i < length; i++)
order[i] = order[i + 1];
/* readjust values in the order array */
for (unsigned i = 0; i < length; i++)
if (order[i] > position)
--order[i];
}
void
queue::Clear()
{
for (unsigned i = 0; i < length; i++) {
struct queue_item *item = &items[i];
assert(!song_in_database(item->song) ||
song_is_detached(item->song));
song_free(item->song);
id_to_position[item->id] = -1;
}
length = 0;
}
static const struct queue_item * static const struct queue_item *
queue_get_order_item_const(const struct queue *queue, unsigned order) queue_get_order_item_const(const struct queue *queue, unsigned order)
{ {
@ -390,8 +384,7 @@ queue_shuffle_order_range(struct queue *queue, unsigned start, unsigned end)
assert(end <= queue->length); assert(end <= queue->length);
for (unsigned i = start; i < end; ++i) for (unsigned i = start; i < end; ++i)
queue_swap_order(queue, i, queue->SwapOrders(i, g_rand_int_range(queue->rand, i, end));
g_rand_int_range(queue->rand, i, end));
} }
/** /**
@ -399,70 +392,66 @@ queue_shuffle_order_range(struct queue *queue, unsigned start, unsigned end)
* priority group. * priority group.
*/ */
void void
queue_shuffle_order_range_with_priority(struct queue *queue, queue::ShuffleOrderRangeWithPriority(unsigned start, unsigned end)
unsigned start, unsigned end)
{ {
assert(queue != NULL); assert(random);
assert(queue->random);
assert(start <= end); assert(start <= end);
assert(end <= queue->length); assert(end <= length);
if (start == end) if (start == end)
return; return;
/* first group the range by priority */ /* first group the range by priority */
queue_sort_order_by_priority(queue, start, end); queue_sort_order_by_priority(this, start, end);
/* now shuffle each priority group */ /* now shuffle each priority group */
unsigned group_start = start; unsigned group_start = start;
uint8_t group_priority = queue_get_order_priority(queue, start); uint8_t group_priority = queue_get_order_priority(this, start);
for (unsigned i = start + 1; i < end; ++i) { for (unsigned i = start + 1; i < end; ++i) {
uint8_t priority = queue_get_order_priority(queue, i); uint8_t priority = queue_get_order_priority(this, i);
assert(priority <= group_priority); assert(priority <= group_priority);
if (priority != group_priority) { if (priority != group_priority) {
/* start of a new group - shuffle the one that /* start of a new group - shuffle the one that
has just ended */ has just ended */
queue_shuffle_order_range(queue, group_start, i); queue_shuffle_order_range(this, group_start, i);
group_start = i; group_start = i;
group_priority = priority; group_priority = priority;
} }
} }
/* shuffle the last group */ /* shuffle the last group */
queue_shuffle_order_range(queue, group_start, end); queue_shuffle_order_range(this, group_start, end);
} }
void void
queue_shuffle_order(struct queue *queue) queue::ShuffleOrder()
{ {
queue_shuffle_order_range_with_priority(queue, 0, queue->length); ShuffleOrderRangeWithPriority(0, length);
} }
static void static void
queue_shuffle_order_first(struct queue *queue, unsigned start, unsigned end) queue_shuffle_order_first(struct queue *queue, unsigned start, unsigned end)
{ {
queue_swap_order(queue, start, queue->SwapOrders(start, g_rand_int_range(queue->rand, start, end));
g_rand_int_range(queue->rand, start, end));
} }
void void
queue_shuffle_order_last(struct queue *queue, unsigned start, unsigned end) queue::ShuffleOrderLast(unsigned start, unsigned end)
{ {
queue_swap_order(queue, end - 1, SwapOrders(end - 1, g_rand_int_range(rand, start, end));
g_rand_int_range(queue->rand, start, end));
} }
void void
queue_shuffle_range(struct queue *queue, unsigned start, unsigned end) queue::ShuffleRange(unsigned start, unsigned end)
{ {
assert(start <= end); assert(start <= end);
assert(end <= queue->length); assert(end <= length);
for (unsigned i = start; i < end; i++) { for (unsigned i = start; i < end; i++) {
unsigned ri = g_rand_int_range(queue->rand, i, end); unsigned ri = g_rand_int_range(rand, i, end);
queue_swap(queue, i, ri); SwapPositions(i, ri);
} }
} }
@ -479,7 +468,7 @@ queue_find_priority_order(const struct queue *queue, unsigned start_order,
assert(start_order <= queue->length); assert(start_order <= queue->length);
for (unsigned order = start_order; order < queue->length; ++order) { for (unsigned order = start_order; order < queue->length; ++order) {
const unsigned position = queue_order_to_position(queue, order); const unsigned position = queue->OrderToPosition(order);
const struct queue_item *item = &queue->items[position]; const struct queue_item *item = &queue->items[position];
if (item->priority <= priority && order != exclude_order) if (item->priority <= priority && order != exclude_order)
return order; return order;
@ -498,7 +487,7 @@ queue_count_same_priority(const struct queue *queue, unsigned start_order,
assert(start_order <= queue->length); assert(start_order <= queue->length);
for (unsigned order = start_order; order < queue->length; ++order) { for (unsigned order = start_order; order < queue->length; ++order) {
const unsigned position = queue_order_to_position(queue, order); const unsigned position = queue->OrderToPosition(order);
const struct queue_item *item = &queue->items[position]; const struct queue_item *item = &queue->items[position];
if (item->priority != priority) if (item->priority != priority)
return order - start_order; return order - start_order;
@ -508,39 +497,37 @@ queue_count_same_priority(const struct queue *queue, unsigned start_order,
} }
bool bool
queue_set_priority(struct queue *queue, unsigned position, uint8_t priority, queue::SetPriority(unsigned position, uint8_t priority, int after_order)
int after_order)
{ {
assert(queue != NULL); assert(position < length);
assert(position < queue->length);
struct queue_item *item = &queue->items[position]; struct queue_item *item = &items[position];
uint8_t old_priority = item->priority; uint8_t old_priority = item->priority;
if (old_priority == priority) if (old_priority == priority)
return false; return false;
item->version = queue->version; item->version = version;
item->priority = priority; item->priority = priority;
if (!queue->random) if (!random)
/* don't reorder if not in random mode */ /* don't reorder if not in random mode */
return true; return true;
unsigned order = queue_position_to_order(queue, position); unsigned _order = PositionToOrder(position);
if (after_order >= 0) { if (after_order >= 0) {
if (order == (unsigned)after_order) if (_order == (unsigned)after_order)
/* don't reorder the current song */ /* don't reorder the current song */
return true; return true;
if (order < (unsigned)after_order) { if (_order < (unsigned)after_order) {
/* the specified song has been played already /* the specified song has been played already
- enqueue it only if its priority has just - enqueue it only if its priority has just
become bigger than the current one's */ become bigger than the current one's */
const unsigned after_position = const unsigned after_position =
queue_order_to_position(queue, after_order); OrderToPosition(after_order);
const struct queue_item *after_item = const struct queue_item *after_item =
&queue->items[after_position]; &items[after_position];
if (old_priority > after_item->priority || if (old_priority > after_item->priority ||
priority <= after_item->priority) priority <= after_item->priority)
/* priority hasn't become bigger */ /* priority hasn't become bigger */
@ -552,44 +539,41 @@ queue_set_priority(struct queue *queue, unsigned position, uint8_t priority,
create a new priority group) */ create a new priority group) */
const unsigned before_order = const unsigned before_order =
queue_find_priority_order(queue, after_order + 1, priority, queue_find_priority_order(this, after_order + 1, priority,
order); _order);
const unsigned new_order = before_order > order const unsigned new_order = before_order > _order
? before_order - 1 ? before_order - 1
: before_order; : before_order;
queue_move_order(queue, order, new_order); queue_move_order(this, _order, new_order);
/* shuffle the song within that priority group */ /* shuffle the song within that priority group */
const unsigned priority_count = const unsigned priority_count =
queue_count_same_priority(queue, new_order, priority); queue_count_same_priority(this, new_order, priority);
assert(priority_count >= 1); assert(priority_count >= 1);
queue_shuffle_order_first(queue, new_order, queue_shuffle_order_first(this, new_order,
new_order + priority_count); new_order + priority_count);
return true; return true;
} }
bool bool
queue_set_priority_range(struct queue *queue, queue::SetPriorityRange(unsigned start_position, unsigned end_position,
unsigned start_position, unsigned end_position, uint8_t priority, int after_order)
uint8_t priority, int after_order)
{ {
assert(queue != NULL);
assert(start_position <= end_position); assert(start_position <= end_position);
assert(end_position <= queue->length); assert(end_position <= length);
bool modified = false; bool modified = false;
int after_position = after_order >= 0 int after_position = after_order >= 0
? (int)queue_order_to_position(queue, after_order) ? (int)OrderToPosition(after_order)
: -1; : -1;
for (unsigned i = start_position; i < end_position; ++i) { for (unsigned i = start_position; i < end_position; ++i) {
after_order = after_position >= 0 after_order = after_position >= 0
? (int)queue_position_to_order(queue, after_position) ? (int)PositionToOrder(after_position)
: -1; : -1;
modified |= queue_set_priority(queue, i, priority, modified |= SetPriority(i, priority, after_order);
after_order);
} }
return modified; return modified;

View File

@ -20,10 +20,11 @@
#ifndef MPD_QUEUE_HXX #ifndef MPD_QUEUE_HXX
#define MPD_QUEUE_HXX #define MPD_QUEUE_HXX
#include "gcc.h"
#include <glib.h> #include <glib.h>
#include <assert.h> #include <assert.h>
#include <stdbool.h>
#include <stdint.h> #include <stdint.h>
enum { enum {
@ -110,268 +111,222 @@ struct queue {
queue(const queue &other) = delete; queue(const queue &other) = delete;
queue &operator=(const queue &other) = delete; queue &operator=(const queue &other) = delete;
unsigned GetLength() const {
assert(length <= max_length);
return length;
}
/**
* Determine if the queue is empty, i.e. there are no songs.
*/
bool IsEmpty() const {
return length == 0;
}
/**
* Determine if the maximum number of songs has been reached.
*/
bool IsFull() const {
assert(length <= max_length);
return length >= max_length;
}
/**
* Is that a valid position number?
*/
bool IsValidPosition(unsigned position) const {
return position < length;
}
/**
* Is that a valid order number?
*/
bool IsValidOrder(unsigned _order) const {
return _order < length;
}
int IdToPosition(unsigned id) const {
if (id >= max_length * QUEUE_HASH_MULT)
return -1;
assert(id_to_position[id] >= -1);
assert(id_to_position[id] < (int)length);
return id_to_position[id];
}
int PositionToId(unsigned position) const
{
assert(position < length);
return items[position].id;
}
gcc_pure
unsigned OrderToPosition(unsigned _order) const {
assert(_order < length);
return order[_order];
}
gcc_pure
unsigned PositionToOrder(unsigned position) const {
assert(position < length);
for (unsigned i = 0;; ++i) {
assert(i < length);
if (order[i] == position)
return i;
}
}
G_GNUC_PURE
uint8_t GetPriorityAtPosition(unsigned position) const {
assert(position < length);
return items[position].priority;
}
/**
* Returns the song at the specified position.
*/
struct song *Get(unsigned position) const {
assert(position < length);
return items[position].song;
}
/**
* Returns the song at the specified order number.
*/
struct song *GetOrder(unsigned _order) const {
return Get(OrderToPosition(_order));
}
/**
* Is the song at the specified position newer than the specified
* version?
*/
bool IsNewerAtPosition(unsigned position, uint32_t _version) const {
assert(position < length);
return _version > version ||
items[position].version >= _version ||
items[position].version == 0;
}
/**
* Returns the order number following the specified one. This takes
* end of queue and "repeat" mode into account.
*
* @return the next order number, or -1 to stop playback
*/
gcc_pure
int GetNextOrder(unsigned order) const;
/**
* Increments the queue's version number. This handles integer
* overflow well.
*/
void IncrementVersion();
/**
* Marks the specified song as "modified" and increments the version
* number.
*/
void ModifyAtOrder(unsigned order);
/**
* Marks all songs as "modified" and increments the version number.
*/
void ModifyAll();
/**
* Appends a song to the queue and returns its position. Prior to
* that, the caller must check if the queue is already full.
*
* If a song is not in the database (determined by
* song_in_database()), it is freed when removed from the queue.
*
* @param priority the priority of this new queue item
*/
unsigned Append(struct song *song, uint8_t priority);
/**
* Swaps two songs, addressed by their position.
*/
void SwapPositions(unsigned position1, unsigned position2);
/**
* Swaps two songs, addressed by their order number.
*/
void SwapOrders(unsigned order1, unsigned order2) {
unsigned tmp = order[order1];
order[order1] = order[order2];
order[order2] = tmp;
}
/**
* Moves a song to a new position.
*/
void MovePostion(unsigned from, unsigned to);
/**
* Moves a range of songs to a new position.
*/
void MoveRange(unsigned start, unsigned end, unsigned to);
/**
* Removes a song from the playlist.
*/
void DeletePosition(unsigned position);
/**
* Removes all songs from the playlist.
*/
void Clear();
/**
* Initializes the "order" array, and restores "normal" order.
*/
void RestoreOrder() {
for (unsigned i = 0; i < length; ++i)
order[i] = i;
}
/**
* Shuffle the order of items in the specified range, taking their
* priorities into account.
*/
void ShuffleOrderRangeWithPriority(unsigned start, unsigned end);
/**
* Shuffles the virtual order of songs, but does not move them
* physically. This is used in random mode.
*/
void ShuffleOrder();
/**
* Shuffles the virtual order of the last song in the specified
* (order) range. This is used in random mode after a song has been
* appended by queue_append().
*/
void ShuffleOrderLast(unsigned start, unsigned end);
/**
* Shuffles a (position) range in the queue. The songs are physically
* shuffled, not by using the "order" mapping.
*/
void ShuffleRange(unsigned start, unsigned end);
bool SetPriority(unsigned position, uint8_t priority, int after_order);
bool SetPriorityRange(unsigned start_position, unsigned end_position,
uint8_t priority, int after_order);
}; };
static inline unsigned
queue_length(const struct queue *queue)
{
assert(queue->length <= queue->max_length);
return queue->length;
}
/**
* Determine if the queue is empty, i.e. there are no songs.
*/
static inline bool
queue_is_empty(const struct queue *queue)
{
return queue->length == 0;
}
/**
* Determine if the maximum number of songs has been reached.
*/
static inline bool
queue_is_full(const struct queue *queue)
{
assert(queue->length <= queue->max_length);
return queue->length >= queue->max_length;
}
/**
* Is that a valid position number?
*/
static inline bool
queue_valid_position(const struct queue *queue, unsigned position)
{
return position < queue->length;
}
/**
* Is that a valid order number?
*/
static inline bool
queue_valid_order(const struct queue *queue, unsigned order)
{
return order < queue->length;
}
static inline int
queue_id_to_position(const struct queue *queue, unsigned id)
{
if (id >= queue->max_length * QUEUE_HASH_MULT)
return -1;
assert(queue->id_to_position[id] >= -1);
assert(queue->id_to_position[id] < (int)queue->length);
return queue->id_to_position[id];
}
static inline int
queue_position_to_id(const struct queue *queue, unsigned position)
{
assert(position < queue->length);
return queue->items[position].id;
}
static inline unsigned
queue_order_to_position(const struct queue *queue, unsigned order)
{
assert(order < queue->length);
return queue->order[order];
}
static inline unsigned
queue_position_to_order(const struct queue *queue, unsigned position)
{
assert(position < queue->length);
for (unsigned i = 0;; ++i) {
assert(i < queue->length);
if (queue->order[i] == position)
return i;
}
}
G_GNUC_PURE
static inline uint8_t
queue_get_priority_at_position(const struct queue *queue, unsigned position)
{
assert(position < queue->length);
return queue->items[position].priority;
}
/**
* Returns the song at the specified position.
*/
static inline struct song *
queue_get(const struct queue *queue, unsigned position)
{
assert(position < queue->length);
return queue->items[position].song;
}
/**
* Returns the song at the specified order number.
*/
static inline struct song *
queue_get_order(const struct queue *queue, unsigned order)
{
return queue_get(queue, queue_order_to_position(queue, order));
}
/**
* Is the song at the specified position newer than the specified
* version?
*/
static inline bool
queue_song_newer(const struct queue *queue, unsigned position,
uint32_t version)
{
assert(position < queue->length);
return version > queue->version ||
queue->items[position].version >= version ||
queue->items[position].version == 0;
}
/**
* Returns the order number following the specified one. This takes
* end of queue and "repeat" mode into account.
*
* @return the next order number, or -1 to stop playback
*/
int
queue_next_order(const struct queue *queue, unsigned order);
/**
* Increments the queue's version number. This handles integer
* overflow well.
*/
void
queue_increment_version(struct queue *queue);
/**
* Marks the specified song as "modified" and increments the version
* number.
*/
void
queue_modify(struct queue *queue, unsigned order);
/**
* Marks all songs as "modified" and increments the version number.
*/
void
queue_modify_all(struct queue *queue);
/**
* Appends a song to the queue and returns its position. Prior to
* that, the caller must check if the queue is already full.
*
* If a song is not in the database (determined by
* song_in_database()), it is freed when removed from the queue.
*
* @param priority the priority of this new queue item
*/
unsigned
queue_append(struct queue *queue, struct song *song, uint8_t priority);
/**
* Swaps two songs, addressed by their position.
*/
void
queue_swap(struct queue *queue, unsigned position1, unsigned position2);
/**
* Swaps two songs, addressed by their order number.
*/
static inline void
queue_swap_order(struct queue *queue, unsigned order1, unsigned order2)
{
unsigned tmp = queue->order[order1];
queue->order[order1] = queue->order[order2];
queue->order[order2] = tmp;
}
/**
* Moves a song to a new position.
*/
void
queue_move(struct queue *queue, unsigned from, unsigned to);
/**
* Moves a range of songs to a new position.
*/
void
queue_move_range(struct queue *queue, unsigned start, unsigned end, unsigned to);
/**
* Removes a song from the playlist.
*/
void
queue_delete(struct queue *queue, unsigned position);
/**
* Removes all songs from the playlist.
*/
void
queue_clear(struct queue *queue);
/**
* Initializes the "order" array, and restores "normal" order.
*/
static inline void
queue_restore_order(struct queue *queue)
{
for (unsigned i = 0; i < queue->length; ++i)
queue->order[i] = i;
}
/**
* Shuffle the order of items in the specified range, taking their
* priorities into account.
*/
void
queue_shuffle_order_range_with_priority(struct queue *queue,
unsigned start, unsigned end);
/**
* Shuffles the virtual order of songs, but does not move them
* physically. This is used in random mode.
*/
void
queue_shuffle_order(struct queue *queue);
/**
* Shuffles the virtual order of the last song in the specified
* (order) range. This is used in random mode after a song has been
* appended by queue_append().
*/
void
queue_shuffle_order_last(struct queue *queue, unsigned start, unsigned end);
/**
* Shuffles a (position) range in the queue. The songs are physically
* shuffled, not by using the "order" mapping.
*/
void
queue_shuffle_range(struct queue *queue, unsigned start, unsigned end);
bool
queue_set_priority(struct queue *queue, unsigned position,
uint8_t priority, int after_order);
bool
queue_set_priority_range(struct queue *queue,
unsigned start_position, unsigned end_position,
uint8_t priority, int after_order);
#endif #endif

View File

@ -171,7 +171,7 @@ enum command_return
handle_shuffle(G_GNUC_UNUSED Client *client, handle_shuffle(G_GNUC_UNUSED Client *client,
G_GNUC_UNUSED int argc, G_GNUC_UNUSED char *argv[]) G_GNUC_UNUSED int argc, G_GNUC_UNUSED char *argv[])
{ {
unsigned start = 0, end = queue_length(&client->playlist.queue); unsigned start = 0, end = client->playlist.queue.GetLength();
if (argc == 2 && !check_range(client, &start, &end, argv[1])) if (argc == 2 && !check_range(client, &start, &end, argv[1]))
return COMMAND_RETURN_ERROR; return COMMAND_RETURN_ERROR;

View File

@ -41,11 +41,11 @@ static void
queue_print_song_info(Client *client, const struct queue *queue, queue_print_song_info(Client *client, const struct queue *queue,
unsigned position) unsigned position)
{ {
song_print_info(client, queue_get(queue, position)); song_print_info(client, queue->Get(position));
client_printf(client, "Pos: %u\nId: %u\n", client_printf(client, "Pos: %u\nId: %u\n",
position, queue_position_to_id(queue, position)); position, queue->PositionToId(position));
uint8_t priority = queue_get_priority_at_position(queue, position); uint8_t priority = queue->GetPriorityAtPosition(position);
if (priority != 0) if (priority != 0)
client_printf(client, "Prio: %u\n", priority); client_printf(client, "Prio: %u\n", priority);
} }
@ -55,7 +55,7 @@ queue_print_info(Client *client, const struct queue *queue,
unsigned start, unsigned end) unsigned start, unsigned end)
{ {
assert(start <= end); assert(start <= end);
assert(end <= queue_length(queue)); assert(end <= queue->GetLength());
for (unsigned i = start; i < end; ++i) for (unsigned i = start; i < end; ++i)
queue_print_song_info(client, queue, i); queue_print_song_info(client, queue, i);
@ -66,11 +66,11 @@ queue_print_uris(Client *client, const struct queue *queue,
unsigned start, unsigned end) unsigned start, unsigned end)
{ {
assert(start <= end); assert(start <= end);
assert(end <= queue_length(queue)); assert(end <= queue->GetLength());
for (unsigned i = start; i < end; ++i) { for (unsigned i = start; i < end; ++i) {
client_printf(client, "%i:", i); client_printf(client, "%i:", i);
song_print_uri(client, queue_get(queue, i)); song_print_uri(client, queue->Get(i));
} }
} }
@ -78,8 +78,8 @@ void
queue_print_changes_info(Client *client, const struct queue *queue, queue_print_changes_info(Client *client, const struct queue *queue,
uint32_t version) uint32_t version)
{ {
for (unsigned i = 0; i < queue_length(queue); i++) { for (unsigned i = 0; i < queue->GetLength(); i++) {
if (queue_song_newer(queue, i, version)) if (queue->IsNewerAtPosition(i, version))
queue_print_song_info(client, queue, i); queue_print_song_info(client, queue, i);
} }
} }
@ -88,18 +88,18 @@ void
queue_print_changes_position(Client *client, const struct queue *queue, queue_print_changes_position(Client *client, const struct queue *queue,
uint32_t version) uint32_t version)
{ {
for (unsigned i = 0; i < queue_length(queue); i++) for (unsigned i = 0; i < queue->GetLength(); i++)
if (queue_song_newer(queue, i, version)) if (queue->IsNewerAtPosition(i, version))
client_printf(client, "cpos: %i\nId: %i\n", client_printf(client, "cpos: %i\nId: %i\n",
i, queue_position_to_id(queue, i)); i, queue->PositionToId(i));
} }
void void
queue_find(Client *client, const struct queue *queue, queue_find(Client *client, const struct queue *queue,
const SongFilter &filter) const SongFilter &filter)
{ {
for (unsigned i = 0; i < queue_length(queue); i++) { for (unsigned i = 0; i < queue->GetLength(); i++) {
const struct song *song = queue_get(queue, i); const struct song *song = queue->Get(i);
if (filter.Match(*song)) if (filter.Match(*song))
queue_print_song_info(client, queue, i); queue_print_song_info(client, queue, i);

View File

@ -61,19 +61,19 @@ queue_save_song(FILE *fp, int idx, const struct song *song)
void void
queue_save(FILE *fp, const struct queue *queue) queue_save(FILE *fp, const struct queue *queue)
{ {
for (unsigned i = 0; i < queue_length(queue); i++) { for (unsigned i = 0; i < queue->GetLength(); i++) {
uint8_t prio = queue_get_priority_at_position(queue, i); uint8_t prio = queue->GetPriorityAtPosition(i);
if (prio != 0) if (prio != 0)
fprintf(fp, PRIO_LABEL "%u\n", prio); fprintf(fp, PRIO_LABEL "%u\n", prio);
queue_save_song(fp, i, queue_get(queue, i)); queue_save_song(fp, i, queue->Get(i));
} }
} }
void void
queue_load_song(TextFile &file, const char *line, queue *queue) queue_load_song(TextFile &file, const char *line, queue *queue)
{ {
if (queue_is_full(queue)) if (queue->IsFull())
return; return;
uint8_t priority = 0; uint8_t priority = 0;
@ -123,7 +123,7 @@ queue_load_song(TextFile &file, const char *line, queue *queue)
} }
} }
queue_append(queue, song, priority); queue->Append(song, priority);
if (db != nullptr) if (db != nullptr)
db->ReturnSong(song); db->ReturnSong(song);

View File

@ -23,21 +23,21 @@ G_GNUC_UNUSED
static void static void
dump_order(const struct queue *queue) dump_order(const struct queue *queue)
{ {
g_printerr("queue length=%u, order:\n", queue_length(queue)); g_printerr("queue length=%u, order:\n", queue->GetLength());
for (unsigned i = 0; i < queue_length(queue); ++i) for (unsigned i = 0; i < queue->GetLength(); ++i)
g_printerr(" [%u] -> %u (prio=%u)\n", i, queue->order[i], g_printerr(" [%u] -> %u (prio=%u)\n", i, queue->order[i],
queue->items[queue->order[i]].priority); queue->items[queue->order[i]].priority);
} }
static void static void
check_descending_priority(G_GNUC_UNUSED const struct queue *queue, check_descending_priority(const struct queue *queue,
unsigned start_order) unsigned start_order)
{ {
assert(start_order < queue_length(queue)); assert(start_order < queue->GetLength());
uint8_t last_priority = 0xff; uint8_t last_priority = 0xff;
for (unsigned order = start_order; order < queue_length(queue); ++order) { for (unsigned order = start_order; order < queue->GetLength(); ++order) {
unsigned position = queue_order_to_position(queue, order); unsigned position = queue->OrderToPosition(order);
uint8_t priority = queue->items[position].priority; uint8_t priority = queue->items[position].priority;
assert(priority <= last_priority); assert(priority <= last_priority);
(void)last_priority; (void)last_priority;
@ -48,74 +48,74 @@ check_descending_priority(G_GNUC_UNUSED const struct queue *queue,
int int
main(G_GNUC_UNUSED int argc, G_GNUC_UNUSED char **argv) main(G_GNUC_UNUSED int argc, G_GNUC_UNUSED char **argv)
{ {
struct song songs[16]; static struct song songs[16];
struct queue queue(32); struct queue queue(32);
for (unsigned i = 0; i < G_N_ELEMENTS(songs); ++i) for (unsigned i = 0; i < G_N_ELEMENTS(songs); ++i)
queue_append(&queue, &songs[i], 0); queue.Append(&songs[i], 0);
assert(queue_length(&queue) == G_N_ELEMENTS(songs)); assert(queue.GetLength() == G_N_ELEMENTS(songs));
/* priority=10 for 4 items */ /* priority=10 for 4 items */
queue_set_priority_range(&queue, 4, 8, 10, -1); queue.SetPriorityRange(4, 8, 10, -1);
queue.random = true; queue.random = true;
queue_shuffle_order(&queue); queue.ShuffleOrder();
check_descending_priority(&queue, 0); check_descending_priority(&queue, 0);
for (unsigned i = 0; i < 4; ++i) { for (unsigned i = 0; i < 4; ++i) {
assert(queue_position_to_order(&queue, i) >= 4); assert(queue.PositionToOrder(i) >= 4);
} }
for (unsigned i = 4; i < 8; ++i) { for (unsigned i = 4; i < 8; ++i) {
assert(queue_position_to_order(&queue, i) < 4); assert(queue.PositionToOrder(i) < 4);
} }
for (unsigned i = 8; i < G_N_ELEMENTS(songs); ++i) { for (unsigned i = 8; i < G_N_ELEMENTS(songs); ++i) {
assert(queue_position_to_order(&queue, i) >= 4); assert(queue.PositionToOrder(i) >= 4);
} }
/* priority=50 one more item */ /* priority=50 one more item */
queue_set_priority_range(&queue, 15, 16, 50, -1); queue.SetPriorityRange(15, 16, 50, -1);
check_descending_priority(&queue, 0); check_descending_priority(&queue, 0);
assert(queue_position_to_order(&queue, 15) == 0); assert(queue.PositionToOrder(15) == 0);
for (unsigned i = 0; i < 4; ++i) { for (unsigned i = 0; i < 4; ++i) {
assert(queue_position_to_order(&queue, i) >= 4); assert(queue.PositionToOrder(i) >= 4);
} }
for (unsigned i = 4; i < 8; ++i) { for (unsigned i = 4; i < 8; ++i) {
assert(queue_position_to_order(&queue, i) >= 1 && assert(queue.PositionToOrder(i) >= 1 &&
queue_position_to_order(&queue, i) < 5); queue.PositionToOrder(i) < 5);
} }
for (unsigned i = 8; i < 15; ++i) { for (unsigned i = 8; i < 15; ++i) {
assert(queue_position_to_order(&queue, i) >= 5); assert(queue.PositionToOrder(i) >= 5);
} }
/* priority=20 for one of the 4 priority=10 items */ /* priority=20 for one of the 4 priority=10 items */
queue_set_priority_range(&queue, 3, 4, 20, -1); queue.SetPriorityRange(3, 4, 20, -1);
check_descending_priority(&queue, 0); check_descending_priority(&queue, 0);
assert(queue_position_to_order(&queue, 3) == 1); assert(queue.PositionToOrder(3) == 1);
assert(queue_position_to_order(&queue, 15) == 0); assert(queue.PositionToOrder(15) == 0);
for (unsigned i = 0; i < 3; ++i) { for (unsigned i = 0; i < 3; ++i) {
assert(queue_position_to_order(&queue, i) >= 5); assert(queue.PositionToOrder(i) >= 5);
} }
for (unsigned i = 4; i < 8; ++i) { for (unsigned i = 4; i < 8; ++i) {
assert(queue_position_to_order(&queue, i) >= 2 && assert(queue.PositionToOrder(i) >= 2 &&
queue_position_to_order(&queue, i) < 6); queue.PositionToOrder(i) < 6);
} }
for (unsigned i = 8; i < 15; ++i) { for (unsigned i = 8; i < 15; ++i) {
assert(queue_position_to_order(&queue, i) >= 6); assert(queue.PositionToOrder(i) >= 6);
} }
/* priority=20 for another one of the 4 priority=10 items; /* priority=20 for another one of the 4 priority=10 items;
@ -124,17 +124,17 @@ main(G_GNUC_UNUSED int argc, G_GNUC_UNUSED char **argv)
unsigned current_order = 4; unsigned current_order = 4;
unsigned current_position = unsigned current_position =
queue_order_to_position(&queue, current_order); queue.OrderToPosition(current_order);
unsigned a_order = 3; unsigned a_order = 3;
unsigned a_position = queue_order_to_position(&queue, a_order); unsigned a_position = queue.OrderToPosition(a_order);
assert(queue.items[a_position].priority == 10); assert(queue.items[a_position].priority == 10);
queue_set_priority(&queue, a_position, 20, current_order); queue.SetPriority(a_position, 20, current_order);
current_order = queue_position_to_order(&queue, current_position); current_order = queue.PositionToOrder(current_position);
assert(current_order == 3); assert(current_order == 3);
a_order = queue_position_to_order(&queue, a_position); a_order = queue.PositionToOrder(a_position);
assert(a_order == 4); assert(a_order == 4);
check_descending_priority(&queue, current_order + 1); check_descending_priority(&queue, current_order + 1);
@ -144,14 +144,14 @@ main(G_GNUC_UNUSED int argc, G_GNUC_UNUSED char **argv)
just created */ just created */
unsigned b_order = 10; unsigned b_order = 10;
unsigned b_position = queue_order_to_position(&queue, b_order); unsigned b_position = queue.OrderToPosition(b_order);
assert(queue.items[b_position].priority == 0); assert(queue.items[b_position].priority == 0);
queue_set_priority(&queue, b_position, 70, current_order); queue.SetPriority(b_position, 70, current_order);
current_order = queue_position_to_order(&queue, current_position); current_order = queue.PositionToOrder(current_position);
assert(current_order == 3); assert(current_order == 3);
b_order = queue_position_to_order(&queue, b_position); b_order = queue.PositionToOrder(b_position);
assert(b_order == 4); assert(b_order == 4);
check_descending_priority(&queue, current_order + 1); check_descending_priority(&queue, current_order + 1);
@ -161,27 +161,26 @@ main(G_GNUC_UNUSED int argc, G_GNUC_UNUSED char **argv)
hasn't changed (it was already higher before) */ hasn't changed (it was already higher before) */
unsigned c_order = 0; unsigned c_order = 0;
unsigned c_position = queue_order_to_position(&queue, c_order); unsigned c_position = queue.OrderToPosition(c_order);
assert(queue.items[c_position].priority == 50); assert(queue.items[c_position].priority == 50);
queue_set_priority(&queue, c_position, 60, current_order); queue.SetPriority(c_position, 60, current_order);
current_order = queue_position_to_order(&queue, current_position); current_order = queue.PositionToOrder(current_position);
assert(current_order == 3); assert(current_order == 3);
c_order = queue_position_to_order(&queue, c_position); c_order = queue.PositionToOrder(c_position);
assert(c_order == 0); assert(c_order == 0);
/* move the prio=20 item back */ /* move the prio=20 item back */
a_order = queue_position_to_order(&queue, a_position); a_order = queue.PositionToOrder(a_position);
assert(a_order == 5); assert(a_order == 5);
assert(queue.items[a_position].priority == 20); assert(queue.items[a_position].priority == 20);
queue_set_priority(&queue, a_position, 5, current_order); queue.SetPriority(a_position, 5, current_order);
current_order = queue.PositionToOrder(current_position);
current_order = queue_position_to_order(&queue, current_position);
assert(current_order == 3); assert(current_order == 3);
a_order = queue_position_to_order(&queue, a_position); a_order = queue.PositionToOrder(a_position);
assert(a_order == 6); assert(a_order == 6);
} }