void playlist_update_queued_song(struct playlist *playlist, struct player_control *pc, const struct song *prev) { int next_order; const struct song *next_song; if (!playlist->playing) return; assert(!queue_is_empty(&playlist->queue)); assert((playlist->queued < 0) == (prev == NULL)); next_order = playlist->current >= 0 ? queue_next_order(&playlist->queue, playlist->current) : 0; if (next_order == 0 && playlist->queue.random && !playlist->queue.single) { /* shuffle the song order again, so we get a different order each time the playlist is played completely */ unsigned current_position = queue_order_to_position(&playlist->queue, playlist->current); queue_shuffle_order(&playlist->queue); /* 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); } if (next_order >= 0) next_song = queue_get_order(&playlist->queue, next_order); else next_song = NULL; if (prev != NULL && next_song != prev) { /* clear the currently queued song */ pc_cancel(pc); playlist->queued = -1; } if (next_order >= 0) { if (next_song != prev) playlist_queue_song_order(playlist, pc, next_order); else playlist->queued = next_order; } }
static void playlist_delete_internal(struct playlist *playlist, unsigned song, const struct song **queued_p) { unsigned songOrder; assert(song < queue_length(&playlist->queue)); songOrder = queue_position_to_order(&playlist->queue, song); if (playlist->playing && playlist->current == (int)songOrder) { bool paused = pc_get_state() == PLAYER_STATE_PAUSE; /* the current song is going to be deleted: stop the player */ pc_stop(); playlist->playing = false; /* see which song is going to be played instead */ playlist->current = queue_next_order(&playlist->queue, playlist->current); if (playlist->current == (int)songOrder) playlist->current = -1; if (playlist->current >= 0 && !paused) /* play the song after the deleted one */ playlist_play_order(playlist, playlist->current); else /* no songs left to play, stop playback completely */ playlist_stop(playlist); *queued_p = NULL; } else if (playlist->current == (int)songOrder) /* there's a "current song" but we're not playing currently - clear "current" */ playlist->current = -1; /* now do it: remove the song */ if (!song_in_database(queue_get(&playlist->queue, song))) pc_song_deleted(queue_get(&playlist->queue, song)); queue_delete(&playlist->queue, song); /* update the "current" and "queued" variables */ if (playlist->current > (int)songOrder) { playlist->current--; } }
void playlist_next(struct playlist *playlist, struct player_control *pc) { int next_order; int current; if (!playlist->playing) return; assert(!queue_is_empty(&playlist->queue)); assert(queue_valid_order(&playlist->queue, 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); if (next_order < 0) { /* no song after this one: stop playback */ playlist_stop(playlist, pc); /* reset "current song" */ playlist->current = -1; } else { if (next_order == 0 && playlist->queue.random) { /* The queue told us that the next song is the first song. This means we are in repeat mode. Shuffle the queue order, so this time, the user hears the songs in a different than before */ assert(playlist->queue.repeat); queue_shuffle_order(&playlist->queue); /* note that playlist->current and playlist->queued are now invalid, but playlist_play_order() will discard them anyway */ } playlist_play_order(playlist, pc, next_order); } /* Consume mode removes each played songs. */ if(playlist->queue.consume) playlist_delete(playlist, pc, queue_order_to_position(&playlist->queue, current)); }