JACK improvements.

* Device enumeration will now report that any channel count is
    supported.
  * When initializing the device, the exact number of channels (ports)
    will be registered to the client as requested.

Public issue https://github.com/mackron/miniaudio/issues/851
This commit is contained in:
David Reid
2025-07-18 16:09:22 +10:00
parent 0b5430572d
commit 5f84285913
+26 -38
View File
@@ -33437,7 +33437,6 @@ static ma_bool32 ma_context_enumerate_device_from_client__jack(ma_context* pCont
{ {
ma_context_state_jack* pContextStateJACK = ma_context_get_backend_state__jack(pContext); ma_context_state_jack* pContextStateJACK = ma_context_get_backend_state__jack(pContext);
ma_device_info deviceInfo; ma_device_info deviceInfo;
const char** ppPorts;
MA_ZERO_OBJECT(&deviceInfo); MA_ZERO_OBJECT(&deviceInfo);
@@ -33456,23 +33455,9 @@ static ma_bool32 ma_context_enumerate_device_from_client__jack(ma_context* pCont
/* Data Format. */ /* Data Format. */
deviceInfo.nativeDataFormatCount = 1; deviceInfo.nativeDataFormatCount = 1;
deviceInfo.nativeDataFormats[0].format = ma_format_f32; deviceInfo.nativeDataFormats[0].format = ma_format_f32; /* JACK is always f32. */
deviceInfo.nativeDataFormats[0].channels = 0; deviceInfo.nativeDataFormats[0].channels = 0; /* JACK can support any number of channels (ports). */
deviceInfo.nativeDataFormats[0].sampleRate = pContextStateJACK->jack_get_sample_rate(pClient);
ppPorts = pContextStateJACK->jack_get_ports(pClient, NULL, MA_JACK_DEFAULT_AUDIO_TYPE, ma_JackPortIsPhysical | ((deviceType == ma_device_type_playback) ? ma_JackPortIsInput : ma_JackPortIsOutput));
if (ppPorts == NULL) {
pContextStateJACK->jack_client_close(pClient);
ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_ERROR, "[JACK] Failed to query physical ports during device enumeration.");
return MA_TRUE;
}
while (ppPorts[deviceInfo.nativeDataFormats[0].channels] != NULL) {
deviceInfo.nativeDataFormats[0].channels += 1;
}
deviceInfo.nativeDataFormats[0].flags = 0;
pContextStateJACK->jack_free((void*)ppPorts);
return callback(deviceType, &deviceInfo, pUserData); return callback(deviceType, &deviceInfo, pUserData);
} }
@@ -33677,15 +33662,13 @@ static ma_result ma_device_init__jack(ma_device* pDevice, const void* pDeviceBac
if (deviceType == ma_device_type_capture || deviceType == ma_device_type_duplex) { if (deviceType == ma_device_type_capture || deviceType == ma_device_type_duplex) {
ma_uint32 iPort; ma_uint32 iPort;
ma_uint32 desiredChannelCount;
const char** ppPorts;
desiredChannelCount = pDescriptorCapture->channels;
pDescriptorCapture->format = ma_format_f32; pDescriptorCapture->format = ma_format_f32;
pDescriptorCapture->channels = 0;
pDescriptorCapture->sampleRate = pContextStateJACK->jack_get_sample_rate(pDeviceStateJACK->pClient); pDescriptorCapture->sampleRate = pContextStateJACK->jack_get_sample_rate(pDeviceStateJACK->pClient);
ma_channel_map_init_standard(ma_standard_channel_map_alsa, pDescriptorCapture->channelMap, ma_countof(pDescriptorCapture->channelMap), pDescriptorCapture->channels);
/* If the application has requested the default channel count, make it equal to the number of output ports of the physical input device. */
if (pDescriptorCapture->channels == 0) {
const char** ppPorts;
ppPorts = pContextStateJACK->jack_get_ports(pDeviceStateJACK->pClient, NULL, MA_JACK_DEFAULT_AUDIO_TYPE, ma_JackPortIsPhysical | ma_JackPortIsOutput); ppPorts = pContextStateJACK->jack_get_ports(pDeviceStateJACK->pClient, NULL, MA_JACK_DEFAULT_AUDIO_TYPE, ma_JackPortIsPhysical | ma_JackPortIsOutput);
if (ppPorts == NULL) { if (ppPorts == NULL) {
@@ -33695,10 +33678,17 @@ static ma_result ma_device_init__jack(ma_device* pDevice, const void* pDeviceBac
} }
/* Need to count the number of ports first so we can allocate some memory. */ /* Need to count the number of ports first so we can allocate some memory. */
while (ppPorts[pDescriptorCapture->channels] != NULL && (desiredChannelCount == 0 || desiredChannelCount > pDescriptorCapture->channels)) { pDescriptorCapture->channels = 0;
while (ppPorts[pDescriptorCapture->channels] != NULL) {
pDescriptorCapture->channels += 1; pDescriptorCapture->channels += 1;
} }
pContextStateJACK->jack_free((void*)ppPorts);
}
ma_channel_map_init_standard(ma_standard_channel_map_alsa, pDescriptorCapture->channelMap, ma_countof(pDescriptorCapture->channelMap), pDescriptorCapture->channels);
pDeviceStateJACK->ppPortsCapture = (ma_jack_port_t**)ma_malloc(sizeof(*pDeviceStateJACK->ppPortsCapture) * pDescriptorCapture->channels, ma_device_get_allocation_callbacks(pDevice)); pDeviceStateJACK->ppPortsCapture = (ma_jack_port_t**)ma_malloc(sizeof(*pDeviceStateJACK->ppPortsCapture) * pDescriptorCapture->channels, ma_device_get_allocation_callbacks(pDevice));
if (pDeviceStateJACK->ppPortsCapture == NULL) { if (pDeviceStateJACK->ppPortsCapture == NULL) {
ma_free(pDeviceStateJACK, ma_device_get_allocation_callbacks(pDevice)); ma_free(pDeviceStateJACK, ma_device_get_allocation_callbacks(pDevice));
@@ -33712,15 +33702,12 @@ static ma_result ma_device_init__jack(ma_device* pDevice, const void* pDeviceBac
pDeviceStateJACK->ppPortsCapture[iPort] = pContextStateJACK->jack_port_register(pDeviceStateJACK->pClient, name, MA_JACK_DEFAULT_AUDIO_TYPE, ma_JackPortIsInput, 0); pDeviceStateJACK->ppPortsCapture[iPort] = pContextStateJACK->jack_port_register(pDeviceStateJACK->pClient, name, MA_JACK_DEFAULT_AUDIO_TYPE, ma_JackPortIsInput, 0);
if (pDeviceStateJACK->ppPortsCapture[iPort] == NULL) { if (pDeviceStateJACK->ppPortsCapture[iPort] == NULL) {
pContextStateJACK->jack_free((void*)ppPorts);
ma_device_uninit__jack(pDevice); ma_device_uninit__jack(pDevice);
ma_log_post(pContextStateJACK->pLog, MA_LOG_LEVEL_ERROR, "[JACK] Failed to register ports."); ma_log_post(pContextStateJACK->pLog, MA_LOG_LEVEL_ERROR, "[JACK] Failed to register ports.");
return MA_FAILED_TO_OPEN_BACKEND_DEVICE; return MA_FAILED_TO_OPEN_BACKEND_DEVICE;
} }
} }
pContextStateJACK->jack_free((void*)ppPorts);
pDescriptorCapture->periodSizeInFrames = periodSizeInFrames; pDescriptorCapture->periodSizeInFrames = periodSizeInFrames;
pDescriptorCapture->periodCount = 1; /* There's no notion of a period in JACK. Just set to 1. */ pDescriptorCapture->periodCount = 1; /* There's no notion of a period in JACK. Just set to 1. */
@@ -33733,15 +33720,13 @@ static ma_result ma_device_init__jack(ma_device* pDevice, const void* pDeviceBac
if (deviceType == ma_device_type_playback || deviceType == ma_device_type_duplex) { if (deviceType == ma_device_type_playback || deviceType == ma_device_type_duplex) {
ma_uint32 iPort; ma_uint32 iPort;
ma_uint32 desiredChannelCount;
const char** ppPorts;
desiredChannelCount = pDescriptorCapture->channels;
pDescriptorPlayback->format = ma_format_f32; pDescriptorPlayback->format = ma_format_f32;
pDescriptorPlayback->channels = 0;
pDescriptorPlayback->sampleRate = pContextStateJACK->jack_get_sample_rate(pDeviceStateJACK->pClient); pDescriptorPlayback->sampleRate = pContextStateJACK->jack_get_sample_rate(pDeviceStateJACK->pClient);
ma_channel_map_init_standard(ma_standard_channel_map_alsa, pDescriptorPlayback->channelMap, ma_countof(pDescriptorPlayback->channelMap), pDescriptorPlayback->channels);
/* If the application has requested the default channel count, make it equal to the number of input ports of the physical output device. */
if (pDescriptorPlayback->channels == 0) {
const char** ppPorts;
ppPorts = pContextStateJACK->jack_get_ports(pDeviceStateJACK->pClient, NULL, MA_JACK_DEFAULT_AUDIO_TYPE, ma_JackPortIsPhysical | ma_JackPortIsInput); ppPorts = pContextStateJACK->jack_get_ports(pDeviceStateJACK->pClient, NULL, MA_JACK_DEFAULT_AUDIO_TYPE, ma_JackPortIsPhysical | ma_JackPortIsInput);
if (ppPorts == NULL) { if (ppPorts == NULL) {
@@ -33750,10 +33735,16 @@ static ma_result ma_device_init__jack(ma_device* pDevice, const void* pDeviceBac
} }
/* Need to count the number of ports first so we can allocate some memory. */ /* Need to count the number of ports first so we can allocate some memory. */
while (ppPorts[pDescriptorPlayback->channels] != NULL && (desiredChannelCount == 0 || desiredChannelCount > pDescriptorPlayback->channels)) { while (ppPorts[pDescriptorPlayback->channels] != NULL) {
pDescriptorPlayback->channels += 1; pDescriptorPlayback->channels += 1;
} }
pContextStateJACK->jack_free((void*)ppPorts);
}
ma_channel_map_init_standard(ma_standard_channel_map_alsa, pDescriptorPlayback->channelMap, ma_countof(pDescriptorPlayback->channelMap), pDescriptorPlayback->channels);
pDeviceStateJACK->ppPortsPlayback = (ma_jack_port_t**)ma_malloc(sizeof(*pDeviceStateJACK->ppPortsPlayback) * pDescriptorPlayback->channels, ma_device_get_allocation_callbacks(pDevice)); pDeviceStateJACK->ppPortsPlayback = (ma_jack_port_t**)ma_malloc(sizeof(*pDeviceStateJACK->ppPortsPlayback) * pDescriptorPlayback->channels, ma_device_get_allocation_callbacks(pDevice));
if (pDeviceStateJACK->ppPortsPlayback == NULL) { if (pDeviceStateJACK->ppPortsPlayback == NULL) {
ma_free(pDeviceStateJACK->ppPortsCapture, ma_device_get_allocation_callbacks(pDevice)); ma_free(pDeviceStateJACK->ppPortsCapture, ma_device_get_allocation_callbacks(pDevice));
@@ -33767,15 +33758,12 @@ static ma_result ma_device_init__jack(ma_device* pDevice, const void* pDeviceBac
pDeviceStateJACK->ppPortsPlayback[iPort] = pContextStateJACK->jack_port_register(pDeviceStateJACK->pClient, name, MA_JACK_DEFAULT_AUDIO_TYPE, ma_JackPortIsOutput, 0); pDeviceStateJACK->ppPortsPlayback[iPort] = pContextStateJACK->jack_port_register(pDeviceStateJACK->pClient, name, MA_JACK_DEFAULT_AUDIO_TYPE, ma_JackPortIsOutput, 0);
if (pDeviceStateJACK->ppPortsPlayback[iPort] == NULL) { if (pDeviceStateJACK->ppPortsPlayback[iPort] == NULL) {
pContextStateJACK->jack_free((void*)ppPorts);
ma_device_uninit__jack(pDevice); ma_device_uninit__jack(pDevice);
ma_log_post(pContextStateJACK->pLog, MA_LOG_LEVEL_ERROR, "[JACK] Failed to register ports."); ma_log_post(pContextStateJACK->pLog, MA_LOG_LEVEL_ERROR, "[JACK] Failed to register ports.");
return MA_FAILED_TO_OPEN_BACKEND_DEVICE; return MA_FAILED_TO_OPEN_BACKEND_DEVICE;
} }
} }
pContextStateJACK->jack_free((void*)ppPorts);
pDescriptorPlayback->periodSizeInFrames = periodSizeInFrames; pDescriptorPlayback->periodSizeInFrames = periodSizeInFrames;
pDescriptorPlayback->periodCount = 1; /* There's no notion of a period in JACK. Just set to 1. */ pDescriptorPlayback->periodCount = 1; /* There's no notion of a period in JACK. Just set to 1. */