Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qpipewire_async_support.cpp
Go to the documentation of this file.
1// Copyright (C) 2025 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
5
6#include <QtMultimedia/private/qpipewire_instance_p.h>
7
9
10namespace QtPipeWire {
11
12namespace {
13
14template <typename Closure>
15auto runWithEventLoopLock(Closure &&closure)
16{
17 auto instance = QPipeWireInstance::instance();
18 if (instance)
19 return instance->runWithEventLoopLock(std::forward<Closure>(closure));
20 else
21 return closure();
22}
23
24} // namespace
25
26// SpaListenerBase
27
29
31 : m_sequenceNumber(s_sequenceNumberAllocator.fetch_add(1, std::memory_order_relaxed))
32{
33}
34
35void SpaListenerBase::removeHooks()
36{
37 spa_hook_remove(&m_listenerHook);
38}
39
40///////////////////////////////////////////////////////////////////////////////////////////////////
41
42// NodeEventListener
43
46{
47 static constexpr struct pw_node_events nodeEvents{
48 .version = PW_VERSION_NODE_EVENTS,
49 .info = NodeEventListener::onInfo,
50 .param = NodeEventListener::onParam,
51 };
52
53 int status = pw_node_add_listener(m_node.get(), &m_listenerHook, &nodeEvents, this);
54 if (status < 0)
55 qFatal() << "Failed to add listener: " << make_error_code(-status).message();
56}
57
59{
60 removeHooks();
61 runWithEventLoopLock([&] {
62 m_node = {};
63 });
64}
65
66void NodeEventListener::enumParams(spa_param_type type)
67{
68 int status = pw_node_enum_params(m_node.get(), m_sequenceNumber, type, 0, 0, nullptr);
69 if (status < 0)
70 qCritical() << "pw_node_enum_params failed:" << make_error_code(-status).message();
71}
72
73void NodeEventListener::onInfo(void *data, const pw_node_info *info)
74{
75 NodeEventListener *self = reinterpret_cast<NodeEventListener *>(data);
76 if (self->m_handler.infoHandler)
77 self->m_handler.infoHandler(info);
78}
79
80void NodeEventListener::onParam(void *data, int seq, uint32_t id, uint32_t index, uint32_t next,
81 const spa_pod *param)
82{
83 NodeEventListener *self = reinterpret_cast<NodeEventListener *>(data);
84 if (self->m_handler.paramHandler)
85 self->m_handler.paramHandler(seq, id, index, next, param);
86}
87
88///////////////////////////////////////////////////////////////////////////////////////////////////
89
90// CoreEventListener
91
93{
94 coreEvents.version = PW_VERSION_CORE_EVENTS;
95}
96
98{
99 runWithEventLoopLock([&] {
100 removeHooks();
101 });
102}
103
104///////////////////////////////////////////////////////////////////////////////////////////////////
105
106// CoreEventDoneListener
107
109{
110 coreEvents.done = [](void *self, uint32_t id, int seq) {
111 Q_ASSERT(QPipeWireInstance::instance()->isInPwThreadLoop());
112 CoreEventDoneListener *listener = reinterpret_cast<CoreEventDoneListener *>(self);
113 if (id == PW_ID_CORE && listener->m_seqnum == seq) {
114 listener->m_seqnum = -1;
115 if (auto handler = std::exchange(listener->m_handler, {}))
116 handler();
117 }
118 };
119}
120
121q23::expected<void, int> CoreEventDoneListener::asyncWait(pw_core *coreConnection,
122 std::function<void()> handler)
123{
124 m_handler = std::move(handler);
125
126 return runWithEventLoopLock([&]() -> q23::expected<void, int> {
127 int status = pw_core_add_listener(coreConnection, &m_listenerHook, &coreEvents, this);
128 if (status < 0) {
129 qFatal() << "pw_core_add_listener failed" << make_error_code(-status).message();
130 return q23::unexpected(status);
131 }
132
133 Q_ASSERT(m_seqnum == -1);
134 status = pw_core_sync(coreConnection, PW_ID_CORE, 0);
135 if (status < 0)
136 return q23::unexpected(status);
137 m_seqnum = status;
138 return {};
139 });
140}
141
142///////////////////////////////////////////////////////////////////////////////////////////////////
143
145
146q23::expected<bool, int> CoreEventSyncHelper::sync(pw_core *coreConnection,
148{
151 });
152 if (voidOrError) {
153 if (timeout)
155
157 return true;
158 }
159 return voidOrError.error();
160}
161
162} // namespace QtPipeWire
163
164QT_END_NAMESPACE
Combined button and popup list for selecting options.
static std::atomic_int s_sequenceNumberAllocator
q23::expected< void, int > asyncWait(pw_core *coreConnection, std::function< void()> handler)
NodeEventListener(PwNodeHandle, NodeHandler)
std::function< void(const struct pw_node_info *)> InfoHandler