aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2011-10-06 20:30:46 +0200
committerMax Kellermann <max@duempel.org>2011-10-06 21:22:48 +0200
commitb2f03e76ffd3af918d8eda0968f54c0b81bbff54 (patch)
treea504e4ef529b087f27c3ff862088fb27cf18afc0
parent63b33b6ec584a6730174c45a119a27b4add76777 (diff)
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.
-rw-r--r--NEWS1
-rw-r--r--src/player_thread.c22
2 files changed, 18 insertions, 5 deletions
diff --git a/NEWS b/NEWS
index eab7062f..44f78e47 100644
--- a/NEWS
+++ b/NEWS
@@ -14,6 +14,7 @@ ver 0.16.5 (2010/??/??)
- make seeking to CUE track more reliable
- the "seek" command works when MPD is stopped
- restore song position from state file (bug fix)
+ - fix crash that sometimes occurred when audio device fails on startup
* WIN32: close sockets properly
* install systemd service file if systemd is available
diff --git a/src/player_thread.c b/src/player_thread.c
index 9a7c917f..52788e51 100644
--- a/src/player_thread.c
+++ b/src/player_thread.c
@@ -74,6 +74,14 @@ struct player {
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
*/
struct song *song;
@@ -290,6 +298,7 @@ player_open_output(struct player *player)
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();
@@ -298,6 +307,8 @@ player_open_output(struct player *player)
return true;
} else {
+ player->output_open = false;
+
/* pause: the user may resume playback as soon as an
audio output becomes available */
player->paused = true;
@@ -342,7 +353,7 @@ player_check_decoder_startup(struct player *player)
decoder_unlock(dc);
- if (audio_format_defined(&player->play_audio_format) &&
+ if (player->output_open &&
!audio_output_all_wait(1))
/* the output devices havn't finished playing
all chunks yet - wait for that */
@@ -386,6 +397,7 @@ player_check_decoder_startup(struct player *player)
static bool
player_send_silence(struct player *player)
{
+ assert(player->output_open);
assert(audio_format_defined(&player->play_audio_format));
struct music_chunk *chunk = music_buffer_allocate(player_buffer);
@@ -579,8 +591,7 @@ static void player_process_command(struct player *player)
break;
case PLAYER_COMMAND_REFRESH:
- if (audio_format_defined(&player->play_audio_format) &&
- !player->paused) {
+ if (player->output_open && !player->paused) {
player_unlock();
audio_output_all_check();
player_lock();
@@ -831,6 +842,7 @@ static void do_play(struct decoder_control *dc)
.decoder_starting = false,
.paused = false,
.queued = true,
+ .output_open = false,
.song = NULL,
.xfade = XFADE_UNKNOWN,
.cross_fading = false,
@@ -883,7 +895,7 @@ static void do_play(struct decoder_control *dc)
/* not enough decoded buffer space yet */
if (!player.paused &&
- audio_format_defined(&player.play_audio_format) &&
+ player.output_open &&
audio_output_all_check() < 4 &&
!player_send_silence(&player))
break;
@@ -988,7 +1000,7 @@ static void do_play(struct decoder_control *dc)
audio_output_all_drain();
break;
}
- } else {
+ } else if (player.output_open) {
/* the decoder is too busy and hasn't provided
new PCM data in time: send silence (if the
output pipe is empty) */