mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-24 01:04:02 +02:00
WinMM: Refactoring for the new backend architecture.
This commit is contained in:
+75
-172
@@ -27761,12 +27761,6 @@ static ma_result ma_device_init__winmm(ma_device* pDevice, const void* pDeviceBa
|
|||||||
pDeviceStateWinMM->pWAVEHDRCapture[iPeriod].dwFlags = 0L;
|
pDeviceStateWinMM->pWAVEHDRCapture[iPeriod].dwFlags = 0L;
|
||||||
pDeviceStateWinMM->pWAVEHDRCapture[iPeriod].dwLoops = 0L;
|
pDeviceStateWinMM->pWAVEHDRCapture[iPeriod].dwLoops = 0L;
|
||||||
pContextStateWinMM->waveInPrepareHeader(pDeviceStateWinMM->hDeviceCapture, &pDeviceStateWinMM->pWAVEHDRCapture[iPeriod], sizeof(MA_WAVEHDR));
|
pContextStateWinMM->waveInPrepareHeader(pDeviceStateWinMM->hDeviceCapture, &pDeviceStateWinMM->pWAVEHDRCapture[iPeriod], sizeof(MA_WAVEHDR));
|
||||||
|
|
||||||
/*
|
|
||||||
The user data of the MA_WAVEHDR structure is a single flag the controls whether or not it is ready for writing. Consider it to be named "isLocked". A value of 0 means
|
|
||||||
it's unlocked and available for writing. A value of 1 means it's locked.
|
|
||||||
*/
|
|
||||||
pDeviceStateWinMM->pWAVEHDRCapture[iPeriod].dwUser = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27777,7 +27771,7 @@ static ma_result ma_device_init__winmm(ma_device* pDevice, const void* pDeviceBa
|
|||||||
pDeviceStateWinMM->pWAVEHDRPlayback = (MA_WAVEHDR*)pDeviceStateWinMM->_pHeapData;
|
pDeviceStateWinMM->pWAVEHDRPlayback = (MA_WAVEHDR*)pDeviceStateWinMM->_pHeapData;
|
||||||
pDeviceStateWinMM->pIntermediaryBufferPlayback = pDeviceStateWinMM->_pHeapData + (sizeof(MA_WAVEHDR)*pDescriptorPlayback->periodCount);
|
pDeviceStateWinMM->pIntermediaryBufferPlayback = pDeviceStateWinMM->_pHeapData + (sizeof(MA_WAVEHDR)*pDescriptorPlayback->periodCount);
|
||||||
} else {
|
} else {
|
||||||
pDeviceStateWinMM->pWAVEHDRPlayback = (MA_WAVEHDR*)pDeviceStateWinMM->_pHeapData + (sizeof(MA_WAVEHDR)*(pDescriptorCapture->periodCount));
|
pDeviceStateWinMM->pWAVEHDRPlayback = (MA_WAVEHDR*)pDeviceStateWinMM->_pHeapData + pDescriptorCapture->periodCount;
|
||||||
pDeviceStateWinMM->pIntermediaryBufferPlayback = pDeviceStateWinMM->_pHeapData + (sizeof(MA_WAVEHDR)*(pDescriptorCapture->periodCount + pDescriptorPlayback->periodCount)) + (pDescriptorCapture->periodSizeInFrames*pDescriptorCapture->periodCount*ma_get_bytes_per_frame(pDescriptorCapture->format, pDescriptorCapture->channels));
|
pDeviceStateWinMM->pIntermediaryBufferPlayback = pDeviceStateWinMM->_pHeapData + (sizeof(MA_WAVEHDR)*(pDescriptorCapture->periodCount + pDescriptorPlayback->periodCount)) + (pDescriptorCapture->periodSizeInFrames*pDescriptorCapture->periodCount*ma_get_bytes_per_frame(pDescriptorCapture->format, pDescriptorCapture->channels));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27792,10 +27786,10 @@ static ma_result ma_device_init__winmm(ma_device* pDevice, const void* pDeviceBa
|
|||||||
pContextStateWinMM->waveOutPrepareHeader(pDeviceStateWinMM->hDevicePlayback, &pDeviceStateWinMM->pWAVEHDRPlayback[iPeriod], sizeof(MA_WAVEHDR));
|
pContextStateWinMM->waveOutPrepareHeader(pDeviceStateWinMM->hDevicePlayback, &pDeviceStateWinMM->pWAVEHDRPlayback[iPeriod], sizeof(MA_WAVEHDR));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The user data of the MA_WAVEHDR structure is a single flag the controls whether or not it is ready for writing. Consider it to be named "isLocked". A value of 0 means
|
We use the WHDR_DONE flag to determine whether not not a buffer is available for writing. Since in playback
|
||||||
it's unlocked and available for writing. A value of 1 means it's locked.
|
mode we want buffers to be writable from the start, we will set the flag here at initialization time.
|
||||||
*/
|
*/
|
||||||
pDeviceStateWinMM->pWAVEHDRPlayback[iPeriod].dwUser = 0;
|
pDeviceStateWinMM->pWAVEHDRPlayback[iPeriod].dwFlags |= MA_WHDR_DONE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27880,9 +27874,6 @@ static ma_result ma_device_start__winmm(ma_device* pDevice)
|
|||||||
ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[WinMM] Failed to attach input buffers to capture device in preparation for capture.");
|
ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[WinMM] Failed to attach input buffers to capture device in preparation for capture.");
|
||||||
return ma_result_from_MMRESULT(resultMM);
|
return ma_result_from_MMRESULT(resultMM);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure all of the buffers start out locked. We don't want to access them until the backend tells us we can. */
|
|
||||||
pWAVEHDR[iPeriod].dwUser = 1; /* 1 = locked. */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Capture devices need to be explicitly started, unlike playback devices. */
|
/* Capture devices need to be explicitly started, unlike playback devices. */
|
||||||
@@ -27929,12 +27920,8 @@ static ma_result ma_device_stop__winmm(ma_device* pDevice)
|
|||||||
/* We need to drain the device. To do this we just loop over each header and if it's locked just wait for the event. */
|
/* We need to drain the device. To do this we just loop over each header and if it's locked just wait for the event. */
|
||||||
pWAVEHDR = pDeviceStateWinMM->pWAVEHDRPlayback;
|
pWAVEHDR = pDeviceStateWinMM->pWAVEHDRPlayback;
|
||||||
for (iPeriod = 0; iPeriod < pDevice->playback.internalPeriods; iPeriod += 1) {
|
for (iPeriod = 0; iPeriod < pDevice->playback.internalPeriods; iPeriod += 1) {
|
||||||
if (pWAVEHDR[iPeriod].dwUser == 1) { /* 1 = locked. */
|
if (WaitForSingleObject(pDeviceStateWinMM->hEventPlayback, INFINITE) != WAIT_OBJECT_0) {
|
||||||
if (WaitForSingleObject(pDeviceStateWinMM->hEventPlayback, INFINITE) != WAIT_OBJECT_0) {
|
break; /* An error occurred so just abandon ship and stop the device without draining. */
|
||||||
break; /* An error occurred so just abandon ship and stop the device without draining. */
|
|
||||||
}
|
|
||||||
|
|
||||||
pWAVEHDR[iPeriod].dwUser = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27947,189 +27934,105 @@ static ma_result ma_device_stop__winmm(ma_device* pDevice)
|
|||||||
return MA_SUCCESS;
|
return MA_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ma_result ma_device_write__winmm(ma_device* pDevice, const void* pPCMFrames, ma_uint32 frameCount, ma_uint32* pFramesWritten)
|
static ma_result ma_device_step__winmm(ma_device* pDevice, ma_blocking_mode blockingMode)
|
||||||
{
|
{
|
||||||
ma_device_state_winmm* pDeviceStateWinMM = ma_device_get_backend_state__winmm(pDevice);
|
ma_device_state_winmm* pDeviceStateWinMM = ma_device_get_backend_state__winmm(pDevice);
|
||||||
ma_context_state_winmm* pContextStateWinMM = ma_context_get_backend_state__winmm(ma_device_get_context(pDevice));
|
ma_context_state_winmm* pContextStateWinMM = ma_context_get_backend_state__winmm(ma_device_get_context(pDevice));
|
||||||
ma_result result = MA_SUCCESS;
|
ma_device_type deviceType = ma_device_get_type(pDevice);
|
||||||
|
HANDLE handles[2];
|
||||||
|
DWORD handleCount;
|
||||||
|
DWORD timeout = (blockingMode == MA_BLOCKING_MODE_BLOCKING) ? INFINITE : 0;
|
||||||
|
DWORD waitResult;
|
||||||
MA_MMRESULT resultMM;
|
MA_MMRESULT resultMM;
|
||||||
ma_uint32 totalFramesWritten;
|
|
||||||
MA_WAVEHDR* pWAVEHDR;
|
|
||||||
|
|
||||||
MA_ASSERT(pDevice != NULL);
|
handleCount = 0;
|
||||||
MA_ASSERT(pPCMFrames != NULL);
|
if (deviceType == ma_device_type_capture || deviceType == ma_device_type_duplex) {
|
||||||
|
handles[handleCount++] = pDeviceStateWinMM->hEventCapture;
|
||||||
if (pFramesWritten != NULL) {
|
}
|
||||||
*pFramesWritten = 0;
|
if (deviceType == ma_device_type_playback || deviceType == ma_device_type_duplex) {
|
||||||
|
handles[handleCount++] = pDeviceStateWinMM->hEventPlayback;
|
||||||
}
|
}
|
||||||
|
|
||||||
pWAVEHDR = pDeviceStateWinMM->pWAVEHDRPlayback;
|
waitResult = WaitForMultipleObjects(handleCount, handles, FALSE, timeout);
|
||||||
|
if (waitResult == WAIT_FAILED) {
|
||||||
/* Keep processing as much data as possible. */
|
return MA_ERROR; /* Backend is in an erroneous state. */
|
||||||
totalFramesWritten = 0;
|
|
||||||
while (totalFramesWritten < frameCount) {
|
|
||||||
/* If the current header has some space available we need to write part of it. */
|
|
||||||
if (pWAVEHDR[pDeviceStateWinMM->iNextHeaderPlayback].dwUser == 0) { /* 0 = unlocked. */
|
|
||||||
/*
|
|
||||||
This header has room in it. We copy as much of it as we can. If we end up fully consuming the buffer we need to
|
|
||||||
write it out and move on to the next iteration.
|
|
||||||
*/
|
|
||||||
ma_uint32 bpf = ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
|
|
||||||
ma_uint32 framesRemainingInHeader = (pWAVEHDR[pDeviceStateWinMM->iNextHeaderPlayback].dwBufferLength/bpf) - pDeviceStateWinMM->headerFramesConsumedPlayback;
|
|
||||||
|
|
||||||
ma_uint32 framesToCopy = ma_min(framesRemainingInHeader, (frameCount - totalFramesWritten));
|
|
||||||
const void* pSrc = ma_offset_ptr(pPCMFrames, totalFramesWritten*bpf);
|
|
||||||
void* pDst = ma_offset_ptr(pWAVEHDR[pDeviceStateWinMM->iNextHeaderPlayback].lpData, pDeviceStateWinMM->headerFramesConsumedPlayback*bpf);
|
|
||||||
MA_COPY_MEMORY(pDst, pSrc, framesToCopy*bpf);
|
|
||||||
|
|
||||||
pDeviceStateWinMM->headerFramesConsumedPlayback += framesToCopy;
|
|
||||||
totalFramesWritten += framesToCopy;
|
|
||||||
|
|
||||||
/* If we've consumed the buffer entirely we need to write it out to the device. */
|
|
||||||
if (pDeviceStateWinMM->headerFramesConsumedPlayback == (pWAVEHDR[pDeviceStateWinMM->iNextHeaderPlayback].dwBufferLength/bpf)) {
|
|
||||||
pWAVEHDR[pDeviceStateWinMM->iNextHeaderPlayback].dwUser = 1; /* 1 = locked. */
|
|
||||||
pWAVEHDR[pDeviceStateWinMM->iNextHeaderPlayback].dwFlags &= ~MA_WHDR_DONE; /* <-- Need to make sure the WHDR_DONE flag is unset. */
|
|
||||||
|
|
||||||
/* Make sure the event is reset to a non-signaled state to ensure we don't prematurely return from WaitForSingleObject(). */
|
|
||||||
ResetEvent(pDeviceStateWinMM->hEventPlayback);
|
|
||||||
|
|
||||||
/* The device will be started here. */
|
|
||||||
resultMM = pContextStateWinMM->waveOutWrite(pDeviceStateWinMM->hDevicePlayback, &pWAVEHDR[pDeviceStateWinMM->iNextHeaderPlayback], sizeof(MA_WAVEHDR));
|
|
||||||
if (resultMM != MA_MMSYSERR_NOERROR) {
|
|
||||||
result = ma_result_from_MMRESULT(resultMM);
|
|
||||||
ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[WinMM] waveOutWrite() failed.");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Make sure we move to the next header. */
|
|
||||||
pDeviceStateWinMM->iNextHeaderPlayback = (pDeviceStateWinMM->iNextHeaderPlayback + 1) % pDevice->playback.internalPeriods;
|
|
||||||
pDeviceStateWinMM->headerFramesConsumedPlayback = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If at this point we have consumed the entire input buffer we can return. */
|
|
||||||
MA_ASSERT(totalFramesWritten <= frameCount);
|
|
||||||
if (totalFramesWritten == frameCount) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Getting here means there's more to process. */
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Getting here means there isn't enough room in the buffer and we need to wait for one to become available. */
|
|
||||||
if (WaitForSingleObject(pDeviceStateWinMM->hEventPlayback, INFINITE) != WAIT_OBJECT_0) {
|
|
||||||
result = MA_ERROR;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Something happened. If the next buffer has been marked as done we need to reset a bit of state. */
|
|
||||||
if ((pWAVEHDR[pDeviceStateWinMM->iNextHeaderPlayback].dwFlags & MA_WHDR_DONE) != 0) {
|
|
||||||
pWAVEHDR[pDeviceStateWinMM->iNextHeaderPlayback].dwUser = 0; /* 0 = unlocked (make it available for writing). */
|
|
||||||
pDeviceStateWinMM->headerFramesConsumedPlayback = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If the device has been stopped we need to break. */
|
|
||||||
if (ma_device_get_status(pDevice) != ma_device_status_started) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pFramesWritten != NULL) {
|
if (!ma_device_is_started(pDevice)) {
|
||||||
*pFramesWritten = totalFramesWritten;
|
return MA_DEVICE_NOT_STARTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
if (waitResult >= WAIT_OBJECT_0 && waitResult <= WAIT_OBJECT_0 + handleCount-1) {
|
||||||
}
|
/* Something is available for processing. */
|
||||||
|
HANDLE handle = handles[waitResult - WAIT_OBJECT_0];
|
||||||
|
ma_uint32 frameCount;
|
||||||
|
|
||||||
static ma_result ma_device_read__winmm(ma_device* pDevice, void* pPCMFrames, ma_uint32 frameCount, ma_uint32* pFramesRead)
|
/* Capture. */
|
||||||
{
|
if (handle == pDeviceStateWinMM->hEventCapture && (deviceType == ma_device_type_capture || deviceType == ma_device_type_duplex)) {
|
||||||
ma_device_state_winmm* pDeviceStateWinMM = ma_device_get_backend_state__winmm(pDevice);
|
MA_WAVEHDR* pWAVEHDR = pDeviceStateWinMM->pWAVEHDRCapture;
|
||||||
ma_context_state_winmm* pContextStateWinMM = ma_context_get_backend_state__winmm(ma_device_get_context(pDevice));
|
|
||||||
ma_result result = MA_SUCCESS;
|
|
||||||
MA_MMRESULT resultMM;
|
|
||||||
ma_uint32 totalFramesRead;
|
|
||||||
MA_WAVEHDR* pWAVEHDR;
|
|
||||||
|
|
||||||
MA_ASSERT(pDevice != NULL);
|
/* Consume any completed header. */
|
||||||
MA_ASSERT(pPCMFrames != NULL);
|
while ((pWAVEHDR[pDeviceStateWinMM->iNextHeaderCapture].dwFlags & MA_WHDR_DONE) != 0) {
|
||||||
|
pWAVEHDR[pDeviceStateWinMM->iNextHeaderCapture].dwFlags &= ~MA_WHDR_DONE;
|
||||||
|
|
||||||
if (pFramesRead != NULL) {
|
frameCount = pWAVEHDR[pDeviceStateWinMM->iNextHeaderCapture].dwBufferLength / ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
|
||||||
*pFramesRead = 0;
|
ma_device_handle_backend_data_callback(pDevice, NULL, pWAVEHDR[pDeviceStateWinMM->iNextHeaderCapture].lpData, frameCount);
|
||||||
}
|
|
||||||
|
|
||||||
pWAVEHDR = pDeviceStateWinMM->pWAVEHDRCapture;
|
|
||||||
|
|
||||||
/* Keep processing as much data as possible. */
|
|
||||||
totalFramesRead = 0;
|
|
||||||
while (totalFramesRead < frameCount) {
|
|
||||||
/* If the current header has some space available we need to write part of it. */
|
|
||||||
if (pWAVEHDR[pDeviceStateWinMM->iNextHeaderCapture].dwUser == 0) { /* 0 = unlocked. */
|
|
||||||
/* The buffer is available for reading. If we fully consume it we need to add it back to the buffer. */
|
|
||||||
ma_uint32 bpf = ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
|
|
||||||
ma_uint32 framesRemainingInHeader = (pWAVEHDR[pDeviceStateWinMM->iNextHeaderCapture].dwBufferLength/bpf) - pDeviceStateWinMM->headerFramesConsumedCapture;
|
|
||||||
|
|
||||||
ma_uint32 framesToCopy = ma_min(framesRemainingInHeader, (frameCount - totalFramesRead));
|
|
||||||
const void* pSrc = ma_offset_ptr(pWAVEHDR[pDeviceStateWinMM->iNextHeaderCapture].lpData, pDeviceStateWinMM->headerFramesConsumedCapture*bpf);
|
|
||||||
void* pDst = ma_offset_ptr(pPCMFrames, totalFramesRead*bpf);
|
|
||||||
MA_COPY_MEMORY(pDst, pSrc, framesToCopy*bpf);
|
|
||||||
|
|
||||||
pDeviceStateWinMM->headerFramesConsumedCapture += framesToCopy;
|
|
||||||
totalFramesRead += framesToCopy;
|
|
||||||
|
|
||||||
/* If we've consumed the buffer entirely we need to add it back to the device. */
|
|
||||||
if (pDeviceStateWinMM->headerFramesConsumedCapture == (pWAVEHDR[pDeviceStateWinMM->iNextHeaderCapture].dwBufferLength/bpf)) {
|
|
||||||
pWAVEHDR[pDeviceStateWinMM->iNextHeaderCapture].dwUser = 1; /* 1 = locked. */
|
|
||||||
pWAVEHDR[pDeviceStateWinMM->iNextHeaderCapture].dwFlags &= ~MA_WHDR_DONE; /* <-- Need to make sure the WHDR_DONE flag is unset. */
|
|
||||||
|
|
||||||
/* Make sure the event is reset to a non-signaled state to ensure we don't prematurely return from WaitForSingleObject(). */
|
|
||||||
ResetEvent(pDeviceStateWinMM->hEventCapture);
|
|
||||||
|
|
||||||
/* The device will be started here. */
|
/* The device will be started here. */
|
||||||
resultMM = pContextStateWinMM->waveInAddBuffer(pDeviceStateWinMM->hDeviceCapture, &pDeviceStateWinMM->pWAVEHDRCapture[pDeviceStateWinMM->iNextHeaderCapture], sizeof(MA_WAVEHDR));
|
resultMM = pContextStateWinMM->waveInAddBuffer(pDeviceStateWinMM->hDeviceCapture, &pDeviceStateWinMM->pWAVEHDRCapture[pDeviceStateWinMM->iNextHeaderCapture], sizeof(MA_WAVEHDR));
|
||||||
if (resultMM != MA_MMSYSERR_NOERROR) {
|
if (resultMM != MA_MMSYSERR_NOERROR) {
|
||||||
result = ma_result_from_MMRESULT(resultMM);
|
|
||||||
ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[WinMM] waveInAddBuffer() failed.");
|
ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[WinMM] waveInAddBuffer() failed.");
|
||||||
break;
|
return ma_result_from_MMRESULT(resultMM);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure we move to the next header. */
|
/* Make sure we move to the next header. */
|
||||||
pDeviceStateWinMM->iNextHeaderCapture = (pDeviceStateWinMM->iNextHeaderCapture + 1) % pDevice->capture.internalPeriods;
|
pDeviceStateWinMM->iNextHeaderCapture = (pDeviceStateWinMM->iNextHeaderCapture + 1) % pDevice->capture.internalPeriods;
|
||||||
pDeviceStateWinMM->headerFramesConsumedCapture = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If at this point we have filled the entire input buffer we can return. */
|
/* Make sure the event is reset to a non-signaled state to ensure we don't prematurely return from WaitForSingleObject(). */
|
||||||
MA_ASSERT(totalFramesRead <= frameCount);
|
ResetEvent(pDeviceStateWinMM->hEventCapture);
|
||||||
if (totalFramesRead == frameCount) {
|
}
|
||||||
break;
|
|
||||||
|
/* Playback. */
|
||||||
|
if (handle == pDeviceStateWinMM->hEventPlayback && (deviceType == ma_device_type_playback || deviceType == ma_device_type_duplex)) {
|
||||||
|
MA_WAVEHDR* pWAVEHDR = pDeviceStateWinMM->pWAVEHDRPlayback;
|
||||||
|
|
||||||
|
/* Fill out any completed header with fresh data. */
|
||||||
|
while ((pWAVEHDR[pDeviceStateWinMM->iNextHeaderPlayback].dwFlags & MA_WHDR_DONE) != 0) {
|
||||||
|
pWAVEHDR[pDeviceStateWinMM->iNextHeaderPlayback].dwFlags &= ~MA_WHDR_DONE;
|
||||||
|
|
||||||
|
frameCount = pWAVEHDR[pDeviceStateWinMM->iNextHeaderPlayback].dwBufferLength / ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
|
||||||
|
ma_device_handle_backend_data_callback(pDevice, pWAVEHDR[pDeviceStateWinMM->iNextHeaderPlayback].lpData, NULL, frameCount);
|
||||||
|
|
||||||
|
/* The device will be started here. */
|
||||||
|
resultMM = pContextStateWinMM->waveOutWrite(pDeviceStateWinMM->hDevicePlayback, &pWAVEHDR[pDeviceStateWinMM->iNextHeaderPlayback], sizeof(MA_WAVEHDR));
|
||||||
|
if (resultMM != MA_MMSYSERR_NOERROR) {
|
||||||
|
ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[WinMM] waveOutWrite() failed.");
|
||||||
|
return ma_result_from_MMRESULT(resultMM);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure we move to the next header. */
|
||||||
|
pDeviceStateWinMM->iNextHeaderPlayback = (pDeviceStateWinMM->iNextHeaderPlayback + 1) % pDevice->playback.internalPeriods;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Getting here means there's more to process. */
|
/* Make sure the event is reset to a non-signaled state to ensure we don't prematurely return from WaitForSingleObject(). */
|
||||||
continue;
|
ResetEvent(pDeviceStateWinMM->hEventPlayback);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
/* Most likely a timeout in non-blocking mode. Nothing to do. */
|
||||||
|
}
|
||||||
|
|
||||||
/* Getting here means there isn't enough any data left to send to the client which means we need to wait for more. */
|
return MA_SUCCESS;
|
||||||
if (WaitForSingleObject(pDeviceStateWinMM->hEventCapture, INFINITE) != WAIT_OBJECT_0) {
|
}
|
||||||
result = MA_ERROR;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Something happened. If the next buffer has been marked as done we need to reset a bit of state. */
|
static void ma_device_loop__winmm(ma_device* pDevice)
|
||||||
if ((pWAVEHDR[pDeviceStateWinMM->iNextHeaderCapture].dwFlags & MA_WHDR_DONE) != 0) {
|
{
|
||||||
pWAVEHDR[pDeviceStateWinMM->iNextHeaderCapture].dwUser = 0; /* 0 = unlocked (make it available for reading). */
|
while (ma_device_is_started(pDevice)) {
|
||||||
pDeviceStateWinMM->headerFramesConsumedCapture = 0;
|
ma_result result = ma_device_step__winmm(pDevice, MA_BLOCKING_MODE_BLOCKING);
|
||||||
}
|
if (result != MA_SUCCESS) {
|
||||||
|
|
||||||
/* If the device has been stopped we need to break. */
|
|
||||||
if (ma_device_get_status(pDevice) != ma_device_status_started) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pFramesRead != NULL) {
|
|
||||||
*pFramesRead = totalFramesRead;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static ma_device_backend_vtable ma_gDeviceBackendVTable_WinMM =
|
static ma_device_backend_vtable ma_gDeviceBackendVTable_WinMM =
|
||||||
@@ -28142,9 +28045,9 @@ static ma_device_backend_vtable ma_gDeviceBackendVTable_WinMM =
|
|||||||
ma_device_uninit__winmm,
|
ma_device_uninit__winmm,
|
||||||
ma_device_start__winmm,
|
ma_device_start__winmm,
|
||||||
ma_device_stop__winmm,
|
ma_device_stop__winmm,
|
||||||
ma_device_read__winmm,
|
NULL,
|
||||||
ma_device_write__winmm,
|
NULL,
|
||||||
NULL, /* onDeviceLopp */
|
ma_device_loop__winmm,
|
||||||
NULL /* onDeviceWakeup */
|
NULL /* onDeviceWakeup */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user