/************************************************************************** * wodPlayer [internal] */ static DWORD CALLBACK wodPlayer(LPVOID pmt) { WORD uDevID = (DWORD_PTR)pmt; WINE_WAVEOUT* wwo = &WOutDev[uDevID]; wwo->state = WINE_WS_STOPPED; SetEvent(wwo->hStartUpEvent); for (;;) { if (wwo->FlowStarted) { AuHandleEvents(wwo->AuServ); if (wwo->state == WINE_WS_PLAYING && wwo->freeBytes && wwo->BufferUsed) nas_send_buffer(wwo); } if (wwo->BufferUsed <= FRAG_SIZE && wwo->writeBytes > 0) wodPlayer_NotifyCompletions(wwo, FALSE); WaitForSingleObject(wwo->msgRing.msg_event, 20); wodPlayer_ProcessMessages(wwo); while(wwo->lpPlayPtr) { wwo->lpPlayPtr->reserved = wwo->WrittenTotal + wwo->lpPlayPtr->dwBufferLength; nas_add_buffer(wwo); wodPlayer_PlayPtrNext(wwo); } return 0; } }
/************************************************************************** * wodPlayer [internal] */ static DWORD CALLBACK wodPlayer(LPVOID pmt) { WORD uDevID = (DWORD_PTR)pmt; WINE_WAVEDEV* wwo = &WOutDev[uDevID]; DWORD dwNextFeedTime = INFINITE; /* Time before DSP needs feeding */ DWORD dwNextNotifyTime = INFINITE; /* Time before next wave completion */ DWORD dwSleepTime; wwo->state = WINE_WS_STOPPED; SetEvent(wwo->hStartUpEvent); for (;;) { /** Wait for the shortest time before an action is required. If there * are no pending actions, wait forever for a command. */ dwSleepTime = min(dwNextFeedTime, dwNextNotifyTime); TRACE("waiting %ums (%u,%u)\n", dwSleepTime, dwNextFeedTime, dwNextNotifyTime); ALSA_WaitRingMessage(&wwo->msgRing, dwSleepTime); wodPlayer_ProcessMessages(wwo); if (wwo->state == WINE_WS_PLAYING) { dwNextFeedTime = wodPlayer_FeedDSP(wwo); dwNextNotifyTime = wodPlayer_NotifyCompletions(wwo, FALSE); if (dwNextFeedTime == INFINITE) { /* FeedDSP ran out of data, but before giving up, */ /* check that a notification didn't give us more */ wodPlayer_ProcessMessages(wwo); if (wwo->lpPlayPtr) { TRACE("recovering\n"); dwNextFeedTime = wodPlayer_FeedDSP(wwo); } } } else { dwNextFeedTime = dwNextNotifyTime = INFINITE; } } return 0; }