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:
parent
63b33b6ec5
commit
b2f03e76ff
1
NEWS
1
NEWS
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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) */
|
||||||
|
|
Loading…
Reference in New Issue