6#include <QtMultimedia/private/qpipewire_propertydict_p.h>
7#include <QtMultimedia/private/qpipewire_support_p.h>
8#include <QtMultimedia/private/qtmultimediaglobal_p.h>
9#if QT_CONFIG(pipewire_symbolloader)
10# include <QtMultimedia/private/qpipewire_symbolloader_p.h>
13#if QT_CONFIG(pipewire_screencapture)
14# include <QtDBus/qdbusinterface.h>
15# include <QtDBus/qdbusmessage.h>
18#include <QtCore/qcoreapplication.h>
19#include <QtCore/qmutex.h>
21#include <spa/utils/names.h>
39 std::weak_ptr<QPipeWireInstance> instance;
42Q_GLOBAL_STATIC(InstanceHolder, s_pipeWireInstance);
48 pw_init(
nullptr,
nullptr);
50 qCDebug(lcPipewire) <<
"PipeWire initialized: compiled against" << pw_get_headers_version()
51 <<
" running " << pw_get_library_version();
56 if (pw_check_library_version(0, 3, 49))
62 std::lock_guard guard{ s_pipeWireInstance->mutex };
63 std::shared_ptr<QPipeWireInstance> ret = s_pipeWireInstance->instance.lock();
65 ret = QPipeWireInstance::create();
67 s_pipeWireInstance->instance = ret;
74#if QT_CONFIG(pipewire_symbolloader)
75 return qPipewireIsLoaded();
81q23::expected<
void, std::error_code>
QPipeWireInstance::hasSPAFactory(
const char *factoryName)
83 std::array<spa_support, 32> support{};
84 uint32_t n_support = pw_get_support(support.data(), uint32_t(support.size()));
86 SpaHandleHandle handle{
87 pw_load_spa_handle(
nullptr, factoryName,
nullptr, n_support,
91 return q23::unexpected{ make_error_code() };
98 return m_eventLoop.isInThread();
103 return m_eventLoop.loop();
106#if QT_CONFIG(pipewire_screencapture)
110 u"/org/freedesktop/portal/desktop"_s,
130#if QT_CONFIG(pipewire_screencapture)
131 if (!m_hasScreenCastPortal)
132 m_hasScreenCastPortal =
133 portalInterfaceVersion(u"org.freedesktop.portal.ScreenCast"_s).has_value();
134 return *m_hasScreenCastPortal;
142 auto connection = PwCoreConnectionHandle{
143 pw_context_connect(m_context.get(),
nullptr,
148 return q23::unexpected(make_error_code(errno));
154 auto connection = PwCoreConnectionHandle{
155 pw_context_connect_fd(m_context.get(), fd,
nullptr,
160 return q23::unexpected(make_error_code(errno));
166 auto instance = std::unique_ptr<QPipeWireInstance>(
new QPipeWireInstance);
167 if (!instance->m_eventLoop || !instance->m_context)
178 int status = m_eventLoop.start();
180 qFatal() <<
"Failed to start event loop" << make_error_code(-status).message();
182 m_context = runWithEventLoopLock([&] {
183 auto applicationName = qApp->applicationName().toUtf8();
184 PwPropertiesHandle props = makeProperties({
185 { PW_KEY_APP_NAME, applicationName.data() },
188 return PwContextHandle{
189 pw_context_new(m_eventLoop.loop(), props.release(), 0),
196 runWithEventLoopLock([&] { m_context = {}; });
bool isInPwThreadLoop() const
q23::expected< PwCoreConnectionHandle, std::error_code > connectToPortal(int fd)
q23::expected< PwCoreConnectionHandle, std::error_code > connectToDaemon()
pw_loop * eventLoop() const
bool hasScreenCastPortal()
Q_LOGGING_CATEGORY(lcPipewire, "qt.multimedia.pipewire")
Q_DECLARE_LOGGING_CATEGORY(lcPipewire)