From 46a062e1498d9b5df46669da525e7b3593a2e7a2 Mon Sep 17 00:00:00 2001 From: David Reid Date: Mon, 27 Dec 2021 09:49:52 +1000 Subject: [PATCH] Add ma_device_get_name(). --- miniaudio.h | 106 ++++++++++++++++++++++++- tests/test_deviceio/ma_test_deviceio.c | 8 +- 2 files changed, 108 insertions(+), 6 deletions(-) diff --git a/miniaudio.h b/miniaudio.h index d1641ca2..cdf31958 100644 --- a/miniaudio.h +++ b/miniaudio.h @@ -5931,11 +5931,15 @@ typedef struct ma_backend_callbacks ma_backend_callbacks; #define MA_DATA_FORMAT_FLAG_EXCLUSIVE_MODE (1U << 1) /* If set, this is supported in exclusive mode. Otherwise not natively supported by exclusive mode. */ +#ifndef MA_MAX_DEVICE_NAME_LENGTH +#define MA_MAX_DEVICE_NAME_LENGTH 255 +#endif + typedef struct { /* Basic info. This is the only information guaranteed to be filled in during device enumeration. */ ma_device_id id; - char name[256]; + char name[MA_MAX_DEVICE_NAME_LENGTH + 1]; /* +1 for null terminator. */ ma_bool32 isDefault; ma_uint32 nativeDataFormatCount; @@ -6644,7 +6648,7 @@ struct ma_device struct { ma_device_id id; /* If using an explicit device, will be set to a copy of the ID used for initialization. Otherwise cleared to 0. */ - char name[256]; /* Maybe temporary. Likely to be replaced with a query API. */ + char name[MA_MAX_DEVICE_NAME_LENGTH + 1]; /* Maybe temporary. Likely to be replaced with a query API. */ ma_share_mode shareMode; /* Set to whatever was passed in when the device was initialized. */ ma_format format; ma_uint32 channels; @@ -6665,7 +6669,7 @@ struct ma_device struct { ma_device_id id; /* If using an explicit device, will be set to a copy of the ID used for initialization. Otherwise cleared to 0. */ - char name[256]; /* Maybe temporary. Likely to be replaced with a query API. */ + char name[MA_MAX_DEVICE_NAME_LENGTH + 1]; /* Maybe temporary. Likely to be replaced with a query API. */ ma_share_mode shareMode; /* Set to whatever was passed in when the device was initialized. */ ma_format format; ma_uint32 channels; @@ -7855,7 +7859,8 @@ MA_SUCCESS if successful; any other error code otherwise. Thread Safety ------------- -Unsafe. This should be considered unsafe because it may be calling into the backend. +Unsafe. This should be considered unsafe because it may be calling into the backend which may or +may not be safe. Callback Safety @@ -7866,6 +7871,59 @@ which may or may not be safe. MA_API ma_result ma_device_get_info(ma_device* pDevice, ma_device_type type, ma_device_info* pDeviceInfo); +/* +Retrieves the name of the device. + + +Parameters +---------- +pDevice (in) + A pointer to the device whose information is being retrieved. + +type (in) + The device type. This parameter is required for duplex devices. When retrieving device + information, you are doing so for an individual playback or capture device. + +pName (out) + A pointer to the buffer that will receive the name. + +nameCap (in) + The capacity of the output buffer, including space for the null terminator. + +pLengthNotIncludingNullTerminator (out, optional) + A pointer to the variable that will receive the length of the name, not including the null + terminator. + + +Return Value +------------ +MA_SUCCESS if successful; any other error code otherwise. + + +Thread Safety +------------- +Unsafe. This should be considered unsafe because it may be calling into the backend which may or +may not be safe. + + +Callback Safety +--------------- +Unsafe. You should avoid calling this in the data callback because it may call into the backend +which may or may not be safe. + + +Remarks +------- +If the name does not fully fit into the output buffer, it'll be truncated. You can pass in NULL to +`pName` if you want to first get the length of the name for the purpose of memory allocation of the +output buffer. Allocating a buffer of size `MA_MAX_DEVICE_NAME_LENGTH + 1` should be enough for +most cases and will avoid the need for the inefficiency of calling this function twice. + +This is implemented in terms of `ma_device_get_info()`. +*/ +MA_API ma_result ma_device_get_name(ma_device* pDevice, ma_device_type type, char* pName, size_t nameCap, size_t* pLengthNotIncludingNullTerminator); + + /* Starts the device. For playback devices this begins playback. For capture devices it begins recording. @@ -38636,6 +38694,45 @@ MA_API ma_result ma_device_get_info(ma_device* pDevice, ma_device_type type, ma_ } } +MA_API ma_result ma_device_get_name(ma_device* pDevice, ma_device_type type, char* pName, size_t nameCap, size_t* pLengthNotIncludingNullTerminator) +{ + ma_result result; + ma_device_info deviceInfo; + + if (pLengthNotIncludingNullTerminator != NULL) { + *pLengthNotIncludingNullTerminator = 0; + } + + if (pName != NULL && nameCap > 0) { + pName[0] = '\0'; + } + + result = ma_device_get_info(pDevice, type, &deviceInfo); + if (result != MA_SUCCESS) { + return result; + } + + if (pName != NULL) { + ma_strncpy_s(pName, nameCap, deviceInfo.name, (size_t)-1); + + /* + For safety, make sure the length is based on the truncated output string rather than the + source. Otherwise the caller might assume the output buffer contains more content than it + actually does. + */ + if (pLengthNotIncludingNullTerminator != NULL) { + *pLengthNotIncludingNullTerminator = strlen(pName); + } + } else { + /* Name not specified. Just report the length of the source string. */ + if (pLengthNotIncludingNullTerminator != NULL) { + *pLengthNotIncludingNullTerminator = strlen(deviceInfo.name); + } + } + + return MA_SUCCESS; +} + MA_API ma_result ma_device_start(ma_device* pDevice) { ma_result result; @@ -88851,6 +88948,7 @@ v0.11.1 - TBD - Result codes are now declared as an enum rather than #defines. - Channel positions (MA_CHANNEL_*) are now declared as an enum rather than #defines. - Add ma_device_get_info() for retrieving device information from an initialized device. + - Add ma_device_get_name() for retrieving the name of an initialized device. - Fix a crash when passing in NULL for the pEngine parameter of ma_engine_init(). - AAudio: Fix an incorrect assert. - AAudio: Fix a bug that resulted in exclusive mode always resulting in initialization failure. diff --git a/tests/test_deviceio/ma_test_deviceio.c b/tests/test_deviceio/ma_test_deviceio.c index c0987024..434ac21f 100644 --- a/tests/test_deviceio/ma_test_deviceio.c +++ b/tests/test_deviceio/ma_test_deviceio.c @@ -528,10 +528,14 @@ int main(int argc, char** argv) /* Print the name of the device. */ if (deviceType == ma_device_type_playback || deviceType == ma_device_type_duplex) { - printf("Playback Device: %s\n", g_State.device.playback.name); + char name[MA_MAX_DEVICE_NAME_LENGTH + 1]; + ma_device_get_name(&g_State.device, ma_device_type_playback, name, sizeof(name), NULL); + printf("Playback Device: %s\n", name); } if (deviceType == ma_device_type_capture || deviceType == ma_device_type_duplex || deviceType == ma_device_type_loopback) { - printf("Capture Device: %s\n", g_State.device.capture.name); + char name[MA_MAX_DEVICE_NAME_LENGTH + 1]; + ma_device_get_name(&g_State.device, ma_device_type_capture, name, sizeof(name), NULL); + printf("Capture Device: %s\n", name); }