Commit d8dad66e authored by David Reid's avatar David Reid

OSS: Add support for retrieving detailed device info.

parent ae46e989
...@@ -62,7 +62,7 @@ ...@@ -62,7 +62,7 @@
// //
// Building for BSD // Building for BSD
// ---------------- // ----------------
// The BSD build uses OSS. Requires linking to -lpthread. Also requires linking to -lossaudio on {Open,Net}BSD, but // The BSD build uses OSS. Requires linking to -lpthread and -lm. Also requires linking to -lossaudio on {Open,Net}BSD, but
// not FreeBSD. // not FreeBSD.
// //
// Building for Android // Building for Android
...@@ -11835,6 +11835,29 @@ int mal_open_temp_device__oss() ...@@ -11835,6 +11835,29 @@ int mal_open_temp_device__oss()
return -1; return -1;
} }
mal_result mal_context_open_device__oss(mal_context* pContext, mal_device_type type, const mal_device_id* pDeviceID, int* pfd)
{
mal_assert(pContext != NULL);
mal_assert(pfd != NULL);
(void)pContext;
*pfd = -1;
char deviceName[64];
if (pDeviceID != NULL) {
mal_strncpy_s(deviceName, sizeof(deviceName), pDeviceID->oss, (size_t)-1);
} else {
mal_strncpy_s(deviceName, sizeof(deviceName), "/dev/dsp", (size_t)-1);
}
*pfd = open(deviceName, (type == mal_device_type_playback) ? O_WRONLY : O_RDONLY, 0);
if (*pfd == -1) {
return MAL_FAILED_TO_OPEN_BACKEND_DEVICE;
}
return MAL_SUCCESS;
}
mal_bool32 mal_context_is_device_id_equal__oss(mal_context* pContext, const mal_device_id* pID0, const mal_device_id* pID1) mal_bool32 mal_context_is_device_id_equal__oss(mal_context* pContext, const mal_device_id* pID0, const mal_device_id* pID1)
{ {
mal_assert(pContext != NULL); mal_assert(pContext != NULL);
...@@ -11923,18 +11946,18 @@ mal_result mal_context_get_device_info__oss(mal_context* pContext, mal_device_ty ...@@ -11923,18 +11946,18 @@ mal_result mal_context_get_device_info__oss(mal_context* pContext, mal_device_ty
// If we get here it means we are _not_ using the default device. // If we get here it means we are _not_ using the default device.
mal_bool32 foundDevice = MAL_FALSE; mal_bool32 foundDevice = MAL_FALSE;
int fd = mal_open_temp_device__oss(); int fdTemp = mal_open_temp_device__oss();
if (fd == -1) { if (fdTemp == -1) {
return mal_context_post_error(pContext, NULL, "[OSS] Failed to open a temporary device for retrieving system information used for device enumeration.", MAL_NO_BACKEND); return mal_context_post_error(pContext, NULL, "[OSS] Failed to open a temporary device for retrieving system information used for device enumeration.", MAL_NO_BACKEND);
} }
oss_sysinfo si; oss_sysinfo si;
int result = ioctl(fd, SNDCTL_SYSINFO, &si); int result = ioctl(fdTemp, SNDCTL_SYSINFO, &si);
if (result != -1) { if (result != -1) {
for (int iAudioDevice = 0; iAudioDevice < si.numaudios; ++iAudioDevice) { for (int iAudioDevice = 0; iAudioDevice < si.numaudios; ++iAudioDevice) {
oss_audioinfo ai; oss_audioinfo ai;
ai.dev = iAudioDevice; ai.dev = iAudioDevice;
result = ioctl(fd, SNDCTL_AUDIOINFO, &ai); result = ioctl(fdTemp, SNDCTL_AUDIOINFO, &ai);
if (result != -1) { if (result != -1) {
if (mal_strcmp(ai.devnode, pDeviceID->oss) == 0) { if (mal_strcmp(ai.devnode, pDeviceID->oss) == 0) {
// It has the same name, so now just confirm the type. // It has the same name, so now just confirm the type.
...@@ -11952,6 +11975,29 @@ mal_result mal_context_get_device_info__oss(mal_context* pContext, mal_device_ty ...@@ -11952,6 +11975,29 @@ mal_result mal_context_get_device_info__oss(mal_context* pContext, mal_device_ty
mal_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), ai.name, (size_t)-1); mal_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), ai.name, (size_t)-1);
} }
pDeviceInfo->minChannels = ai.min_channels;
pDeviceInfo->maxChannels = ai.max_channels;
pDeviceInfo->minSampleRate = ai.min_rate;
pDeviceInfo->maxSampleRate = ai.max_rate;
pDeviceInfo->formatCount = 0;
unsigned int formatMask;
if (deviceType == mal_device_type_playback) {
formatMask = ai.oformats;
} else {
formatMask = ai.iformats;
}
if ((formatMask & AFMT_U8) != 0) {
pDeviceInfo->formats[pDeviceInfo->formatCount++] = mal_format_u8;
}
if ((formatMask & AFMT_S16_LE) != 0) {
pDeviceInfo->formats[pDeviceInfo->formatCount++] = mal_format_s16;
}
if ((formatMask & AFMT_S32_LE) != 0) {
pDeviceInfo->formats[pDeviceInfo->formatCount++] = mal_format_s32;
}
foundDevice = MAL_TRUE; foundDevice = MAL_TRUE;
break; break;
} }
...@@ -11959,18 +12005,19 @@ mal_result mal_context_get_device_info__oss(mal_context* pContext, mal_device_ty ...@@ -11959,18 +12005,19 @@ mal_result mal_context_get_device_info__oss(mal_context* pContext, mal_device_ty
} }
} }
} else { } else {
close(fd); close(fdTemp);
return mal_context_post_error(pContext, NULL, "[OSS] Failed to retrieve system information for device enumeration.", MAL_NO_BACKEND); return mal_context_post_error(pContext, NULL, "[OSS] Failed to retrieve system information for device enumeration.", MAL_NO_BACKEND);
} }
close(fd); close(fdTemp);
if (foundDevice) { if (!foundDevice) {
return MAL_SUCCESS;
} else {
return MAL_NO_DEVICE; return MAL_NO_DEVICE;
} }
return MAL_SUCCESS;
} }
mal_result mal_context_init__oss(mal_context* pContext) mal_result mal_context_init__oss(mal_context* pContext)
...@@ -12026,15 +12073,8 @@ mal_result mal_device_init__oss(mal_context* pContext, mal_device_type type, mal ...@@ -12026,15 +12073,8 @@ mal_result mal_device_init__oss(mal_context* pContext, mal_device_type type, mal
mal_assert(pDevice != NULL); mal_assert(pDevice != NULL);
mal_zero_object(&pDevice->oss); mal_zero_object(&pDevice->oss);
char deviceName[64]; mal_result result = mal_context_open_device__oss(pContext, type, pDeviceID, &pDevice->oss.fd);
if (pDeviceID != NULL) { if (result != MAL_SUCCESS) {
mal_strncpy_s(deviceName, sizeof(deviceName), pDeviceID->oss, (size_t)-1);
} else {
mal_strncpy_s(deviceName, sizeof(deviceName), "/dev/dsp", (size_t)-1);
}
pDevice->oss.fd = open(deviceName, (type == mal_device_type_playback) ? O_WRONLY : O_RDONLY, 0);
if (pDevice->oss.fd == -1) {
return mal_post_error(pDevice, "[OSS] Failed to open device.", MAL_FAILED_TO_OPEN_BACKEND_DEVICE); return mal_post_error(pDevice, "[OSS] Failed to open device.", MAL_FAILED_TO_OPEN_BACKEND_DEVICE);
} }
...@@ -12053,8 +12093,8 @@ mal_result mal_device_init__oss(mal_context* pContext, mal_device_type type, mal ...@@ -12053,8 +12093,8 @@ mal_result mal_device_init__oss(mal_context* pContext, mal_device_type type, mal
case mal_format_u8: case mal_format_u8:
default: ossFormat = AFMT_U8; break; default: ossFormat = AFMT_U8; break;
} }
int result = ioctl(pDevice->oss.fd, SNDCTL_DSP_SETFMT, &ossFormat); int ossResult = ioctl(pDevice->oss.fd, SNDCTL_DSP_SETFMT, &ossFormat);
if (result == -1) { if (ossResult == -1) {
close(pDevice->oss.fd); close(pDevice->oss.fd);
return mal_post_error(pDevice, "[OSS] Failed to set format.", MAL_FORMAT_NOT_SUPPORTED); return mal_post_error(pDevice, "[OSS] Failed to set format.", MAL_FORMAT_NOT_SUPPORTED);
} }
...@@ -12069,8 +12109,8 @@ mal_result mal_device_init__oss(mal_context* pContext, mal_device_type type, mal ...@@ -12069,8 +12109,8 @@ mal_result mal_device_init__oss(mal_context* pContext, mal_device_type type, mal
// Channels. // Channels.
int ossChannels = (int)pConfig->channels; int ossChannels = (int)pConfig->channels;
result = ioctl(pDevice->oss.fd, SNDCTL_DSP_CHANNELS, &ossChannels); ossResult = ioctl(pDevice->oss.fd, SNDCTL_DSP_CHANNELS, &ossChannels);
if (result == -1) { if (ossResult == -1) {
close(pDevice->oss.fd); close(pDevice->oss.fd);
return mal_post_error(pDevice, "[OSS] Failed to set channel count.", MAL_FORMAT_NOT_SUPPORTED); return mal_post_error(pDevice, "[OSS] Failed to set channel count.", MAL_FORMAT_NOT_SUPPORTED);
} }
...@@ -12080,8 +12120,8 @@ mal_result mal_device_init__oss(mal_context* pContext, mal_device_type type, mal ...@@ -12080,8 +12120,8 @@ mal_result mal_device_init__oss(mal_context* pContext, mal_device_type type, mal
// Sample rate. // Sample rate.
int ossSampleRate = (int)pConfig->sampleRate; int ossSampleRate = (int)pConfig->sampleRate;
result = ioctl(pDevice->oss.fd, SNDCTL_DSP_SPEED, &ossSampleRate); ossResult = ioctl(pDevice->oss.fd, SNDCTL_DSP_SPEED, &ossSampleRate);
if (result == -1) { if (ossResult == -1) {
close(pDevice->oss.fd); close(pDevice->oss.fd);
return mal_post_error(pDevice, "[OSS] Failed to set sample rate.", MAL_FORMAT_NOT_SUPPORTED); return mal_post_error(pDevice, "[OSS] Failed to set sample rate.", MAL_FORMAT_NOT_SUPPORTED);
} }
...@@ -12107,8 +12147,8 @@ mal_result mal_device_init__oss(mal_context* pContext, mal_device_type type, mal ...@@ -12107,8 +12147,8 @@ mal_result mal_device_init__oss(mal_context* pContext, mal_device_type type, mal
} }
int ossFragment = (int)((pDevice->periods << 16) | ossFragmentSizePower); int ossFragment = (int)((pDevice->periods << 16) | ossFragmentSizePower);
result = ioctl(pDevice->oss.fd, SNDCTL_DSP_SETFRAGMENT, &ossFragment); ossResult = ioctl(pDevice->oss.fd, SNDCTL_DSP_SETFRAGMENT, &ossFragment);
if (result == -1) { if (ossResult == -1) {
close(pDevice->oss.fd); close(pDevice->oss.fd);
return mal_post_error(pDevice, "[OSS] Failed to set fragment size and period count.", MAL_FORMAT_NOT_SUPPORTED); return mal_post_error(pDevice, "[OSS] Failed to set fragment size and period count.", MAL_FORMAT_NOT_SUPPORTED);
} }
......
cc mal_test_0.c -o ./bin/mal_test_0 -Wall -lpthread cc mal_test_0.c -o ./bin/mal_test_0 -Wall -lpthread -lm
c++ mal_test_0.cpp -o ./bin/mal_test_0_cpp -Wall -lpthread c++ mal_test_0.cpp -o ./bin/mal_test_0_cpp -Wall -lpthread -lm
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment