Exemple #1
0
/**
 * Wrapper for audio_output_all_open().  Upon failure, it pauses the
 * player.
 *
 * @return true on success
 */
static bool
player_open_output(struct player *player)
{
	assert(audio_format_defined(&player->play_audio_format));
	assert(pc.state == PLAYER_STATE_PLAY ||
	       pc.state == PLAYER_STATE_PAUSE);

	if (audio_output_all_open(&player->play_audio_format, player_buffer)) {
		player->output_open = true;
		player->paused = false;

		player_lock();
		pc.state = PLAYER_STATE_PLAY;
		player_unlock();

		return true;
	} else {
		player->output_open = false;

		/* pause: the user may resume playback as soon as an
		   audio output becomes available */
		player->paused = true;

		player_lock();
		pc.error = PLAYER_ERROR_AUDIO;
		pc.state = PLAYER_STATE_PAUSE;
		player_unlock();

		return false;
	}
}
Exemple #2
0
/**
 * Wrapper for audio_output_all_open().  Upon failure, it pauses the
 * player.
 *
 * @return true on success
 */
static bool
player_open_output(struct player *player)
{
	struct player_control *pc = player->pc;

	assert(audio_format_defined(&player->play_audio_format));
	assert(pc->state == PLAYER_STATE_PLAY ||
	       pc->state == PLAYER_STATE_PAUSE);

	GError *error = NULL;
	if (audio_output_all_open(&player->play_audio_format, player_buffer,
				  &error)) {
		player->output_open = true;
		player->paused = false;

		player_lock(pc);
		pc->state = PLAYER_STATE_PLAY;
		player_unlock(pc);

		return true;
	} else {
		g_warning("%s", error->message);

		player->output_open = false;

		/* pause: the user may resume playback as soon as an
		   audio output becomes available */
		player->paused = true;

		player_lock(pc);
		pc_set_error(pc, PLAYER_ERROR_OUTPUT, error);
		pc->state = PLAYER_STATE_PAUSE;
		player_unlock(pc);

		return false;
	}
}
/**
 * Player lock must be held before calling.
 */
static void player_process_command(struct player *player)
{
	struct player_control *pc = player->pc;
	G_GNUC_UNUSED struct decoder_control *dc = player->dc;

	switch (pc->command) {
	case PLAYER_COMMAND_NONE:
	case PLAYER_COMMAND_STOP:
	case PLAYER_COMMAND_EXIT:
	case PLAYER_COMMAND_CLOSE_AUDIO:
		break;

	case PLAYER_COMMAND_UPDATE_AUDIO:
		player_unlock(pc);
		audio_output_all_enable_disable();
		player_lock(pc);
		player_command_finished_locked(pc);
		break;

	case PLAYER_COMMAND_QUEUE:
		assert(pc->next_song != NULL);
		assert(!player->queued);
		assert(!player_dc_at_next_song(player));

		player->queued = true;
		player_command_finished_locked(pc);
		break;

	case PLAYER_COMMAND_PAUSE:
		player_unlock(pc);

		player->paused = !player->paused;
		if (player->paused) {
			audio_output_all_pause();
			player_lock(pc);

			pc->state = PLAYER_STATE_PAUSE;
		} else if (!audio_format_defined(&player->play_audio_format)) {
			/* the decoder hasn't provided an audio format
			   yet - don't open the audio device yet */
			player_lock(pc);

			pc->state = PLAYER_STATE_PLAY;
		} else if (audio_output_all_open(&player->play_audio_format, player_buffer)) {
			/* unpaused, continue playing */
			player_lock(pc);

			pc->state = PLAYER_STATE_PLAY;
		} else {
			/* the audio device has failed - rollback to
			   pause mode */
			pc->error = PLAYER_ERROR_AUDIO;

			player->paused = true;

			player_lock(pc);
		}

		player_command_finished_locked(pc);
		break;

	case PLAYER_COMMAND_SEEK:
		player_unlock(pc);
		player_seek_decoder(player);
		player_lock(pc);
		break;

	case PLAYER_COMMAND_CANCEL:
		if (pc->next_song == NULL) {
			/* the cancel request arrived too late, we're
			   already playing the queued song...  stop
			   everything now */
			pc->command = PLAYER_COMMAND_STOP;
			return;
		}

		if (player_dc_at_next_song(player)) {
			/* the decoder is already decoding the song -
			   stop it and reset the position */
			player_unlock(pc);
			player_dc_stop(player);
			player_lock(pc);
		}

		pc->next_song = NULL;
		player->queued = false;
		player_command_finished_locked(pc);
		break;

	case PLAYER_COMMAND_REFRESH:
		if (audio_format_defined(&player->play_audio_format) &&
		    !player->paused) {
			player_unlock(pc);
			audio_output_all_check();
			player_lock(pc);
		}

		pc->elapsed_time = audio_output_all_get_elapsed_time();
		if (pc->elapsed_time < 0.0)
			pc->elapsed_time = player->elapsed_time;

		player_command_finished_locked(pc);
		break;
	}
}
/**
 * The decoder has acknowledged the "START" command (see
 * player_wait_for_decoder()).  This function checks if the decoder
 * initialization has completed yet.
 *
 * The player lock is not held.
 */
static bool
player_check_decoder_startup(struct player *player)
{
	struct player_control *pc = player->pc;
	struct decoder_control *dc = player->dc;

	assert(player->decoder_starting);

	decoder_lock(dc);

	if (decoder_has_failed(dc)) {
		/* the decoder failed */
		decoder_unlock(dc);

		player_lock(pc);
		pc->errored_song = dc->song;
		pc->error = PLAYER_ERROR_FILE;
		player_unlock(pc);

		return false;
	} else if (!decoder_is_starting(dc)) {
		/* the decoder is ready and ok */

		decoder_unlock(dc);

		if (audio_format_defined(&player->play_audio_format) &&
		    !audio_output_all_wait(pc, 1))
			/* the output devices havn't finished playing
			   all chunks yet - wait for that */
			return true;

		player_lock(pc);
		pc->total_time = real_song_duration(dc->song, dc->total_time);
		pc->audio_format = dc->in_audio_format;
		player_unlock(pc);

		player->play_audio_format = dc->out_audio_format;
		player->decoder_starting = false;

		if (!player->paused &&
		    !audio_output_all_open(&dc->out_audio_format,
					   player_buffer)) {
			char *uri = song_get_uri(dc->song);
			g_warning("problems opening audio device "
				  "while playing \"%s\"", uri);
			g_free(uri);

			player_lock(pc);
			pc->error = PLAYER_ERROR_AUDIO;

			/* pause: the user may resume playback as soon
			   as an audio output becomes available */
			pc->state = PLAYER_STATE_PAUSE;
			player_unlock(pc);

			player->paused = true;
			return true;
		}

		return true;
	} else {
		/* the decoder is not yet ready; wait
		   some more */
		player_wait_decoder(pc, dc);
		decoder_unlock(dc);

		return true;
	}
}