Module: wine Branch: master Commit: ee5f6f229e4504d9435af8e653b8080b0fbb0fa5 URL: http://source.winehq.org/git/wine.git/?a=commit;h=ee5f6f229e4504d9435af8e653...
Author: Jörg Höhle hoehle@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;