winealsa: Implement a light form of locking for dsoutput.

This commit is contained in:
Maarten Lankhorst 2007-07-29 16:17:22 +02:00 committed by Alexandre Julliard
parent eca194da7f
commit 3d3d4e2c8b
1 changed files with 97 additions and 14 deletions

View File

@ -88,7 +88,7 @@ struct IDsDriverBufferImpl
snd_pcm_t *pcm; snd_pcm_t *pcm;
snd_pcm_hw_params_t *hw_params; snd_pcm_hw_params_t *hw_params;
snd_pcm_sw_params_t *sw_params; snd_pcm_sw_params_t *sw_params;
snd_pcm_uframes_t mmap_buflen_frames, mmap_pos, mmap_commitahead, mmap_writeahead; snd_pcm_uframes_t mmap_buflen_frames, mmap_pos, mmap_commitahead;
}; };
/** Fill buffers, for starting and stopping /** Fill buffers, for starting and stopping
@ -225,7 +225,7 @@ static int DSDB_CreateMMAP(IDsDriverBufferImpl* pdbi)
return DSERR_GENERIC; return DSERR_GENERIC;
} }
snd_pcm_format_set_silence(format, areas->addr, pdbi->mmap_buflen_frames); snd_pcm_format_set_silence(format, areas->addr, pdbi->mmap_buflen_frames);
err = snd_pcm_mmap_commit(pcm, ofs, avail); pdbi->mmap_pos = ofs + snd_pcm_mmap_commit(pcm, ofs, 0);
pdbi->mmap_buffer = areas->addr; pdbi->mmap_buffer = areas->addr;
TRACE("created mmap buffer of %ld frames (%d bytes) at %p\n", TRACE("created mmap buffer of %ld frames (%d bytes) at %p\n",
@ -284,16 +284,88 @@ static HRESULT WINAPI IDsDriverBufferImpl_Lock(PIDSDRIVERBUFFER iface,
DWORD dwWritePosition,DWORD dwWriteLen, DWORD dwWritePosition,DWORD dwWriteLen,
DWORD dwFlags) DWORD dwFlags)
{ {
FIXME("(%p) stub\n", iface); IDsDriverBufferImpl *This = (IDsDriverBufferImpl *)iface;
return DSERR_UNSUPPORTED; snd_pcm_uframes_t writepos;
TRACE("%d bytes from %d\n", dwWriteLen, dwWritePosition);
/* **** */
EnterCriticalSection(&This->pcm_crst);
if (dwWriteLen > This->mmap_buflen_bytes || dwWritePosition >= This->mmap_buflen_bytes)
{
/* **** */
LeaveCriticalSection(&This->pcm_crst);
return DSERR_INVALIDPARAM;
}
if (ppvAudio2) *ppvAudio2 = NULL;
if (pdwLen2) *pdwLen2 = 0;
*ppvAudio1 = (LPBYTE)This->mmap_buffer + dwWritePosition;
*pdwLen1 = dwWriteLen;
if (dwWritePosition+dwWriteLen > This->mmap_buflen_bytes)
{
DWORD remainder = This->mmap_buflen_bytes - dwWritePosition;
*pdwLen1 = remainder;
if (ppvAudio2 && pdwLen2)
{
*ppvAudio2 = This->mmap_buffer;
*pdwLen2 = dwWriteLen - remainder;
}
else dwWriteLen = remainder;
}
writepos = snd_pcm_bytes_to_frames(This->pcm, dwWritePosition);
if (writepos == This->mmap_pos && snd_pcm_state(This->pcm) == SND_PCM_STATE_RUNNING)
{
const snd_pcm_channel_area_t *areas;
snd_pcm_uframes_t writelen = snd_pcm_bytes_to_frames(This->pcm, dwWriteLen), putin = writelen;
TRACE("Hit mmap_pos, locking data!\n");
snd_pcm_mmap_begin(This->pcm, &areas, &This->mmap_pos, &putin);
}
LeaveCriticalSection(&This->pcm_crst);
/* **** */
return DS_OK;
} }
static HRESULT WINAPI IDsDriverBufferImpl_Unlock(PIDSDRIVERBUFFER iface, static HRESULT WINAPI IDsDriverBufferImpl_Unlock(PIDSDRIVERBUFFER iface,
LPVOID pvAudio1,DWORD dwLen1, LPVOID pvAudio1,DWORD dwLen1,
LPVOID pvAudio2,DWORD dwLen2) LPVOID pvAudio2,DWORD dwLen2)
{ {
FIXME("(%p) stub\n", iface); IDsDriverBufferImpl *This = (IDsDriverBufferImpl *)iface;
return DSERR_UNSUPPORTED; snd_pcm_uframes_t writepos;
if (!dwLen1)
return DS_OK;
/* **** */
EnterCriticalSection(&This->pcm_crst);
writepos = snd_pcm_bytes_to_frames(This->pcm, (DWORD_PTR)pvAudio1 - (DWORD_PTR)This->mmap_buffer);
if (writepos == This->mmap_pos)
{
const snd_pcm_channel_area_t *areas;
snd_pcm_uframes_t writelen = snd_pcm_bytes_to_frames(This->pcm, dwLen1);
TRACE("Committing data\n");
This->mmap_pos += snd_pcm_mmap_commit(This->pcm, This->mmap_pos, writelen);
if (This->mmap_pos == This->mmap_buflen_frames)
This->mmap_pos = 0;
if (!This->mmap_pos && dwLen2)
{
writelen = snd_pcm_bytes_to_frames(This->pcm, dwLen2);
snd_pcm_mmap_begin(This->pcm, &areas, &This->mmap_pos, &writelen);
This->mmap_pos += snd_pcm_mmap_commit(This->pcm, This->mmap_pos, writelen);
assert(This->mmap_pos < This->mmap_buflen_frames);
}
}
LeaveCriticalSection(&This->pcm_crst);
/* **** */
return DS_OK;
} }
static HRESULT SetFormat(IDsDriverBufferImpl *This, LPWAVEFORMATEX pwfx, BOOL forced) static HRESULT SetFormat(IDsDriverBufferImpl *This, LPWAVEFORMATEX pwfx, BOOL forced)
@ -384,7 +456,6 @@ static HRESULT SetFormat(IDsDriverBufferImpl *This, LPWAVEFORMATEX pwfx, BOOL fo
This->mmap_commitahead = 3 * psize; This->mmap_commitahead = 3 * psize;
while (This->mmap_commitahead <= 512) while (This->mmap_commitahead <= 512)
This->mmap_commitahead += psize; This->mmap_commitahead += psize;
This->mmap_writeahead = This->mmap_commitahead;
if (This->pcm) if (This->pcm)
{ {
@ -462,6 +533,7 @@ static HRESULT WINAPI IDsDriverBufferImpl_GetPosition(PIDSDRIVERBUFFER iface,
snd_pcm_uframes_t hw_pptr=0, hw_wptr=0; snd_pcm_uframes_t hw_pptr=0, hw_wptr=0;
snd_pcm_state_t state; snd_pcm_state_t state;
/* **** */
EnterCriticalSection(&This->pcm_crst); EnterCriticalSection(&This->pcm_crst);
if (!This->pcm) if (!This->pcm)
@ -471,6 +543,9 @@ static HRESULT WINAPI IDsDriverBufferImpl_GetPosition(PIDSDRIVERBUFFER iface,
return DSERR_GENERIC; return DSERR_GENERIC;
} }
if (!lpdwPlay && !lpdwWrite)
CommitAll(This);
state = snd_pcm_state(This->pcm); state = snd_pcm_state(This->pcm);
if (state != SND_PCM_STATE_PREPARED && state != SND_PCM_STATE_RUNNING) if (state != SND_PCM_STATE_PREPARED && state != SND_PCM_STATE_RUNNING)
@ -480,21 +555,20 @@ static HRESULT WINAPI IDsDriverBufferImpl_GetPosition(PIDSDRIVERBUFFER iface,
} }
if (state == SND_PCM_STATE_RUNNING) if (state == SND_PCM_STATE_RUNNING)
{ {
snd_pcm_uframes_t used = CommitAll(This); snd_pcm_uframes_t used = This->mmap_buflen_frames - snd_pcm_avail_update(This->pcm);
if (This->mmap_pos > used) if (This->mmap_pos > used)
hw_pptr = This->mmap_pos - used; hw_pptr = This->mmap_pos - used;
else else
hw_pptr = This->mmap_buflen_frames - used + This->mmap_pos; hw_pptr = This->mmap_buflen_frames + This->mmap_pos - used;
hw_wptr = hw_pptr + (This->mmap_writeahead > used ? used : This->mmap_writeahead);
hw_wptr %= This->mmap_buflen_frames;
hw_pptr %= This->mmap_buflen_frames; hw_pptr %= This->mmap_buflen_frames;
hw_wptr = This->mmap_pos;
TRACE("At position: %ld (%ld) - Used %ld\n", hw_pptr, This->mmap_pos, used); TRACE("At position: %ld (%ld) - Used %ld\n", hw_pptr, This->mmap_pos, used);
} }
LeaveCriticalSection(&This->pcm_crst); LeaveCriticalSection(&This->pcm_crst);
/* **** */
if (lpdwPlay) if (lpdwPlay)
*lpdwPlay = snd_pcm_frames_to_bytes(This->pcm, hw_pptr); *lpdwPlay = snd_pcm_frames_to_bytes(This->pcm, hw_pptr);
@ -512,8 +586,8 @@ static HRESULT WINAPI IDsDriverBufferImpl_Play(PIDSDRIVERBUFFER iface, DWORD dwR
/* **** */ /* **** */
EnterCriticalSection(&This->pcm_crst); EnterCriticalSection(&This->pcm_crst);
snd_pcm_start(This->pcm);
CommitAll(This); CommitAll(This);
snd_pcm_start(This->pcm);
/* **** */ /* **** */
LeaveCriticalSection(&This->pcm_crst); LeaveCriticalSection(&This->pcm_crst);
return DS_OK; return DS_OK;
@ -521,13 +595,22 @@ static HRESULT WINAPI IDsDriverBufferImpl_Play(PIDSDRIVERBUFFER iface, DWORD dwR
static HRESULT WINAPI IDsDriverBufferImpl_Stop(PIDSDRIVERBUFFER iface) static HRESULT WINAPI IDsDriverBufferImpl_Stop(PIDSDRIVERBUFFER iface)
{ {
const snd_pcm_channel_area_t *areas;
snd_pcm_uframes_t avail;
snd_pcm_format_t format;
IDsDriverBufferImpl *This = (IDsDriverBufferImpl *)iface; IDsDriverBufferImpl *This = (IDsDriverBufferImpl *)iface;
TRACE("(%p)\n",iface); TRACE("(%p)\n",iface);
/* **** */ /* **** */
EnterCriticalSection(&This->pcm_crst); EnterCriticalSection(&This->pcm_crst);
avail = This->mmap_buflen_frames;
snd_pcm_drop(This->pcm); snd_pcm_drop(This->pcm);
snd_pcm_prepare(This->pcm); snd_pcm_prepare(This->pcm);
snd_pcm_mmap_begin(This->pcm, &areas, &This->mmap_pos, &avail);
snd_pcm_hw_params_get_format(This->hw_params, &format);
snd_pcm_format_set_silence(format, areas->addr, This->mmap_buflen_frames);
This->mmap_pos += snd_pcm_mmap_commit(This->pcm, This->mmap_pos, avail);
/* **** */ /* **** */
LeaveCriticalSection(&This->pcm_crst); LeaveCriticalSection(&This->pcm_crst);
return DS_OK; return DS_OK;
@ -585,7 +668,7 @@ static HRESULT WINAPI IDsDriverImpl_GetDriverDesc(PIDSDRIVER iface, PDSDRIVERDES
IDsDriverImpl *This = (IDsDriverImpl *)iface; IDsDriverImpl *This = (IDsDriverImpl *)iface;
TRACE("(%p,%p)\n",iface,pDesc); TRACE("(%p,%p)\n",iface,pDesc);
memcpy(pDesc, &(WOutDev[This->wDevID].ds_desc), sizeof(DSDRIVERDESC)); memcpy(pDesc, &(WOutDev[This->wDevID].ds_desc), sizeof(DSDRIVERDESC));
pDesc->dwFlags = DSDDESC_DONTNEEDPRIMARYLOCK | DSDDESC_DONTNEEDSECONDARYLOCK | DSDDESC_DONTNEEDWRITELEAD; pDesc->dwFlags = DSDDESC_DONTNEEDSECONDARYLOCK | DSDDESC_DONTNEEDWRITELEAD;
pDesc->dnDevNode = WOutDev[This->wDevID].waveDesc.dnDevNode; pDesc->dnDevNode = WOutDev[This->wDevID].waveDesc.dnDevNode;
pDesc->wVxdId = 0; pDesc->wVxdId = 0;
pDesc->wReserved = 0; pDesc->wReserved = 0;