player_thread: add flag "output_open", fixes assertion failure

Previously, the condition "defined(play_audio_format)" was used to see
if an output device has been opened, but if the device had failed on
startup, an assertion failure could occur.  This patch adds a separate
flag.
This commit is contained in:
Max Kellermann 2011-10-06 20:30:46 +02:00
parent 63b33b6ec5
commit b2f03e76ff
2 changed files with 18 additions and 5 deletions

1
NEWS
View File

@ -14,6 +14,7 @@ ver 0.16.5 (2010/??/??)
- make seeking to CUE track more reliable - make seeking to CUE track more reliable
- the "seek" command works when MPD is stopped - the "seek" command works when MPD is stopped
- restore song position from state file (bug fix) - restore song position from state file (bug fix)
- fix crash that sometimes occurred when audio device fails on startup
* WIN32: close sockets properly * WIN32: close sockets properly
* install systemd service file if systemd is available * install systemd service file if systemd is available

View File

@ -73,6 +73,14 @@ struct player {
*/ */
bool queued; bool queued;
/**
* Was any audio output opened successfully? It might have
* failed meanwhile, but was not explicitly closed by the
* player thread. When this flag is unset, some output
* methods must not be called.
*/
bool output_open;
/** /**
* the song currently being played * the song currently being played
*/ */
@ -290,6 +298,7 @@ player_open_output(struct player *player)
pc.state == PLAYER_STATE_PAUSE); pc.state == PLAYER_STATE_PAUSE);
if (audio_output_all_open(&player->play_audio_format, player_buffer)) { if (audio_output_all_open(&player->play_audio_format, player_buffer)) {
player->output_open = true;
player->paused = false; player->paused = false;
player_lock(); player_lock();
@ -298,6 +307,8 @@ player_open_output(struct player *player)
return true; return true;
} else { } else {
player->output_open = false;
/* pause: the user may resume playback as soon as an /* pause: the user may resume playback as soon as an
audio output becomes available */ audio output becomes available */
player->paused = true; player->paused = true;
@ -342,7 +353,7 @@ player_check_decoder_startup(struct player *player)
decoder_unlock(dc); decoder_unlock(dc);
if (audio_format_defined(&player->play_audio_format) && if (player->output_open &&
!audio_output_all_wait(1)) !audio_output_all_wait(1))
/* the output devices havn't finished playing /* the output devices havn't finished playing
all chunks yet - wait for that */ all chunks yet - wait for that */
@ -386,6 +397,7 @@ player_check_decoder_startup(struct player *player)
static bool static bool
player_send_silence(struct player *player) player_send_silence(struct player *player)
{ {
assert(player->output_open);
assert(audio_format_defined(&player->play_audio_format)); assert(audio_format_defined(&player->play_audio_format));
struct music_chunk *chunk = music_buffer_allocate(player_buffer); struct music_chunk *chunk = music_buffer_allocate(player_buffer);
@ -579,8 +591,7 @@ static void player_process_command(struct player *player)
break; break;
case PLAYER_COMMAND_REFRESH: case PLAYER_COMMAND_REFRESH:
if (audio_format_defined(&player->play_audio_format) && if (player->output_open && !player->paused) {
!player->paused) {
player_unlock(); player_unlock();
audio_output_all_check(); audio_output_all_check();
player_lock(); player_lock();
@ -831,6 +842,7 @@ static void do_play(struct decoder_control *dc)
.decoder_starting = false, .decoder_starting = false,
.paused = false, .paused = false,
.queued = true, .queued = true,
.output_open = false,
.song = NULL, .song = NULL,
.xfade = XFADE_UNKNOWN, .xfade = XFADE_UNKNOWN,
.cross_fading = false, .cross_fading = false,
@ -883,7 +895,7 @@ static void do_play(struct decoder_control *dc)
/* not enough decoded buffer space yet */ /* not enough decoded buffer space yet */
if (!player.paused && if (!player.paused &&
audio_format_defined(&player.play_audio_format) && player.output_open &&
audio_output_all_check() < 4 && audio_output_all_check() < 4 &&
!player_send_silence(&player)) !player_send_silence(&player))
break; break;
@ -988,7 +1000,7 @@ static void do_play(struct decoder_control *dc)
audio_output_all_drain(); audio_output_all_drain();
break; break;
} }
} else { } else if (player.output_open) {
/* the decoder is too busy and hasn't provided /* the decoder is too busy and hasn't provided
new PCM data in time: send silence (if the new PCM data in time: send silence (if the
output pipe is empty) */ output pipe is empty) */