Пример #1
0
/**
 * This is the "PLAYLIST" event handler.  It is invoked by the player
 * thread whenever it requests a new queued song, or when it exits.
 */
void
playlist_sync(struct playlist *playlist, struct player_control *pc)
{
	if (!playlist->playing)
		/* this event has reached us out of sync: we aren't
		   playing anymore; ignore the event */
		return;

	player_lock(pc);
	enum player_state pc_state = pc_get_state(pc);
	const struct song *pc_next_song = pc->next_song;
	player_unlock(pc);

	if (pc_state == PLAYER_STATE_STOP)
		/* the player thread has stopped: check if playback
		   should be restarted with the next song.  That can
		   happen if the playlist isn't filling the queue fast
		   enough */
		playlist_resume_playback(playlist, pc);
	else {
		/* check if the player thread has already started
		   playing the queued song */
		if (pc_next_song == NULL && playlist->queued != -1)
			playlist_song_started(playlist, pc);

		player_lock(pc);
		pc_next_song = pc->next_song;
		player_unlock(pc);

		/* make sure the queued song is always set (if
		   possible) */
		if (pc_next_song == NULL && playlist->queued < 0)
			playlist_update_queued_song(playlist, pc, NULL);
	}
}
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--;
	}
}
Пример #3
0
/**
 * The player has stopped for some reason.  Check the error, and
 * decide whether to re-start playback
 */
static void
playlist_resume_playback(struct playlist *playlist, struct player_control *pc)
{
	enum player_error error;

	assert(playlist->playing);
	assert(pc_get_state(pc) == PLAYER_STATE_STOP);

	error = pc_get_error_type(pc);
	if (error == PLAYER_ERROR_NONE)
		playlist->error_count = 0;
	else
		++playlist->error_count;

	if ((playlist->stop_on_error && error != PLAYER_ERROR_NONE) ||
	    error == PLAYER_ERROR_OUTPUT ||
	    playlist->error_count >= queue_length(&playlist->queue))
		/* too many errors, or critical error: stop
		   playback */
		playlist_stop(playlist, pc);
	else
		/* continue playback at the next song */
		playlist_next(playlist, pc);
}