[PATCH 4/8] wineoss: Introduce a stream structure.

Andrew Eikum aeikum at codeweavers.com
Mon Apr 11 08:59:44 CDT 2022


Signed-off-by: Andrew Eikum <aeikum at codeweavers.com>

On Wed, Apr 06, 2022 at 07:55:54AM +0100, Huw Davies wrote:
> Signed-off-by: Huw Davies <huw at codeweavers.com>
> ---
>  dlls/wineoss.drv/mmdevdrv.c | 427 +++++++++++++++++++-----------------
>  dlls/wineoss.drv/unixlib.h  |  19 ++
>  2 files changed, 242 insertions(+), 204 deletions(-)
> 
> diff --git a/dlls/wineoss.drv/mmdevdrv.c b/dlls/wineoss.drv/mmdevdrv.c
> index af49c88e6cf..4f8460a3b3b 100644
> --- a/dlls/wineoss.drv/mmdevdrv.c
> +++ b/dlls/wineoss.drv/mmdevdrv.c
> @@ -108,25 +108,14 @@ struct ACImpl {
>      IMMDevice *parent;
>      IUnknown *pUnkFTMarshal;
>  
> -    WAVEFORMATEX *fmt;
> -
>      EDataFlow dataflow;
> -    DWORD flags;
> -    AUDCLNT_SHAREMODE share;
> -    HANDLE event;
>      float *vols;
>      UINT32 channel_count;
> +    struct oss_stream *stream;
>  
> -    int fd;
>      oss_audioinfo ai;
>  
> -    BOOL initted, playing;
> -    UINT64 written_frames, last_pos_frames;
> -    UINT32 period_us, period_frames, bufsize_frames, held_frames, tmp_buffer_frames, in_oss_frames;
> -    UINT32 oss_bufsize_bytes, lcl_offs_frames; /* offs into local_buffer where valid data starts */
> -
> -    BYTE *local_buffer, *tmp_buffer;
> -    LONG32 getbuf_last; /* <0 when using tmp_buffer */
> +    BOOL initted;
>      HANDLE timer;
>  
>      CRITICAL_SECTION lock;
> @@ -443,6 +432,7 @@ HRESULT WINAPI AUDDRV_GetAudioEndpoint(GUID *guid, IMMDevice *dev,
>          IAudioClient **out)
>  {
>      ACImpl *This;
> +    struct oss_stream *stream;
>      const OSSDevice *oss_dev;
>      HRESULT hr;
>      int len;
> @@ -459,16 +449,26 @@ HRESULT WINAPI AUDDRV_GetAudioEndpoint(GUID *guid, IMMDevice *dev,
>      if(!This)
>          return E_OUTOFMEMORY;
>  
> +    stream = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This->stream));
> +    if(!stream){
> +        HeapFree(GetProcessHeap(), 0, This);
> +        return E_OUTOFMEMORY;
> +    }
> +    stream->flow = oss_dev->flow;
> +    This->stream = stream;
> +
>      hr = CoCreateFreeThreadedMarshaler((IUnknown *)&This->IAudioClient3_iface, &This->pUnkFTMarshal);
>      if (FAILED(hr)) {
> +         HeapFree(GetProcessHeap(), 0, stream);
>           HeapFree(GetProcessHeap(), 0, This);
>           return hr;
>      }
>  
> -    This->fd = open_device(oss_dev->devnode, oss_dev->flow);
> -    if(This->fd < 0){
> +    stream->fd = open_device(oss_dev->devnode, oss_dev->flow);
> +    if(stream->fd < 0){
>          WARN("Unable to open device %s: %d (%s)\n", oss_dev->devnode, errno,
>                  strerror(errno));
> +        HeapFree(GetProcessHeap(), 0, stream);
>          HeapFree(GetProcessHeap(), 0, This);
>          return AUDCLNT_E_DEVICE_INVALIDATED;
>      }
> @@ -476,10 +476,11 @@ HRESULT WINAPI AUDDRV_GetAudioEndpoint(GUID *guid, IMMDevice *dev,
>      This->dataflow = oss_dev->flow;
>  
>      This->ai.dev = -1;
> -    if(ioctl(This->fd, SNDCTL_ENGINEINFO, &This->ai) < 0){
> +    if(ioctl(stream->fd, SNDCTL_ENGINEINFO, &This->ai) < 0){
>          WARN("Unable to get audio info for device %s: %d (%s)\n", oss_dev->devnode,
>                  errno, strerror(errno));
> -        close(This->fd);
> +        close(stream->fd);
> +        HeapFree(GetProcessHeap(), 0, stream);
>          HeapFree(GetProcessHeap(), 0, This);
>          return E_FAIL;
>      }
> @@ -554,6 +555,7 @@ static ULONG WINAPI AudioClient_AddRef(IAudioClient3 *iface)
>  static ULONG WINAPI AudioClient_Release(IAudioClient3 *iface)
>  {
>      ACImpl *This = impl_from_IAudioClient3(iface);
> +    struct oss_stream *stream = This->stream;
>      ULONG ref;
>  
>      ref = InterlockedDecrement(&This->ref);
> @@ -575,16 +577,17 @@ static ULONG WINAPI AudioClient_Release(IAudioClient3 *iface)
>          IUnknown_Release(This->pUnkFTMarshal);
>          This->lock.DebugInfo->Spare[0] = 0;
>          DeleteCriticalSection(&This->lock);
> -        close(This->fd);
> +        close(stream->fd);
>          if(This->initted){
>              EnterCriticalSection(&g_sessions_lock);
>              list_remove(&This->entry);
>              LeaveCriticalSection(&g_sessions_lock);
>          }
>          HeapFree(GetProcessHeap(), 0, This->vols);
> -        HeapFree(GetProcessHeap(), 0, This->local_buffer);
> -        HeapFree(GetProcessHeap(), 0, This->tmp_buffer);
> -        CoTaskMemFree(This->fmt);
> +        HeapFree(GetProcessHeap(), 0, stream->local_buffer);
> +        HeapFree(GetProcessHeap(), 0, stream->tmp_buffer);
> +        CoTaskMemFree(stream->fmt);
> +        HeapFree(GetProcessHeap(), 0, stream);
>          HeapFree(GetProcessHeap(), 0, This);
>      }
>      return ref;
> @@ -880,6 +883,7 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
>          const GUID *sessionguid)
>  {
>      ACImpl *This = impl_from_IAudioClient3(iface);
> +    struct oss_stream *stream = This->stream;
>      int i;
>      HRESULT hr;
>  
> @@ -939,31 +943,31 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
>          return AUDCLNT_E_ALREADY_INITIALIZED;
>      }
>  
> -    hr = setup_oss_device(mode, This->fd, fmt, NULL);
> +    hr = setup_oss_device(mode, stream->fd, fmt, NULL);
>      if(FAILED(hr)){
>          LeaveCriticalSection(&This->lock);
>          LeaveCriticalSection(&g_sessions_lock);
>          return hr;
>      }
>  
> -    This->fmt = clone_format(fmt);
> -    if(!This->fmt){
> +    stream->fmt = clone_format(fmt);
> +    if(!stream->fmt){
>          LeaveCriticalSection(&This->lock);
>          LeaveCriticalSection(&g_sessions_lock);
>          return E_OUTOFMEMORY;
>      }
>  
> -    This->period_us = period / 10;
> -    This->period_frames = MulDiv(fmt->nSamplesPerSec, period, 10000000);
> +    stream->period_us = period / 10;
> +    stream->period_frames = MulDiv(fmt->nSamplesPerSec, period, 10000000);
>  
> -    This->bufsize_frames = MulDiv(duration, fmt->nSamplesPerSec, 10000000);
> +    stream->bufsize_frames = MulDiv(duration, fmt->nSamplesPerSec, 10000000);
>      if(mode == AUDCLNT_SHAREMODE_EXCLUSIVE)
> -        This->bufsize_frames -= This->bufsize_frames % This->period_frames;
> -    This->local_buffer = HeapAlloc(GetProcessHeap(), 0,
> -            This->bufsize_frames * fmt->nBlockAlign);
> -    if(!This->local_buffer){
> -        CoTaskMemFree(This->fmt);
> -        This->fmt = NULL;
> +        stream->bufsize_frames -= stream->bufsize_frames % stream->period_frames;
> +    stream->local_buffer = HeapAlloc(GetProcessHeap(), 0,
> +            stream->bufsize_frames * fmt->nBlockAlign);
> +    if(!stream->local_buffer){
> +        CoTaskMemFree(stream->fmt);
> +        stream->fmt = NULL;
>          LeaveCriticalSection(&This->lock);
>          LeaveCriticalSection(&g_sessions_lock);
>          return E_OUTOFMEMORY;
> @@ -972,8 +976,8 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
>      This->channel_count = fmt->nChannels;
>      This->vols = HeapAlloc(GetProcessHeap(), 0, This->channel_count * sizeof(float));
>      if(!This->vols){
> -        CoTaskMemFree(This->fmt);
> -        This->fmt = NULL;
> +        CoTaskMemFree(stream->fmt);
> +        stream->fmt = NULL;
>          LeaveCriticalSection(&This->lock);
>          LeaveCriticalSection(&g_sessions_lock);
>          return E_OUTOFMEMORY;
> @@ -982,17 +986,17 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
>      for(i = 0; i < This->channel_count; ++i)
>          This->vols[i] = 1.f;
>  
> -    This->share = mode;
> -    This->flags = flags;
> -    This->oss_bufsize_bytes = 0;
> +    stream->share = mode;
> +    stream->flags = flags;
> +    stream->oss_bufsize_bytes = 0;
>  
>      hr = get_audio_session(sessionguid, This->parent, This->channel_count,
>              &This->session);
>      if(FAILED(hr)){
>          HeapFree(GetProcessHeap(), 0, This->vols);
>          This->vols = NULL;
> -        CoTaskMemFree(This->fmt);
> -        This->fmt = NULL;
> +        CoTaskMemFree(stream->fmt);
> +        stream->fmt = NULL;
>          LeaveCriticalSection(&This->lock);
>          LeaveCriticalSection(&g_sessions_lock);
>          return hr;
> @@ -1012,6 +1016,7 @@ static HRESULT WINAPI AudioClient_GetBufferSize(IAudioClient3 *iface,
>          UINT32 *frames)
>  {
>      ACImpl *This = impl_from_IAudioClient3(iface);
> +    struct oss_stream *stream = This->stream;
>  
>      TRACE("(%p)->(%p)\n", This, frames);
>  
> @@ -1025,7 +1030,7 @@ static HRESULT WINAPI AudioClient_GetBufferSize(IAudioClient3 *iface,
>          return AUDCLNT_E_NOT_INITIALIZED;
>      }
>  
> -    *frames = This->bufsize_frames;
> +    *frames = stream->bufsize_frames;
>  
>      TRACE("buffer size: %u\n", *frames);
>  
> @@ -1038,6 +1043,7 @@ static HRESULT WINAPI AudioClient_GetStreamLatency(IAudioClient3 *iface,
>          REFERENCE_TIME *latency)
>  {
>      ACImpl *This = impl_from_IAudioClient3(iface);
> +    struct oss_stream *stream = This->stream;
>  
>      TRACE("(%p)->(%p)\n", This, latency);
>  
> @@ -1053,7 +1059,7 @@ static HRESULT WINAPI AudioClient_GetStreamLatency(IAudioClient3 *iface,
>  
>      /* pretend we process audio in Period chunks, so max latency includes
>       * the period time.  Some native machines add .6666ms in shared mode. */
> -    *latency = (REFERENCE_TIME)This->period_us * 10 + 6666;
> +    *latency = (REFERENCE_TIME)stream->period_us * 10 + 6666;
>  
>      LeaveCriticalSection(&This->lock);
>  
> @@ -1064,6 +1070,7 @@ static HRESULT WINAPI AudioClient_GetCurrentPadding(IAudioClient3 *iface,
>          UINT32 *numpad)
>  {
>      ACImpl *This = impl_from_IAudioClient3(iface);
> +    struct oss_stream *stream = This->stream;
>  
>      TRACE("(%p)->(%p)\n", This, numpad);
>  
> @@ -1077,7 +1084,7 @@ static HRESULT WINAPI AudioClient_GetCurrentPadding(IAudioClient3 *iface,
>          return AUDCLNT_E_NOT_INITIALIZED;
>      }
>  
> -    *numpad = This->held_frames;
> +    *numpad = stream->held_frames;
>  
>      TRACE("padding: %u\n", *numpad);
>  
> @@ -1239,19 +1246,19 @@ static HRESULT WINAPI AudioClient_GetDevicePeriod(IAudioClient3 *iface,
>      return S_OK;
>  }
>  
> -static void silence_buffer(ACImpl *This, BYTE *buffer, UINT32 frames)
> +static void silence_buffer(struct oss_stream *stream, BYTE *buffer, UINT32 frames)
>  {
> -    WAVEFORMATEXTENSIBLE *fmtex = (WAVEFORMATEXTENSIBLE*)This->fmt;
> -    if((This->fmt->wFormatTag == WAVE_FORMAT_PCM ||
> -            (This->fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
> +    WAVEFORMATEXTENSIBLE *fmtex = (WAVEFORMATEXTENSIBLE*)stream->fmt;
> +    if((stream->fmt->wFormatTag == WAVE_FORMAT_PCM ||
> +            (stream->fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
>               IsEqualGUID(&fmtex->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM))) &&
> -            This->fmt->wBitsPerSample == 8)
> -        memset(buffer, 128, frames * This->fmt->nBlockAlign);
> +            stream->fmt->wBitsPerSample == 8)
> +        memset(buffer, 128, frames * stream->fmt->nBlockAlign);
>      else
> -        memset(buffer, 0, frames * This->fmt->nBlockAlign);
> +        memset(buffer, 0, frames * stream->fmt->nBlockAlign);
>  }
>  
> -static void oss_write_data(ACImpl *This)
> +static void oss_write_data(struct oss_stream *stream, BOOL mute)
>  {
>      ssize_t written_bytes;
>      UINT32 written_frames, in_oss_frames, write_limit, max_period, write_offs_frames, new_frames;
> @@ -1259,25 +1266,25 @@ static void oss_write_data(ACImpl *This)
>      audio_buf_info bi;
>      BYTE *buf;
>  
> -    if(ioctl(This->fd, SNDCTL_DSP_GETOSPACE, &bi) < 0){
> +    if(ioctl(stream->fd, SNDCTL_DSP_GETOSPACE, &bi) < 0){
>          WARN("GETOSPACE failed: %d (%s)\n", errno, strerror(errno));
>          return;
>      }
>  
> -    max_period = max(bi.fragsize / This->fmt->nBlockAlign, This->period_frames);
> +    max_period = max(bi.fragsize / stream->fmt->nBlockAlign, stream->period_frames);
>  
> -    if(bi.bytes > This->oss_bufsize_bytes){
> +    if(bi.bytes > stream->oss_bufsize_bytes){
>          TRACE("New buffer size (%u) is larger than old buffer size (%u)\n",
> -                bi.bytes, This->oss_bufsize_bytes);
> -        This->oss_bufsize_bytes = bi.bytes;
> +                bi.bytes, stream->oss_bufsize_bytes);
> +        stream->oss_bufsize_bytes = bi.bytes;
>          in_oss_frames = 0;
>      }else
> -        in_oss_frames = (This->oss_bufsize_bytes - bi.bytes) / This->fmt->nBlockAlign;
> +        in_oss_frames = (stream->oss_bufsize_bytes - bi.bytes) / stream->fmt->nBlockAlign;
>  
> -    if(in_oss_frames > This->in_oss_frames){
> +    if(in_oss_frames > stream->in_oss_frames){
>          TRACE("Capping reported frames from %u to %u\n",
> -                in_oss_frames, This->in_oss_frames);
> -        in_oss_frames = This->in_oss_frames;
> +                in_oss_frames, stream->in_oss_frames);
> +        in_oss_frames = stream->in_oss_frames;
>      }
>  
>      write_limit = 0;
> @@ -1292,48 +1299,48 @@ static void oss_write_data(ACImpl *This)
>       *        ^^^^^^^^^^ - held_frames
>       *        ^ - lcl_offs_frames
>       */
> -    advanced = This->in_oss_frames - in_oss_frames;
> -    if(advanced > This->held_frames)
> -        advanced = This->held_frames;
> -    This->lcl_offs_frames += advanced;
> -    This->lcl_offs_frames %= This->bufsize_frames;
> -    This->held_frames -= advanced;
> -    This->in_oss_frames = in_oss_frames;
> +    advanced = stream->in_oss_frames - in_oss_frames;
> +    if(advanced > stream->held_frames)
> +        advanced = stream->held_frames;
> +    stream->lcl_offs_frames += advanced;
> +    stream->lcl_offs_frames %= stream->bufsize_frames;
> +    stream->held_frames -= advanced;
> +    stream->in_oss_frames = in_oss_frames;
>      TRACE("advanced by %lu, lcl_offs: %u, held: %u, in_oss: %u\n",
> -            advanced, This->lcl_offs_frames, This->held_frames, This->in_oss_frames);
> +            advanced, stream->lcl_offs_frames, stream->held_frames, stream->in_oss_frames);
>  
>  
> -    if(This->held_frames == This->in_oss_frames)
> +    if(stream->held_frames == stream->in_oss_frames)
>          return;
>  
> -    write_offs_frames = (This->lcl_offs_frames + This->in_oss_frames) % This->bufsize_frames;
> -    new_frames = This->held_frames - This->in_oss_frames;
> +    write_offs_frames = (stream->lcl_offs_frames + stream->in_oss_frames) % stream->bufsize_frames;
> +    new_frames = stream->held_frames - stream->in_oss_frames;
>  
> -    if(write_offs_frames + new_frames > This->bufsize_frames)
> -        to_write_frames = This->bufsize_frames - write_offs_frames;
> +    if(write_offs_frames + new_frames > stream->bufsize_frames)
> +        to_write_frames = stream->bufsize_frames - write_offs_frames;
>      else
>          to_write_frames = new_frames;
>  
>      to_write_frames = min(to_write_frames, write_limit);
> -    to_write_bytes = to_write_frames * This->fmt->nBlockAlign;
> +    to_write_bytes = to_write_frames * stream->fmt->nBlockAlign;
>      TRACE("going to write %lu frames from %u (%lu of %u)\n", to_write_frames,
>              write_offs_frames, to_write_frames + write_offs_frames,
> -            This->bufsize_frames);
> +            stream->bufsize_frames);
>  
> -    buf = This->local_buffer + write_offs_frames * This->fmt->nBlockAlign;
> +    buf = stream->local_buffer + write_offs_frames * stream->fmt->nBlockAlign;
>  
> -    if(This->session->mute)
> -        silence_buffer(This, buf, to_write_frames);
> +    if(mute)
> +        silence_buffer(stream, buf, to_write_frames);
>  
> -    written_bytes = write(This->fd, buf, to_write_bytes);
> +    written_bytes = write(stream->fd, buf, to_write_bytes);
>      if(written_bytes < 0){
>          /* EAGAIN is OSS buffer full, log that too */
>          WARN("write failed: %d (%s)\n", errno, strerror(errno));
>          return;
>      }
> -    written_frames = written_bytes / This->fmt->nBlockAlign;
> +    written_frames = written_bytes / stream->fmt->nBlockAlign;
>  
> -    This->in_oss_frames += written_frames;
> +    stream->in_oss_frames += written_frames;
>  
>      if(written_frames < to_write_frames){
>          /* OSS buffer probably full */
> @@ -1344,70 +1351,72 @@ static void oss_write_data(ACImpl *This)
>          /* wrapped and have some data back at the start to write */
>  
>          to_write_frames = min(write_limit - written_frames, new_frames - written_frames);
> -        to_write_bytes = to_write_frames * This->fmt->nBlockAlign;
> +        to_write_bytes = to_write_frames * stream->fmt->nBlockAlign;
>  
> -        if(This->session->mute)
> -            silence_buffer(This, This->local_buffer, to_write_frames);
> +        if(mute)
> +            silence_buffer(stream, stream->local_buffer, to_write_frames);
>  
>          TRACE("wrapping to write %lu frames from beginning\n", to_write_frames);
>  
> -        written_bytes = write(This->fd, This->local_buffer, to_write_bytes);
> +        written_bytes = write(stream->fd, stream->local_buffer, to_write_bytes);
>          if(written_bytes < 0){
>              WARN("write failed: %d (%s)\n", errno, strerror(errno));
>              return;
>          }
> -        written_frames = written_bytes / This->fmt->nBlockAlign;
> -        This->in_oss_frames += written_frames;
> +        written_frames = written_bytes / stream->fmt->nBlockAlign;
> +        stream->in_oss_frames += written_frames;
>      }
>  }
>  
> -static void oss_read_data(ACImpl *This)
> +static void oss_read_data(struct oss_stream *stream)
>  {
>      UINT64 pos, readable;
>      ssize_t nread;
>  
> -    pos = (This->held_frames + This->lcl_offs_frames) % This->bufsize_frames;
> -    readable = (This->bufsize_frames - pos) * This->fmt->nBlockAlign;
> +    pos = (stream->held_frames + stream->lcl_offs_frames) % stream->bufsize_frames;
> +    readable = (stream->bufsize_frames - pos) * stream->fmt->nBlockAlign;
>  
> -    nread = read(This->fd, This->local_buffer + pos * This->fmt->nBlockAlign,
> +    nread = read(stream->fd, stream->local_buffer + pos * stream->fmt->nBlockAlign,
>              readable);
>      if(nread < 0){
>          WARN("read failed: %d (%s)\n", errno, strerror(errno));
>          return;
>      }
>  
> -    This->held_frames += nread / This->fmt->nBlockAlign;
> +    stream->held_frames += nread / stream->fmt->nBlockAlign;
>  
> -    if(This->held_frames > This->bufsize_frames){
> +    if(stream->held_frames > stream->bufsize_frames){
>          WARN("Overflow of unread data\n");
> -        This->lcl_offs_frames += This->held_frames;
> -        This->lcl_offs_frames %= This->bufsize_frames;
> -        This->held_frames = This->bufsize_frames;
> +        stream->lcl_offs_frames += stream->held_frames;
> +        stream->lcl_offs_frames %= stream->bufsize_frames;
> +        stream->held_frames = stream->bufsize_frames;
>      }
>  }
>  
>  static void CALLBACK oss_period_callback(void *user, BOOLEAN timer)
>  {
>      ACImpl *This = user;
> +    struct oss_stream *stream = This->stream;
>  
>      EnterCriticalSection(&This->lock);
>  
> -    if(This->playing){
> -        if(This->dataflow == eRender && This->held_frames)
> -            oss_write_data(This);
> -        else if(This->dataflow == eCapture)
> -            oss_read_data(This);
> +    if(stream->playing){
> +        if(stream->flow == eRender && stream->held_frames)
> +            oss_write_data(stream, This->session->mute);
> +        else if(stream->flow == eCapture)
> +            oss_read_data(stream);
>      }
>  
>      LeaveCriticalSection(&This->lock);
>  
> -    if(This->event)
> -        SetEvent(This->event);
> +    if(stream->event)
> +        SetEvent(stream->event);
>  }
>  
>  static HRESULT WINAPI AudioClient_Start(IAudioClient3 *iface)
>  {
>      ACImpl *This = impl_from_IAudioClient3(iface);
> +    struct oss_stream *stream = This->stream;
>  
>      TRACE("(%p)\n", This);
>  
> @@ -1418,24 +1427,24 @@ static HRESULT WINAPI AudioClient_Start(IAudioClient3 *iface)
>          return AUDCLNT_E_NOT_INITIALIZED;
>      }
>  
> -    if((This->flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK) && !This->event){
> +    if((stream->flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK) && !stream->event){
>          LeaveCriticalSection(&This->lock);
>          return AUDCLNT_E_EVENTHANDLE_NOT_SET;
>      }
>  
> -    if(This->playing){
> +    if(stream->playing){
>          LeaveCriticalSection(&This->lock);
>          return AUDCLNT_E_NOT_STOPPED;
>      }
>  
>      if(!This->timer){
>          if(!CreateTimerQueueTimer(&This->timer, g_timer_q,
> -                    oss_period_callback, This, 0, This->period_us / 1000,
> +                    oss_period_callback, This, 0, stream->period_us / 1000,
>                      WT_EXECUTEINTIMERTHREAD))
>              ERR("Unable to create period timer: %u\n", GetLastError());
>      }
>  
> -    This->playing = TRUE;
> +    stream->playing = TRUE;
>  
>      LeaveCriticalSection(&This->lock);
>  
> @@ -1445,6 +1454,7 @@ static HRESULT WINAPI AudioClient_Start(IAudioClient3 *iface)
>  static HRESULT WINAPI AudioClient_Stop(IAudioClient3 *iface)
>  {
>      ACImpl *This = impl_from_IAudioClient3(iface);
> +    struct oss_stream *stream = This->stream;
>  
>      TRACE("(%p)\n", This);
>  
> @@ -1455,13 +1465,13 @@ static HRESULT WINAPI AudioClient_Stop(IAudioClient3 *iface)
>          return AUDCLNT_E_NOT_INITIALIZED;
>      }
>  
> -    if(!This->playing){
> +    if(!stream->playing){
>          LeaveCriticalSection(&This->lock);
>          return S_FALSE;
>      }
>  
> -    This->playing = FALSE;
> -    This->in_oss_frames = 0;
> +    stream->playing = FALSE;
> +    stream->in_oss_frames = 0;
>  
>      LeaveCriticalSection(&This->lock);
>  
> @@ -1471,6 +1481,7 @@ static HRESULT WINAPI AudioClient_Stop(IAudioClient3 *iface)
>  static HRESULT WINAPI AudioClient_Reset(IAudioClient3 *iface)
>  {
>      ACImpl *This = impl_from_IAudioClient3(iface);
> +    struct oss_stream *stream = This->stream;
>  
>      TRACE("(%p)\n", This);
>  
> @@ -1481,25 +1492,25 @@ static HRESULT WINAPI AudioClient_Reset(IAudioClient3 *iface)
>          return AUDCLNT_E_NOT_INITIALIZED;
>      }
>  
> -    if(This->playing){
> +    if(stream->playing){
>          LeaveCriticalSection(&This->lock);
>          return AUDCLNT_E_NOT_STOPPED;
>      }
>  
> -    if(This->getbuf_last){
> +    if(stream->getbuf_last){
>          LeaveCriticalSection(&This->lock);
>          return AUDCLNT_E_BUFFER_OPERATION_PENDING;
>      }
>  
> -    if(This->dataflow == eRender){
> -        This->written_frames = 0;
> -        This->last_pos_frames = 0;
> +    if(stream->flow == eRender){
> +        stream->written_frames = 0;
> +        stream->last_pos_frames = 0;
>      }else{
> -        This->written_frames += This->held_frames;
> +        stream->written_frames += stream->held_frames;
>      }
> -    This->held_frames = 0;
> -    This->lcl_offs_frames = 0;
> -    This->in_oss_frames = 0;
> +    stream->held_frames = 0;
> +    stream->lcl_offs_frames = 0;
> +    stream->in_oss_frames = 0;
>  
>      LeaveCriticalSection(&This->lock);
>  
> @@ -1510,6 +1521,7 @@ static HRESULT WINAPI AudioClient_SetEventHandle(IAudioClient3 *iface,
>          HANDLE event)
>  {
>      ACImpl *This = impl_from_IAudioClient3(iface);
> +    struct oss_stream *stream = This->stream;
>  
>      TRACE("(%p)->(%p)\n", This, event);
>  
> @@ -1523,18 +1535,18 @@ static HRESULT WINAPI AudioClient_SetEventHandle(IAudioClient3 *iface,
>          return AUDCLNT_E_NOT_INITIALIZED;
>      }
>  
> -    if(!(This->flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK)){
> +    if(!(stream->flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK)){
>          LeaveCriticalSection(&This->lock);
>          return AUDCLNT_E_EVENTHANDLE_NOT_EXPECTED;
>      }
>  
> -    if (This->event){
> +    if (stream->event){
>          LeaveCriticalSection(&This->lock);
>          FIXME("called twice\n");
>          return HRESULT_FROM_WIN32(ERROR_INVALID_NAME);
>      }
>  
> -    This->event = event;
> +    stream->event = event;
>  
>      LeaveCriticalSection(&This->lock);
>  
> @@ -1781,6 +1793,7 @@ static HRESULT WINAPI AudioRenderClient_GetBuffer(IAudioRenderClient *iface,
>          UINT32 frames, BYTE **data)
>  {
>      ACImpl *This = impl_from_IAudioRenderClient(iface);
> +    struct oss_stream *stream = This->stream;
>      UINT32 write_pos;
>  
>      TRACE("(%p)->(%u, %p)\n", This, frames, data);
> @@ -1792,7 +1805,7 @@ static HRESULT WINAPI AudioRenderClient_GetBuffer(IAudioRenderClient *iface,
>  
>      EnterCriticalSection(&This->lock);
>  
> -    if(This->getbuf_last){
> +    if(stream->getbuf_last){
>          LeaveCriticalSection(&This->lock);
>          return AUDCLNT_E_OUT_OF_ORDER;
>      }
> @@ -1802,52 +1815,52 @@ static HRESULT WINAPI AudioRenderClient_GetBuffer(IAudioRenderClient *iface,
>          return S_OK;
>      }
>  
> -    if(This->held_frames + frames > This->bufsize_frames){
> +    if(stream->held_frames + frames > stream->bufsize_frames){
>          LeaveCriticalSection(&This->lock);
>          return AUDCLNT_E_BUFFER_TOO_LARGE;
>      }
>  
>      write_pos =
> -        (This->lcl_offs_frames + This->held_frames) % This->bufsize_frames;
> -    if(write_pos + frames > This->bufsize_frames){
> -        if(This->tmp_buffer_frames < frames){
> -            HeapFree(GetProcessHeap(), 0, This->tmp_buffer);
> -            This->tmp_buffer = HeapAlloc(GetProcessHeap(), 0,
> -                    frames * This->fmt->nBlockAlign);
> -            if(!This->tmp_buffer){
> +        (stream->lcl_offs_frames + stream->held_frames) % stream->bufsize_frames;
> +    if(write_pos + frames > stream->bufsize_frames){
> +        if(stream->tmp_buffer_frames < frames){
> +            HeapFree(GetProcessHeap(), 0, stream->tmp_buffer);
> +            stream->tmp_buffer = HeapAlloc(GetProcessHeap(), 0,
> +                    frames * stream->fmt->nBlockAlign);
> +            if(!stream->tmp_buffer){
>                  LeaveCriticalSection(&This->lock);
>                  return E_OUTOFMEMORY;
>              }
> -            This->tmp_buffer_frames = frames;
> +            stream->tmp_buffer_frames = frames;
>          }
> -        *data = This->tmp_buffer;
> -        This->getbuf_last = -frames;
> +        *data = stream->tmp_buffer;
> +        stream->getbuf_last = -frames;
>      }else{
> -        *data = This->local_buffer + write_pos * This->fmt->nBlockAlign;
> -        This->getbuf_last = frames;
> +        *data = stream->local_buffer + write_pos * stream->fmt->nBlockAlign;
> +        stream->getbuf_last = frames;
>      }
>  
> -    silence_buffer(This, *data, frames);
> +    silence_buffer(stream, *data, frames);
>  
>      LeaveCriticalSection(&This->lock);
>  
>      return S_OK;
>  }
>  
> -static void oss_wrap_buffer(ACImpl *This, BYTE *buffer, UINT32 written_frames)
> +static void oss_wrap_buffer(struct oss_stream *stream, BYTE *buffer, UINT32 written_frames)
>  {
>      UINT32 write_offs_frames =
> -        (This->lcl_offs_frames + This->held_frames) % This->bufsize_frames;
> -    UINT32 write_offs_bytes = write_offs_frames * This->fmt->nBlockAlign;
> -    UINT32 chunk_frames = This->bufsize_frames - write_offs_frames;
> -    UINT32 chunk_bytes = chunk_frames * This->fmt->nBlockAlign;
> -    UINT32 written_bytes = written_frames * This->fmt->nBlockAlign;
> +        (stream->lcl_offs_frames + stream->held_frames) % stream->bufsize_frames;
> +    UINT32 write_offs_bytes = write_offs_frames * stream->fmt->nBlockAlign;
> +    UINT32 chunk_frames = stream->bufsize_frames - write_offs_frames;
> +    UINT32 chunk_bytes = chunk_frames * stream->fmt->nBlockAlign;
> +    UINT32 written_bytes = written_frames * stream->fmt->nBlockAlign;
>  
>      if(written_bytes <= chunk_bytes){
> -        memcpy(This->local_buffer + write_offs_bytes, buffer, written_bytes);
> +        memcpy(stream->local_buffer + write_offs_bytes, buffer, written_bytes);
>      }else{
> -        memcpy(This->local_buffer + write_offs_bytes, buffer, chunk_bytes);
> -        memcpy(This->local_buffer, buffer + chunk_bytes,
> +        memcpy(stream->local_buffer + write_offs_bytes, buffer, chunk_bytes);
> +        memcpy(stream->local_buffer, buffer + chunk_bytes,
>                  written_bytes - chunk_bytes);
>      }
>  }
> @@ -1856,6 +1869,7 @@ static HRESULT WINAPI AudioRenderClient_ReleaseBuffer(
>          IAudioRenderClient *iface, UINT32 written_frames, DWORD flags)
>  {
>      ACImpl *This = impl_from_IAudioRenderClient(iface);
> +    struct oss_stream *stream = This->stream;
>      BYTE *buffer;
>  
>      TRACE("(%p)->(%u, %x)\n", This, written_frames, flags);
> @@ -1863,36 +1877,36 @@ static HRESULT WINAPI AudioRenderClient_ReleaseBuffer(
>      EnterCriticalSection(&This->lock);
>  
>      if(!written_frames){
> -        This->getbuf_last = 0;
> +        stream->getbuf_last = 0;
>          LeaveCriticalSection(&This->lock);
>          return S_OK;
>      }
>  
> -    if(!This->getbuf_last){
> +    if(!stream->getbuf_last){
>          LeaveCriticalSection(&This->lock);
>          return AUDCLNT_E_OUT_OF_ORDER;
>      }
>  
> -    if(written_frames > (This->getbuf_last >= 0 ? This->getbuf_last : -This->getbuf_last)){
> +    if(written_frames > (stream->getbuf_last >= 0 ? stream->getbuf_last : -stream->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);
> +    if(stream->getbuf_last >= 0)
> +        buffer = stream->local_buffer + stream->fmt->nBlockAlign *
> +          ((stream->lcl_offs_frames + stream->held_frames) % stream->bufsize_frames);
>      else
> -        buffer = This->tmp_buffer;
> +        buffer = stream->tmp_buffer;
>  
>      if(flags & AUDCLNT_BUFFERFLAGS_SILENT)
> -        silence_buffer(This, buffer, written_frames);
> +        silence_buffer(stream, buffer, written_frames);
>  
> -    if(This->getbuf_last < 0)
> -        oss_wrap_buffer(This, buffer, written_frames);
> +    if(stream->getbuf_last < 0)
> +        oss_wrap_buffer(stream, buffer, written_frames);
>  
> -    This->held_frames += written_frames;
> -    This->written_frames += written_frames;
> -    This->getbuf_last = 0;
> +    stream->held_frames += written_frames;
> +    stream->written_frames += written_frames;
> +    stream->getbuf_last = 0;
>  
>      LeaveCriticalSection(&This->lock);
>  
> @@ -1948,6 +1962,7 @@ static HRESULT WINAPI AudioCaptureClient_GetBuffer(IAudioCaptureClient *iface,
>          UINT64 *qpcpos)
>  {
>      ACImpl *This = impl_from_IAudioCaptureClient(iface);
> +    struct oss_stream *stream = This->stream;
>  
>      TRACE("(%p)->(%p, %p, %p, %p, %p)\n", This, data, frames, flags,
>              devpos, qpcpos);
> @@ -1962,12 +1977,12 @@ static HRESULT WINAPI AudioCaptureClient_GetBuffer(IAudioCaptureClient *iface,
>  
>      EnterCriticalSection(&This->lock);
>  
> -    if(This->getbuf_last){
> +    if(stream->getbuf_last){
>          LeaveCriticalSection(&This->lock);
>          return AUDCLNT_E_OUT_OF_ORDER;
>      }
>  
> -    if(This->held_frames < This->period_frames){
> +    if(stream->held_frames < stream->period_frames){
>          *frames = 0;
>          LeaveCriticalSection(&This->lock);
>          return AUDCLNT_S_BUFFER_EMPTY;
> @@ -1975,37 +1990,37 @@ static HRESULT WINAPI AudioCaptureClient_GetBuffer(IAudioCaptureClient *iface,
>  
>      *flags = 0;
>  
> -    *frames = This->period_frames;
> +    *frames = stream->period_frames;
>  
> -    if(This->lcl_offs_frames + *frames > This->bufsize_frames){
> +    if(stream->lcl_offs_frames + *frames > stream->bufsize_frames){
>          UINT32 chunk_bytes, offs_bytes, frames_bytes;
> -        if(This->tmp_buffer_frames < *frames){
> -            HeapFree(GetProcessHeap(), 0, This->tmp_buffer);
> -            This->tmp_buffer = HeapAlloc(GetProcessHeap(), 0,
> -                    *frames * This->fmt->nBlockAlign);
> -            if(!This->tmp_buffer){
> +        if(stream->tmp_buffer_frames < *frames){
> +            HeapFree(GetProcessHeap(), 0, stream->tmp_buffer);
> +            stream->tmp_buffer = HeapAlloc(GetProcessHeap(), 0,
> +                    *frames * stream->fmt->nBlockAlign);
> +            if(!stream->tmp_buffer){
>                  LeaveCriticalSection(&This->lock);
>                  return E_OUTOFMEMORY;
>              }
> -            This->tmp_buffer_frames = *frames;
> +            stream->tmp_buffer_frames = *frames;
>          }
>  
> -        *data = This->tmp_buffer;
> -        chunk_bytes = (This->bufsize_frames - This->lcl_offs_frames) *
> -            This->fmt->nBlockAlign;
> -        offs_bytes = This->lcl_offs_frames * This->fmt->nBlockAlign;
> -        frames_bytes = *frames * This->fmt->nBlockAlign;
> -        memcpy(This->tmp_buffer, This->local_buffer + offs_bytes, chunk_bytes);
> -        memcpy(This->tmp_buffer + chunk_bytes, This->local_buffer,
> +        *data = stream->tmp_buffer;
> +        chunk_bytes = (stream->bufsize_frames - stream->lcl_offs_frames) *
> +            stream->fmt->nBlockAlign;
> +        offs_bytes = stream->lcl_offs_frames * stream->fmt->nBlockAlign;
> +        frames_bytes = *frames * stream->fmt->nBlockAlign;
> +        memcpy(stream->tmp_buffer, stream->local_buffer + offs_bytes, chunk_bytes);
> +        memcpy(stream->tmp_buffer + chunk_bytes, stream->local_buffer,
>                  frames_bytes - chunk_bytes);
>      }else
> -        *data = This->local_buffer +
> -            This->lcl_offs_frames * This->fmt->nBlockAlign;
> +        *data = stream->local_buffer +
> +            stream->lcl_offs_frames * stream->fmt->nBlockAlign;
>  
> -    This->getbuf_last = *frames;
> +    stream->getbuf_last = *frames;
>  
>      if(devpos)
> -       *devpos = This->written_frames;
> +       *devpos = stream->written_frames;
>      if(qpcpos){
>          LARGE_INTEGER stamp, freq;
>          QueryPerformanceCounter(&stamp);
> @@ -2022,32 +2037,33 @@ static HRESULT WINAPI AudioCaptureClient_ReleaseBuffer(
>          IAudioCaptureClient *iface, UINT32 done)
>  {
>      ACImpl *This = impl_from_IAudioCaptureClient(iface);
> +    struct oss_stream *stream = This->stream;
>  
>      TRACE("(%p)->(%u)\n", This, done);
>  
>      EnterCriticalSection(&This->lock);
>  
>      if(!done){
> -        This->getbuf_last = 0;
> +        stream->getbuf_last = 0;
>          LeaveCriticalSection(&This->lock);
>          return S_OK;
>      }
>  
> -    if(!This->getbuf_last){
> +    if(!stream->getbuf_last){
>          LeaveCriticalSection(&This->lock);
>          return AUDCLNT_E_OUT_OF_ORDER;
>      }
>  
> -    if(This->getbuf_last != done){
> +    if(stream->getbuf_last != done){
>          LeaveCriticalSection(&This->lock);
>          return AUDCLNT_E_INVALID_SIZE;
>      }
>  
> -    This->written_frames += done;
> -    This->held_frames -= done;
> -    This->lcl_offs_frames += done;
> -    This->lcl_offs_frames %= This->bufsize_frames;
> -    This->getbuf_last = 0;
> +    stream->written_frames += done;
> +    stream->held_frames -= done;
> +    stream->lcl_offs_frames += done;
> +    stream->lcl_offs_frames %= stream->bufsize_frames;
> +    stream->getbuf_last = 0;
>  
>      LeaveCriticalSection(&This->lock);
>  
> @@ -2058,6 +2074,7 @@ static HRESULT WINAPI AudioCaptureClient_GetNextPacketSize(
>          IAudioCaptureClient *iface, UINT32 *frames)
>  {
>      ACImpl *This = impl_from_IAudioCaptureClient(iface);
> +    struct oss_stream *stream = This->stream;
>  
>      TRACE("(%p)->(%p)\n", This, frames);
>  
> @@ -2066,7 +2083,7 @@ static HRESULT WINAPI AudioCaptureClient_GetNextPacketSize(
>  
>      EnterCriticalSection(&This->lock);
>  
> -    *frames = This->held_frames < This->period_frames ? 0 : This->period_frames;
> +    *frames = stream->held_frames < stream->period_frames ? 0 : stream->period_frames;
>  
>      LeaveCriticalSection(&This->lock);
>  
> @@ -2122,13 +2139,14 @@ static ULONG WINAPI AudioClock_Release(IAudioClock *iface)
>  static HRESULT WINAPI AudioClock_GetFrequency(IAudioClock *iface, UINT64 *freq)
>  {
>      ACImpl *This = impl_from_IAudioClock(iface);
> +    struct oss_stream *stream = This->stream;
>  
>      TRACE("(%p)->(%p)\n", This, freq);
>  
> -    if(This->share == AUDCLNT_SHAREMODE_SHARED)
> -        *freq = (UINT64)This->fmt->nSamplesPerSec * This->fmt->nBlockAlign;
> +    if(stream->share == AUDCLNT_SHAREMODE_SHARED)
> +        *freq = (UINT64)stream->fmt->nSamplesPerSec * stream->fmt->nBlockAlign;
>      else
> -        *freq = This->fmt->nSamplesPerSec;
> +        *freq = stream->fmt->nSamplesPerSec;
>  
>      return S_OK;
>  }
> @@ -2137,6 +2155,7 @@ static HRESULT WINAPI AudioClock_GetPosition(IAudioClock *iface, UINT64 *pos,
>          UINT64 *qpctime)
>  {
>      ACImpl *This = impl_from_IAudioClock(iface);
> +    struct oss_stream *stream = This->stream;
>  
>      TRACE("(%p)->(%p, %p)\n", This, pos, qpctime);
>  
> @@ -2145,32 +2164,32 @@ static HRESULT WINAPI AudioClock_GetPosition(IAudioClock *iface, UINT64 *pos,
>  
>      EnterCriticalSection(&This->lock);
>  
> -    if(This->dataflow == eRender){
> -        *pos = This->written_frames - This->held_frames;
> -        if(*pos < This->last_pos_frames)
> -            *pos = This->last_pos_frames;
> -    }else if(This->dataflow == eCapture){
> +    if(stream->flow == eRender){
> +        *pos = stream->written_frames - stream->held_frames;
> +        if(*pos < stream->last_pos_frames)
> +            *pos = stream->last_pos_frames;
> +    }else if(stream->flow == eCapture){
>          audio_buf_info bi;
>          UINT32 held;
>  
> -        if(ioctl(This->fd, SNDCTL_DSP_GETISPACE, &bi) < 0){
> +        if(ioctl(stream->fd, SNDCTL_DSP_GETISPACE, &bi) < 0){
>              TRACE("GETISPACE failed: %d (%s)\n", errno, strerror(errno));
>              held = 0;
>          }else{
>              if(bi.bytes <= bi.fragsize)
>                  held = 0;
>              else
> -                held = bi.bytes / This->fmt->nBlockAlign;
> +                held = bi.bytes / stream->fmt->nBlockAlign;
>          }
>  
> -        *pos = This->written_frames + held;
> +        *pos = stream->written_frames + held;
>      }
>  
> -    This->last_pos_frames = *pos;
> +    stream->last_pos_frames = *pos;
>  
>      TRACE("returning: %s\n", wine_dbgstr_longlong(*pos));
> -    if(This->share == AUDCLNT_SHAREMODE_SHARED)
> -        *pos *= This->fmt->nBlockAlign;
> +    if(stream->share == AUDCLNT_SHAREMODE_SHARED)
> +        *pos *= stream->fmt->nBlockAlign;
>  
>      LeaveCriticalSection(&This->lock);
>  
> @@ -2340,7 +2359,7 @@ static HRESULT WINAPI AudioSessionControl_GetState(IAudioSessionControl2 *iface,
>  
>      LIST_FOR_EACH_ENTRY(client, &This->session->clients, ACImpl, entry){
>          EnterCriticalSection(&client->lock);
> -        if(client->playing){
> +        if(client->stream->playing){
>              *state = AudioSessionStateActive;
>              LeaveCriticalSection(&client->lock);
>              LeaveCriticalSection(&g_sessions_lock);
> diff --git a/dlls/wineoss.drv/unixlib.h b/dlls/wineoss.drv/unixlib.h
> index 1a80794f150..f498609898a 100644
> --- a/dlls/wineoss.drv/unixlib.h
> +++ b/dlls/wineoss.drv/unixlib.h
> @@ -18,6 +18,25 @@
>  
>  #include "mmdeviceapi.h"
>  
> +struct oss_stream
> +{
> +    WAVEFORMATEX *fmt;
> +    EDataFlow flow;
> +    UINT flags;
> +    AUDCLNT_SHAREMODE share;
> +    HANDLE event;
> +
> +    int fd;
> +
> +    BOOL playing;
> +    UINT64 written_frames, last_pos_frames;
> +    UINT32 period_us, period_frames, bufsize_frames, held_frames, tmp_buffer_frames, in_oss_frames;
> +    UINT32 oss_bufsize_bytes, lcl_offs_frames; /* offs into local_buffer where valid data starts */
> +
> +    BYTE *local_buffer, *tmp_buffer;
> +    INT32 getbuf_last; /* <0 when using tmp_buffer */
> +};
> +
>  /* From <dlls/mmdevapi/mmdevapi.h> */
>  enum DriverPriority
>  {
> -- 
> 2.25.1
> 
> 



More information about the wine-devel mailing list