From 6263c056f262fb28640137d22971664d2e5b348f Mon Sep 17 00:00:00 2001 From: Eduardo Habkost <ehabkost@redhat.com> Date: Fri, 16 Oct 2009 18:14:09 -0300 Subject: [PATCH] Fix VDI audio stop RH-Author: Markus Armbruster <armbru@redhat.com> Message-id: <877hv5li44.fsf@pike.pond.sub.org> Patchwork-id: 3579 O-Subject: [RHEL5.5 PATCH] Fix VDI audio stop Bugzilla: 520394 RH-Acked-by: Yaniv Kamay <ykamay@redhat.com> RH-Acked-by: Juan Quintela <quintela@redhat.com> RH-Acked-by: Kevin Wolf <kwolf@redhat.com> RH-Acked-by: Marcelo Tosatti <mtosatti@redhat.com> QEMU calls audio_pcm_ops ctl_in() and ctl_out() to enable and disable voices. It assumes the callbacks are idempotent. In particular, stopping a stopped voice is okay and has no effect. I confirmed this with the upstream maintainer[*]. QEMU can actually stop a stopped device on exit. For VDI, these callbacks use libqspice's PlaybackPlug and RecordPlug methods start() and stop(). libqspice considers stopping a stopped device a programming error, and fails an assertion. Same for starting a running device, but we haven't been able to make QEMU do that. This patch is Yaniv Kamay's upstream fix[**]. It applies verbatim. It also fixes a typo in the declaration of InterfaceVoiceIn member base: it was declared HWVoiceOut instead of HWVoiceIn. The typo had no ill effect, because a HWVoiceIn fits into a HWVoiceOut. I'm not thrilled about mixing two unrelated fixes like that, but in the end I decided to stick to upstream. If you feel strongly we should not fix this in RHEL, or fix it in a separate patch with its own BZ, I'm happy to respin. Tested by Yaniv Kamay. Bug 520394. Please ACK. [*] http://lists.gnu.org/archive/html/qemu-devel/2009-09/msg02106.html [**] Unfortunately, I can't point you to the upstream repository, because no public repo has been set up yet. Signed-off-by: Eduardo Habkost <ehabkost@redhat.com> --- qemu/audio/vd_interface_audio.c | 31 ++++++++++++++++++++++++++----- 1 files changed, 26 insertions(+), 5 deletions(-) diff --git a/qemu/audio/vd_interface_audio.c b/qemu/audio/vd_interface_audio.c index b8135de..8087cc3 100644 --- a/qemu/audio/vd_interface_audio.c +++ b/qemu/audio/vd_interface_audio.c @@ -137,12 +137,14 @@ static void end_wave(void) typedef struct InterfaceVoiceOut { HWVoiceOut base; uint64_t prev_ticks; + int active; } InterfaceVoiceOut; typedef struct InterfaceVoiceIn { - HWVoiceOut base; + HWVoiceIn base; uint64_t prev_ticks; uint32_t samples[LINE_IN_SAMPLES]; + int active; } InterfaceVoiceIn; static struct audio_option options[] = { @@ -161,7 +163,7 @@ typedef struct Interface_audio { uint32_t silence[LINE_IN_SAMPLES]; InterfaceVoiceOut *voic_out; - HWVoiceIn *voic_in; + InterfaceVoiceIn *voic_in; } Interface_audio; static Interface_audio driver = { @@ -187,7 +189,7 @@ static VDObjectRef interface_play_plug(PlaybackInterface *playback, PlaybackPlug } ASSERT(plug && playback == driver.play_interface && enabled); driver.play_plug = plug; - *enabled = driver.voic_out ? driver.voic_out->base.enabled : 0; + *enabled = driver.voic_out ? driver.voic_out->active : 0; return (VDObjectRef)plug; } @@ -233,7 +235,7 @@ static VDObjectRef interface_record_plug(RecordInterface *recorder, RecordPlug* ASSERT(!driver.record_plug && plug && recorder == driver.record_interface && enabled); driver.record_plug = plug; - *enabled = driver.voic_in ? driver.voic_in->enabled : 0; + *enabled = driver.voic_in ? driver.voic_in->active : 0; return (VDObjectRef)plug; } @@ -343,6 +345,7 @@ static int line_out_init(HWVoiceOut *hw, struct audsettings *as) audio_pcm_init_info(&hw->info, &settings); hw->samples = LINE_OUT_SAMPLES; driver.voic_out = voice_out; + voice_out->active = 0; return 0; } @@ -422,12 +425,20 @@ static int line_out_ctl(HWVoiceOut *hw, int cmd, ...) switch (cmd) { case VOICE_ENABLE: + if (voice_out->active) { + break; + } + voice_out->active = 1; voice_out->prev_ticks = get_monotonic_time(); if (driver.play_plug) { driver.play_plug->start(driver.play_plug); } break; case VOICE_DISABLE: + if (!voice_out->active) { + break; + } + voice_out->active = 0; if (driver.play_plug) { if (driver.play_frame) { uint32_t *frame = driver.play_frame; @@ -445,6 +456,7 @@ static int line_out_ctl(HWVoiceOut *hw, int cmd, ...) static int line_in_init(HWVoiceIn *hw, struct audsettings *as) { + InterfaceVoiceIn *voice_in = (InterfaceVoiceIn *)hw; struct audsettings settings; dprintf(""); @@ -462,7 +474,8 @@ static int line_in_init(HWVoiceIn *hw, struct audsettings *as) audio_pcm_init_info(&hw->info, &settings); hw->samples = LINE_IN_SAMPLES; - driver.voic_in = hw; + driver.voic_in = voice_in; + voice_in->active = 0; return 0; } @@ -541,6 +554,10 @@ static int line_in_ctl(HWVoiceIn *hw, int cmd, ...) switch (cmd) { case VOICE_ENABLE: + if (voice_in->active) { + break; + } + voice_in->active = 1; #ifdef WAVE_CAPTURE start_wave(); #endif @@ -550,6 +567,10 @@ static int line_in_ctl(HWVoiceIn *hw, int cmd, ...) } break; case VOICE_DISABLE: + if (!voice_in->active) { + break; + } + voice_in->active = 0; #ifdef WAVE_CAPTURE end_wave(); #endif -- 1.6.3.rc4.29.g8146