From 139e31bc002e73bbb2e34268cae9e0918aaa4fef Mon Sep 17 00:00:00 2001 From: Andrew Eikum Date: Mon, 9 Jan 2012 15:25:32 -0600 Subject: [PATCH] wineoss.drv: Fix IAudioRenderClient::{Get,Release}Buffer protocol. --- dlls/wineoss.drv/mmdevdrv.c | 38 ++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/dlls/wineoss.drv/mmdevdrv.c b/dlls/wineoss.drv/mmdevdrv.c index bc4d9527d03..aaa94eef50b 100644 --- a/dlls/wineoss.drv/mmdevdrv.c +++ b/dlls/wineoss.drv/mmdevdrv.c @@ -128,6 +128,7 @@ struct ACImpl { BYTE *local_buffer, *tmp_buffer; int buf_state; + long getbuf_last; /* <0 when using tmp_buffer */ HANDLE timer; CRITICAL_SECTION lock; @@ -1495,7 +1496,7 @@ static HRESULT WINAPI AudioClient_Reset(IAudioClient *iface) return AUDCLNT_E_NOT_STOPPED; } - if(This->buf_state != NOT_LOCKED){ + if(This->buf_state != NOT_LOCKED || This->getbuf_last){ LeaveCriticalSection(&This->lock); return AUDCLNT_E_BUFFER_OPERATION_PENDING; } @@ -1689,15 +1690,16 @@ static HRESULT WINAPI AudioRenderClient_GetBuffer(IAudioRenderClient *iface, if(!data) return E_POINTER; + *data = NULL; + EnterCriticalSection(&This->lock); - if(This->buf_state != NOT_LOCKED){ + if(This->getbuf_last){ LeaveCriticalSection(&This->lock); return AUDCLNT_E_OUT_OF_ORDER; } if(!frames){ - This->buf_state = LOCKED_NORMAL; LeaveCriticalSection(&This->lock); return S_OK; } @@ -1727,10 +1729,10 @@ static HRESULT WINAPI AudioRenderClient_GetBuffer(IAudioRenderClient *iface, This->tmp_buffer_frames = frames; } *data = This->tmp_buffer; - This->buf_state = LOCKED_WRAPPED; + This->getbuf_last = -frames; }else{ *data = This->local_buffer + write_pos * This->fmt->nBlockAlign; - This->buf_state = LOCKED_NORMAL; + This->getbuf_last = frames; } LeaveCriticalSection(&This->lock); @@ -1766,13 +1768,23 @@ static HRESULT WINAPI AudioRenderClient_ReleaseBuffer( EnterCriticalSection(&This->lock); - if(This->buf_state == NOT_LOCKED || !written_frames){ - This->buf_state = NOT_LOCKED; + if(!written_frames){ + This->getbuf_last = 0; LeaveCriticalSection(&This->lock); - return written_frames ? AUDCLNT_E_OUT_OF_ORDER : S_OK; + return S_OK; } - if(This->buf_state == LOCKED_NORMAL) + if(!This->getbuf_last){ + LeaveCriticalSection(&This->lock); + return AUDCLNT_E_OUT_OF_ORDER; + } + + if(written_frames > (This->getbuf_last >= 0 ? This->getbuf_last : -This->getbuf_last)){ + LeaveCriticalSection(&This->lock); + return AUDCLNT_E_INVALID_SIZE; + } + + if(This->getbuf_last >= 0) buffer = This->local_buffer + This->fmt->nBlockAlign * ((This->lcl_offs_frames + This->held_frames) % This->bufsize_frames); else @@ -1782,7 +1794,7 @@ static HRESULT WINAPI AudioRenderClient_ReleaseBuffer( oss_silence_buffer(This, buffer, written_frames); if(This->held_frames){ - if(This->buf_state == LOCKED_WRAPPED) + if(This->getbuf_last < 0) oss_wrap_buffer(This, buffer, written_frames); This->held_frames += written_frames; @@ -1797,7 +1809,7 @@ static HRESULT WINAPI AudioRenderClient_ReleaseBuffer( written_frames * This->fmt->nBlockAlign); if(w_bytes < 0){ if(errno != EAGAIN){ - This->buf_state = NOT_LOCKED; + This->getbuf_last = 0; LeaveCriticalSection(&This->lock); ERR("write failed: %d (%s)\n", errno, strerror(errno)); return E_FAIL; @@ -1808,7 +1820,7 @@ static HRESULT WINAPI AudioRenderClient_ReleaseBuffer( This->inbuf_frames += w_frames; if(w_frames < written_frames){ - if(This->buf_state == LOCKED_WRAPPED) + if(This->getbuf_last < 0) oss_wrap_buffer(This, This->tmp_buffer + w_bytes, written_frames - w_frames); else @@ -1818,7 +1830,7 @@ static HRESULT WINAPI AudioRenderClient_ReleaseBuffer( } This->written_frames += written_frames; - This->buf_state = NOT_LOCKED; + This->getbuf_last = 0; LeaveCriticalSection(&This->lock);