diff options
-rw-r--r-- | src/Playlist.cxx | 63 | ||||
-rw-r--r-- | src/PlaylistControl.cxx | 42 | ||||
-rw-r--r-- | src/PlaylistEdit.cxx | 102 | ||||
-rw-r--r-- | src/PlaylistPrint.cxx | 8 | ||||
-rw-r--r-- | src/PlaylistSave.cxx | 4 | ||||
-rw-r--r-- | src/PlaylistState.cxx | 15 | ||||
-rw-r--r-- | src/Queue.cxx | 342 | ||||
-rw-r--r-- | src/Queue.hxx | 417 | ||||
-rw-r--r-- | src/QueueCommands.cxx | 2 | ||||
-rw-r--r-- | src/QueuePrint.cxx | 26 | ||||
-rw-r--r-- | src/QueueSave.cxx | 10 | ||||
-rw-r--r-- | test/TestQueuePriority.cxx | 89 |
12 files changed, 517 insertions, 603 deletions
diff --git a/src/Playlist.cxx b/src/Playlist.cxx index bb3daba8d..7f89e4ea9 100644 --- a/src/Playlist.cxx +++ b/src/Playlist.cxx @@ -36,7 +36,7 @@ extern "C" { void playlist_increment_version_all(struct playlist *playlist) { - queue_modify_all(&playlist->queue); + playlist->queue.ModifyAll(); idle_add(IDLE_PLAYLIST); } @@ -48,7 +48,7 @@ playlist_tag_changed(struct playlist *playlist) assert(playlist->current >= 0); - queue_modify(&playlist->queue, playlist->current); + playlist->queue.ModifyAtOrder(playlist->current); idle_add(IDLE_PLAYLIST); } @@ -61,12 +61,12 @@ playlist_queue_song_order(struct playlist *playlist, struct player_control *pc, { char *uri; - assert(queue_valid_order(&playlist->queue, order)); + assert(playlist->queue.IsValidOrder(order)); playlist->queued = order; struct song *song = - song_dup_detached(queue_get_order(&playlist->queue, order)); + song_dup_detached(playlist->queue.GetOrder(order)); uri = song_get_uri(song); 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) playlist_delete(playlist, pc, - queue_order_to_position(&playlist->queue, - current)); + playlist->queue.OrderToPosition(current)); idle_add(IDLE_PLAYER); } @@ -105,7 +104,7 @@ playlist_get_queued_song(struct playlist *playlist) if (!playlist->playing || playlist->queued < 0) return NULL; - return queue_get_order(&playlist->queue, playlist->queued); + return playlist->queue.GetOrder(playlist->queued); } void @@ -119,11 +118,11 @@ playlist_update_queued_song(struct playlist *playlist, if (!playlist->playing) return; - assert(!queue_is_empty(&playlist->queue)); + assert(!playlist->queue.IsEmpty()); assert((playlist->queued < 0) == (prev == NULL)); next_order = playlist->current >= 0 - ? queue_next_order(&playlist->queue, playlist->current) + ? playlist->queue.GetNextOrder(playlist->current) : 0; 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 completely */ unsigned current_position = - queue_order_to_position(&playlist->queue, - playlist->current); + playlist->queue.OrderToPosition(playlist->current); - queue_shuffle_order(&playlist->queue); + playlist->queue.ShuffleOrder(); /* make sure that the playlist->current still points to the current song, after the song order has been shuffled */ playlist->current = - queue_position_to_order(&playlist->queue, - current_position); + playlist->queue.PositionToOrder(current_position); } if (next_order >= 0) - next_song = queue_get_order(&playlist->queue, next_order); + next_song = playlist->queue.GetOrder(next_order); else next_song = NULL; @@ -174,7 +171,7 @@ playlist_play_order(struct playlist *playlist, struct player_control *pc, playlist->queued = -1; struct song *song = - song_dup_detached(queue_get_order(&playlist->queue, orderNum)); + song_dup_detached(playlist->queue.GetOrder(orderNum)); uri = song_get_uri(song); 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) || error == PLAYER_ERROR_OUTPUT || - playlist->error_count >= queue_length(&playlist->queue)) + playlist->error_count >= playlist->queue.GetLength()) /* too many errors, or critical error: stop playback */ playlist_stop(playlist, pc); @@ -306,10 +303,9 @@ playlist_order(struct playlist *playlist) { if (playlist->current >= 0) /* update playlist.current, order==position now */ - playlist->current = queue_order_to_position(&playlist->queue, - playlist->current); + playlist->current = playlist->queue.OrderToPosition(playlist->current); - queue_restore_order(&playlist->queue); + playlist->queue.RestoreOrder(); } void @@ -362,20 +358,18 @@ playlist_set_random(struct playlist *playlist, struct player_control *pc, int current_position = playlist->playing && playlist->current >= 0 - ? (int)queue_order_to_position(&playlist->queue, - playlist->current) + ? (int)playlist->queue.OrderToPosition(playlist->current) : -1; - queue_shuffle_order(&playlist->queue); + playlist->queue.ShuffleOrder(); if (current_position >= 0) { /* make sure the current song is the first in the order list, so the whole rest of the playlist is played after that */ unsigned current_order = - queue_position_to_order(&playlist->queue, - current_position); - queue_swap_order(&playlist->queue, 0, current_order); + playlist->queue.PositionToOrder(current_position); + playlist->queue.SwapOrders(0, current_order); playlist->current = 0; } else playlist->current = -1; @@ -391,8 +385,7 @@ int playlist_get_current_song(const struct playlist *playlist) { if (playlist->current >= 0) - return queue_order_to_position(&playlist->queue, - playlist->current); + return playlist->queue.OrderToPosition(playlist->current); return -1; } @@ -403,13 +396,11 @@ playlist_get_next_song(const struct playlist *playlist) if (playlist->current >= 0) { if (playlist->queue.single == 1 && playlist->queue.repeat == 1) - return queue_order_to_position(&playlist->queue, - playlist->current); - else if (playlist->current + 1 < (int)queue_length(&playlist->queue)) - return queue_order_to_position(&playlist->queue, - playlist->current + 1); + return playlist->queue.OrderToPosition(playlist->current); + else if (playlist->current + 1 < (int)playlist->queue.GetLength()) + return playlist->queue.OrderToPosition(playlist->current + 1); else if (playlist->queue.repeat == 1) - return queue_order_to_position(&playlist->queue, 0); + return playlist->queue.OrderToPosition(0); } return -1; @@ -424,11 +415,11 @@ playlist_get_version(const struct playlist *playlist) int playlist_get_length(const struct playlist *playlist) { - return queue_length(&playlist->queue); + return playlist->queue.GetLength(); } unsigned playlist_get_song_id(const struct playlist *playlist, unsigned song) { - return queue_position_to_id(&playlist->queue, song); + return playlist->queue.PositionToId(song); } diff --git a/src/PlaylistControl.cxx b/src/PlaylistControl.cxx index 89c680523..e4c3298fe 100644 --- a/src/PlaylistControl.cxx +++ b/src/PlaylistControl.cxx @@ -50,16 +50,14 @@ playlist_stop(struct playlist *playlist, struct player_control *pc) result in a new random order */ unsigned current_position = - queue_order_to_position(&playlist->queue, - playlist->current); + playlist->queue.OrderToPosition(playlist->current); - queue_shuffle_order(&playlist->queue); + playlist->queue.ShuffleOrder(); /* make sure that "current" stays valid, and the next "play" command plays the same song again */ playlist->current = - queue_position_to_order(&playlist->queue, - current_position); + playlist->queue.PositionToOrder(current_position); } } @@ -74,7 +72,7 @@ playlist_play(struct playlist *playlist, struct player_control *pc, if (song == -1) { /* play any song ("current" song, or the first song */ - if (queue_is_empty(&playlist->queue)) + if (playlist->queue.IsEmpty()) return PLAYLIST_RESULT_SUCCESS; if (playlist->playing) { @@ -88,7 +86,7 @@ playlist_play(struct playlist *playlist, struct player_control *pc, i = playlist->current >= 0 ? playlist->current : 0; - } else if (!queue_valid_position(&playlist->queue, song)) + } else if (!playlist->queue.IsValidPosition(song)) return PLAYLIST_RESULT_BAD_RANGE; 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 no-random mode); convert it to a order number, because random mode is enabled */ - i = queue_position_to_order(&playlist->queue, song); + i = playlist->queue.PositionToOrder(song); if (!playlist->playing) playlist->current = 0; /* swap the new song with the previous "current" one, so playback continues as planned */ - queue_swap_order(&playlist->queue, - i, playlist->current); + playlist->queue.SwapOrders(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); } - song = queue_id_to_position(&playlist->queue, id); + song = playlist->queue.IdToPosition(id); if (song < 0) return PLAYLIST_RESULT_NO_SUCH_SONG; @@ -142,15 +139,15 @@ playlist_next(struct playlist *playlist, struct player_control *pc) if (!playlist->playing) return; - assert(!queue_is_empty(&playlist->queue)); - assert(queue_valid_order(&playlist->queue, playlist->current)); + assert(!playlist->queue.IsEmpty()); + assert(playlist->queue.IsValidOrder(playlist->current)); current = playlist->current; playlist->stop_on_error = false; /* 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) { /* no song after this one: stop playback */ playlist_stop(playlist, pc); @@ -167,7 +164,7 @@ playlist_next(struct playlist *playlist, struct player_control *pc) songs in a different than before */ assert(playlist->queue.repeat); - queue_shuffle_order(&playlist->queue); + playlist->queue.ShuffleOrder(); /* note that playlist->current and playlist->queued are 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. */ if(playlist->queue.consume) playlist_delete(playlist, pc, - queue_order_to_position(&playlist->queue, - current)); + playlist->queue.OrderToPosition(current)); } void @@ -190,7 +186,7 @@ playlist_previous(struct playlist *playlist, struct player_control *pc) if (!playlist->playing) return; - assert(queue_length(&playlist->queue) > 0); + assert(playlist->queue.GetLength() > 0); if (playlist->current > 0) { /* play the preceding song */ @@ -199,7 +195,7 @@ playlist_previous(struct playlist *playlist, struct player_control *pc) } else if (playlist->queue.repeat) { /* play the last song in "repeat" mode */ playlist_play_order(playlist, pc, - queue_length(&playlist->queue) - 1); + playlist->queue.GetLength() - 1); } else { /* re-start playing the current song if it's the first one */ @@ -215,13 +211,13 @@ playlist_seek_song(struct playlist *playlist, struct player_control *pc, unsigned i; bool success; - if (!queue_valid_position(&playlist->queue, song)) + if (!playlist->queue.IsValidPosition(song)) return PLAYLIST_RESULT_BAD_RANGE; queued = playlist_get_queued_song(playlist); if (playlist->queue.random) - i = queue_position_to_order(&playlist->queue, song); + i = playlist->queue.PositionToOrder(song); else i = song; @@ -240,7 +236,7 @@ playlist_seek_song(struct playlist *playlist, struct player_control *pc, } 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); if (!success) { 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, unsigned id, float seek_time) { - int song = queue_id_to_position(&playlist->queue, id); + int song = playlist->queue.IdToPosition(id); if (song < 0) return PLAYLIST_RESULT_NO_SUCH_SONG; diff --git a/src/PlaylistEdit.cxx b/src/PlaylistEdit.cxx index 90a65fd29..e9e085897 100644 --- a/src/PlaylistEdit.cxx +++ b/src/PlaylistEdit.cxx @@ -40,7 +40,7 @@ extern "C" { static void playlist_increment_version(struct playlist *playlist) { - queue_increment_version(&playlist->queue); + playlist->queue.IncrementVersion(); idle_add(IDLE_PLAYLIST); } @@ -50,7 +50,7 @@ playlist_clear(struct playlist *playlist, struct player_control *pc) { playlist_stop(playlist, pc); - queue_clear(&playlist->queue); + playlist->queue.Clear(); playlist->current = -1; @@ -75,12 +75,12 @@ playlist_append_song(struct playlist *playlist, struct player_control *pc, const struct song *queued; unsigned id; - if (queue_is_full(&playlist->queue)) + if (playlist->queue.IsFull()) return PLAYLIST_RESULT_TOO_LARGE; queued = playlist_get_queued_song(playlist); - id = queue_append(&playlist->queue, song, 0); + id = playlist->queue.Append(song, 0); if (playlist->queue.random) { /* 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; else start = playlist->current + 1; - if (start < queue_length(&playlist->queue)) - queue_shuffle_order_last(&playlist->queue, start, - queue_length(&playlist->queue)); + if (start < playlist->queue.GetLength()) + playlist->queue.ShuffleOrderLast(start, + playlist->queue.GetLength()); } playlist_increment_version(playlist); @@ -140,23 +140,20 @@ playlist_swap_songs(struct playlist *playlist, struct player_control *pc, { const struct song *queued; - if (!queue_valid_position(&playlist->queue, song1) || - !queue_valid_position(&playlist->queue, song2)) + if (!playlist->queue.IsValidPosition(song1) || + !playlist->queue.IsValidPosition(song2)) return PLAYLIST_RESULT_BAD_RANGE; queued = playlist_get_queued_song(playlist); - queue_swap(&playlist->queue, song1, song2); + playlist->queue.SwapPositions(song1, song2); if (playlist->queue.random) { /* update the queue order, so that playlist->current still points to the current song order */ - queue_swap_order(&playlist->queue, - queue_position_to_order(&playlist->queue, - song1), - queue_position_to_order(&playlist->queue, - song2)); + playlist->queue.SwapOrders(playlist->queue.PositionToOrder(song1), + playlist->queue.PositionToOrder(song2)); } else { /* correct the "current" song order */ @@ -177,8 +174,8 @@ enum playlist_result playlist_swap_songs_id(struct playlist *playlist, struct player_control *pc, unsigned id1, unsigned id2) { - int song1 = queue_id_to_position(&playlist->queue, id1); - int song2 = queue_id_to_position(&playlist->queue, id2); + int song1 = playlist->queue.IdToPosition(id1); + int song2 = playlist->queue.IdToPosition(id2); if (song1 < 0 || song2 < 0) return PLAYLIST_RESULT_NO_SUCH_SONG; @@ -191,11 +188,11 @@ playlist_set_priority(struct playlist *playlist, struct player_control *pc, unsigned start, unsigned end, uint8_t priority) { - if (start >= queue_length(&playlist->queue)) + if (start >= playlist->queue.GetLength()) return PLAYLIST_RESULT_BAD_RANGE; - if (end > queue_length(&playlist->queue)) - end = queue_length(&playlist->queue); + if (end > playlist->queue.GetLength()) + end = playlist->queue.GetLength(); if (start >= end) return PLAYLIST_RESULT_SUCCESS; @@ -203,24 +200,22 @@ playlist_set_priority(struct playlist *playlist, struct player_control *pc, /* remember "current" and "queued" */ int current_position = playlist->current >= 0 - ? (int)queue_order_to_position(&playlist->queue, - playlist->current) + ? (int)playlist->queue.OrderToPosition(playlist->current) : -1; const struct song *queued = playlist_get_queued_song(playlist); /* apply the priority changes */ - queue_set_priority_range(&playlist->queue, start, end, priority, - playlist->current); + playlist->queue.SetPriorityRange(start, end, priority, + playlist->current); playlist_increment_version(playlist); /* restore "current" and choose a new "queued" */ if (current_position >= 0) - playlist->current = queue_position_to_order(&playlist->queue, - current_position); + playlist->current = playlist->queue.PositionToOrder(current_position); 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, 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) return PLAYLIST_RESULT_NO_SUCH_SONG; @@ -247,9 +242,9 @@ playlist_delete_internal(struct playlist *playlist, struct player_control *pc, { 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) { 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 */ - playlist->current = queue_next_order(&playlist->queue, - playlist->current); + playlist->current = playlist->queue.GetNextOrder(playlist->current); if (playlist->current == (int)songOrder) playlist->current = -1; @@ -282,7 +276,7 @@ playlist_delete_internal(struct playlist *playlist, struct player_control *pc, /* now do it: remove the song */ - queue_delete(&playlist->queue, song); + playlist->queue.DeletePosition(song); /* update the "current" and "queued" variables */ @@ -297,7 +291,7 @@ playlist_delete(struct playlist *playlist, struct player_control *pc, { const struct song *queued; - if (song >= queue_length(&playlist->queue)) + if (song >= playlist->queue.GetLength()) return PLAYLIST_RESULT_BAD_RANGE; queued = playlist_get_queued_song(playlist); @@ -316,11 +310,11 @@ playlist_delete_range(struct playlist *playlist, struct player_control *pc, { const struct song *queued; - if (start >= queue_length(&playlist->queue)) + if (start >= playlist->queue.GetLength()) return PLAYLIST_RESULT_BAD_RANGE; - if (end > queue_length(&playlist->queue)) - end = queue_length(&playlist->queue); + if (end > playlist->queue.GetLength()) + end = playlist->queue.GetLength(); if (start >= end) return PLAYLIST_RESULT_SUCCESS; @@ -341,7 +335,7 @@ enum playlist_result playlist_delete_id(struct playlist *playlist, struct player_control *pc, unsigned id) { - int song = queue_id_to_position(&playlist->queue, id); + int song = playlist->queue.IdToPosition(id); if (song < 0) return PLAYLIST_RESULT_NO_SUCH_SONG; @@ -352,8 +346,8 @@ void playlist_delete_song(struct playlist *playlist, struct player_control *pc, const struct song *song) { - for (int i = queue_length(&playlist->queue) - 1; i >= 0; --i) - if (song == queue_get(&playlist->queue, i)) + for (int i = playlist->queue.GetLength() - 1; i >= 0; --i) + if (song == playlist->queue.Get(i)) playlist_delete(playlist, pc, i); } @@ -364,12 +358,12 @@ playlist_move_range(struct playlist *playlist, struct player_control *pc, const struct song *queued; int currentSong; - if (!queue_valid_position(&playlist->queue, start) || - !queue_valid_position(&playlist->queue, end - 1)) + if (!playlist->queue.IsValidPosition(start) || + !playlist->queue.IsValidPosition(end - 1)) return PLAYLIST_RESULT_BAD_RANGE; - if ((to >= 0 && to + end - start - 1 >= queue_length(&playlist->queue)) || - (to < 0 && abs(to) > (int)queue_length(&playlist->queue))) + if ((to >= 0 && to + end - start - 1 >= playlist->queue.GetLength()) || + (to < 0 && abs(to) > (int)playlist->queue.GetLength())) return PLAYLIST_RESULT_BAD_RANGE; 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 */ currentSong = playlist->current >= 0 - ? (int)queue_order_to_position(&playlist->queue, - playlist->current) + ? (int)playlist->queue.OrderToPosition(playlist->current) : -1; if (to < 0 && playlist->current >= 0) { if (start <= (unsigned)currentSong && (unsigned)currentSong < end) /* no-op, can't be moved to offset of itself */ return PLAYLIST_RESULT_SUCCESS; - to = (currentSong + abs(to)) % queue_length(&playlist->queue); + to = (currentSong + abs(to)) % playlist->queue.GetLength(); if (start < (unsigned)to) to--; } - queue_move_range(&playlist->queue, start, end, to); + playlist->queue.MoveRange(start, end, to); if (!playlist->queue.random) { /* update current/queued */ @@ -422,7 +415,7 @@ enum playlist_result playlist_move_id(struct playlist *playlist, struct player_control *pc, unsigned id1, int to) { - int song = queue_id_to_position(&playlist->queue, id1); + int song = playlist->queue.IdToPosition(id1); if (song < 0) return PLAYLIST_RESULT_NO_SUCH_SONG; @@ -435,9 +428,9 @@ playlist_shuffle(struct playlist *playlist, struct player_control *pc, { const struct song *queued; - if (end > queue_length(&playlist->queue)) + if (end > playlist->queue.GetLength()) /* correct the "end" offset */ - end = queue_length(&playlist->queue); + end = playlist->queue.GetLength(); if ((start+1) >= end) /* needs at least two entries. */ @@ -446,17 +439,16 @@ playlist_shuffle(struct playlist *playlist, struct player_control *pc, queued = playlist_get_queued_song(playlist); if (playlist->playing && playlist->current >= 0) { unsigned current_position; - current_position = queue_order_to_position(&playlist->queue, - playlist->current); + current_position = playlist->queue.OrderToPosition(playlist->current); if (current_position >= start && current_position < end) { /* put current playing song first */ - queue_swap(&playlist->queue, start, current_position); + playlist->queue.SwapPositions(start, current_position); if (playlist->queue.random) { playlist->current = - queue_position_to_order(&playlist->queue, start); + playlist->queue.PositionToOrder(start); } else playlist->current = start; @@ -469,7 +461,7 @@ playlist_shuffle(struct playlist *playlist, struct player_control *pc, playlist->current = -1; } - queue_shuffle_range(&playlist->queue, start, end); + playlist->queue.ShuffleRange(start, end); playlist_increment_version(playlist); diff --git a/src/PlaylistPrint.cxx b/src/PlaylistPrint.cxx index cbbd71bbd..7df7a9c39 100644 --- a/src/PlaylistPrint.cxx +++ b/src/PlaylistPrint.cxx @@ -41,7 +41,7 @@ playlist_print_uris(Client *client, const struct playlist *playlist) { const struct queue *queue = &playlist->queue; - queue_print_uris(client, queue, 0, queue_length(queue)); + queue_print_uris(client, queue, 0, queue->GetLength()); } bool @@ -50,9 +50,9 @@ playlist_print_info(Client *client, const struct playlist *playlist, { const struct queue *queue = &playlist->queue; - if (end > queue_length(queue)) + if (end > queue->GetLength()) /* correct the "end" offset */ - end = queue_length(queue); + end = queue->GetLength(); if (start > end) /* 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; int position; - position = queue_id_to_position(queue, id); + position = queue->IdToPosition(id); if (position < 0) /* no such song */ return false; diff --git a/src/PlaylistSave.cxx b/src/PlaylistSave.cxx index 7b88a8434..4d537accf 100644 --- a/src/PlaylistSave.cxx +++ b/src/PlaylistSave.cxx @@ -98,8 +98,8 @@ spl_save_queue(const char *name_utf8, const struct queue *queue) if (file == NULL) return PLAYLIST_RESULT_ERRNO; - for (unsigned i = 0; i < queue_length(queue); i++) - playlist_print_song(file, queue_get(queue, i)); + for (unsigned i = 0; i < queue->GetLength(); i++) + playlist_print_song(file, queue->Get(i)); fclose(file); diff --git a/src/PlaylistState.cxx b/src/PlaylistState.cxx index 32929d077..7e93e7803 100644 --- a/src/PlaylistState.cxx +++ b/src/PlaylistState.cxx @@ -74,8 +74,7 @@ playlist_state_save(FILE *fp, const struct playlist *playlist, fputs(PLAYLIST_STATE_FILE_STATE_PLAY "\n", fp); } fprintf(fp, PLAYLIST_STATE_FILE_CURRENT "%i\n", - queue_order_to_position(&playlist->queue, - playlist->current)); + playlist->queue.OrderToPosition(playlist->current)); fprintf(fp, PLAYLIST_STATE_FILE_TIME "%i\n", (int)player_status.elapsed_time); } else { @@ -83,8 +82,7 @@ playlist_state_save(FILE *fp, const struct playlist *playlist, if (playlist->current >= 0) fprintf(fp, PLAYLIST_STATE_FILE_CURRENT "%i\n", - queue_order_to_position(&playlist->queue, - playlist->current)); + playlist->queue.OrderToPosition(playlist->current)); } 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 @@ -195,8 +193,8 @@ playlist_state_restore(const char *line, TextFile &file, playlist_set_random(playlist, pc, random_mode); - if (!queue_is_empty(&playlist->queue)) { - if (!queue_valid_position(&playlist->queue, current)) + if (!playlist->queue.IsEmpty()) { + if (!playlist->queue.IsValidPosition(current)) current = 0; if (state == PLAYER_STATE_PLAY && @@ -239,8 +237,7 @@ playlist_state_get_hash(const struct playlist *playlist, ? ((int)player_status.elapsed_time << 8) : 0) ^ (playlist->current >= 0 - ? (queue_order_to_position(&playlist->queue, - playlist->current) << 16) + ? (playlist->queue.OrderToPosition(playlist->current) << 16) : 0) ^ ((int)pc_get_cross_fade(pc) << 20) ^ (player_status.state << 24) ^ diff --git a/src/Queue.cxx b/src/Queue.cxx index a8a737540..f64bbf5c9 100644 --- a/src/Queue.cxx +++ b/src/Queue.cxx @@ -23,6 +23,34 @@ #include <stdlib.h> +queue::queue(unsigned _max_length) + :max_length(_max_length), length(0), + version(1), + items(g_new(struct queue_item, max_length)), + order((unsigned *)g_malloc(sizeof(order[0]) * max_length)), + id_to_position((int *)g_malloc(sizeof(id_to_position[0]) * + max_length * QUEUE_HASH_MULT)), + repeat(false), + single(false), + consume(false), + random(false), + rand(g_rand_new()) +{ + for (unsigned i = 0; i < max_length * QUEUE_HASH_MULT; ++i) + id_to_position[i] = -1; +} + +queue::~queue() +{ + Clear(); + + g_free(items); + g_free(order); + g_free(id_to_position); + + g_rand_free(rand); +} + /** * Generate a non-existing id number. */ @@ -42,15 +70,15 @@ queue_generate_id(const struct queue *queue) } int -queue_next_order(const struct queue *queue, unsigned order) +queue::GetNextOrder(unsigned _order) const { - assert(order < queue->length); + assert(_order < 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)) + 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 @@ -59,79 +87,77 @@ queue_next_order(const struct queue *queue, unsigned order) } void -queue_increment_version(struct queue *queue) +queue::IncrementVersion() { static unsigned long max = ((uint32_t) 1 << 31) - 1; - queue->version++; + version++; - if (queue->version >= max) { - for (unsigned i = 0; i < queue->length; i++) - queue->items[i].version = 0; + if (version >= max) { + for (unsigned i = 0; i < length; i++) + items[i].version = 0; - queue->version = 1; + version = 1; } } void -queue_modify(struct queue *queue, unsigned order) +queue::ModifyAtOrder(unsigned _order) { - unsigned position; - - assert(order < queue->length); + assert(_order < length); - position = queue->order[order]; - queue->items[position].version = queue->version; + unsigned position = order[_order]; + items[position].version = version; - queue_increment_version(queue); + IncrementVersion(); } void -queue_modify_all(struct queue *queue) +queue::ModifyAll() { - for (unsigned i = 0; i < queue->length; i++) - queue->items[i].version = queue->version; + for (unsigned i = 0; i < length; i++) + items[i].version = version; - queue_increment_version(queue); + IncrementVersion(); } unsigned -queue_append(struct queue *queue, struct song *song, uint8_t priority) +queue::Append(struct song *song, uint8_t priority) { - unsigned id = queue_generate_id(queue); + unsigned id = queue_generate_id(this); - assert(!queue_is_full(queue)); + assert(!IsFull()); - auto &item = queue->items[queue->length]; + auto &item = items[length]; item.song = song_dup_detached(song); item.id = id; - item.version = queue->version; + item.version = version; item.priority = priority; - queue->order[queue->length] = queue->length; - queue->id_to_position[id] = queue->length; + order[length] = length; + id_to_position[id] = length; - ++queue->length; + ++length; return id; } void -queue_swap(struct queue *queue, unsigned position1, unsigned position2) +queue::SwapPositions(unsigned position1, unsigned position2) { struct queue_item tmp; - unsigned id1 = queue->items[position1].id; - unsigned id2 = queue->items[position2].id; + unsigned id1 = items[position1].id; + unsigned id2 = items[position2].id; - tmp = queue->items[position1]; - queue->items[position1] = queue->items[position2]; - queue->items[position2] = tmp; + tmp = items[position1]; + items[position1] = items[position2]; + items[position2] = tmp; - queue->items[position1].version = queue->version; - queue->items[position2].version = queue->version; + items[position1].version = version; + items[position2].version = version; - queue->id_to_position[id1] = position2; - queue->id_to_position[id2] = position1; + id_to_position[id1] = position2; + id_to_position[id2] = position1; } static void @@ -145,79 +171,79 @@ queue_move_song_to(struct queue *queue, unsigned from, unsigned to) } void -queue_move(struct queue *queue, unsigned from, unsigned to) +queue::MovePostion(unsigned from, unsigned to) { - struct queue_item item = queue->items[from]; + 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(queue, i + 1, 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(queue, i - 1, i); + queue_move_song_to(this, i - 1, i); /* put song at _to_ */ - queue->id_to_position[item.id] = to; - queue->items[to] = item; - queue->items[to].version = queue->version; + id_to_position[item.id] = to; + items[to] = item; + items[to].version = 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; + 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_move_range(struct queue *queue, unsigned start, unsigned end, unsigned to) +queue::MoveRange(unsigned start, unsigned end, unsigned to) { - struct queue_item items[end - start]; + struct queue_item tmp[end - start]; // Copy the original block [start,end-1] for (unsigned i = start; i < end; i++) - items[i - start] = queue->items[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(queue, i, start + i - end); + 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(queue, i, i + end - start); + 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++) { - 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; + id_to_position[tmp[i-start].id] = to + i - start; + items[to + i - start] = tmp[i-start]; + items[to + i - start].version = version; } - if (queue->random) { + 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 < 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; + 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; } } } @@ -232,8 +258,7 @@ queue_move_order(struct queue *queue, unsigned from_order, unsigned to_order) assert(from_order < queue->length); assert(to_order <= queue->length); - const unsigned from_position = - queue_order_to_position(queue, from_order); + const unsigned from_position = queue->OrderToPosition(from_order); if (from_order < to_order) { for (unsigned i = from_order; i < to_order; ++i) @@ -247,85 +272,54 @@ queue_move_order(struct queue *queue, unsigned from_order, unsigned to_order) } void -queue_delete(struct queue *queue, unsigned position) +queue::DeletePosition(unsigned position) { - struct song *song; - unsigned id, order; + assert(position < length); - assert(position < queue->length); - - song = queue_get(queue, position); + struct song *song = Get(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); + const unsigned id = PositionToId(position); + const unsigned _order = PositionToOrder(position); - --queue->length; + --length; /* release the song id */ - queue->id_to_position[id] = -1; + 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); + 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 < queue->length; i++) - queue->order[i] = queue->order[i + 1]; + for (unsigned i = _order; i < length; i++) + order[i] = 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]; + for (unsigned i = 0; i < length; i++) + if (order[i] > position) + --order[i]; } void -queue_clear(struct queue *queue) +queue::Clear() { - for (unsigned i = 0; i < queue->length; i++) { - struct queue_item *item = &queue->items[i]; + 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); - queue->id_to_position[item->id] = -1; + id_to_position[item->id] = -1; } - queue->length = 0; -} - -queue::queue(unsigned _max_length) - :max_length(_max_length), length(0), - version(1), - items(g_new(struct queue_item, max_length)), - order((unsigned *)g_malloc(sizeof(order[0]) * max_length)), - id_to_position((int *)g_malloc(sizeof(id_to_position[0]) * - max_length * QUEUE_HASH_MULT)), - repeat(false), - single(false), - consume(false), - random(false), - rand(g_rand_new()) -{ - for (unsigned i = 0; i < max_length * QUEUE_HASH_MULT; ++i) - id_to_position[i] = -1; -} - -queue::~queue() -{ - queue_clear(this); - - g_free(items); - g_free(order); - g_free(id_to_position); - - g_rand_free(rand); + length = 0; } static const struct queue_item * @@ -390,8 +384,7 @@ queue_shuffle_order_range(struct queue *queue, unsigned start, unsigned end) assert(end <= queue->length); for (unsigned i = start; i < end; ++i) - queue_swap_order(queue, i, - g_rand_int_range(queue->rand, i, end)); + queue->SwapOrders(i, 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. */ void -queue_shuffle_order_range_with_priority(struct queue *queue, - unsigned start, unsigned end) +queue::ShuffleOrderRangeWithPriority(unsigned start, unsigned end) { - assert(queue != NULL); - assert(queue->random); + assert(random); assert(start <= end); - assert(end <= queue->length); + assert(end <= length); if (start == end) return; /* 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 */ 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) { - uint8_t priority = queue_get_order_priority(queue, i); + uint8_t priority = queue_get_order_priority(this, i); assert(priority <= group_priority); if (priority != group_priority) { /* start of a new group - shuffle the one that has just ended */ - queue_shuffle_order_range(queue, group_start, i); + queue_shuffle_order_range(this, group_start, i); group_start = i; group_priority = priority; } } /* shuffle the last group */ - queue_shuffle_order_range(queue, group_start, end); + queue_shuffle_order_range(this, group_start, end); } void -queue_shuffle_order(struct queue *queue) +queue::ShuffleOrder() { - queue_shuffle_order_range_with_priority(queue, 0, queue->length); + ShuffleOrderRangeWithPriority(0, length); } static void queue_shuffle_order_first(struct queue *queue, unsigned start, unsigned end) { - queue_swap_order(queue, start, - g_rand_int_range(queue->rand, start, end)); + queue->SwapOrders(start, g_rand_int_range(queue->rand, start, end)); } void -queue_shuffle_order_last(struct queue *queue, unsigned start, unsigned end) +queue::ShuffleOrderLast(unsigned start, unsigned end) { - queue_swap_order(queue, end - 1, - g_rand_int_range(queue->rand, start, end)); + SwapOrders(end - 1, g_rand_int_range(rand, start, end)); } void -queue_shuffle_range(struct queue *queue, unsigned start, unsigned end) +queue::ShuffleRange(unsigned start, unsigned end) { assert(start <= end); - assert(end <= queue->length); + assert(end <= length); for (unsigned i = start; i < end; i++) { - unsigned ri = g_rand_int_range(queue->rand, i, end); - queue_swap(queue, i, ri); + unsigned ri = g_rand_int_range(rand, i, end); + SwapPositions(i, ri); } } @@ -479,7 +468,7 @@ queue_find_priority_order(const struct queue *queue, unsigned start_order, assert(start_order <= queue->length); 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]; if (item->priority <= priority && order != exclude_order) return order; @@ -498,7 +487,7 @@ queue_count_same_priority(const struct queue *queue, unsigned start_order, assert(start_order <= queue->length); 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]; if (item->priority != priority) return order - start_order; @@ -508,39 +497,37 @@ queue_count_same_priority(const struct queue *queue, unsigned start_order, } bool -queue_set_priority(struct queue *queue, unsigned position, uint8_t priority, - int after_order) +queue::SetPriority(unsigned position, uint8_t priority, int after_order) { - assert(queue != NULL); - assert(position < queue->length); + assert(position < length); - struct queue_item *item = &queue->items[position]; + struct queue_item *item = &items[position]; uint8_t old_priority = item->priority; if (old_priority == priority) return false; - item->version = queue->version; + item->version = version; item->priority = priority; - if (!queue->random) + if (!random) /* don't reorder if not in random mode */ return true; - unsigned order = queue_position_to_order(queue, position); + unsigned _order = PositionToOrder(position); if (after_order >= 0) { - if (order == (unsigned)after_order) + if (_order == (unsigned)after_order) /* don't reorder the current song */ return true; - if (order < (unsigned)after_order) { + if (_order < (unsigned)after_order) { /* the specified song has been played already - enqueue it only if its priority has just become bigger than the current one's */ const unsigned after_position = - queue_order_to_position(queue, after_order); + OrderToPosition(after_order); const struct queue_item *after_item = - &queue->items[after_position]; + &items[after_position]; if (old_priority > after_item->priority || priority <= after_item->priority) /* 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) */ const unsigned before_order = - queue_find_priority_order(queue, after_order + 1, priority, - order); - const unsigned new_order = before_order > order + queue_find_priority_order(this, after_order + 1, priority, + _order); + const unsigned new_order = before_order > _order ? before_order - 1 : before_order; - queue_move_order(queue, order, new_order); + queue_move_order(this, _order, new_order); /* shuffle the song within that priority group */ const unsigned priority_count = - queue_count_same_priority(queue, new_order, priority); + queue_count_same_priority(this, new_order, priority); assert(priority_count >= 1); - queue_shuffle_order_first(queue, new_order, + queue_shuffle_order_first(this, new_order, new_order + priority_count); return true; } bool -queue_set_priority_range(struct queue *queue, - unsigned start_position, unsigned end_position, - uint8_t priority, int after_order) +queue::SetPriorityRange(unsigned start_position, unsigned end_position, + uint8_t priority, int after_order) { - assert(queue != NULL); assert(start_position <= end_position); - assert(end_position <= queue->length); + assert(end_position <= length); bool modified = false; int after_position = after_order >= 0 - ? (int)queue_order_to_position(queue, after_order) + ? (int)OrderToPosition(after_order) : -1; for (unsigned i = start_position; i < end_position; ++i) { after_order = after_position >= 0 - ? (int)queue_position_to_order(queue, after_position) + ? (int)PositionToOrder(after_position) : -1; - modified |= queue_set_priority(queue, i, priority, - after_order); + modified |= SetPriority(i, priority, after_order); } return modified; diff --git a/src/Queue.hxx b/src/Queue.hxx index 6ab0a833f..501fb0564 100644 --- a/src/Queue.hxx +++ b/src/Queue.hxx @@ -20,10 +20,11 @@ #ifndef MPD_QUEUE_HXX #define MPD_QUEUE_HXX +#include "gcc.h" + #include <glib.h> #include <assert.h> -#include <stdbool.h> #include <stdint.h> enum { @@ -110,268 +111,222 @@ struct queue { queue(const queue &other) = delete; queue &operator=(const queue &other) = delete; -}; -static inline unsigned -queue_length(const struct queue *queue) -{ - assert(queue->length <= queue->max_length); + unsigned GetLength() const { + assert(length <= max_length); - return queue->length; -} + return 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 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. - */ -static inline bool -queue_is_full(const struct queue *queue) -{ - assert(queue->length <= queue->max_length); + /** + * Determine if the maximum number of songs has been reached. + */ + bool IsFull() const { + assert(length <= max_length); - return queue->length >= queue->max_length; -} + return length >= 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 position number? + */ + bool IsValidPosition(unsigned position) const { + return position < 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; + /** + * Is that a valid order number? + */ + bool IsValidOrder(unsigned _order) const { + return _order < length; } -} -G_GNUC_PURE -static inline uint8_t -queue_get_priority_at_position(const struct queue *queue, unsigned position) -{ - assert(position < queue->length); + int IdToPosition(unsigned id) const { + if (id >= max_length * QUEUE_HASH_MULT) + return -1; - return queue->items[position].priority; -} + assert(id_to_position[id] >= -1); + assert(id_to_position[id] < (int)length); -/** - * Returns the song at the specified position. - */ -static inline struct song * -queue_get(const struct queue *queue, unsigned position) -{ - assert(position < queue->length); + return id_to_position[id]; + } - return queue->items[position].song; -} + int PositionToId(unsigned position) const + { + assert(position < length); -/** - * 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)); -} + return items[position].id; + } -/** - * 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); + gcc_pure + unsigned OrderToPosition(unsigned _order) const { + assert(_order < length); - return version > queue->version || - queue->items[position].version >= version || - queue->items[position].version == 0; -} + return order[_order]; + } -/** - * 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); + gcc_pure + unsigned PositionToOrder(unsigned position) const { + assert(position < length); -/** - * Increments the queue's version number. This handles integer - * overflow well. - */ -void -queue_increment_version(struct queue *queue); + for (unsigned i = 0;; ++i) { + assert(i < length); -/** - * Marks the specified song as "modified" and increments the version - * number. - */ -void -queue_modify(struct queue *queue, unsigned order); + if (order[i] == position) + return i; + } + } -/** - * Marks all songs as "modified" and increments the version number. - */ -void -queue_modify_all(struct queue *queue); + G_GNUC_PURE + uint8_t GetPriorityAtPosition(unsigned position) const { + assert(position < length); -/** - * 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); + return items[position].priority; + } -/** - * Swaps two songs, addressed by their position. - */ -void -queue_swap(struct queue *queue, unsigned position1, unsigned position2); + /** + * Returns the song at the specified position. + */ + struct song *Get(unsigned position) const { + assert(position < length); -/** - * 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; -} + return items[position].song; + } -/** - * Moves a song to a new position. - */ -void -queue_move(struct queue *queue, unsigned from, unsigned to); + /** + * Returns the song at the specified order number. + */ + struct song *GetOrder(unsigned _order) const { + return Get(OrderToPosition(_order)); + } -/** - * Moves a range of songs to a new position. - */ -void -queue_move_range(struct queue *queue, unsigned start, unsigned end, unsigned to); + /** + * Is the song at the specified position newer than the specified + * version? + */ + bool IsNewerAtPosition(unsigned position, uint32_t _version) const { + assert(position < length); -/** - * Removes a song from the playlist. - */ -void -queue_delete(struct queue *queue, unsigned position); + return _version > version || + items[position].version >= _version || + items[position].version == 0; + } -/** - * Removes all songs from the playlist. - */ -void -queue_clear(struct queue *queue); + /** + * 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; -/** - * 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; -} + /** + * Increments the queue's version number. This handles integer + * overflow well. + */ + void IncrementVersion(); -/** - * 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); + /** + * Marks the specified song as "modified" and increments the version + * number. + */ + void ModifyAtOrder(unsigned order); -/** - * 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); + /** + * Marks all songs as "modified" and increments the version number. + */ + void ModifyAll(); -/** - * 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); + /** + * 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); -/** - * 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); + /** + * Swaps two songs, addressed by their position. + */ + void SwapPositions(unsigned position1, unsigned position2); -bool -queue_set_priority(struct queue *queue, unsigned position, - uint8_t priority, int after_order); + /** + * 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; + } -bool -queue_set_priority_range(struct queue *queue, - unsigned start_position, unsigned end_position, - uint8_t priority, int after_order); + /** + * 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); +}; #endif diff --git a/src/QueueCommands.cxx b/src/QueueCommands.cxx index 72649444b..3e24f0c92 100644 --- a/src/QueueCommands.cxx +++ b/src/QueueCommands.cxx @@ -171,7 +171,7 @@ enum command_return handle_shuffle(G_GNUC_UNUSED Client *client, 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])) return COMMAND_RETURN_ERROR; diff --git a/src/QueuePrint.cxx b/src/QueuePrint.cxx index 289ae26b8..28abc5a8c 100644 --- a/src/QueuePrint.cxx +++ b/src/QueuePrint.cxx @@ -41,11 +41,11 @@ static void queue_print_song_info(Client *client, const struct queue *queue, 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", - 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) client_printf(client, "Prio: %u\n", priority); } @@ -55,7 +55,7 @@ queue_print_info(Client *client, const struct queue *queue, unsigned start, unsigned end) { assert(start <= end); - assert(end <= queue_length(queue)); + assert(end <= queue->GetLength()); for (unsigned i = start; i < end; ++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) { assert(start <= end); - assert(end <= queue_length(queue)); + assert(end <= queue->GetLength()); for (unsigned i = start; i < end; ++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, uint32_t version) { - for (unsigned i = 0; i < queue_length(queue); i++) { - if (queue_song_newer(queue, i, version)) + for (unsigned i = 0; i < queue->GetLength(); i++) { + if (queue->IsNewerAtPosition(i, version)) queue_print_song_info(client, queue, i); } } @@ -88,18 +88,18 @@ void queue_print_changes_position(Client *client, const struct queue *queue, uint32_t version) { - for (unsigned i = 0; i < queue_length(queue); i++) - if (queue_song_newer(queue, i, version)) + for (unsigned i = 0; i < queue->GetLength(); i++) + if (queue->IsNewerAtPosition(i, version)) client_printf(client, "cpos: %i\nId: %i\n", - i, queue_position_to_id(queue, i)); + i, queue->PositionToId(i)); } void queue_find(Client *client, const struct queue *queue, const SongFilter &filter) { - for (unsigned i = 0; i < queue_length(queue); i++) { - const struct song *song = queue_get(queue, i); + for (unsigned i = 0; i < queue->GetLength(); i++) { + const struct song *song = queue->Get(i); if (filter.Match(*song)) queue_print_song_info(client, queue, i); diff --git a/src/QueueSave.cxx b/src/QueueSave.cxx index a667bc855..09b0645f8 100644 --- a/src/QueueSave.cxx +++ b/src/QueueSave.cxx @@ -61,19 +61,19 @@ queue_save_song(FILE *fp, int idx, const struct song *song) void queue_save(FILE *fp, const struct queue *queue) { - for (unsigned i = 0; i < queue_length(queue); i++) { - uint8_t prio = queue_get_priority_at_position(queue, i); + for (unsigned i = 0; i < queue->GetLength(); i++) { + uint8_t prio = queue->GetPriorityAtPosition(i); if (prio != 0) 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 queue_load_song(TextFile &file, const char *line, queue *queue) { - if (queue_is_full(queue)) + if (queue->IsFull()) return; 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) db->ReturnSong(song); diff --git a/test/TestQueuePriority.cxx b/test/TestQueuePriority.cxx index 5a0f69167..cab56d82f 100644 --- a/test/TestQueuePriority.cxx +++ b/test/TestQueuePriority.cxx @@ -23,21 +23,21 @@ G_GNUC_UNUSED static void dump_order(const struct queue *queue) { - g_printerr("queue length=%u, order:\n", queue_length(queue)); - for (unsigned i = 0; i < queue_length(queue); ++i) + g_printerr("queue length=%u, order:\n", queue->GetLength()); + for (unsigned i = 0; i < queue->GetLength(); ++i) g_printerr(" [%u] -> %u (prio=%u)\n", i, queue->order[i], queue->items[queue->order[i]].priority); } static void -check_descending_priority(G_GNUC_UNUSED const struct queue *queue, +check_descending_priority(const struct queue *queue, unsigned start_order) { - assert(start_order < queue_length(queue)); + assert(start_order < queue->GetLength()); uint8_t last_priority = 0xff; - for (unsigned order = start_order; order < queue_length(queue); ++order) { - unsigned position = queue_order_to_position(queue, order); + for (unsigned order = start_order; order < queue->GetLength(); ++order) { + unsigned position = queue->OrderToPosition(order); uint8_t priority = queue->items[position].priority; assert(priority <= last_priority); (void)last_priority; @@ -48,74 +48,74 @@ check_descending_priority(G_GNUC_UNUSED const struct queue *queue, int main(G_GNUC_UNUSED int argc, G_GNUC_UNUSED char **argv) { - struct song songs[16]; + static struct song songs[16]; struct queue queue(32); 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 */ - queue_set_priority_range(&queue, 4, 8, 10, -1); + queue.SetPriorityRange(4, 8, 10, -1); queue.random = true; - queue_shuffle_order(&queue); + queue.ShuffleOrder(); check_descending_priority(&queue, 0); 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) { - assert(queue_position_to_order(&queue, i) < 4); + assert(queue.PositionToOrder(i) < 4); } 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 */ - queue_set_priority_range(&queue, 15, 16, 50, -1); + queue.SetPriorityRange(15, 16, 50, -1); 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) { - assert(queue_position_to_order(&queue, i) >= 4); + assert(queue.PositionToOrder(i) >= 4); } for (unsigned i = 4; i < 8; ++i) { - assert(queue_position_to_order(&queue, i) >= 1 && - queue_position_to_order(&queue, i) < 5); + assert(queue.PositionToOrder(i) >= 1 && + queue.PositionToOrder(i) < 5); } 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 */ - queue_set_priority_range(&queue, 3, 4, 20, -1); + queue.SetPriorityRange(3, 4, 20, -1); check_descending_priority(&queue, 0); - assert(queue_position_to_order(&queue, 3) == 1); - assert(queue_position_to_order(&queue, 15) == 0); + assert(queue.PositionToOrder(3) == 1); + assert(queue.PositionToOrder(15) == 0); 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) { - assert(queue_position_to_order(&queue, i) >= 2 && - queue_position_to_order(&queue, i) < 6); + assert(queue.PositionToOrder(i) >= 2 && + queue.PositionToOrder(i) < 6); } 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; @@ -124,17 +124,17 @@ main(G_GNUC_UNUSED int argc, G_GNUC_UNUSED char **argv) unsigned current_order = 4; unsigned current_position = - queue_order_to_position(&queue, current_order); + queue.OrderToPosition(current_order); 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); - 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); - a_order = queue_position_to_order(&queue, a_position); + a_order = queue.PositionToOrder(a_position); assert(a_order == 4); check_descending_priority(&queue, current_order + 1); @@ -144,14 +144,14 @@ main(G_GNUC_UNUSED int argc, G_GNUC_UNUSED char **argv) just created */ 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); - 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); - b_order = queue_position_to_order(&queue, b_position); + b_order = queue.PositionToOrder(b_position); assert(b_order == 4); 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) */ 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); - 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); - c_order = queue_position_to_order(&queue, c_position); + c_order = queue.PositionToOrder(c_position); assert(c_order == 0); /* 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(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_position_to_order(&queue, current_position); + current_order = queue.PositionToOrder(current_position); assert(current_order == 3); - a_order = queue_position_to_order(&queue, a_position); + a_order = queue.PositionToOrder(a_position); assert(a_order == 6); } |