/** * 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; } }
/** * 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; } }