Skip to content

Commit

Permalink
feat(ALC_SOFT_system_events): Add alcEventIsSupportedSOFT method in A…
Browse files Browse the repository at this point in the history
…LC_SOFT_system_events unreleased extension

The purpose of this addition (to my collection) are allow to retrieve which events are supported and if events are fully supported or if some case isn't managed for some reason

For exemple only some backends provide system events:
 * pipewire -> Full support of extension
 * wasapi -> Full support of extension
 * pulseaudio -> Support of add and remove devices events only
 * coreaudio -> Support of default device change only
  • Loading branch information
MathiusD committed Nov 24, 2023
1 parent 1f6d19f commit 62b5dd2
Show file tree
Hide file tree
Showing 15 changed files with 194 additions and 22 deletions.
40 changes: 40 additions & 0 deletions alc/alc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
#include "al/filter.h"
#include "al/listener.h"
#include "al/source.h"
#include "alc/events.h"
#include "albit.h"
#include "alconfig.h"
#include "almalloc.h"
Expand Down Expand Up @@ -3469,3 +3470,42 @@ FORCE_ALIGN ALCboolean ALC_APIENTRY alcReopenDeviceSOFT(ALCdevice *device,
ResetDeviceParams(dev.get(), attribs);
return ALC_TRUE;
}

/************************************************
* ALC event query functions
************************************************/

FORCE_ALIGN ALCenum ALC_APIENTRY alcEventIsSupportedSOFT(ALCenum eventType, ALCenum deviceType) noexcept
{
auto etype = alc::GetEventType(eventType);
if(!etype)
{
WARN("Invalid event type: 0x%04x\n", eventType);
alcSetError(nullptr, ALC_INVALID_ENUM);
return ALC_EVENT_NOT_SUPPORTED;
}
switch(deviceType)
{
case al::to_underlying(alc::DeviceType::Playback):
{
if(!PlaybackFactory)
{
return ALC_EVENT_NOT_SUPPORTED;
}

auto supported = PlaybackFactory->queryEventSupport(*etype, BackendType::Playback);
return al::to_underlying(supported);
}
case al::to_underlying(alc::DeviceType::Capture):
{
if(!CaptureFactory)
{
return ALC_EVENT_NOT_SUPPORTED;
}

auto supported = CaptureFactory->queryEventSupport(*etype, BackendType::Capture);
return al::to_underlying(supported);
}
}
return ALC_EVENT_NOT_SUPPORTED;
}
5 changes: 5 additions & 0 deletions alc/backends/base.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#include "core/device.h"
#include "core/except.h"
#include "alc/events.h"


using uint = unsigned int;
Expand Down Expand Up @@ -79,6 +80,10 @@ struct BackendFactory {

virtual bool querySupport(BackendType type) = 0;

virtual alc::EventSupport queryEventSupport(alc::EventType eventType, BackendType type) {
return alc::EventSupport::NoSupport;
}

virtual std::string probe(BackendType type) = 0;

virtual BackendPtr createBackend(DeviceBase *device, BackendType type) = 0;
Expand Down
11 changes: 10 additions & 1 deletion alc/backends/coreaudio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@
#include "core/device.h"
#include "core/logging.h"
#include "ringbuffer.h"
#include "alc/events.h"

#include <AudioUnit/AudioUnit.h>
#include <AudioToolbox/AudioToolbox.h>
Expand Down Expand Up @@ -1013,3 +1012,13 @@ BackendPtr CoreAudioBackendFactory::createBackend(DeviceBase *device, BackendTyp
return BackendPtr{new CoreAudioCapture{device}};
return nullptr;
}

alc::EventSupport CoreAudioBackendFactory::queryEventSupport(alc::EventType eventType, BackendType type)
{
switch(eventType) {
case alc::EventType::DefaultDeviceChanged: {
return alc::EventSupport::FullSupport;
}
}
return alc::EventSupport::NoSupport;
}
2 changes: 2 additions & 0 deletions alc/backends/coreaudio.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ struct CoreAudioBackendFactory final : public BackendFactory {

bool querySupport(BackendType type) override;

alc::EventSupport queryEventSupport(alc::EventType eventType, BackendType type) override;

std::string probe(BackendType type) override;

BackendPtr createBackend(DeviceBase *device, BackendType type) override;
Expand Down
17 changes: 16 additions & 1 deletion alc/backends/pipewire.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@

#include "albit.h"
#include "alc/alconfig.h"
#include "alc/events.h"
#include "almalloc.h"
#include "alnumeric.h"
#include "alspan.h"
Expand Down Expand Up @@ -2266,3 +2265,19 @@ BackendFactory &PipeWireBackendFactory::getFactory()
static PipeWireBackendFactory factory{};
return factory;
}

alc::EventSupport PipeWireBackendFactory::queryEventSupport(alc::EventType eventType, BackendType type)
{
switch(eventType) {
case alc::EventType::DefaultDeviceChanged: {
return alc::EventSupport::FullSupport;
}
case alc::EventType::DeviceAdded: {
return alc::EventSupport::FullSupport;
}
case alc::EventType::DeviceRemoved: {
return alc::EventSupport::FullSupport;
}
}
return alc::EventSupport::NoSupport;
}
2 changes: 2 additions & 0 deletions alc/backends/pipewire.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ struct PipeWireBackendFactory final : public BackendFactory {

bool querySupport(BackendType type) override;

alc::EventSupport queryEventSupport(alc::EventType eventType, BackendType type) override;

std::string probe(BackendType type) override;

BackendPtr createBackend(DeviceBase *device, BackendType type) override;
Expand Down
14 changes: 13 additions & 1 deletion alc/backends/pulseaudio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@

#include "albit.h"
#include "alc/alconfig.h"
#include "alc/events.h"
#include "almalloc.h"
#include "alnumeric.h"
#include "alspan.h"
Expand Down Expand Up @@ -1491,3 +1490,16 @@ BackendFactory &PulseBackendFactory::getFactory()
static PulseBackendFactory factory{};
return factory;
}

alc::EventSupport PulseBackendFactory::queryEventSupport(alc::EventType eventType, BackendType type)
{
switch(eventType) {
case alc::EventType::DeviceAdded: {
return alc::EventSupport::FullSupport;
}
case alc::EventType::DeviceRemoved: {
return alc::EventSupport::FullSupport;
}
}
return alc::EventSupport::NoSupport;
}
2 changes: 2 additions & 0 deletions alc/backends/pulseaudio.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ class PulseBackendFactory final : public BackendFactory {

bool querySupport(BackendType type) override;

alc::EventSupport queryEventSupport(alc::EventType eventType, BackendType type) override;

std::string probe(BackendType type) override;

BackendPtr createBackend(DeviceBase *device, BackendType type) override;
Expand Down
17 changes: 16 additions & 1 deletion alc/backends/wasapi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@

#include "albit.h"
#include "alc/alconfig.h"
#include "alc/events.h"
#include "alnumeric.h"
#include "alspan.h"
#include "althrd_setname.h"
Expand Down Expand Up @@ -2741,3 +2740,19 @@ BackendFactory &WasapiBackendFactory::getFactory()
static WasapiBackendFactory factory{};
return factory;
}

EventSupport WasapiBackendFactory::queryEventSupport(EventType eventType, BackendType type)
{
switch(eventType) {
case EventType::DefaultDeviceChanged: {
return EventSupport::FullSupport;
}
case EventType::DeviceAdded: {
return EventSupport::FullSupport;
}
case EventType::DeviceRemoved: {
return EventSupport::FullSupport;
}
}
return EventSupport::NoSupport;
}
2 changes: 2 additions & 0 deletions alc/backends/wasapi.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ struct WasapiBackendFactory final : public BackendFactory {

bool querySupport(BackendType type) override;

alc::EventSupport queryEventSupport(alc::EventType eventType, BackendType type) override;

std::string probe(BackendType type) override;

BackendPtr createBackend(DeviceBase *device, BackendType type) override;
Expand Down
26 changes: 12 additions & 14 deletions alc/events.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,13 @@

#include "events.h"

#include <optional>

#include "alspan.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)
Expand All @@ -39,6 +26,17 @@ ALCenum EnumFromEventType(const alc::EventType type)

namespace alc {

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;
}

void Event(EventType eventType, DeviceType deviceType, ALCdevice *device, std::string_view message) noexcept
{
auto eventlock = std::unique_lock{EventMutex};
Expand Down Expand Up @@ -73,7 +71,7 @@ FORCE_ALIGN ALCboolean ALC_APIENTRY alcEventControlSOFT(ALCsizei count, const AL
alc::EventBitSet eventSet{0};
for(ALCenum type : al::span{events, static_cast<ALCuint>(count)})
{
auto etype = GetEventType(type);
auto etype = alc::GetEventType(type);
if(!etype)
{
WARN("Invalid event type: 0x%04x\n", type);
Expand Down
9 changes: 9 additions & 0 deletions alc/events.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include <bitset>
#include <mutex>
#include <optional>
#include <string_view>


Expand All @@ -19,6 +20,14 @@ enum class EventType : uint8_t {
Count
};

std::optional<alc::EventType> GetEventType(ALCenum type);

enum class EventSupport : ALCenum {
FullSupport = ALC_EVENT_SUPPORTED,
PartialSupport = ALC_EVENT_PARTIALLY_SUPPORTED,
NoSupport = ALC_EVENT_NOT_SUPPORTED,
};

enum class DeviceType : ALCenum {
Playback = ALC_PLAYBACK_DEVICE_SOFT,
Capture = ALC_CAPTURE_DEVICE_SOFT,
Expand Down
1 change: 1 addition & 0 deletions alc/export_list.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ inline const FuncExport alcFunctions[]{

DECL(alcReopenDeviceSOFT),

DECL(alcEventIsSupportedSOFT),
DECL(alcEventControlSOFT),
DECL(alcEventCallbackSOFT),

Expand Down
13 changes: 9 additions & 4 deletions include/AL/alext.h
Original file line number Diff line number Diff line change
Expand Up @@ -715,16 +715,21 @@ void AL_APIENTRY alGetObjectLabelEXT(ALenum identifier, ALuint name, ALsizei buf

#ifndef ALC_SOFT_system_events
#define ALC_SOFT_system_events
#define ALC_PLAYBACK_DEVICE_SOFT 0x19D4
#define ALC_CAPTURE_DEVICE_SOFT 0x19D5
#define ALC_PLAYBACK_DEVICE_SOFT 0x19D4
#define ALC_CAPTURE_DEVICE_SOFT 0x19D5
#define ALC_EVENT_TYPE_DEFAULT_DEVICE_CHANGED_SOFT 0x19D6
#define ALC_EVENT_TYPE_DEVICE_ADDED_SOFT 0x19D7
#define ALC_EVENT_TYPE_DEVICE_REMOVED_SOFT 0x19D8
#define ALC_EVENT_TYPE_DEVICE_ADDED_SOFT 0x19D7
#define ALC_EVENT_TYPE_DEVICE_REMOVED_SOFT 0x19D8
#define ALC_EVENT_SUPPORTED 0x19D9
#define ALC_EVENT_PARTIALLY_SUPPORTED 0x19DA
#define ALC_EVENT_NOT_SUPPORTED 0x19DB
typedef void (ALC_APIENTRY*ALCEVENTPROCTYPESOFT)(ALCenum eventType, ALCenum deviceType,
ALCdevice *device, ALCsizei length, const ALCchar *message, void *userParam) ALC_API_NOEXCEPT17;
typedef ALCenum (ALC_APIENTRY*LPALCEVENTISSUPPORTEDSOFT)(ALCenum eventType, ALCenum deviceType) ALC_API_NOEXCEPT17;
typedef ALCboolean (ALC_APIENTRY*LPALCEVENTCONTROLSOFT)(ALCsizei count, const ALCenum *events, ALCboolean enable) ALC_API_NOEXCEPT17;
typedef void (ALC_APIENTRY*LPALCEVENTCALLBACKSOFT)(ALCEVENTPROCTYPESOFT callback, void *userParam) ALC_API_NOEXCEPT17;
#ifdef AL_ALEXT_PROTOTYPES
ALCenum ALC_APIENTRY alcEventIsSupportedSOFT(ALCenum eventType, ALCenum deviceType) ALC_API_NOEXCEPT;
ALCboolean ALC_APIENTRY alcEventControlSOFT(ALCsizei count, const ALCenum *events, ALCboolean enable) ALC_API_NOEXCEPT;
void ALC_APIENTRY alcEventCallbackSOFT(ALCEVENTPROCTYPESOFT callback, void *userParam) ALC_API_NOEXCEPT;
#endif
Expand Down
55 changes: 55 additions & 0 deletions utils/openal-info.c
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,60 @@ static void printModeInfo(ALCdevice *device)
}
}

static void printALCSOFTSystemEventIsSupportedResult(LPALCEVENTISSUPPORTEDSOFT alcEventIsSupportedSOFT, ALCenum eventType, ALCenum deviceType)
{
if (alcEventIsSupportedSOFT == NULL)
{
printf("ERROR (alcEventIsSupportedSOFT missing)\n");
return;
}
ALCenum supported = alcEventIsSupportedSOFT(eventType, deviceType);
if (supported == ALC_EVENT_SUPPORTED)
{
printf("SUPPORTED\n");
}
else if (supported == ALC_EVENT_PARTIALLY_SUPPORTED)
{
printf("PARTIALLY SUPPORTED\n");
}
else if (supported == ALC_EVENT_NOT_SUPPORTED)
{
printf("NOT SUPPORTED\n");
}
else
{
printf("UNEXPECTED RETURN : %d\n", supported);
}
}

static void printALC_SOFT_system_event(void)
{
printf("ALC_SOFT_system_events:");
if (alcIsExtensionPresent(NULL, "ALC_SOFT_system_events"))
{
static LPALCEVENTISSUPPORTEDSOFT alcEventIsSupportedSOFT;
alcEventIsSupportedSOFT = FUNCTION_CAST(LPALCEVENTISSUPPORTEDSOFT, alGetProcAddress("alcEventIsSupportedSOFT"));
printf(" Supported.\n");
printf(" Events:\n");
printf(" ALC_EVENT_TYPE_DEFAULT_DEVICE_CHANGED_SOFT for ALC_PLAYBACK_DEVICE_SOFT - ");
printALCSOFTSystemEventIsSupportedResult(alcEventIsSupportedSOFT, ALC_EVENT_TYPE_DEFAULT_DEVICE_CHANGED_SOFT, ALC_PLAYBACK_DEVICE_SOFT);
printf(" ALC_EVENT_TYPE_DEFAULT_DEVICE_CHANGED_SOFT for ALC_CAPTURE_DEVICE_SOFT - ");
printALCSOFTSystemEventIsSupportedResult(alcEventIsSupportedSOFT, ALC_EVENT_TYPE_DEFAULT_DEVICE_CHANGED_SOFT, ALC_CAPTURE_DEVICE_SOFT);
printf(" ALC_EVENT_TYPE_DEVICE_ADDED_SOFT for ALC_PLAYBACK_DEVICE_SOFT - ");
printALCSOFTSystemEventIsSupportedResult(alcEventIsSupportedSOFT, ALC_EVENT_TYPE_DEVICE_ADDED_SOFT, ALC_PLAYBACK_DEVICE_SOFT);
printf(" ALC_EVENT_TYPE_DEVICE_ADDED_SOFT for ALC_CAPTURE_DEVICE_SOFT - ");
printALCSOFTSystemEventIsSupportedResult(alcEventIsSupportedSOFT, ALC_EVENT_TYPE_DEVICE_ADDED_SOFT, ALC_CAPTURE_DEVICE_SOFT);
printf(" ALC_EVENT_TYPE_DEVICE_REMOVED_SOFT for ALC_PLAYBACK_DEVICE_SOFT - ");
printALCSOFTSystemEventIsSupportedResult(alcEventIsSupportedSOFT, ALC_EVENT_TYPE_DEVICE_REMOVED_SOFT, ALC_PLAYBACK_DEVICE_SOFT);
printf(" ALC_EVENT_TYPE_DEVICE_REMOVED_SOFT for ALC_CAPTURE_DEVICE_SOFT - ");
printALCSOFTSystemEventIsSupportedResult(alcEventIsSupportedSOFT, ALC_EVENT_TYPE_DEVICE_REMOVED_SOFT, ALC_CAPTURE_DEVICE_SOFT);
}
else
{
printf(" Not supported.\n");
}
}

static void printALInfo(void)
{
printf("OpenAL vendor string: %s\n", alGetString(AL_VENDOR));
Expand Down Expand Up @@ -435,6 +489,7 @@ int main(int argc, char *argv[])
}
printALCInfo(device);
printHRTFInfo(device);
printALC_SOFT_system_event();

context = alcCreateContext(device, NULL);
if(!context || alcMakeContextCurrent(context) == ALC_FALSE)
Expand Down

0 comments on commit 62b5dd2

Please sign in to comment.