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_audiocontextmanager_p.h>
7
9
10namespace QtPipeWire {
11
12// SpaListenerBase
13
15
17 : m_sequenceNumber(s_sequenceNumberAllocator.fetch_add(1, std::memory_order_relaxed))
18{
19}
20
21void SpaListenerBase::removeHooks()
22{
23 spa_hook_remove(&m_listenerHook);
24}
25
26///////////////////////////////////////////////////////////////////////////////////////////////////
27
28// NodeEventListener
29
32{
33 static constexpr struct pw_node_events nodeEvents{
34 .version = PW_VERSION_NODE_EVENTS,
35 .info = NodeEventListener::onInfo,
36 .param = NodeEventListener::onParam,
37 };
38
39 int status = pw_node_add_listener(m_node.get(), &m_listenerHook, &nodeEvents, this);
40 if (status < 0)
41 qFatal() << "Failed to add listener: " << make_error_code(-status).message();
42}
43
45{
46 removeHooks();
47 QAudioContextManager::withEventLoopLock([&] {
48 m_node = {};
49 });
50}
51
52void NodeEventListener::enumParams(spa_param_type type)
53{
54 int status = pw_node_enum_params(m_node.get(), m_sequenceNumber, type, 0, 0, nullptr);
55 if (status < 0)
56 qCritical() << "pw_node_enum_params failed:" << make_error_code(-status).message();
57}
58
59void NodeEventListener::onInfo(void *data, const pw_node_info *info)
60{
61 NodeEventListener *self = reinterpret_cast<NodeEventListener *>(data);
62 if (self->m_handler.infoHandler)
63 self->m_handler.infoHandler(info);
64}
65
66void NodeEventListener::onParam(void *data, int seq, uint32_t id, uint32_t index, uint32_t next,
67 const spa_pod *param)
68{
69 NodeEventListener *self = reinterpret_cast<NodeEventListener *>(data);
70 if (self->m_handler.paramHandler)
71 self->m_handler.paramHandler(seq, id, index, next, param);
72}
73
74///////////////////////////////////////////////////////////////////////////////////////////////////
75
76// CoreEventListener
77
79{
80 coreEvents.version = PW_VERSION_CORE_EVENTS;
81}
82
84{
85 QAudioContextManager::withEventLoopLock([&] {
86 removeHooks();
87 });
88}
89
90///////////////////////////////////////////////////////////////////////////////////////////////////
91
92// CoreEventDoneListener
93
95{
96 coreEvents.done = [](void *self, uint32_t id, int seq) {
97 Q_ASSERT(QAudioContextManager::isInPwThreadLoop());
98 CoreEventDoneListener *listener = reinterpret_cast<CoreEventDoneListener *>(self);
99 if (id == PW_ID_CORE && listener->m_seqnum == seq) {
100 listener->m_seqnum = -1;
101 if (auto handler = std::exchange(listener->m_handler, {}))
102 handler();
103 }
104 };
105}
106
107q23::expected<void, int> CoreEventDoneListener::asyncWait(pw_core *coreConnection,
108 std::function<void()> handler)
109{
110 m_handler = std::move(handler);
111
112 return QAudioContextManager::withEventLoopLock([&]() -> q23::expected<void, int> {
113 int status = pw_core_add_listener(coreConnection, &m_listenerHook, &coreEvents, this);
114 if (status < 0) {
115 qFatal() << "pw_core_add_listener failed" << make_error_code(-status).message();
116 return q23::unexpected(status);
117 }
118
119 Q_ASSERT(m_seqnum == -1);
120 status = pw_core_sync(coreConnection, PW_ID_CORE, 0);
121 if (status < 0)
122 return q23::unexpected(status);
123 m_seqnum = status;
124 return {};
125 });
126}
127
128///////////////////////////////////////////////////////////////////////////////////////////////////
129
131
132q23::expected<bool, int> CoreEventSyncHelper::sync(pw_core *coreConnection,
134{
137 });
138 if (voidOrError) {
139 if (timeout)
141
143 return true;
144 }
145 return voidOrError.error();
146}
147
148} // namespace QtPipeWire
149
150QT_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