Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 3160499aacb81f6735941eb4c372d87a > files > 109

kvm-83-164.el5_5.30.src.rpm

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