void queue_shuffle_order(struct queue *queue) { assert(queue->random); for (unsigned i = 0; i < queue->length; i++) queue_swap_order(queue, i, g_rand_int_range(queue->rand, i, queue->length)); }
enum playlist_result playlist_play(struct playlist *playlist, struct player_control *pc, int song) { unsigned i = song; pc_clear_error(pc); if (song == -1) { /* play any song ("current" song, or the first song */ if (queue_is_empty(&playlist->queue)) return PLAYLIST_RESULT_SUCCESS; if (playlist->playing) { /* already playing: unpause playback, just in case it was paused, and return */ pc_set_pause(pc, false); return PLAYLIST_RESULT_SUCCESS; } /* select a song: "current" song, or the first one */ i = playlist->current >= 0 ? playlist->current : 0; } else if (!queue_valid_position(&playlist->queue, song)) return PLAYLIST_RESULT_BAD_RANGE; if (playlist->queue.random) { if (song >= 0) /* "i" is currently the song position (which 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); 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); i = playlist->current; } playlist->stop_on_error = false; playlist->error_count = 0; playlist_play_order(playlist, pc, i); return PLAYLIST_RESULT_SUCCESS; }
void playlist_set_random(struct playlist *playlist, struct player_control *pc, bool status) { const struct song *queued; if (status == playlist->queue.random) return; queued = playlist_get_queued_song(playlist); playlist->queue.random = status; if (playlist->queue.random) { /* shuffle the queue order, but preserve playlist->current */ int current_position = playlist->playing && playlist->current >= 0 ? (int)queue_order_to_position(&playlist->queue, playlist->current) : -1; queue_shuffle_order(&playlist->queue); 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->current = 0; } else playlist->current = -1; } else playlist_order(playlist); playlist_update_queued_song(playlist, pc, queued); idle_add(IDLE_OPTIONS); }
enum playlist_result playlist_swap_songs(struct playlist *playlist, struct player_control *pc, unsigned song1, unsigned song2) { const struct song *queued; if (!queue_valid_position(&playlist->queue, song1) || !queue_valid_position(&playlist->queue, song2)) return PLAYLIST_RESULT_BAD_RANGE; queued = playlist_get_queued_song(playlist); queue_swap(&playlist->queue, 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)); } else { /* correct the "current" song order */ if (playlist->current == (int)song1) playlist->current = song2; else if (playlist->current == (int)song2) playlist->current = song1; } playlist_increment_version(playlist); playlist_update_queued_song(playlist, pc, queued); return PLAYLIST_RESULT_SUCCESS; }
void queue_shuffle_order_last(struct queue *queue, unsigned start, unsigned end) { queue_swap_order(queue, end - 1, g_rand_int_range(queue->rand, start, end)); }