From d59b08d4b81146da12e9ae64d24d2473537a60bb Mon Sep 17 00:00:00 2001 From: David Reid Date: Sun, 3 Feb 2019 06:44:20 +1000 Subject: [PATCH] Begin work on rearranging mal_config in preparation for full-duplex. --- mini_al.h | 122 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 64 insertions(+), 58 deletions(-) diff --git a/mini_al.h b/mini_al.h index 36f3af83..f8bba9df 100644 --- a/mini_al.h +++ b/mini_al.h @@ -1575,8 +1575,6 @@ typedef struct typedef struct { mal_device_type deviceType; - mal_device_id* pPlaybackDeviceID; - mal_device_id* pCaptureDeviceID; mal_format format; mal_uint32 channels; mal_uint32 sampleRate; @@ -1584,11 +1582,27 @@ typedef struct mal_uint32 bufferSizeInFrames; mal_uint32 bufferSizeInMilliseconds; mal_uint32 periods; - mal_share_mode shareMode; mal_performance_profile performanceProfile; mal_device_callback_proc dataCallback; mal_stop_proc stopCallback; void* pUserData; + struct + { + mal_device_id* pDeviceID; + mal_format format; + mal_uint32 channels; + mal_channel channelMap[MAL_MAX_CHANNELS]; + mal_share_mode shareMode; + } playback; + struct + { + mal_device_id* pDeviceID; + mal_format format; + mal_uint32 channels; + mal_channel channelMap[MAL_MAX_CHANNELS]; + mal_share_mode shareMode; + } capture; + struct { mal_bool32 noMMap; // Disables MMap mode. @@ -1996,7 +2010,6 @@ MAL_ALIGNED_STRUCT(MAL_SIMD_ALIGNMENT) mal_device mal_device_callback_proc onData; mal_stop_proc onStop; void* pUserData; // Application defined data. - mal_device_config initConfig; // TODO: Get rid of this. The configuration passed in to mal_device_init(). Mainly used for reinitializing the backend device. mal_mutex lock; mal_event wakeupEvent; mal_event startEvent; @@ -2022,6 +2035,7 @@ MAL_ALIGNED_STRUCT(MAL_SIMD_ALIGNMENT) mal_device struct { char name[256]; /* Maybe temporary. Likely to be replaced with a query API. */ + mal_share_mode shareMode; /* Set to whatever was passed in when the device was initialized. */ mal_bool32 usingDefaultFormat : 1; mal_bool32 usingDefaultChannels : 1; mal_bool32 usingDefaultSampleRate : 1; @@ -2041,6 +2055,7 @@ MAL_ALIGNED_STRUCT(MAL_SIMD_ALIGNMENT) mal_device struct { char name[256]; /* Maybe temporary. Likely to be replaced with a query API. */ + mal_share_mode shareMode; /* Set to whatever was passed in when the device was initialized. */ mal_bool32 usingDefaultFormat : 1; mal_bool32 usingDefaultChannels : 1; mal_bool32 usingDefaultSampleRate : 1; @@ -6125,7 +6140,8 @@ HRESULT STDMETHODCALLTYPE mal_IMMNotificationClient_OnDefaultDeviceChanged(mal_I // Not currently supporting automatic stream routing in exclusive mode. This is not working correctly on my machine due to // AUDCLNT_E_DEVICE_IN_USE errors when reinitializing the device. If this is a bug in mini_al, we can try re-enabling this once // it's fixed. - if (pThis->pDevice->initConfig.shareMode == mal_share_mode_exclusive) { + if (dataFlow == mal_eRender && pThis->pDevice->playback.shareMode == mal_share_mode_exclusive || + dataFlow == mal_eCapture && pThis->pDevice->capture.shareMode == mal_share_mode_exclusive) { return S_OK; } @@ -7027,7 +7043,7 @@ mal_result mal_device_reinit__wasapi(mal_device* pDevice, mal_device_type device data.usingDefaultChannels = pDevice->usingDefaultChannels; data.usingDefaultSampleRate = pDevice->usingDefaultSampleRate; data.usingDefaultChannelMap = pDevice->usingDefaultChannelMap; - data.shareMode = pDevice->initConfig.shareMode; + data.shareMode = (deviceType == mal_device_type_playback) ? pDevice->playback.shareMode : pDevice->capture.shareMode; data.bufferSizeInMillisecondsIn = pDevice->bufferSizeInMilliseconds; data.periodsIn = pDevice->periods; mal_result result = mal_device_init_internal__wasapi(pDevice->pContext, deviceType, NULL, &data); @@ -7137,7 +7153,7 @@ mal_result mal_device_init__wasapi(mal_context* pContext, const mal_device_confi data.bufferSizeInMillisecondsIn = pConfig->bufferSizeInMilliseconds; data.periodsIn = pConfig->periods; - result = mal_device_init_internal__wasapi(pDevice->pContext, mal_device_type_capture, pConfig->pCaptureDeviceID, &data); + result = mal_device_init_internal__wasapi(pDevice->pContext, mal_device_type_capture, pConfig->capture.pDeviceID, &data); if (result != MAL_SUCCESS) { return result; } @@ -7195,7 +7211,7 @@ mal_result mal_device_init__wasapi(mal_context* pContext, const mal_device_confi data.periodsIn = pConfig->periods; } - result = mal_device_init_internal__wasapi(pDevice->pContext, mal_device_type_playback, pConfig->pPlaybackDeviceID, &data); + result = mal_device_init_internal__wasapi(pDevice->pContext, mal_device_type_playback, pConfig->playback.pDeviceID, &data); if (result != MAL_SUCCESS) { if (pConfig->deviceType == mal_device_type_duplex) { if (pDevice->wasapi.pCaptureClient != NULL) { @@ -7409,7 +7425,8 @@ mal_result mal_device__get_available_frames__wasapi(mal_device* pDevice, mal_IAu } // Slightly different rules for exclusive and shared modes. - if (pDevice->initConfig.shareMode == mal_share_mode_exclusive) { + mal_share_mode shareMode = ((mal_ptr)pAudioClient == pDevice->wasapi.pAudioClientPlayback) ? pDevice->playback.shareMode : pDevice->capture.shareMode; + if (shareMode == mal_share_mode_exclusive) { *pFrameCount = paddingFramesCount; } else { if ((mal_ptr)pAudioClient == pDevice->wasapi.pAudioClientPlayback) { @@ -8594,7 +8611,7 @@ mal_result mal_device_init__dsound(mal_context* pContext, const mal_device_confi // Unfortunately DirectSound uses different APIs and data structures for playback and catpure devices :( if (pConfig->deviceType == mal_device_type_playback) { - mal_result result = mal_context_create_IDirectSound__dsound(pContext, pConfig->shareMode, pConfig->pPlaybackDeviceID, (mal_IDirectSound**)&pDevice->dsound.pPlayback); + mal_result result = mal_context_create_IDirectSound__dsound(pContext, pConfig->shareMode, pConfig->playback.pDeviceID, (mal_IDirectSound**)&pDevice->dsound.pPlayback); if (result != MAL_SUCCESS) { mal_device_uninit__dsound(pDevice); return result; @@ -8708,7 +8725,7 @@ mal_result mal_device_init__dsound(mal_context* pContext, const mal_device_confi return mal_post_error(pDevice, MAL_LOG_LEVEL_ERROR, "[DirectSound] IDirectSound_CreateSoundBuffer() failed for playback device's secondary buffer.", MAL_FAILED_TO_OPEN_BACKEND_DEVICE); } } else { - mal_result result = mal_context_create_IDirectSoundCapture__dsound(pContext, pConfig->shareMode, pConfig->pCaptureDeviceID, (mal_IDirectSoundCapture**)&pDevice->dsound.pCapture); + mal_result result = mal_context_create_IDirectSoundCapture__dsound(pContext, pConfig->shareMode, pConfig->capture.pDeviceID, (mal_IDirectSoundCapture**)&pDevice->dsound.pCapture); if (result != MAL_SUCCESS) { mal_device_uninit__dsound(pDevice); return result; @@ -9573,11 +9590,11 @@ mal_result mal_device_init__winmm(mal_context* pContext, const mal_device_config UINT winMMDeviceIDPlayback = 0; UINT winMMDeviceIDCapture = 0; - if (pConfig->pPlaybackDeviceID != NULL) { - winMMDeviceIDPlayback = (UINT)pConfig->pPlaybackDeviceID->winmm; + if (pConfig->playback.pDeviceID != NULL) { + winMMDeviceIDPlayback = (UINT)pConfig->playback.pDeviceID->winmm; } - if (pConfig->pCaptureDeviceID != NULL) { - winMMDeviceIDCapture = (UINT)pConfig->pCaptureDeviceID->winmm; + if (pConfig->capture.pDeviceID != NULL) { + winMMDeviceIDCapture = (UINT)pConfig->capture.pDeviceID->winmm; } const char* errorMsg = ""; @@ -11299,7 +11316,7 @@ mal_result mal_device_init__alsa(mal_context* pContext, const mal_device_config* mal_snd_pcm_format_t formatALSA = mal_convert_mal_format_to_alsa_format(pConfig->format); - mal_result result = mal_context_open_pcm__alsa(pContext, pConfig->shareMode, pConfig->deviceType, (pConfig->deviceType == mal_device_type_playback) ? pConfig->pPlaybackDeviceID : pConfig->pCaptureDeviceID, (mal_snd_pcm_t**)&pDevice->alsa.pPCM); + mal_result result = mal_context_open_pcm__alsa(pContext, pConfig->shareMode, pConfig->deviceType, (pConfig->deviceType == mal_device_type_playback) ? pConfig->playback.pDeviceID : pConfig->capture.pDeviceID, (mal_snd_pcm_t**)&pDevice->alsa.pPCM); if (result != MAL_SUCCESS) { return result; } @@ -13229,11 +13246,11 @@ mal_result mal_device_init__pulse(mal_context* pContext, const mal_device_config return MAL_SHARE_MODE_NOT_SUPPORTED; } - if ((pConfig->deviceType == mal_device_type_playback || pConfig->deviceType == mal_device_type_duplex) && pConfig->pPlaybackDeviceID != NULL) { - devPlayback = pConfig->pPlaybackDeviceID->pulse; + if ((pConfig->deviceType == mal_device_type_playback || pConfig->deviceType == mal_device_type_duplex) && pConfig->playback.pDeviceID != NULL) { + devPlayback = pConfig->playback.pDeviceID->pulse; } - if ((pConfig->deviceType == mal_device_type_capture || pConfig->deviceType == mal_device_type_duplex) && pConfig->pCaptureDeviceID != NULL) { - devCapture = pConfig->pCaptureDeviceID->pulse; + if ((pConfig->deviceType == mal_device_type_capture || pConfig->deviceType == mal_device_type_duplex) && pConfig->capture.pDeviceID != NULL) { + devCapture = pConfig->capture.pDeviceID->pulse; } mal_uint32 bufferSizeInFrames = pConfig->bufferSizeInFrames; @@ -14104,8 +14121,8 @@ mal_result mal_device_init__jack(mal_context* pContext, const mal_device_config* } /* Only supporting default devices with JACK. */ - if (((pConfig->deviceType == mal_device_type_playback || pConfig->deviceType == mal_device_type_duplex) && pConfig->pPlaybackDeviceID != NULL && pConfig->pPlaybackDeviceID->jack != 0) || - ((pConfig->deviceType == mal_device_type_capture || pConfig->deviceType == mal_device_type_duplex) && pConfig->pCaptureDeviceID != NULL && pConfig->pCaptureDeviceID->jack != 0)) { + if (((pConfig->deviceType == mal_device_type_playback || pConfig->deviceType == mal_device_type_duplex) && pConfig->playback.pDeviceID != NULL && pConfig->playback.pDeviceID->jack != 0) || + ((pConfig->deviceType == mal_device_type_capture || pConfig->deviceType == mal_device_type_duplex) && pConfig->capture.pDeviceID != NULL && pConfig->capture.pDeviceID->jack != 0)) { return MAL_NO_DEVICE; } @@ -16413,7 +16430,7 @@ mal_result mal_device_init__coreaudio(mal_context* pContext, const mal_device_co data.usingDefaultChannelMap = pDevice->usingDefaultChannelMap; data.shareMode = pDevice->initConfig.shareMode; - mal_result result = mal_device_init_internal__coreaudio(pDevice->pContext, pConfig->deviceType, pConfig->pPlaybackDeviceID, pConfig->pCaptureDeviceID, &data, (void*)pDevice); + mal_result result = mal_device_init_internal__coreaudio(pDevice->pContext, pConfig->deviceType, pConfig->playback.pDeviceID, pConfig->capture.pDeviceID, &data, (void*)pDevice); if (result != MAL_SUCCESS) { return result; } @@ -17079,11 +17096,11 @@ mal_result mal_device_init__sndio(mal_context* pContext, const mal_device_config const char* deviceNamePlayback = MAL_SIO_DEVANY; const char* deviceNameCapture = MAL_SIO_DEVANY; - if (pConfig->pPlaybackDeviceID != NULL) { - deviceNamePlayback = pConfig->pPlaybackDeviceID->sndio; + if (pConfig->playback.pDeviceID != NULL) { + deviceNamePlayback = pConfig->playback.pDeviceID->sndio; } - if (pConfig->pCaptureDeviceID != NULL) { - deviceNameCapture = pConfig->pCaptureDeviceID->sndio; + if (pConfig->capture.pDeviceID != NULL) { + deviceNameCapture = pConfig->capture.pDeviceID->sndio; } if (pConfig->deviceType == mal_device_type_playback) { @@ -17719,11 +17736,11 @@ mal_result mal_device_init__audio4(mal_context* pContext, const mal_device_confi // The first thing to do is open the file. const char* deviceNamePlayback = "/dev/audio"; const char* deviceNameCapture = "/dev/audio"; - if (pConfig->pPlaybackDeviceID != NULL) { - deviceNamePlayback = pConfig->pPlaybackDeviceID->audio4; + if (pConfig->playback.pDeviceID != NULL) { + deviceNamePlayback = pConfig->playback.pDeviceID->audio4; } - if (pConfig->pCaptureDeviceID != NULL) { - deviceNameCapture = pConfig->pCaptureDeviceID->audio4; + if (pConfig->capture.pDeviceID != NULL) { + deviceNameCapture = pConfig->capture.pDeviceID->audio4; } if (pConfig->deviceType == mal_device_type_playback) { @@ -18012,7 +18029,7 @@ int mal_open_temp_device__oss() return -1; } -mal_result mal_context_open_device__oss(mal_context* pContext, mal_device_type deviceType, const mal_device_id* pPlaybackDeviceID, const mal_device_id* pCaptureDevice, int* pfd) +mal_result mal_context_open_device__oss(mal_context* pContext, mal_device_type deviceType, const mal_device_id* pDeviceID, int* pfd) { mal_assert(pContext != NULL); mal_assert(pfd != NULL); @@ -18020,28 +18037,17 @@ mal_result mal_context_open_device__oss(mal_context* pContext, mal_device_type d *pfd = -1; - const char* deviceNamePlayback = "/dev/dsp"; - const char* deviceNameCapture = "/dev/dsp"; - if (pPlaybackDeviceID != NULL) { - deviceNamePlayback = pPlaybackDeviceID->oss; - } - if (pCaptureDeviceID != NULL) { - deviceNameCapture = pCaptureDeviceID->oss; - } - - if (deviceType == mal_device_type_playback) { - *pfd = open(deviceNamePlayback, O_WRONLY, 0); - } else if (deviceType == mal_device_type_capture) { - *pfd = open(deviceNameCapture, O_RDONLY, 0); - } else if (deviceType == mal_device_type_duplex) { - /* TODO: Implement me. */ - mal_assert(MAL_FALSE); - return MAL_INVALID_ARGS; - } else { - mal_assert(MAL_FALSE); /* Should never hit this. */ + /* This function should only be called for playback or capture, not duplex. */ + if (deviceType == mal_device_type_duplex) { return MAL_INVALID_ARGS; } + const char* deviceName = "/dev/dsp"; + if (pDeviceID != NULL) { + deviceName = pDeviceID->oss; + } + + *pfd = open(deviceName, (deviceType == mal_device_type_playback) ? O_WRONLY : O_RDONLY, 0); if (*pfd == -1) { return MAL_FAILED_TO_OPEN_BACKEND_DEVICE; } @@ -18230,7 +18236,7 @@ mal_result mal_device_init__oss(mal_context* pContext, const mal_device_config* return MAL_INVALID_ARGS; } - mal_result result = mal_context_open_device__oss(pContext, pConfig->deviceType, pConfig->pPlaybackDeviceID, pConfig->pCaptureDeviceID, &pDevice->oss.fd); + mal_result result = mal_context_open_device__oss(pContext, pConfig->deviceType, (pConfig->deviceType == mal_device_type_playback) ? pConfig->playback.pDeviceID : pConfig->capture.pDeviceID, &pDevice->oss.fd); if (result != MAL_SUCCESS) { return mal_post_error(pDevice, MAL_LOG_LEVEL_ERROR, "[OSS] Failed to open device.", MAL_FAILED_TO_OPEN_BACKEND_DEVICE); } @@ -20960,7 +20966,6 @@ mal_result mal_device_init(mal_context* pContext, const mal_device_config* pConf mal_zero_object(pDevice); pDevice->pContext = pContext; - pDevice->initConfig = config; // Set the user data and log callback ASAP to ensure it is available for the entire initialization process. pDevice->pUserData = config.pUserData; @@ -20973,8 +20978,9 @@ mal_result mal_device_init(mal_context* pContext, const mal_device_config* pConf } } + /* TODO: This is only used in Core Audio. Move this to the Core Audio backend. Also, this logic does not handle full-duplex devices properly */ - if (config.pPlaybackDeviceID == NULL || config.pCaptureDeviceID == NULL) { + if (config.playback.pDeviceID == NULL || config.capture.pDeviceID == NULL) { pDevice->isDefaultDevice = MAL_TRUE; } @@ -21062,15 +21068,15 @@ mal_result mal_device_init(mal_context* pContext, const mal_device_config* pConf // If the backend did not fill out a name for the device, try a generic method. if (pDevice->type == mal_device_type_capture || pDevice->type == mal_device_type_duplex) { if (pDevice->capture.name[0] == '\0') { - if (mal_context__try_get_device_name_by_id(pContext, mal_device_type_capture, config.pCaptureDeviceID, pDevice->capture.name, sizeof(pDevice->capture.name)) != MAL_SUCCESS) { - mal_strncpy_s(pDevice->capture.name, sizeof(pDevice->capture.name), (config.pCaptureDeviceID == NULL) ? MAL_DEFAULT_CAPTURE_DEVICE_NAME : "Capture Device", (size_t)-1); + if (mal_context__try_get_device_name_by_id(pContext, mal_device_type_capture, config.capture.pDeviceID, pDevice->capture.name, sizeof(pDevice->capture.name)) != MAL_SUCCESS) { + mal_strncpy_s(pDevice->capture.name, sizeof(pDevice->capture.name), (config.capture.pDeviceID == NULL) ? MAL_DEFAULT_CAPTURE_DEVICE_NAME : "Capture Device", (size_t)-1); } } } if (pDevice->type == mal_device_type_playback || pDevice->type == mal_device_type_duplex) { if (pDevice->playback.name[0] == '\0') { - if (mal_context__try_get_device_name_by_id(pContext, mal_device_type_playback, config.pPlaybackDeviceID, pDevice->playback.name, sizeof(pDevice->playback.name)) != MAL_SUCCESS) { - mal_strncpy_s(pDevice->playback.name, sizeof(pDevice->playback.name), (config.pPlaybackDeviceID == NULL) ? MAL_DEFAULT_PLAYBACK_DEVICE_NAME : "Playback Device", (size_t)-1); + if (mal_context__try_get_device_name_by_id(pContext, mal_device_type_playback, config.playback.pDeviceID, pDevice->playback.name, sizeof(pDevice->playback.name)) != MAL_SUCCESS) { + mal_strncpy_s(pDevice->playback.name, sizeof(pDevice->playback.name), (config.playback.pDeviceID == NULL) ? MAL_DEFAULT_PLAYBACK_DEVICE_NAME : "Playback Device", (size_t)-1); } } }