=?UTF-8?Q?J=C3=B6rg=20H=C3=B6hle=20?=: winecoreaudio: Fix AudioCaptureClient Get/ReleaseBuffer protocol.

Alexandre Julliard julliard at winehq.org
Fri Jan 13 11:44:31 CST 2012


Module: wine
Branch: master
Commit: ee5f6f229e4504d9435af8e653b8080b0fbb0fa5
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=ee5f6f229e4504d9435af8e653b8080b0fbb0fa5

Author: Jörg Höhle <hoehle at users.sourceforge.net>
Date:   Sun Aug 21 23:35:11 2011 +0200

winecoreaudio: Fix AudioCaptureClient Get/ReleaseBuffer protocol.

---

 dlls/winecoreaudio.drv/mmdevdrv.c |   56 +++++++++++++++++++++++--------------
 1 files changed, 35 insertions(+), 21 deletions(-)

diff --git a/dlls/winecoreaudio.drv/mmdevdrv.c b/dlls/winecoreaudio.drv/mmdevdrv.c
index 5d69e3c..6161e51 100644
--- a/dlls/winecoreaudio.drv/mmdevdrv.c
+++ b/dlls/winecoreaudio.drv/mmdevdrv.c
@@ -1950,32 +1950,38 @@ static HRESULT WINAPI AudioCaptureClient_GetBuffer(IAudioCaptureClient *iface,
     }
 
     if(This->public_buffer){
-        *data = This->public_buffer->mAudioData;
         *frames =
             This->public_buffer->mAudioDataByteSize / This->fmt->nBlockAlign;
     }else{
         struct list *head = list_head(&This->avail_buffers);
         if(!head){
-            *data = NULL;
             *frames = 0;
         }else{
             AQBuffer *buf = LIST_ENTRY(head, AQBuffer, entry);
             This->public_buffer = buf->buf;
-            *data = This->public_buffer->mAudioData;
             *frames =
                 This->public_buffer->mAudioDataByteSize / This->fmt->nBlockAlign;
             list_remove(&buf->entry);
+            if(!*frames){
+                OSStatus sc = AudioQueueEnqueueBuffer(This->aqueue, This->public_buffer, 0, NULL);
+                if(sc != noErr)
+                    ERR("Unable to enqueue buffer: %lx\n", sc);
+                This->public_buffer = NULL;
+                WARN("empty packet\n");
+            }
         }
     }
 
-    *flags = 0;
-    This->written_frames += *frames;
-    This->inbuf_frames -= *frames;
-    This->getbuf_last = 1;
-
-    if(devpos || qpcpos)
-        AudioClock_GetPosition_nolock(This, devpos, qpcpos);
+    if((This->getbuf_last = *frames)){
+        UINT64 pos;
+        *flags = 0;
+        *data = This->public_buffer->mAudioData;
 
+        if(devpos)
+            *devpos = This->written_frames;
+        if(qpcpos) /* fixme: qpc of recording time */
+            AudioClock_GetPosition_nolock(This, &pos, qpcpos);
+    }
     OSSpinLockUnlock(&This->lock);
 
     return *frames ? S_OK : AUDCLNT_S_BUFFER_EMPTY;
@@ -1985,34 +1991,42 @@ static HRESULT WINAPI AudioCaptureClient_ReleaseBuffer(
         IAudioCaptureClient *iface, UINT32 done)
 {
     ACImpl *This = impl_from_IAudioCaptureClient(iface);
-    UINT32 pbuf_frames;
     OSStatus sc;
 
     TRACE("(%p)->(%u)\n", This, done);
 
     OSSpinLockLock(&This->lock);
 
+    if(!done){
+        This->getbuf_last = 0;
+        OSSpinLockUnlock(&This->lock);
+        return S_OK;
+    }
+
     if(!This->getbuf_last){
         OSSpinLockUnlock(&This->lock);
         return AUDCLNT_E_OUT_OF_ORDER;
     }
 
-    pbuf_frames = This->public_buffer->mAudioDataByteSize / This->fmt->nBlockAlign;
-    if(done != 0 && done != pbuf_frames){
+    if(This->getbuf_last != done){
         OSSpinLockUnlock(&This->lock);
         return AUDCLNT_E_INVALID_SIZE;
     }
 
-    if(done){
-        sc = AudioQueueEnqueueBuffer(This->aqueue, This->public_buffer,
-                0, NULL);
-        if(sc != noErr)
-            WARN("Unable to enqueue buffer: %lx\n", sc);
-        This->public_buffer = NULL;
-    }
-
+    This->written_frames += done;
+    This->inbuf_frames -= done;
     This->getbuf_last = 0;
 
+    sc = AudioQueueEnqueueBuffer(This->aqueue, This->public_buffer, 0, NULL);
+    if(sc != noErr){
+        OSSpinLockUnlock(&This->lock);
+        /* fixme: can't zero public_buffer or we lose memory, but then
+         * GetBuffer will see that packet again and again. */
+        ERR("Unable to enqueue buffer: %lx\n", sc);
+        return AUDCLNT_E_DEVICE_INVALIDATED;
+    }
+    This->public_buffer = NULL;
+
     OSSpinLockUnlock(&This->lock);
 
     return S_OK;




More information about the wine-cvs mailing list