Maarten Lankhorst : winealsa: Simplify the feeding of capture buffers.
Alexandre Julliard
julliard at winehq.org
Fri Dec 7 13:19:12 CST 2007
Module: wine
Branch: master
Commit: 5290f53193d0d43ad2867098228a2599422ebf61
URL: http://source.winehq.org/git/wine.git/?a=commit;h=5290f53193d0d43ad2867098228a2599422ebf61
Author: Maarten Lankhorst <maarten at codeweavers.com>
Date: Fri Dec 7 10:50:03 2007 +0100
winealsa: Simplify the feeding of capture buffers.
---
dlls/winealsa.drv/wavein.c | 178 +++++++++++++-------------------------------
1 files changed, 52 insertions(+), 126 deletions(-)
diff --git a/dlls/winealsa.drv/wavein.c b/dlls/winealsa.drv/wavein.c
index 6d1cf24..652e0cd 100644
--- a/dlls/winealsa.drv/wavein.c
+++ b/dlls/winealsa.drv/wavein.c
@@ -146,8 +146,6 @@ static DWORD CALLBACK widRecorder(LPVOID pmt)
WAVEHDR* lpWaveHdr;
DWORD dwSleepTime;
DWORD bytesRead;
- LPVOID buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, wwi->dwPeriodSize);
- char *pOffset = buffer;
enum win_wm_message msg;
DWORD param;
HANDLE ev;
@@ -171,140 +169,69 @@ static DWORD CALLBACK widRecorder(LPVOID pmt)
*/
if (wwi->lpQueuePtr != NULL && wwi->state == WINE_WS_PLAYING)
{
- int periods;
- DWORD frames;
- DWORD bytes;
- DWORD read;
+ DWORD frames;
+ DWORD bytes;
+ DWORD read;
lpWaveHdr = wwi->lpQueuePtr;
/* read all the fragments accumulated so far */
- frames = snd_pcm_avail_update(wwi->pcm);
- bytes = snd_pcm_frames_to_bytes(wwi->pcm, frames);
+ frames = snd_pcm_avail_update(wwi->pcm);
+ bytes = snd_pcm_frames_to_bytes(wwi->pcm, frames);
- TRACE("frames = %d bytes = %d\n", frames, bytes);
- periods = bytes / wwi->dwPeriodSize;
- while ((periods > 0) && (wwi->lpQueuePtr))
+ TRACE("frames = %d bytes = %d state=%d\n", frames, bytes, snd_pcm_state(wwi->pcm));
+ if (snd_pcm_state(wwi->pcm) == SND_PCM_STATE_XRUN)
{
- periods--;
- bytes = wwi->dwPeriodSize;
- TRACE("bytes = %d\n",bytes);
- if (lpWaveHdr->dwBufferLength - lpWaveHdr->dwBytesRecorded >= wwi->dwPeriodSize)
+ FIXME("Recovering from XRUN!\n");
+ snd_pcm_prepare(wwi->pcm);
+ frames = snd_pcm_avail_update(wwi->pcm);
+ bytes = snd_pcm_frames_to_bytes(wwi->pcm, frames);
+ snd_pcm_start(wwi->pcm);
+ snd_pcm_forward(wwi->pcm, frames - snd_pcm_bytes_to_frames(wwi->pcm, wwi->dwPeriodSize));
+ continue;
+ }
+ while (frames > 0 && wwi->lpQueuePtr)
+ {
+ TRACE("bytes = %d\n", bytes);
+ if (lpWaveHdr->dwBufferLength - lpWaveHdr->dwBytesRecorded < bytes)
{
- /* directly read fragment in wavehdr */
- read = wwi->read(wwi->pcm, lpWaveHdr->lpData + lpWaveHdr->dwBytesRecorded, frames_per_period);
- 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));
- }
+ bytes = lpWaveHdr->dwBufferLength - lpWaveHdr->dwBytesRecorded;
+ frames = snd_pcm_bytes_to_frames(wwi->pcm, bytes);
}
- 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;
+ /* 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 (local)\n", bytesRead);
+ 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;
- if (read == (DWORD) -1) {
- TRACE("read(%s, %p, %d) failed (%s)\n", wwi->pcmname,
- buffer, frames_per_period, strerror(errno));
- continue;
- }
+ lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
+ lpWaveHdr->dwFlags |= WHDR_DONE;
- /* 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;
- }
- }
- }
- }
- }
+ 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);
@@ -383,7 +310,6 @@ static DWORD CALLBACK widRecorder(LPVOID pmt)
wwi->hThread = 0;
wwi->state = WINE_WS_CLOSED;
SetEvent(ev);
- HeapFree(GetProcessHeap(), 0, buffer);
ExitThread(0);
/* shouldn't go here */
default:
More information about the wine-cvs
mailing list