Skip to content

Commit 81e0efb

Browse files
gnifkraxel
authored andcommitted
audio/jack: honour the enable state of the audio device
When the guest closes the audio device we must start dropping input samples from JACK and zeroing the output buffer samples. Failure to do so causes sound artifacts during operations such as guest OS reboot, and causes a hang of the input pipeline breaking it until QEMU is restated. Closing and reconnecting to JACK was tested during these enable/disable calls which works well for Linux guests, however Windows re-opens the audio hardware repeatedly even when doing simple tasks like playing a system sounds. As such it was decided it is better to feed silence to JACK while the device is disabled. Signed-off-by: Geoffrey McRae <[email protected]> Message-id: [email protected] Signed-off-by: Gerd Hoffmann <[email protected]>
1 parent de82640 commit 81e0efb

File tree

1 file changed

+21
-8
lines changed

1 file changed

+21
-8
lines changed

audio/jackaudio.c

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ typedef struct QJackClient {
5656
AudiodevJackPerDirectionOptions *opt;
5757

5858
bool out;
59-
bool finished;
59+
bool enabled;
6060
bool connect_ports;
6161
int packets;
6262

@@ -271,9 +271,17 @@ static int qjack_process(jack_nframes_t nframes, void *arg)
271271
}
272272

273273
if (c->out) {
274-
qjack_buffer_read_l(&c->fifo, buffers, nframes);
274+
if (likely(c->enabled)) {
275+
qjack_buffer_read_l(&c->fifo, buffers, nframes);
276+
} else {
277+
for(int i = 0; i < c->nchannels; ++i) {
278+
memset(buffers[i], 0, nframes * sizeof(float));
279+
}
280+
}
275281
} else {
276-
qjack_buffer_write_l(&c->fifo, buffers, nframes);
282+
if (likely(c->enabled)) {
283+
qjack_buffer_write_l(&c->fifo, buffers, nframes);
284+
}
277285
}
278286

279287
return 0;
@@ -314,8 +322,8 @@ static void qjack_client_recover(QJackClient *c)
314322
if (c->state == QJACK_STATE_DISCONNECTED &&
315323
c->packets % 100 == 0) {
316324

317-
/* if not finished then attempt to recover */
318-
if (!c->finished) {
325+
/* if enabled then attempt to recover */
326+
if (c->enabled) {
319327
dolog("attempting to reconnect to server\n");
320328
qjack_client_init(c);
321329
}
@@ -387,7 +395,6 @@ static int qjack_client_init(QJackClient *c)
387395
char client_name[jack_client_name_size()];
388396
jack_options_t options = JackNullOption;
389397

390-
c->finished = false;
391398
c->connect_ports = true;
392399

393400
snprintf(client_name, sizeof(client_name), "%s-%s",
@@ -483,8 +490,10 @@ static int qjack_init_out(HWVoiceOut *hw, struct audsettings *as,
483490
}
484491

485492
jo->c.out = true;
493+
jo->c.enabled = false;
486494
jo->c.nchannels = as->nchannels;
487495
jo->c.opt = dev->u.jack.out;
496+
488497
int ret = qjack_client_init(&jo->c);
489498
if (ret != 0) {
490499
return ret;
@@ -519,8 +528,10 @@ static int qjack_init_in(HWVoiceIn *hw, struct audsettings *as,
519528
}
520529

521530
ji->c.out = false;
531+
ji->c.enabled = false;
522532
ji->c.nchannels = as->nchannels;
523533
ji->c.opt = dev->u.jack.in;
534+
524535
int ret = qjack_client_init(&ji->c);
525536
if (ret != 0) {
526537
return ret;
@@ -568,23 +579,25 @@ static void qjack_client_fini(QJackClient *c)
568579
static void qjack_fini_out(HWVoiceOut *hw)
569580
{
570581
QJackOut *jo = (QJackOut *)hw;
571-
jo->c.finished = true;
572582
qjack_client_fini(&jo->c);
573583
}
574584

575585
static void qjack_fini_in(HWVoiceIn *hw)
576586
{
577587
QJackIn *ji = (QJackIn *)hw;
578-
ji->c.finished = true;
579588
qjack_client_fini(&ji->c);
580589
}
581590

582591
static void qjack_enable_out(HWVoiceOut *hw, bool enable)
583592
{
593+
QJackOut *jo = (QJackOut *)hw;
594+
jo->c.enabled = enable;
584595
}
585596

586597
static void qjack_enable_in(HWVoiceIn *hw, bool enable)
587598
{
599+
QJackIn *ji = (QJackIn *)hw;
600+
ji->c.enabled = enable;
588601
}
589602

590603
static int qjack_thread_creator(jack_native_thread_t *thread,

0 commit comments

Comments
 (0)