mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-23 16:54:03 +02:00
Migrate the WinMM backend over to the new callback system.
This commit is contained in:
+144
-331
@@ -16705,6 +16705,8 @@ static ma_result ma_get_best_info_from_formats_flags__winmm(DWORD dwFormats, WOR
|
||||
|
||||
static ma_result ma_formats_flags_to_WAVEFORMATEX__winmm(DWORD dwFormats, WORD channels, WAVEFORMATEX* pWF)
|
||||
{
|
||||
ma_result result;
|
||||
|
||||
MA_ASSERT(pWF != NULL);
|
||||
|
||||
MA_ZERO_OBJECT(pWF);
|
||||
@@ -16715,62 +16717,9 @@ static ma_result ma_formats_flags_to_WAVEFORMATEX__winmm(DWORD dwFormats, WORD c
|
||||
pWF->nChannels = 2;
|
||||
}
|
||||
|
||||
if (channels == 1) {
|
||||
pWF->wBitsPerSample = 16;
|
||||
if ((dwFormats & WAVE_FORMAT_48M16) != 0) {
|
||||
pWF->nSamplesPerSec = 48000;
|
||||
} else if ((dwFormats & WAVE_FORMAT_44M16) != 0) {
|
||||
pWF->nSamplesPerSec = 44100;
|
||||
} else if ((dwFormats & WAVE_FORMAT_2M16) != 0) {
|
||||
pWF->nSamplesPerSec = 22050;
|
||||
} else if ((dwFormats & WAVE_FORMAT_1M16) != 0) {
|
||||
pWF->nSamplesPerSec = 11025;
|
||||
} else if ((dwFormats & WAVE_FORMAT_96M16) != 0) {
|
||||
pWF->nSamplesPerSec = 96000;
|
||||
} else {
|
||||
pWF->wBitsPerSample = 8;
|
||||
if ((dwFormats & WAVE_FORMAT_48M08) != 0) {
|
||||
pWF->nSamplesPerSec = 48000;
|
||||
} else if ((dwFormats & WAVE_FORMAT_44M08) != 0) {
|
||||
pWF->nSamplesPerSec = 44100;
|
||||
} else if ((dwFormats & WAVE_FORMAT_2M08) != 0) {
|
||||
pWF->nSamplesPerSec = 22050;
|
||||
} else if ((dwFormats & WAVE_FORMAT_1M08) != 0) {
|
||||
pWF->nSamplesPerSec = 11025;
|
||||
} else if ((dwFormats & WAVE_FORMAT_96M08) != 0) {
|
||||
pWF->nSamplesPerSec = 96000;
|
||||
} else {
|
||||
return MA_FORMAT_NOT_SUPPORTED;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
pWF->wBitsPerSample = 16;
|
||||
if ((dwFormats & WAVE_FORMAT_48S16) != 0) {
|
||||
pWF->nSamplesPerSec = 48000;
|
||||
} else if ((dwFormats & WAVE_FORMAT_44S16) != 0) {
|
||||
pWF->nSamplesPerSec = 44100;
|
||||
} else if ((dwFormats & WAVE_FORMAT_2S16) != 0) {
|
||||
pWF->nSamplesPerSec = 22050;
|
||||
} else if ((dwFormats & WAVE_FORMAT_1S16) != 0) {
|
||||
pWF->nSamplesPerSec = 11025;
|
||||
} else if ((dwFormats & WAVE_FORMAT_96S16) != 0) {
|
||||
pWF->nSamplesPerSec = 96000;
|
||||
} else {
|
||||
pWF->wBitsPerSample = 8;
|
||||
if ((dwFormats & WAVE_FORMAT_48S08) != 0) {
|
||||
pWF->nSamplesPerSec = 48000;
|
||||
} else if ((dwFormats & WAVE_FORMAT_44S08) != 0) {
|
||||
pWF->nSamplesPerSec = 44100;
|
||||
} else if ((dwFormats & WAVE_FORMAT_2S08) != 0) {
|
||||
pWF->nSamplesPerSec = 22050;
|
||||
} else if ((dwFormats & WAVE_FORMAT_1S08) != 0) {
|
||||
pWF->nSamplesPerSec = 11025;
|
||||
} else if ((dwFormats & WAVE_FORMAT_96S08) != 0) {
|
||||
pWF->nSamplesPerSec = 96000;
|
||||
} else {
|
||||
return MA_FORMAT_NOT_SUPPORTED;
|
||||
}
|
||||
}
|
||||
result = ma_get_best_info_from_formats_flags__winmm(dwFormats, channels, &pWF->wBitsPerSample, &pWF->nSamplesPerSec);
|
||||
if (result != MA_SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
|
||||
pWF->nBlockAlign = (WORD)(pWF->nChannels * pWF->wBitsPerSample / 8);
|
||||
@@ -16856,22 +16805,21 @@ static ma_result ma_context_get_device_info_from_WAVECAPS(ma_context* pContext,
|
||||
return result;
|
||||
}
|
||||
|
||||
pDeviceInfo->minChannels = pCaps->wChannels;
|
||||
pDeviceInfo->maxChannels = pCaps->wChannels;
|
||||
pDeviceInfo->minSampleRate = sampleRate;
|
||||
pDeviceInfo->maxSampleRate = sampleRate;
|
||||
pDeviceInfo->formatCount = 1;
|
||||
if (bitsPerSample == 8) {
|
||||
pDeviceInfo->formats[0] = ma_format_u8;
|
||||
pDeviceInfo->nativeDataFormats[0].format = ma_format_u8;
|
||||
} else if (bitsPerSample == 16) {
|
||||
pDeviceInfo->formats[0] = ma_format_s16;
|
||||
pDeviceInfo->nativeDataFormats[0].format = ma_format_s16;
|
||||
} else if (bitsPerSample == 24) {
|
||||
pDeviceInfo->formats[0] = ma_format_s24;
|
||||
pDeviceInfo->nativeDataFormats[0].format = ma_format_s24;
|
||||
} else if (bitsPerSample == 32) {
|
||||
pDeviceInfo->formats[0] = ma_format_s32;
|
||||
pDeviceInfo->nativeDataFormats[0].format = ma_format_s32;
|
||||
} else {
|
||||
return MA_FORMAT_NOT_SUPPORTED;
|
||||
}
|
||||
pDeviceInfo->nativeDataFormats[0].channels = pCaps->wChannels;
|
||||
pDeviceInfo->nativeDataFormats[0].sampleRate = sampleRate;
|
||||
pDeviceInfo->nativeDataFormats[0].flags = 0;
|
||||
pDeviceInfo->nativeDataFormatCount = 1;
|
||||
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
@@ -16887,7 +16835,7 @@ static ma_result ma_context_get_device_info_from_WAVEOUTCAPS2(ma_context* pConte
|
||||
MA_COPY_MEMORY(caps.szPname, pCaps->szPname, sizeof(caps.szPname));
|
||||
caps.dwFormats = pCaps->dwFormats;
|
||||
caps.wChannels = pCaps->wChannels;
|
||||
caps.NameGuid = pCaps->NameGuid;
|
||||
caps.NameGuid = pCaps->NameGuid;
|
||||
return ma_context_get_device_info_from_WAVECAPS(pContext, &caps, pDeviceInfo);
|
||||
}
|
||||
|
||||
@@ -16902,7 +16850,7 @@ static ma_result ma_context_get_device_info_from_WAVEINCAPS2(ma_context* pContex
|
||||
MA_COPY_MEMORY(caps.szPname, pCaps->szPname, sizeof(caps.szPname));
|
||||
caps.dwFormats = pCaps->dwFormats;
|
||||
caps.wChannels = pCaps->wChannels;
|
||||
caps.NameGuid = pCaps->NameGuid;
|
||||
caps.NameGuid = pCaps->NameGuid;
|
||||
return ma_context_get_device_info_from_WAVECAPS(pContext, &caps, pDeviceInfo);
|
||||
}
|
||||
|
||||
@@ -16978,16 +16926,12 @@ static ma_result ma_context_enumerate_devices__winmm(ma_context* pContext, ma_en
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
|
||||
static ma_result ma_context_get_device_info__winmm(ma_context* pContext, ma_device_type deviceType, const ma_device_id* pDeviceID, ma_share_mode shareMode, ma_device_info* pDeviceInfo)
|
||||
static ma_result ma_context_get_device_info__winmm(ma_context* pContext, ma_device_type deviceType, const ma_device_id* pDeviceID, ma_device_info* pDeviceInfo)
|
||||
{
|
||||
UINT winMMDeviceID;
|
||||
|
||||
MA_ASSERT(pContext != NULL);
|
||||
|
||||
if (shareMode == ma_share_mode_exclusive) {
|
||||
return MA_SHARE_MODE_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
winMMDeviceID = 0;
|
||||
if (pDeviceID != NULL) {
|
||||
winMMDeviceID = (UINT)pDeviceID->winmm;
|
||||
@@ -17026,7 +16970,7 @@ static ma_result ma_context_get_device_info__winmm(ma_context* pContext, ma_devi
|
||||
}
|
||||
|
||||
|
||||
static void ma_device_uninit__winmm(ma_device* pDevice)
|
||||
static ma_result ma_device_uninit__winmm(ma_device* pDevice)
|
||||
{
|
||||
MA_ASSERT(pDevice != NULL);
|
||||
|
||||
@@ -17044,9 +16988,27 @@ static void ma_device_uninit__winmm(ma_device* pDevice)
|
||||
ma__free_from_callbacks(pDevice->winmm._pHeapData, &pDevice->pContext->allocationCallbacks);
|
||||
|
||||
MA_ZERO_OBJECT(&pDevice->winmm); /* Safety. */
|
||||
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
|
||||
static ma_result ma_device_init__winmm(ma_context* pContext, const ma_device_config* pConfig, ma_device* pDevice)
|
||||
static ma_uint32 ma_calculate_period_size_in_frames__winmm(ma_uint32 periodSizeInFrames, ma_uint32 periodSizeInMilliseconds, ma_uint32 sampleRate)
|
||||
{
|
||||
/* DirectSound has a minimum period size of 40ms. */
|
||||
ma_uint32 minPeriodSizeInFrames = ma_calculate_buffer_size_in_frames_from_milliseconds(40, sampleRate);
|
||||
|
||||
if (periodSizeInFrames == 0) {
|
||||
periodSizeInFrames = ma_calculate_buffer_size_in_frames_from_milliseconds(periodSizeInMilliseconds, sampleRate);
|
||||
}
|
||||
|
||||
if (periodSizeInFrames < minPeriodSizeInFrames) {
|
||||
periodSizeInFrames = minPeriodSizeInFrames;
|
||||
}
|
||||
|
||||
return periodSizeInFrames;
|
||||
}
|
||||
|
||||
static ma_result ma_device_init__winmm(ma_device* pDevice, const ma_device_config* pConfig, ma_device_descriptor* pDescriptorPlayback, ma_device_descriptor* pDescriptorCapture)
|
||||
{
|
||||
const char* errorMsg = "";
|
||||
ma_result errorCode = MA_ERROR;
|
||||
@@ -17054,9 +17016,9 @@ static ma_result ma_device_init__winmm(ma_context* pContext, const ma_device_con
|
||||
ma_uint32 heapSize;
|
||||
UINT winMMDeviceIDPlayback = 0;
|
||||
UINT winMMDeviceIDCapture = 0;
|
||||
ma_uint32 periodSizeInMilliseconds;
|
||||
|
||||
MA_ASSERT(pDevice != NULL);
|
||||
|
||||
MA_ZERO_OBJECT(&pDevice->winmm);
|
||||
|
||||
if (pConfig->deviceType == ma_device_type_loopback) {
|
||||
@@ -17069,26 +17031,11 @@ static ma_result ma_device_init__winmm(ma_context* pContext, const ma_device_con
|
||||
return MA_SHARE_MODE_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
periodSizeInMilliseconds = pConfig->periodSizeInMilliseconds;
|
||||
if (periodSizeInMilliseconds == 0) {
|
||||
periodSizeInMilliseconds = ma_calculate_buffer_size_in_milliseconds_from_frames(pConfig->periodSizeInFrames, pConfig->sampleRate);
|
||||
if (pDescriptorPlayback->pDeviceID != NULL) {
|
||||
winMMDeviceIDPlayback = (UINT)pDescriptorPlayback->pDeviceID->winmm;
|
||||
}
|
||||
|
||||
/* WinMM has horrible latency. */
|
||||
if (pDevice->usingDefaultBufferSize) {
|
||||
if (pConfig->performanceProfile == ma_performance_profile_low_latency) {
|
||||
periodSizeInMilliseconds = 40;
|
||||
} else {
|
||||
periodSizeInMilliseconds = 400;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (pConfig->playback.pDeviceID != NULL) {
|
||||
winMMDeviceIDPlayback = (UINT)pConfig->playback.pDeviceID->winmm;
|
||||
}
|
||||
if (pConfig->capture.pDeviceID != NULL) {
|
||||
winMMDeviceIDCapture = (UINT)pConfig->capture.pDeviceID->winmm;
|
||||
if (pDescriptorCapture->pDeviceID != NULL) {
|
||||
winMMDeviceIDCapture = (UINT)pDescriptorCapture->pDeviceID->winmm;
|
||||
}
|
||||
|
||||
/* The capture device needs to be initialized first. */
|
||||
@@ -17105,7 +17052,7 @@ static ma_result ma_device_init__winmm(ma_context* pContext, const ma_device_con
|
||||
}
|
||||
|
||||
/* The format should be based on the device's actual format. */
|
||||
if (((MA_PFN_waveInGetDevCapsA)pContext->winmm.waveInGetDevCapsA)(winMMDeviceIDCapture, &caps, sizeof(caps)) != MMSYSERR_NOERROR) {
|
||||
if (((MA_PFN_waveInGetDevCapsA)pDevice->pContext->winmm.waveInGetDevCapsA)(winMMDeviceIDCapture, &caps, sizeof(caps)) != MMSYSERR_NOERROR) {
|
||||
errorMsg = "[WinMM] Failed to retrieve internal device caps.", errorCode = MA_FORMAT_NOT_SUPPORTED;
|
||||
goto on_error;
|
||||
}
|
||||
@@ -17122,12 +17069,12 @@ static ma_result ma_device_init__winmm(ma_context* pContext, const ma_device_con
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
pDevice->capture.internalFormat = ma_format_from_WAVEFORMATEX(&wf);
|
||||
pDevice->capture.internalChannels = wf.nChannels;
|
||||
pDevice->capture.internalSampleRate = wf.nSamplesPerSec;
|
||||
ma_get_standard_channel_map(ma_standard_channel_map_microsoft, pDevice->capture.internalChannels, pDevice->capture.internalChannelMap);
|
||||
pDevice->capture.internalPeriods = pConfig->periods;
|
||||
pDevice->capture.internalPeriodSizeInFrames = ma_calculate_buffer_size_in_frames_from_milliseconds(periodSizeInMilliseconds, pDevice->capture.internalSampleRate);
|
||||
pDescriptorCapture->format = ma_format_from_WAVEFORMATEX(&wf);
|
||||
pDescriptorCapture->channels = wf.nChannels;
|
||||
pDescriptorCapture->sampleRate = wf.nSamplesPerSec;
|
||||
ma_get_standard_channel_map(ma_standard_channel_map_microsoft, pDescriptorCapture->channels, pDescriptorCapture->channelMap);
|
||||
pDescriptorCapture->periodCount = pDescriptorCapture->periodCount;
|
||||
pDescriptorCapture->periodSizeInFrames = ma_calculate_period_size_in_frames__winmm(pDescriptorCapture->periodSizeInFrames, pDescriptorCapture->periodSizeInMilliseconds, pDescriptorCapture->sampleRate);
|
||||
}
|
||||
|
||||
if (pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) {
|
||||
@@ -17143,7 +17090,7 @@ static ma_result ma_device_init__winmm(ma_context* pContext, const ma_device_con
|
||||
}
|
||||
|
||||
/* The format should be based on the device's actual format. */
|
||||
if (((MA_PFN_waveOutGetDevCapsA)pContext->winmm.waveOutGetDevCapsA)(winMMDeviceIDPlayback, &caps, sizeof(caps)) != MMSYSERR_NOERROR) {
|
||||
if (((MA_PFN_waveOutGetDevCapsA)pDevice->pContext->winmm.waveOutGetDevCapsA)(winMMDeviceIDPlayback, &caps, sizeof(caps)) != MMSYSERR_NOERROR) {
|
||||
errorMsg = "[WinMM] Failed to retrieve internal device caps.", errorCode = MA_FORMAT_NOT_SUPPORTED;
|
||||
goto on_error;
|
||||
}
|
||||
@@ -17154,18 +17101,18 @@ static ma_result ma_device_init__winmm(ma_context* pContext, const ma_device_con
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
resultMM = ((MA_PFN_waveOutOpen)pContext->winmm.waveOutOpen)((LPHWAVEOUT)&pDevice->winmm.hDevicePlayback, winMMDeviceIDPlayback, &wf, (DWORD_PTR)pDevice->winmm.hEventPlayback, (DWORD_PTR)pDevice, CALLBACK_EVENT | WAVE_ALLOWSYNC);
|
||||
resultMM = ((MA_PFN_waveOutOpen)pDevice->pContext->winmm.waveOutOpen)((LPHWAVEOUT)&pDevice->winmm.hDevicePlayback, winMMDeviceIDPlayback, &wf, (DWORD_PTR)pDevice->winmm.hEventPlayback, (DWORD_PTR)pDevice, CALLBACK_EVENT | WAVE_ALLOWSYNC);
|
||||
if (resultMM != MMSYSERR_NOERROR) {
|
||||
errorMsg = "[WinMM] Failed to open playback device.", errorCode = MA_FAILED_TO_OPEN_BACKEND_DEVICE;
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
pDevice->playback.internalFormat = ma_format_from_WAVEFORMATEX(&wf);
|
||||
pDevice->playback.internalChannels = wf.nChannels;
|
||||
pDevice->playback.internalSampleRate = wf.nSamplesPerSec;
|
||||
ma_get_standard_channel_map(ma_standard_channel_map_microsoft, pDevice->playback.internalChannels, pDevice->playback.internalChannelMap);
|
||||
pDevice->playback.internalPeriods = pConfig->periods;
|
||||
pDevice->playback.internalPeriodSizeInFrames = ma_calculate_buffer_size_in_frames_from_milliseconds(periodSizeInMilliseconds, pDevice->playback.internalSampleRate);
|
||||
pDescriptorPlayback->format = ma_format_from_WAVEFORMATEX(&wf);
|
||||
pDescriptorPlayback->channels = wf.nChannels;
|
||||
pDescriptorPlayback->sampleRate = wf.nSamplesPerSec;
|
||||
ma_get_standard_channel_map(ma_standard_channel_map_microsoft, pDescriptorPlayback->channels, pDescriptorPlayback->channelMap);
|
||||
pDescriptorPlayback->periodCount = pDescriptorPlayback->periodCount;
|
||||
pDescriptorPlayback->periodSizeInFrames = ma_calculate_period_size_in_frames__winmm(pDescriptorPlayback->periodSizeInFrames, pDescriptorPlayback->periodSizeInMilliseconds, pDescriptorPlayback->sampleRate);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -17175,13 +17122,13 @@ static ma_result ma_device_init__winmm(ma_context* pContext, const ma_device_con
|
||||
*/
|
||||
heapSize = 0;
|
||||
if (pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) {
|
||||
heapSize += sizeof(WAVEHDR)*pDevice->capture.internalPeriods + (pDevice->capture.internalPeriodSizeInFrames*pDevice->capture.internalPeriods*ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels));
|
||||
heapSize += sizeof(WAVEHDR)*pDescriptorCapture->periodCount + (pDescriptorCapture->periodSizeInFrames * pDescriptorCapture->periodCount * ma_get_bytes_per_frame(pDescriptorCapture->format, pDescriptorCapture->channels));
|
||||
}
|
||||
if (pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) {
|
||||
heapSize += sizeof(WAVEHDR)*pDevice->playback.internalPeriods + (pDevice->playback.internalPeriodSizeInFrames*pDevice->playback.internalPeriods*ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels));
|
||||
heapSize += sizeof(WAVEHDR)*pDescriptorPlayback->periodCount + (pDescriptorPlayback->periodSizeInFrames * pDescriptorPlayback->periodCount * ma_get_bytes_per_frame(pDescriptorPlayback->format, pDescriptorPlayback->channels));
|
||||
}
|
||||
|
||||
pDevice->winmm._pHeapData = (ma_uint8*)ma__calloc_from_callbacks(heapSize, &pContext->allocationCallbacks);
|
||||
pDevice->winmm._pHeapData = (ma_uint8*)ma__calloc_from_callbacks(heapSize, &pDevice->pContext->allocationCallbacks);
|
||||
if (pDevice->winmm._pHeapData == NULL) {
|
||||
errorMsg = "[WinMM] Failed to allocate memory for the intermediary buffer.", errorCode = MA_OUT_OF_MEMORY;
|
||||
goto on_error;
|
||||
@@ -17194,21 +17141,21 @@ static ma_result ma_device_init__winmm(ma_context* pContext, const ma_device_con
|
||||
|
||||
if (pConfig->deviceType == ma_device_type_capture) {
|
||||
pDevice->winmm.pWAVEHDRCapture = pDevice->winmm._pHeapData;
|
||||
pDevice->winmm.pIntermediaryBufferCapture = pDevice->winmm._pHeapData + (sizeof(WAVEHDR)*(pDevice->capture.internalPeriods));
|
||||
pDevice->winmm.pIntermediaryBufferCapture = pDevice->winmm._pHeapData + (sizeof(WAVEHDR)*(pDescriptorCapture->periodCount));
|
||||
} else {
|
||||
pDevice->winmm.pWAVEHDRCapture = pDevice->winmm._pHeapData;
|
||||
pDevice->winmm.pIntermediaryBufferCapture = pDevice->winmm._pHeapData + (sizeof(WAVEHDR)*(pDevice->capture.internalPeriods + pDevice->playback.internalPeriods));
|
||||
pDevice->winmm.pIntermediaryBufferCapture = pDevice->winmm._pHeapData + (sizeof(WAVEHDR)*(pDescriptorCapture->periodCount + pDescriptorPlayback->periodCount));
|
||||
}
|
||||
|
||||
/* Prepare headers. */
|
||||
for (iPeriod = 0; iPeriod < pDevice->capture.internalPeriods; ++iPeriod) {
|
||||
ma_uint32 periodSizeInBytes = ma_get_period_size_in_bytes(pDevice->capture.internalPeriodSizeInFrames, pDevice->capture.internalFormat, pDevice->capture.internalChannels);
|
||||
for (iPeriod = 0; iPeriod < pDescriptorCapture->periodCount; ++iPeriod) {
|
||||
ma_uint32 periodSizeInBytes = ma_get_period_size_in_bytes(pDescriptorCapture->periodSizeInFrames, pDescriptorCapture->format, pDescriptorCapture->channels);
|
||||
|
||||
((WAVEHDR*)pDevice->winmm.pWAVEHDRCapture)[iPeriod].lpData = (LPSTR)(pDevice->winmm.pIntermediaryBufferCapture + (periodSizeInBytes*iPeriod));
|
||||
((WAVEHDR*)pDevice->winmm.pWAVEHDRCapture)[iPeriod].dwBufferLength = periodSizeInBytes;
|
||||
((WAVEHDR*)pDevice->winmm.pWAVEHDRCapture)[iPeriod].dwFlags = 0L;
|
||||
((WAVEHDR*)pDevice->winmm.pWAVEHDRCapture)[iPeriod].dwLoops = 0L;
|
||||
((MA_PFN_waveInPrepareHeader)pContext->winmm.waveInPrepareHeader)((HWAVEIN)pDevice->winmm.hDeviceCapture, &((WAVEHDR*)pDevice->winmm.pWAVEHDRCapture)[iPeriod], sizeof(WAVEHDR));
|
||||
((MA_PFN_waveInPrepareHeader)pDevice->pContext->winmm.waveInPrepareHeader)((HWAVEIN)pDevice->winmm.hDeviceCapture, &((WAVEHDR*)pDevice->winmm.pWAVEHDRCapture)[iPeriod], sizeof(WAVEHDR));
|
||||
|
||||
/*
|
||||
The user data of the 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
|
||||
@@ -17217,26 +17164,27 @@ static ma_result ma_device_init__winmm(ma_context* pContext, const ma_device_con
|
||||
((WAVEHDR*)pDevice->winmm.pWAVEHDRCapture)[iPeriod].dwUser = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) {
|
||||
ma_uint32 iPeriod;
|
||||
|
||||
if (pConfig->deviceType == ma_device_type_playback) {
|
||||
pDevice->winmm.pWAVEHDRPlayback = pDevice->winmm._pHeapData;
|
||||
pDevice->winmm.pIntermediaryBufferPlayback = pDevice->winmm._pHeapData + (sizeof(WAVEHDR)*pDevice->playback.internalPeriods);
|
||||
pDevice->winmm.pIntermediaryBufferPlayback = pDevice->winmm._pHeapData + (sizeof(WAVEHDR)*pDescriptorPlayback->periodCount);
|
||||
} else {
|
||||
pDevice->winmm.pWAVEHDRPlayback = pDevice->winmm._pHeapData + (sizeof(WAVEHDR)*(pDevice->capture.internalPeriods));
|
||||
pDevice->winmm.pIntermediaryBufferPlayback = pDevice->winmm._pHeapData + (sizeof(WAVEHDR)*(pDevice->capture.internalPeriods + pDevice->playback.internalPeriods)) + (pDevice->capture.internalPeriodSizeInFrames*pDevice->capture.internalPeriods*ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels));
|
||||
pDevice->winmm.pWAVEHDRPlayback = pDevice->winmm._pHeapData + (sizeof(WAVEHDR)*(pDescriptorCapture->periodCount));
|
||||
pDevice->winmm.pIntermediaryBufferPlayback = pDevice->winmm._pHeapData + (sizeof(WAVEHDR)*(pDescriptorCapture->periodCount + pDescriptorPlayback->periodCount)) + (pDescriptorCapture->periodSizeInFrames*pDescriptorCapture->periodCount*ma_get_bytes_per_frame(pDescriptorCapture->format, pDescriptorCapture->channels));
|
||||
}
|
||||
|
||||
/* Prepare headers. */
|
||||
for (iPeriod = 0; iPeriod < pDevice->playback.internalPeriods; ++iPeriod) {
|
||||
ma_uint32 periodSizeInBytes = ma_get_period_size_in_bytes(pDevice->playback.internalPeriodSizeInFrames, pDevice->playback.internalFormat, pDevice->playback.internalChannels);
|
||||
for (iPeriod = 0; iPeriod < pDescriptorPlayback->periodCount; ++iPeriod) {
|
||||
ma_uint32 periodSizeInBytes = ma_get_period_size_in_bytes(pDescriptorPlayback->periodSizeInFrames, pDescriptorPlayback->format, pDescriptorPlayback->channels);
|
||||
|
||||
((WAVEHDR*)pDevice->winmm.pWAVEHDRPlayback)[iPeriod].lpData = (LPSTR)(pDevice->winmm.pIntermediaryBufferPlayback + (periodSizeInBytes*iPeriod));
|
||||
((WAVEHDR*)pDevice->winmm.pWAVEHDRPlayback)[iPeriod].dwBufferLength = periodSizeInBytes;
|
||||
((WAVEHDR*)pDevice->winmm.pWAVEHDRPlayback)[iPeriod].dwFlags = 0L;
|
||||
((WAVEHDR*)pDevice->winmm.pWAVEHDRPlayback)[iPeriod].dwLoops = 0L;
|
||||
((MA_PFN_waveOutPrepareHeader)pContext->winmm.waveOutPrepareHeader)((HWAVEOUT)pDevice->winmm.hDevicePlayback, &((WAVEHDR*)pDevice->winmm.pWAVEHDRPlayback)[iPeriod], sizeof(WAVEHDR));
|
||||
((MA_PFN_waveOutPrepareHeader)pDevice->pContext->winmm.waveOutPrepareHeader)((HWAVEOUT)pDevice->winmm.hDevicePlayback, &((WAVEHDR*)pDevice->winmm.pWAVEHDRPlayback)[iPeriod], sizeof(WAVEHDR));
|
||||
|
||||
/*
|
||||
The user data of the 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
|
||||
@@ -17252,29 +17200,68 @@ on_error:
|
||||
if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
|
||||
if (pDevice->winmm.pWAVEHDRCapture != NULL) {
|
||||
ma_uint32 iPeriod;
|
||||
for (iPeriod = 0; iPeriod < pDevice->capture.internalPeriods; ++iPeriod) {
|
||||
((MA_PFN_waveInUnprepareHeader)pContext->winmm.waveInUnprepareHeader)((HWAVEIN)pDevice->winmm.hDeviceCapture, &((WAVEHDR*)pDevice->winmm.pWAVEHDRCapture)[iPeriod], sizeof(WAVEHDR));
|
||||
for (iPeriod = 0; iPeriod < pDescriptorCapture->periodCount; ++iPeriod) {
|
||||
((MA_PFN_waveInUnprepareHeader)pDevice->pContext->winmm.waveInUnprepareHeader)((HWAVEIN)pDevice->winmm.hDeviceCapture, &((WAVEHDR*)pDevice->winmm.pWAVEHDRCapture)[iPeriod], sizeof(WAVEHDR));
|
||||
}
|
||||
}
|
||||
|
||||
((MA_PFN_waveInClose)pContext->winmm.waveInClose)((HWAVEIN)pDevice->winmm.hDeviceCapture);
|
||||
((MA_PFN_waveInClose)pDevice->pContext->winmm.waveInClose)((HWAVEIN)pDevice->winmm.hDeviceCapture);
|
||||
}
|
||||
|
||||
if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
|
||||
if (pDevice->winmm.pWAVEHDRCapture != NULL) {
|
||||
ma_uint32 iPeriod;
|
||||
for (iPeriod = 0; iPeriod < pDevice->playback.internalPeriods; ++iPeriod) {
|
||||
((MA_PFN_waveOutUnprepareHeader)pContext->winmm.waveOutUnprepareHeader)((HWAVEOUT)pDevice->winmm.hDevicePlayback, &((WAVEHDR*)pDevice->winmm.pWAVEHDRPlayback)[iPeriod], sizeof(WAVEHDR));
|
||||
for (iPeriod = 0; iPeriod < pDescriptorPlayback->periodCount; ++iPeriod) {
|
||||
((MA_PFN_waveOutUnprepareHeader)pDevice->pContext->winmm.waveOutUnprepareHeader)((HWAVEOUT)pDevice->winmm.hDevicePlayback, &((WAVEHDR*)pDevice->winmm.pWAVEHDRPlayback)[iPeriod], sizeof(WAVEHDR));
|
||||
}
|
||||
}
|
||||
|
||||
((MA_PFN_waveOutClose)pContext->winmm.waveOutClose)((HWAVEOUT)pDevice->winmm.hDevicePlayback);
|
||||
((MA_PFN_waveOutClose)pDevice->pContext->winmm.waveOutClose)((HWAVEOUT)pDevice->winmm.hDevicePlayback);
|
||||
}
|
||||
|
||||
ma__free_from_callbacks(pDevice->winmm._pHeapData, &pContext->allocationCallbacks);
|
||||
ma__free_from_callbacks(pDevice->winmm._pHeapData, &pDevice->pContext->allocationCallbacks);
|
||||
return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, errorMsg, errorCode);
|
||||
}
|
||||
|
||||
static ma_result ma_device_start__winmm(ma_device* pDevice)
|
||||
{
|
||||
MA_ASSERT(pDevice != NULL);
|
||||
|
||||
if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
|
||||
MMRESULT resultMM;
|
||||
WAVEHDR* pWAVEHDR;
|
||||
ma_uint32 iPeriod;
|
||||
|
||||
pWAVEHDR = (WAVEHDR*)pDevice->winmm.pWAVEHDRCapture;
|
||||
|
||||
/* Make sure the event is reset to a non-signaled state to ensure we don't prematurely return from WaitForSingleObject(). */
|
||||
ResetEvent((HANDLE)pDevice->winmm.hEventCapture);
|
||||
|
||||
/* To start the device we attach all of the buffers and then start it. As the buffers are filled with data we will get notifications. */
|
||||
for (iPeriod = 0; iPeriod < pDevice->capture.internalPeriods; ++iPeriod) {
|
||||
resultMM = ((MA_PFN_waveInAddBuffer)pDevice->pContext->winmm.waveInAddBuffer)((HWAVEIN)pDevice->winmm.hDeviceCapture, &((LPWAVEHDR)pDevice->winmm.pWAVEHDRCapture)[iPeriod], sizeof(WAVEHDR));
|
||||
if (resultMM != MMSYSERR_NOERROR) {
|
||||
return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[WinMM] Failed to attach input buffers to capture device in preparation for capture.", 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. */
|
||||
resultMM = ((MA_PFN_waveInStart)pDevice->pContext->winmm.waveInStart)((HWAVEIN)pDevice->winmm.hDeviceCapture);
|
||||
if (resultMM != MMSYSERR_NOERROR) {
|
||||
return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[WinMM] Failed to start backend device.", ma_result_from_MMRESULT(resultMM));
|
||||
}
|
||||
}
|
||||
|
||||
if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
|
||||
/* Don't need to do anything for playback. It'll be started automatically in ma_device_start__winmm(). */
|
||||
}
|
||||
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
|
||||
static ma_result ma_device_stop__winmm(ma_device* pDevice)
|
||||
{
|
||||
MMRESULT resultMM;
|
||||
@@ -17502,197 +17489,6 @@ static ma_result ma_device_read__winmm(ma_device* pDevice, void* pPCMFrames, ma_
|
||||
return result;
|
||||
}
|
||||
|
||||
static ma_result ma_device_main_loop__winmm(ma_device* pDevice)
|
||||
{
|
||||
ma_result result = MA_SUCCESS;
|
||||
ma_bool32 exitLoop = MA_FALSE;
|
||||
ma_uint8 capturedDeviceData[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
|
||||
ma_uint8 playbackDeviceData[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
|
||||
ma_uint32 capturedDeviceDataCapInFrames = sizeof(capturedDeviceData) / ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
|
||||
ma_uint32 playbackDeviceDataCapInFrames = sizeof(playbackDeviceData) / ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
|
||||
|
||||
MA_ASSERT(pDevice != NULL);
|
||||
|
||||
/* The capture device needs to be started immediately. */
|
||||
if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
|
||||
MMRESULT resultMM;
|
||||
WAVEHDR* pWAVEHDR;
|
||||
ma_uint32 iPeriod;
|
||||
|
||||
pWAVEHDR = (WAVEHDR*)pDevice->winmm.pWAVEHDRCapture;
|
||||
|
||||
/* Make sure the event is reset to a non-signaled state to ensure we don't prematurely return from WaitForSingleObject(). */
|
||||
ResetEvent((HANDLE)pDevice->winmm.hEventCapture);
|
||||
|
||||
/* To start the device we attach all of the buffers and then start it. As the buffers are filled with data we will get notifications. */
|
||||
for (iPeriod = 0; iPeriod < pDevice->capture.internalPeriods; ++iPeriod) {
|
||||
resultMM = ((MA_PFN_waveInAddBuffer)pDevice->pContext->winmm.waveInAddBuffer)((HWAVEIN)pDevice->winmm.hDeviceCapture, &((LPWAVEHDR)pDevice->winmm.pWAVEHDRCapture)[iPeriod], sizeof(WAVEHDR));
|
||||
if (resultMM != MMSYSERR_NOERROR) {
|
||||
return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[WinMM] Failed to attach input buffers to capture device in preparation for capture.", 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. */
|
||||
resultMM = ((MA_PFN_waveInStart)pDevice->pContext->winmm.waveInStart)((HWAVEIN)pDevice->winmm.hDeviceCapture);
|
||||
if (resultMM != MMSYSERR_NOERROR) {
|
||||
return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[WinMM] Failed to start backend device.", ma_result_from_MMRESULT(resultMM));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
while (ma_device_get_state(pDevice) == MA_STATE_STARTED && !exitLoop) {
|
||||
switch (pDevice->type)
|
||||
{
|
||||
case ma_device_type_duplex:
|
||||
{
|
||||
/* The process is: device_read -> convert -> callback -> convert -> device_write */
|
||||
ma_uint32 totalCapturedDeviceFramesProcessed = 0;
|
||||
ma_uint32 capturedDevicePeriodSizeInFrames = ma_min(pDevice->capture.internalPeriodSizeInFrames, pDevice->playback.internalPeriodSizeInFrames);
|
||||
|
||||
while (totalCapturedDeviceFramesProcessed < capturedDevicePeriodSizeInFrames) {
|
||||
ma_uint32 capturedDeviceFramesRemaining;
|
||||
ma_uint32 capturedDeviceFramesProcessed;
|
||||
ma_uint32 capturedDeviceFramesToProcess;
|
||||
ma_uint32 capturedDeviceFramesToTryProcessing = capturedDevicePeriodSizeInFrames - totalCapturedDeviceFramesProcessed;
|
||||
if (capturedDeviceFramesToTryProcessing > capturedDeviceDataCapInFrames) {
|
||||
capturedDeviceFramesToTryProcessing = capturedDeviceDataCapInFrames;
|
||||
}
|
||||
|
||||
result = ma_device_read__winmm(pDevice, capturedDeviceData, capturedDeviceFramesToTryProcessing, &capturedDeviceFramesToProcess);
|
||||
if (result != MA_SUCCESS) {
|
||||
exitLoop = MA_TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
capturedDeviceFramesRemaining = capturedDeviceFramesToProcess;
|
||||
capturedDeviceFramesProcessed = 0;
|
||||
|
||||
for (;;) {
|
||||
ma_uint8 capturedClientData[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
|
||||
ma_uint8 playbackClientData[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
|
||||
ma_uint32 capturedClientDataCapInFrames = sizeof(capturedClientData) / ma_get_bytes_per_frame(pDevice->capture.format, pDevice->capture.channels);
|
||||
ma_uint32 playbackClientDataCapInFrames = sizeof(playbackClientData) / ma_get_bytes_per_frame(pDevice->playback.format, pDevice->playback.channels);
|
||||
ma_uint64 capturedClientFramesToProcessThisIteration = ma_min(capturedClientDataCapInFrames, playbackClientDataCapInFrames);
|
||||
ma_uint64 capturedDeviceFramesToProcessThisIteration = capturedDeviceFramesRemaining;
|
||||
ma_uint8* pRunningCapturedDeviceFrames = ma_offset_ptr(capturedDeviceData, capturedDeviceFramesProcessed * ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels));
|
||||
|
||||
/* Convert capture data from device format to client format. */
|
||||
result = ma_data_converter_process_pcm_frames(&pDevice->capture.converter, pRunningCapturedDeviceFrames, &capturedDeviceFramesToProcessThisIteration, capturedClientData, &capturedClientFramesToProcessThisIteration);
|
||||
if (result != MA_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
If we weren't able to generate any output frames it must mean we've exhaused all of our input. The only time this would not be the case is if capturedClientData was too small
|
||||
which should never be the case when it's of the size MA_DATA_CONVERTER_STACK_BUFFER_SIZE.
|
||||
*/
|
||||
if (capturedClientFramesToProcessThisIteration == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
ma_device__on_data(pDevice, playbackClientData, capturedClientData, (ma_uint32)capturedClientFramesToProcessThisIteration); /* Safe cast .*/
|
||||
|
||||
capturedDeviceFramesProcessed += (ma_uint32)capturedDeviceFramesToProcessThisIteration; /* Safe cast. */
|
||||
capturedDeviceFramesRemaining -= (ma_uint32)capturedDeviceFramesToProcessThisIteration; /* Safe cast. */
|
||||
|
||||
/* At this point the playbackClientData buffer should be holding data that needs to be written to the device. */
|
||||
for (;;) {
|
||||
ma_uint64 convertedClientFrameCount = capturedClientFramesToProcessThisIteration;
|
||||
ma_uint64 convertedDeviceFrameCount = playbackDeviceDataCapInFrames;
|
||||
result = ma_data_converter_process_pcm_frames(&pDevice->playback.converter, playbackClientData, &convertedClientFrameCount, playbackDeviceData, &convertedDeviceFrameCount);
|
||||
if (result != MA_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
|
||||
result = ma_device_write__winmm(pDevice, playbackDeviceData, (ma_uint32)convertedDeviceFrameCount, NULL); /* Safe cast. */
|
||||
if (result != MA_SUCCESS) {
|
||||
exitLoop = MA_TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
capturedClientFramesToProcessThisIteration -= (ma_uint32)convertedClientFrameCount; /* Safe cast. */
|
||||
if (capturedClientFramesToProcessThisIteration == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* In case an error happened from ma_device_write__winmm()... */
|
||||
if (result != MA_SUCCESS) {
|
||||
exitLoop = MA_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
totalCapturedDeviceFramesProcessed += capturedDeviceFramesProcessed;
|
||||
}
|
||||
} break;
|
||||
|
||||
case ma_device_type_capture:
|
||||
{
|
||||
/* We read in chunks of the period size, but use a stack allocated buffer for the intermediary. */
|
||||
ma_uint32 periodSizeInFrames = pDevice->capture.internalPeriodSizeInFrames;
|
||||
ma_uint32 framesReadThisPeriod = 0;
|
||||
while (framesReadThisPeriod < periodSizeInFrames) {
|
||||
ma_uint32 framesRemainingInPeriod = periodSizeInFrames - framesReadThisPeriod;
|
||||
ma_uint32 framesProcessed;
|
||||
ma_uint32 framesToReadThisIteration = framesRemainingInPeriod;
|
||||
if (framesToReadThisIteration > capturedDeviceDataCapInFrames) {
|
||||
framesToReadThisIteration = capturedDeviceDataCapInFrames;
|
||||
}
|
||||
|
||||
result = ma_device_read__winmm(pDevice, capturedDeviceData, framesToReadThisIteration, &framesProcessed);
|
||||
if (result != MA_SUCCESS) {
|
||||
exitLoop = MA_TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
ma_device__send_frames_to_client(pDevice, framesProcessed, capturedDeviceData);
|
||||
|
||||
framesReadThisPeriod += framesProcessed;
|
||||
}
|
||||
} break;
|
||||
|
||||
case ma_device_type_playback:
|
||||
{
|
||||
/* We write in chunks of the period size, but use a stack allocated buffer for the intermediary. */
|
||||
ma_uint32 periodSizeInFrames = pDevice->playback.internalPeriodSizeInFrames;
|
||||
ma_uint32 framesWrittenThisPeriod = 0;
|
||||
while (framesWrittenThisPeriod < periodSizeInFrames) {
|
||||
ma_uint32 framesRemainingInPeriod = periodSizeInFrames - framesWrittenThisPeriod;
|
||||
ma_uint32 framesProcessed;
|
||||
ma_uint32 framesToWriteThisIteration = framesRemainingInPeriod;
|
||||
if (framesToWriteThisIteration > playbackDeviceDataCapInFrames) {
|
||||
framesToWriteThisIteration = playbackDeviceDataCapInFrames;
|
||||
}
|
||||
|
||||
ma_device__read_frames_from_client(pDevice, framesToWriteThisIteration, playbackDeviceData);
|
||||
|
||||
result = ma_device_write__winmm(pDevice, playbackDeviceData, framesToWriteThisIteration, &framesProcessed);
|
||||
if (result != MA_SUCCESS) {
|
||||
exitLoop = MA_TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
framesWrittenThisPeriod += framesProcessed;
|
||||
}
|
||||
} break;
|
||||
|
||||
/* To silence a warning. Will never hit this. */
|
||||
case ma_device_type_loopback:
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Here is where the device is started. */
|
||||
ma_device_stop__winmm(pDevice);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static ma_result ma_context_uninit__winmm(ma_context* pContext)
|
||||
{
|
||||
MA_ASSERT(pContext != NULL);
|
||||
@@ -17702,7 +17498,7 @@ static ma_result ma_context_uninit__winmm(ma_context* pContext)
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
|
||||
static ma_result ma_context_init__winmm(const ma_context_config* pConfig, ma_context* pContext)
|
||||
static ma_result ma_context_init__winmm(ma_context* pContext, const ma_context_config* pConfig, ma_backend_callbacks* pCallbacks)
|
||||
{
|
||||
MA_ASSERT(pContext != NULL);
|
||||
|
||||
@@ -17731,14 +17527,17 @@ static ma_result ma_context_init__winmm(const ma_context_config* pConfig, ma_con
|
||||
pContext->winmm.waveInStart = ma_dlsym(pContext, pContext->winmm.hWinMM, "waveInStart");
|
||||
pContext->winmm.waveInReset = ma_dlsym(pContext, pContext->winmm.hWinMM, "waveInReset");
|
||||
|
||||
pContext->onUninit = ma_context_uninit__winmm;
|
||||
pContext->onEnumDevices = ma_context_enumerate_devices__winmm;
|
||||
pContext->onGetDeviceInfo = ma_context_get_device_info__winmm;
|
||||
pContext->onDeviceInit = ma_device_init__winmm;
|
||||
pContext->onDeviceUninit = ma_device_uninit__winmm;
|
||||
pContext->onDeviceStart = NULL; /* Not used with synchronous backends. */
|
||||
pContext->onDeviceStop = NULL; /* Not used with synchronous backends. */
|
||||
pContext->onDeviceMainLoop = ma_device_main_loop__winmm;
|
||||
pCallbacks->onContextInit = ma_context_init__winmm;
|
||||
pCallbacks->onContextUninit = ma_context_uninit__winmm;
|
||||
pCallbacks->onContextEnumerateDevices = ma_context_enumerate_devices__winmm;
|
||||
pCallbacks->onContextGetDeviceInfo = ma_context_get_device_info__winmm;
|
||||
pCallbacks->onDeviceInit = ma_device_init__winmm;
|
||||
pCallbacks->onDeviceUninit = ma_device_uninit__winmm;
|
||||
pCallbacks->onDeviceStart = ma_device_start__winmm;
|
||||
pCallbacks->onDeviceStop = ma_device_stop__winmm;
|
||||
pCallbacks->onDeviceRead = ma_device_read__winmm;
|
||||
pCallbacks->onDeviceWrite = ma_device_write__winmm;
|
||||
pCallbacks->onDeviceAudioThread = NULL; /* This is a blocking read-write API, so this can be NULL since miniaudio will manage the audio thread for us. */
|
||||
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
@@ -31920,6 +31719,12 @@ MA_API ma_result ma_context_init(const ma_backend backends[], ma_uint32 backendC
|
||||
pContext->callbacks.onContextInit = ma_context_init__dsound;
|
||||
} break;
|
||||
#endif
|
||||
#ifdef MA_HAS_WINMM
|
||||
case ma_backend_winmm:
|
||||
{
|
||||
pContext->callbacks.onContextInit = ma_context_init__winmm;
|
||||
} break;
|
||||
#endif
|
||||
#ifdef MA_HAS_CUSTOM
|
||||
case ma_backend_custom:
|
||||
{
|
||||
@@ -31953,7 +31758,7 @@ MA_API ma_result ma_context_init(const ma_backend backends[], ma_uint32 backendC
|
||||
#ifdef MA_HAS_WINMM
|
||||
case ma_backend_winmm:
|
||||
{
|
||||
result = ma_context_init__winmm(pConfig, pContext);
|
||||
/*result = ma_context_init__winmm(pConfig, pContext);*/
|
||||
} break;
|
||||
#endif
|
||||
#ifdef MA_HAS_ALSA
|
||||
@@ -32598,6 +32403,10 @@ MA_API ma_result ma_device_init(ma_context* pContext, const ma_device_config* pC
|
||||
descriptorPlayback.periodSizeInMilliseconds = (pConfig->performanceProfile == ma_performance_profile_low_latency) ? MA_DEFAULT_PERIOD_SIZE_IN_MILLISECONDS_LOW_LATENCY : MA_DEFAULT_PERIOD_SIZE_IN_MILLISECONDS_CONSERVATIVE;
|
||||
}
|
||||
|
||||
if (descriptorPlayback.periodCount == 0) {
|
||||
descriptorPlayback.periodCount = MA_DEFAULT_PERIODS;
|
||||
}
|
||||
|
||||
|
||||
MA_ZERO_OBJECT(&descriptorCapture);
|
||||
descriptorCapture.pDeviceID = pConfig->capture.pDeviceID;
|
||||
@@ -32614,6 +32423,10 @@ MA_API ma_result ma_device_init(ma_context* pContext, const ma_device_config* pC
|
||||
descriptorCapture.periodSizeInMilliseconds = (pConfig->performanceProfile == ma_performance_profile_low_latency) ? MA_DEFAULT_PERIOD_SIZE_IN_MILLISECONDS_LOW_LATENCY : MA_DEFAULT_PERIOD_SIZE_IN_MILLISECONDS_CONSERVATIVE;
|
||||
}
|
||||
|
||||
if (descriptorCapture.periodCount == 0) {
|
||||
descriptorCapture.periodCount = MA_DEFAULT_PERIODS;
|
||||
}
|
||||
|
||||
|
||||
result = pContext->callbacks.onDeviceInit(pDevice, pConfig, &descriptorPlayback, &descriptorCapture);
|
||||
if (result != MA_SUCCESS) {
|
||||
|
||||
Reference in New Issue
Block a user