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