diff options
author | Chris Robinson <[email protected]> | 2023-05-30 21:16:41 -0700 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2023-05-30 21:16:41 -0700 |
commit | 517bb94c0953de768f6aacca45456fd63bb2c96d (patch) | |
tree | 28852929ea0c61e1e7ad6f20233c861c5ae3f040 /alc/events.cpp | |
parent | 2e75909ce90027267775d53e997d4936d6ef31a5 (diff) |
Add a callback to report system device changes
Devices being added or removed, or the default device changing. Not all
backends report this (none do currently), but it'll be supported where it can.
Diffstat (limited to 'alc/events.cpp')
-rw-r--r-- | alc/events.cpp | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/alc/events.cpp b/alc/events.cpp new file mode 100644 index 00000000..3c9c59ee --- /dev/null +++ b/alc/events.cpp @@ -0,0 +1,98 @@ + +#include "config.h" + +#include "events.h" + +#include <optional> + +#include "alspan.h" +#include "common/threads.h" +#include "core/logging.h" +#include "device.h" + + +namespace { + +std::optional<alc::EventType> GetEventType(ALCenum type) +{ + switch(type) + { + case ALC_EVENT_TYPE_DEFAULT_DEVICE_CHANGED_SOFT: return alc::EventType::DefaultDeviceChanged; + case ALC_EVENT_TYPE_DEVICE_ADDED_SOFT: return alc::EventType::DeviceAdded; + case ALC_EVENT_TYPE_DEVICE_REMOVED_SOFT: return alc::EventType::DeviceRemoved; + } + return std::nullopt; +} + +ALCenum EnumFromEventType(const alc::EventType type) +{ + switch(type) + { + case alc::EventType::DefaultDeviceChanged: return ALC_EVENT_TYPE_DEFAULT_DEVICE_CHANGED_SOFT; + case alc::EventType::DeviceAdded: return ALC_EVENT_TYPE_DEVICE_ADDED_SOFT; + case alc::EventType::DeviceRemoved: return ALC_EVENT_TYPE_DEVICE_REMOVED_SOFT; + case alc::EventType::Count: break; + } + throw std::runtime_error{"Invalid EventType: "+std::to_string(al::to_underlying(type))}; +} + +} // namespace + +namespace alc { + +void Event(EventType eventType, ALCdevice *device, std::string_view message) noexcept +{ + auto eventlock = std::unique_lock{EventMutex}; + if(EventCallback && EventsEnabled.test(al::to_underlying(eventType))) + EventCallback(EnumFromEventType(eventType), device, + static_cast<ALCsizei>(message.length()), message.data(), EventUserPtr); +} + +} // namespace alc + +FORCE_ALIGN ALCboolean ALC_APIENTRY alcEventControlSOFT(ALCsizei count, const ALCenum *types, + ALCboolean enable) noexcept +{ + if(enable != ALC_FALSE && enable != ALC_TRUE) + { + alcSetError(nullptr, ALC_INVALID_ENUM); + return ALC_FALSE; + } + if(count < 0) + { + alcSetError(nullptr, ALC_INVALID_VALUE); + return ALC_FALSE; + } + if(count == 0) + return ALC_TRUE; + if(!types) + { + alcSetError(nullptr, ALC_INVALID_VALUE); + return ALC_FALSE; + } + + std::bitset<al::to_underlying(alc::EventType::Count)> eventSet{0}; + for(ALCenum type : al::span{types, static_cast<ALCuint>(count)}) + { + auto etype = GetEventType(type); + if(!etype) + { + WARN("Invalid event type: 0x%04x\n", type); + alcSetError(nullptr, ALC_INVALID_ENUM); + return ALC_FALSE; + } + eventSet.set(al::to_underlying(*etype)); + } + + auto eventlock = std::unique_lock{alc::EventMutex}; + if(enable) alc::EventsEnabled |= eventSet; + else alc::EventsEnabled &= eventSet; + return ALC_TRUE; +} + +FORCE_ALIGN void ALC_APIENTRY alcEventCallbackSOFT(ALCEVENTPROCTYPESOFT callback, void *userParam) noexcept +{ + auto eventlock = std::unique_lock{alc::EventMutex}; + alc::EventCallback = callback; + alc::EventUserPtr = userParam; +} |