summaryrefslogtreecommitdiff
path: root/Source/Core/AudioCommon
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Core/AudioCommon')
-rw-r--r--Source/Core/AudioCommon/CubebUtils.cpp98
-rw-r--r--Source/Core/AudioCommon/CubebUtils.h6
2 files changed, 104 insertions, 0 deletions
diff --git a/Source/Core/AudioCommon/CubebUtils.cpp b/Source/Core/AudioCommon/CubebUtils.cpp
index 6ad94f612c..e63f75c26e 100644
--- a/Source/Core/AudioCommon/CubebUtils.cpp
+++ b/Source/Core/AudioCommon/CubebUtils.cpp
@@ -72,3 +72,101 @@ std::shared_ptr<cubeb> CubebUtils::GetContext()
weak = shared = {ctx, DestroyContext};
return shared;
}
+
+std::vector<std::pair<std::string, std::string>> CubebUtils::ListInputDevices()
+{
+ std::vector<std::pair<std::string, std::string>> devices;
+
+ cubeb_device_collection collection;
+ auto cubeb_ctx = CubebUtils::GetContext();
+ const int r = cubeb_enumerate_devices(cubeb_ctx.get(), CUBEB_DEVICE_TYPE_INPUT, &collection);
+
+ if (r != CUBEB_OK)
+ {
+ ERROR_LOG_FMT(AUDIO, "Error listing cubeb input devices");
+ return devices;
+ }
+
+ INFO_LOG_FMT(AUDIO, "Listing cubeb input devices:");
+ for (uint32_t i = 0; i < collection.count; i++)
+ {
+ const auto& info = collection.device[i];
+ const auto device_state = info.state;
+ const char* state_name = [device_state] {
+ switch (device_state)
+ {
+ case CUBEB_DEVICE_STATE_DISABLED:
+ return "disabled";
+ case CUBEB_DEVICE_STATE_UNPLUGGED:
+ return "unplugged";
+ case CUBEB_DEVICE_STATE_ENABLED:
+ return "enabled";
+ default:
+ return "unknown?";
+ }
+ }();
+
+ // According to cubeb_device_info definition in cubeb.h:
+ // > "Optional vendor name, may be NULL."
+ // In practice, it seems some other fields might be NULL as well.
+ static constexpr auto fmt_str = [](const char* ptr) constexpr -> const char* {
+ return (ptr == nullptr) ? "(null)" : ptr;
+ };
+
+ INFO_LOG_FMT(AUDIO,
+ "[{}] Device ID: {}\n"
+ "\tName: {}\n"
+ "\tGroup ID: {}\n"
+ "\tVendor: {}\n"
+ "\tState: {}",
+ i, fmt_str(info.device_id), fmt_str(info.friendly_name), fmt_str(info.group_id),
+ fmt_str(info.vendor_name), state_name);
+
+ if (info.device_id == nullptr)
+ continue; // Shouldn't happen
+
+ if (info.state == CUBEB_DEVICE_STATE_ENABLED)
+ {
+ devices.emplace_back(info.device_id, fmt_str(info.friendly_name));
+ }
+ }
+
+ cubeb_device_collection_destroy(cubeb_ctx.get(), &collection);
+
+ return devices;
+}
+
+cubeb_devid CubebUtils::GetInputDeviceById(std::string_view id)
+{
+ if (id.empty())
+ return nullptr;
+
+ cubeb_device_collection collection;
+ auto cubeb_ctx = CubebUtils::GetContext();
+ const int r = cubeb_enumerate_devices(cubeb_ctx.get(), CUBEB_DEVICE_TYPE_INPUT, &collection);
+
+ if (r != CUBEB_OK)
+ {
+ ERROR_LOG_FMT(AUDIO, "Error enumerating cubeb input devices");
+ return nullptr;
+ }
+
+ cubeb_devid device_id = nullptr;
+ for (uint32_t i = 0; i < collection.count; i++)
+ {
+ const auto& info = collection.device[i];
+ if (id.compare(info.device_id) == 0)
+ {
+ device_id = info.devid;
+ break;
+ }
+ }
+ if (device_id == nullptr)
+ {
+ WARN_LOG_FMT(AUDIO, "Failed to find selected input device, defaulting to system preferences");
+ }
+
+ cubeb_device_collection_destroy(cubeb_ctx.get(), &collection);
+
+ return device_id;
+}
diff --git a/Source/Core/AudioCommon/CubebUtils.h b/Source/Core/AudioCommon/CubebUtils.h
index 718c5f39c8..11ecdf5a3f 100644
--- a/Source/Core/AudioCommon/CubebUtils.h
+++ b/Source/Core/AudioCommon/CubebUtils.h
@@ -4,10 +4,16 @@
#pragma once
#include <memory>
+#include <string>
+#include <string_view>
+#include <utility>
+#include <vector>
struct cubeb;
namespace CubebUtils
{
std::shared_ptr<cubeb> GetContext();
+std::vector<std::pair<std::string, std::string>> ListInputDevices();
+const void* GetInputDeviceById(std::string_view id);
} // namespace CubebUtils