6 #include <pulse/context.h>
7 #include <pulse/introspect.h>
8 #include <pulse/subscribe.h>
9 #include <pulse/thread-mainloop.h>
16 static pa_context* paContext =
nullptr;
17 static qint64 reconnectTime = 0;
18 static QString defaultSink;
21 static bool CheckPAOperation(pa_operation* operation){
22 if(operation ==
nullptr)
25 pa_operation_unref(operation);
29 static void SinkCallback(pa_context* context,
const pa_sink_info* info,
int eol,
void* data){
30 QMutexLocker locker(&mutex);
32 if(info ==
nullptr || info->name != defaultSink)
38 static void ServerCallback(pa_context* context,
const pa_server_info* info,
void* data){
39 QMutexLocker locker(&mutex);
44 defaultSink = info->default_sink_name;
47 static void SubscribeCallback(pa_context* context, pa_subscription_event_type_t type, uint32_t index,
void* data){
48 const pa_subscription_event_type_t eventFacility =
static_cast<pa_subscription_event_type_t
>(type & PA_SUBSCRIPTION_EVENT_FACILITY_MASK);
49 if(eventFacility == PA_SUBSCRIPTION_EVENT_SINK){
52 if(!CheckPAOperation(pa_context_get_sink_info_by_index(context, index, SinkCallback,
nullptr)))
53 qWarning(
"getMuteState(): pa_context_get_sink_info_by_index() error");
55 else if(eventFacility == PA_SUBSCRIPTION_EVENT_SERVER){
58 if(!CheckPAOperation(pa_context_get_server_info(context, ServerCallback,
nullptr)))
59 qWarning(
"getMuteState(): pa_context_get_server_info() error");
63 static void ContextStateCallback(pa_context* context,
void* data){
64 if(context != paContext)
67 pa_context_state_t state = pa_context_get_state(context);
68 if(state == PA_CONTEXT_READY){
69 pa_context_set_subscribe_callback(context, SubscribeCallback,
nullptr);
70 if(!CheckPAOperation(pa_context_subscribe(context,
71 static_cast<pa_subscription_mask_t>(PA_SUBSCRIPTION_MASK_SINK |
72 PA_SUBSCRIPTION_MASK_SERVER),
75 qWarning(
"getMuteState(): pa_context_subscribe() error");
78 if(!CheckPAOperation(pa_context_get_server_info(context, ServerCallback,
nullptr)))
79 qWarning(
"getMuteState(): pa_context_get_server_info() error");
82 if(!CheckPAOperation(pa_context_get_sink_info_list(context, SinkCallback,
nullptr)))
83 qWarning(
"getMuteState(): pa_context_get_sink_info_list() error");
85 else if(state == PA_CONTEXT_FAILED || state == PA_CONTEXT_TERMINATED){
86 QMutexLocker locker(&mutex);
90 if(paContext !=
nullptr){
91 pa_context_unref(paContext);
95 reconnectTime = QDateTime::currentMSecsSinceEpoch() + 1000;
104 static pa_threaded_mainloop* mainLoop =
nullptr;
106 QMutexLocker locker(&mutex);
110 if(mainLoop ==
nullptr){
111 mainLoop = pa_threaded_mainloop_new();
112 if(mainLoop ==
nullptr)
115 if(pa_threaded_mainloop_start(mainLoop) != 0){
116 pa_threaded_mainloop_free(mainLoop);
125 if(paContext ==
nullptr && QDateTime::currentMSecsSinceEpoch() >= reconnectTime){
126 pa_threaded_mainloop_lock(mainLoop);
128 pa_mainloop_api* api = pa_threaded_mainloop_get_api(mainLoop);
129 Q_ASSERT(api !=
nullptr);
131 paContext = pa_context_new(api,
"QPulse");
132 Q_ASSERT(paContext !=
nullptr);
133 pa_context_set_state_callback(paContext, &ContextStateCallback,
nullptr);
134 pa_context_connect(paContext,
nullptr, PA_CONTEXT_NOFAIL,
nullptr);
136 pa_threaded_mainloop_unlock(mainLoop);