winealsa: Simplify the feeding of capture buffers.
This commit is contained in:
parent
9fb2cacd64
commit
5290f53193
|
@ -146,8 +146,6 @@ static DWORD CALLBACK widRecorder(LPVOID pmt)
|
||||||
WAVEHDR* lpWaveHdr;
|
WAVEHDR* lpWaveHdr;
|
||||||
DWORD dwSleepTime;
|
DWORD dwSleepTime;
|
||||||
DWORD bytesRead;
|
DWORD bytesRead;
|
||||||
LPVOID buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, wwi->dwPeriodSize);
|
|
||||||
char *pOffset = buffer;
|
|
||||||
enum win_wm_message msg;
|
enum win_wm_message msg;
|
||||||
DWORD param;
|
DWORD param;
|
||||||
HANDLE ev;
|
HANDLE ev;
|
||||||
|
@ -171,140 +169,69 @@ static DWORD CALLBACK widRecorder(LPVOID pmt)
|
||||||
*/
|
*/
|
||||||
if (wwi->lpQueuePtr != NULL && wwi->state == WINE_WS_PLAYING)
|
if (wwi->lpQueuePtr != NULL && wwi->state == WINE_WS_PLAYING)
|
||||||
{
|
{
|
||||||
int periods;
|
DWORD frames;
|
||||||
DWORD frames;
|
DWORD bytes;
|
||||||
DWORD bytes;
|
DWORD read;
|
||||||
DWORD read;
|
|
||||||
|
|
||||||
lpWaveHdr = wwi->lpQueuePtr;
|
lpWaveHdr = wwi->lpQueuePtr;
|
||||||
/* read all the fragments accumulated so far */
|
/* read all the fragments accumulated so far */
|
||||||
frames = snd_pcm_avail_update(wwi->pcm);
|
frames = snd_pcm_avail_update(wwi->pcm);
|
||||||
bytes = snd_pcm_frames_to_bytes(wwi->pcm, frames);
|
bytes = snd_pcm_frames_to_bytes(wwi->pcm, frames);
|
||||||
|
|
||||||
TRACE("frames = %d bytes = %d\n", frames, bytes);
|
TRACE("frames = %d bytes = %d state=%d\n", frames, bytes, snd_pcm_state(wwi->pcm));
|
||||||
periods = bytes / wwi->dwPeriodSize;
|
if (snd_pcm_state(wwi->pcm) == SND_PCM_STATE_XRUN)
|
||||||
while ((periods > 0) && (wwi->lpQueuePtr))
|
|
||||||
{
|
{
|
||||||
periods--;
|
FIXME("Recovering from XRUN!\n");
|
||||||
bytes = wwi->dwPeriodSize;
|
snd_pcm_prepare(wwi->pcm);
|
||||||
TRACE("bytes = %d\n",bytes);
|
frames = snd_pcm_avail_update(wwi->pcm);
|
||||||
if (lpWaveHdr->dwBufferLength - lpWaveHdr->dwBytesRecorded >= wwi->dwPeriodSize)
|
bytes = snd_pcm_frames_to_bytes(wwi->pcm, frames);
|
||||||
{
|
snd_pcm_start(wwi->pcm);
|
||||||
/* directly read fragment in wavehdr */
|
snd_pcm_forward(wwi->pcm, frames - snd_pcm_bytes_to_frames(wwi->pcm, wwi->dwPeriodSize));
|
||||||
read = wwi->read(wwi->pcm, lpWaveHdr->lpData + lpWaveHdr->dwBytesRecorded, frames_per_period);
|
continue;
|
||||||
bytesRead = snd_pcm_frames_to_bytes(wwi->pcm, read);
|
|
||||||
|
|
||||||
TRACE("bytesRead=%d (direct)\n", bytesRead);
|
|
||||||
if (read != (DWORD) -1)
|
|
||||||
{
|
|
||||||
/* update number of bytes recorded in current buffer and by this device */
|
|
||||||
lpWaveHdr->dwBytesRecorded += bytesRead;
|
|
||||||
InterlockedExchangeAdd((LONG*)&wwi->dwTotalRecorded, bytesRead);
|
|
||||||
|
|
||||||
/* buffer is full. notify client */
|
|
||||||
if (lpWaveHdr->dwBytesRecorded == lpWaveHdr->dwBufferLength)
|
|
||||||
{
|
|
||||||
/* must copy the value of next waveHdr, because we have no idea of what
|
|
||||||
* will be done with the content of lpWaveHdr in callback
|
|
||||||
*/
|
|
||||||
LPWAVEHDR lpNext = lpWaveHdr->lpNext;
|
|
||||||
|
|
||||||
lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
|
|
||||||
lpWaveHdr->dwFlags |= WHDR_DONE;
|
|
||||||
|
|
||||||
wwi->lpQueuePtr = lpNext;
|
|
||||||
widNotifyClient(wwi, WIM_DATA, (DWORD)lpWaveHdr, 0);
|
|
||||||
lpWaveHdr = lpNext;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
FIXME("read(%s, %p, %d) failed (%s)\n", wwi->pcmname,
|
|
||||||
lpWaveHdr->lpData + lpWaveHdr->dwBytesRecorded,
|
|
||||||
frames_per_period, snd_strerror(read));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* read the fragment in a local buffer */
|
|
||||||
read = wwi->read(wwi->pcm, buffer, frames_per_period);
|
|
||||||
bytesRead = snd_pcm_frames_to_bytes(wwi->pcm, read);
|
|
||||||
pOffset = buffer;
|
|
||||||
|
|
||||||
TRACE("bytesRead=%d (local)\n", bytesRead);
|
|
||||||
|
|
||||||
if (read == (DWORD) -1) {
|
|
||||||
TRACE("read(%s, %p, %d) failed (%s)\n", wwi->pcmname,
|
|
||||||
buffer, frames_per_period, strerror(errno));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* copy data in client buffers */
|
|
||||||
while (read != (DWORD) -1 && bytesRead > 0)
|
|
||||||
{
|
|
||||||
DWORD dwToCopy = min (bytesRead, lpWaveHdr->dwBufferLength - lpWaveHdr->dwBytesRecorded);
|
|
||||||
|
|
||||||
memcpy(lpWaveHdr->lpData + lpWaveHdr->dwBytesRecorded,
|
|
||||||
pOffset,
|
|
||||||
dwToCopy);
|
|
||||||
|
|
||||||
/* update number of bytes recorded in current buffer and by this device */
|
|
||||||
lpWaveHdr->dwBytesRecorded += dwToCopy;
|
|
||||||
InterlockedExchangeAdd((LONG*)&wwi->dwTotalRecorded, dwToCopy);
|
|
||||||
bytesRead -= dwToCopy;
|
|
||||||
pOffset += dwToCopy;
|
|
||||||
|
|
||||||
/* client buffer is full. notify client */
|
|
||||||
if (lpWaveHdr->dwBytesRecorded == lpWaveHdr->dwBufferLength)
|
|
||||||
{
|
|
||||||
/* must copy the value of next waveHdr, because we have no idea of what
|
|
||||||
* will be done with the content of lpWaveHdr in callback
|
|
||||||
*/
|
|
||||||
LPWAVEHDR lpNext = lpWaveHdr->lpNext;
|
|
||||||
TRACE("lpNext=%p\n", lpNext);
|
|
||||||
|
|
||||||
lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
|
|
||||||
lpWaveHdr->dwFlags |= WHDR_DONE;
|
|
||||||
|
|
||||||
wwi->lpQueuePtr = lpNext;
|
|
||||||
widNotifyClient(wwi, WIM_DATA, (DWORD)lpWaveHdr, 0);
|
|
||||||
|
|
||||||
lpWaveHdr = lpNext;
|
|
||||||
if (!lpNext && bytesRead) {
|
|
||||||
/* before we give up, check for more header messages */
|
|
||||||
while (ALSA_PeekRingMessage(&wwi->msgRing, &msg, ¶m, &ev))
|
|
||||||
{
|
|
||||||
if (msg == WINE_WM_HEADER) {
|
|
||||||
LPWAVEHDR hdr;
|
|
||||||
ALSA_RetrieveRingMessage(&wwi->msgRing, &msg, ¶m, &ev);
|
|
||||||
hdr = ((LPWAVEHDR)param);
|
|
||||||
TRACE("msg = %s, hdr = %p, ev = %p\n", ALSA_getCmdString(msg), hdr, ev);
|
|
||||||
hdr->lpNext = 0;
|
|
||||||
if (lpWaveHdr == 0) {
|
|
||||||
/* new head of queue */
|
|
||||||
wwi->lpQueuePtr = lpWaveHdr = hdr;
|
|
||||||
} else {
|
|
||||||
/* insert buffer at the end of queue */
|
|
||||||
LPWAVEHDR* wh;
|
|
||||||
for (wh = &(wwi->lpQueuePtr); *wh; wh = &((*wh)->lpNext));
|
|
||||||
*wh = hdr;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lpWaveHdr == 0) {
|
|
||||||
/* no more buffer to copy data to, but we did read more.
|
|
||||||
* what hasn't been copied will be dropped
|
|
||||||
*/
|
|
||||||
WARN("buffer under run! %u bytes dropped.\n", bytesRead);
|
|
||||||
wwi->lpQueuePtr = NULL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
while (frames > 0 && wwi->lpQueuePtr)
|
||||||
|
{
|
||||||
|
TRACE("bytes = %d\n", bytes);
|
||||||
|
if (lpWaveHdr->dwBufferLength - lpWaveHdr->dwBytesRecorded < bytes)
|
||||||
|
{
|
||||||
|
bytes = lpWaveHdr->dwBufferLength - lpWaveHdr->dwBytesRecorded;
|
||||||
|
frames = snd_pcm_bytes_to_frames(wwi->pcm, bytes);
|
||||||
|
}
|
||||||
|
/* directly read fragment in wavehdr */
|
||||||
|
read = wwi->read(wwi->pcm, lpWaveHdr->lpData + lpWaveHdr->dwBytesRecorded, frames);
|
||||||
|
bytesRead = snd_pcm_frames_to_bytes(wwi->pcm, read);
|
||||||
|
|
||||||
|
TRACE("bytesRead=(%d(%d)/(%d)) -> (%d/%d) \n", bytesRead, read, frames, lpWaveHdr->dwBufferLength, lpWaveHdr->dwBufferLength - lpWaveHdr->dwBytesRecorded);
|
||||||
|
if (read != (DWORD) -1)
|
||||||
|
{
|
||||||
|
/* update number of bytes recorded in current buffer and by this device */
|
||||||
|
lpWaveHdr->dwBytesRecorded += bytesRead;
|
||||||
|
InterlockedExchangeAdd((LONG*)&wwi->dwTotalRecorded, bytesRead);
|
||||||
|
frames -= read;
|
||||||
|
bytes -= bytesRead;
|
||||||
|
|
||||||
|
/* buffer is full. notify client */
|
||||||
|
if (!snd_pcm_bytes_to_frames(wwi->pcm, lpWaveHdr->dwBytesRecorded - lpWaveHdr->dwBufferLength))
|
||||||
|
{
|
||||||
|
/* must copy the value of next waveHdr, because we have no idea of what
|
||||||
|
* will be done with the content of lpWaveHdr in callback
|
||||||
|
*/
|
||||||
|
LPWAVEHDR lpNext = lpWaveHdr->lpNext;
|
||||||
|
|
||||||
|
lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
|
||||||
|
lpWaveHdr->dwFlags |= WHDR_DONE;
|
||||||
|
|
||||||
|
wwi->lpQueuePtr = lpNext;
|
||||||
|
widNotifyClient(wwi, WIM_DATA, (DWORD)lpWaveHdr, 0);
|
||||||
|
lpWaveHdr = lpNext;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
WARN("read(%s, %p, %d) failed (%d/%s)\n", wwi->pcmname,
|
||||||
|
lpWaveHdr->lpData + lpWaveHdr->dwBytesRecorded,
|
||||||
|
frames, frames, snd_strerror(read));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ALSA_WaitRingMessage(&wwi->msgRing, dwSleepTime);
|
ALSA_WaitRingMessage(&wwi->msgRing, dwSleepTime);
|
||||||
|
|
||||||
|
@ -383,7 +310,6 @@ static DWORD CALLBACK widRecorder(LPVOID pmt)
|
||||||
wwi->hThread = 0;
|
wwi->hThread = 0;
|
||||||
wwi->state = WINE_WS_CLOSED;
|
wwi->state = WINE_WS_CLOSED;
|
||||||
SetEvent(ev);
|
SetEvent(ev);
|
||||||
HeapFree(GetProcessHeap(), 0, buffer);
|
|
||||||
ExitThread(0);
|
ExitThread(0);
|
||||||
/* shouldn't go here */
|
/* shouldn't go here */
|
||||||
default:
|
default:
|
||||||
|
|
Loading…
Reference in New Issue