qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] audio/dsound: fix invalid parameters error


From: KJ Liew
Subject: [PATCH] audio/dsound: fix invalid parameters error
Date: Fri, 17 Jan 2020 10:26:21 -0800

QEMU Windows has broken dsound backend since the rewrite of audio API in
version 4.2.0. Both playback and capture buffers failed to lock with
invalid parameters error.

--- ../orig/qemu-4.2.0/audio/dsoundaudio.c      2019-12-12 10:20:47.000000000 
-0800
+++ ../qemu-4.2.0/audio/dsoundaudio.c   2020-01-17 08:05:46.783966900 -0800
@@ -53,6 +53,7 @@
 typedef struct {
     HWVoiceOut hw;
     LPDIRECTSOUNDBUFFER dsound_buffer;
+    void *last_buf;
     dsound *s;
 } DSoundVoiceOut;
 
@@ -414,10 +415,10 @@
     DSoundVoiceOut *ds = (DSoundVoiceOut *) hw;
     LPDIRECTSOUNDBUFFER dsb = ds->dsound_buffer;
     HRESULT hr;
-    DWORD ppos, act_size;
+    DWORD ppos, act_size, last_size;
     size_t req_size;
     int err;
-    void *ret;
+    void *ret, *last_ret;
 
     hr = IDirectSoundBuffer_GetCurrentPosition(dsb, &ppos, NULL);
     if (FAILED(hr)) {
@@ -426,17 +427,24 @@
         return NULL;
     }
 
+    if (ppos == hw->pos_emul) {
+        *size = 0;
+        return ds->last_buf;
+    }
+
     req_size = audio_ring_dist(ppos, hw->pos_emul, hw->size_emul);
     req_size = MIN(req_size, hw->size_emul - hw->pos_emul);
 
-    err = dsound_lock_out(dsb, &hw->info, hw->pos_emul, req_size, &ret, NULL,
-                          &act_size, NULL, false, ds->s);
+    err = dsound_lock_out(dsb, &hw->info, hw->pos_emul, req_size, &ret, 
&last_ret,
+                          &act_size, &last_size, false, ds->s);
     if (err) {
         dolog("Failed to lock buffer\n");
         *size = 0;
         return NULL;
     }
 
+    ds->last_buf = g_realloc(ds->last_buf, act_size);
+    memcpy(ds->last_buf, ret, act_size);
     *size = act_size;
     return ret;
 }
@@ -445,6 +453,8 @@
 {
     DSoundVoiceOut *ds = (DSoundVoiceOut *) hw;
     LPDIRECTSOUNDBUFFER dsb = ds->dsound_buffer;
+    if (len == 0)
+        return 0;
     int err = dsound_unlock_out(dsb, buf, NULL, len, 0);
 
     if (err) {
@@ -508,10 +518,10 @@
     DSoundVoiceIn *ds = (DSoundVoiceIn *) hw;
     LPDIRECTSOUNDCAPTUREBUFFER dscb = ds->dsound_capture_buffer;
     HRESULT hr;
-    DWORD cpos, act_size;
+    DWORD cpos, act_size, last_size;
     size_t req_size;
     int err;
-    void *ret;
+    void *ret, *last_ret;
 
     hr = IDirectSoundCaptureBuffer_GetCurrentPosition(dscb, &cpos, NULL);
     if (FAILED(hr)) {
@@ -520,11 +530,16 @@
         return NULL;
     }
 
+    if (cpos == hw->pos_emul) {
+        *size = 0;
+        return NULL;
+    }
+
     req_size = audio_ring_dist(cpos, hw->pos_emul, hw->size_emul);
     req_size = MIN(req_size, hw->size_emul - hw->pos_emul);
 
-    err = dsound_lock_in(dscb, &hw->info, hw->pos_emul, req_size, &ret, NULL,
-                         &act_size, NULL, false, ds->s);
+    err = dsound_lock_in(dscb, &hw->info, hw->pos_emul, req_size, &ret, 
&last_ret,
+                         &act_size, &last_size, false, ds->s);
     if (err) {
         dolog("Failed to lock buffer\n");
         *size = 0;


reply via email to

[Prev in Thread] Current Thread [Next in Thread]