diff options
author | Chris Robinson <[email protected]> | 2023-05-31 20:55:16 -0700 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2023-06-01 06:31:19 -0700 |
commit | 360fdcbc721644e7b07aab7cbea4fc11bfa144d8 (patch) | |
tree | bb29ee82f156861503899015f40e95451f004013 /alc/backends/pulseaudio.cpp | |
parent | f8d8a1a3900fd51dc3bffb91f88c7725982a7ccc (diff) |
Handle device added/removed events with PulseAudio
Diffstat (limited to 'alc/backends/pulseaudio.cpp')
-rw-r--r-- | alc/backends/pulseaudio.cpp | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/alc/backends/pulseaudio.cpp b/alc/backends/pulseaudio.cpp index 7554b467..16a2450f 100644 --- a/alc/backends/pulseaudio.cpp +++ b/alc/backends/pulseaudio.cpp @@ -41,6 +41,7 @@ #include "albit.h" #include "alc/alconfig.h" +#include "alc/events.h" #include "almalloc.h" #include "alnumeric.h" #include "alspan.h" @@ -65,6 +66,8 @@ using uint = unsigned int; MAGIC(pa_context_get_state); \ MAGIC(pa_context_disconnect); \ MAGIC(pa_context_set_state_callback); \ + MAGIC(pa_context_set_subscribe_callback); \ + MAGIC(pa_context_subscribe); \ MAGIC(pa_context_errno); \ MAGIC(pa_context_connect); \ MAGIC(pa_context_get_server_info); \ @@ -136,6 +139,8 @@ PULSE_FUNCS(MAKE_FUNC) #define pa_context_get_state ppa_context_get_state #define pa_context_disconnect ppa_context_disconnect #define pa_context_set_state_callback ppa_context_set_state_callback +#define pa_context_set_subscribe_callback ppa_context_set_subscribe_callback +#define pa_context_subscribe ppa_context_subscribe #define pa_context_errno ppa_context_errno #define pa_context_connect ppa_context_connect #define pa_context_get_server_info ppa_context_get_server_info @@ -270,6 +275,9 @@ constexpr pa_context_flags_t& operator|=(pa_context_flags_t &lhs, pa_context_fla return lhs; } +constexpr pa_subscription_mask_t operator|(pa_subscription_mask_t lhs, pa_subscription_mask_t rhs) +{ return pa_subscription_mask_t(lhs | al::to_underlying(rhs)); } + struct DevMap { std::string name; @@ -422,6 +430,39 @@ struct MainloopUniqueLock : public std::unique_lock<PulseMainloop> { } + void setEventHandler() + { + pa_operation *op{pa_context_subscribe(mutex()->mContext, + PA_SUBSCRIPTION_MASK_SINK | PA_SUBSCRIPTION_MASK_SOURCE, + [](pa_context*, int, void *pdata) noexcept + { static_cast<PulseMainloop*>(pdata)->signal(); }, + mutex())}; + waitForOperation(op); + + /* Watch for device added/removed events. + * + * TODO: Also track the "default" device, in as much as PulseAudio has + * the concept of a default device (whatever device is opened when not + * specifying a specific sink or source name). There doesn't seem to be + * an event for this. + */ + auto handler = [](pa_context*, pa_subscription_event_type_t t, uint32_t, void*) noexcept + { + const auto eventFacility = (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK); + if(eventFacility == PA_SUBSCRIPTION_EVENT_SINK + || eventFacility == PA_SUBSCRIPTION_EVENT_SOURCE) + { + const auto eventType = (t & PA_SUBSCRIPTION_EVENT_TYPE_MASK); + if(eventType == PA_SUBSCRIPTION_EVENT_NEW) + alc::Event(alc::EventType::DeviceAdded, "Device added"); + else if(eventType == PA_SUBSCRIPTION_EVENT_REMOVE) + alc::Event(alc::EventType::DeviceRemoved, "Device removed"); + } + }; + pa_context_set_subscribe_callback(mutex()->mContext, handler, nullptr); + } + + void contextStateCallback(pa_context *context) noexcept { pa_context_state_t state{pa_context_get_state(context)}; @@ -1395,6 +1436,7 @@ bool PulseBackendFactory::init() MainloopUniqueLock plock{gGlobalMainloop}; plock.connectContext(); + plock.setEventHandler(); return true; } catch(...) { |