6#include <QtMultimedia/private/qpipewire_portal_p.h>
7#include <QtMultimedia/private/qpipewire_propertydict_p.h>
8#include <QtMultimedia/private/qpipewire_support_p.h>
9#include <QtMultimedia/private/qtmultimediaglobal_p.h>
10#if QT_CONFIG(pipewire_symbolloader)
11# include <QtMultimedia/private/qpipewire_symbolloader_p.h>
14#include <QtCore/qcoreapplication.h>
15#include <QtCore/qmutex.h>
17#include <spa/utils/names.h>
35 std::weak_ptr<QPipeWireInstance> instance;
38Q_GLOBAL_STATIC(InstanceHolder, s_pipeWireInstance);
44 pw_init(
nullptr,
nullptr);
46 qCDebug(lcPipewire) <<
"PipeWire initialized: compiled against" << pw_get_headers_version()
47 <<
" running " << pw_get_library_version();
52 if (pw_check_library_version(0, 3, 49))
58 std::lock_guard guard{ s_pipeWireInstance->mutex };
59 std::shared_ptr<QPipeWireInstance> ret = s_pipeWireInstance->instance.lock();
61 ret = QPipeWireInstance::create();
63 s_pipeWireInstance->instance = ret;
70#if QT_CONFIG(pipewire_symbolloader)
71 return qPipewireIsLoaded();
77q23::expected<
void, std::error_code>
QPipeWireInstance::hasSPAFactory(
const char *factoryName)
79 std::array<spa_support, 32> support{};
80 uint32_t n_support = pw_get_support(support.data(), uint32_t(support.size()));
82 SpaHandleHandle handle{
83 pw_load_spa_handle(
nullptr, factoryName,
nullptr, n_support,
87 return q23::unexpected{ make_error_code() };
94 return m_eventLoop.isInThread();
99 return m_eventLoop.loop();
104#if QT_CONFIG(pipewire_screencapture)
105 if (!m_hasScreenCastPortal)
106 m_hasScreenCastPortal =
107 portalInterfaceVersion(
"org.freedesktop.portal.ScreenCast"_L1).has_value();
108 return *m_hasScreenCastPortal;
116 auto connection = PwCoreConnectionHandle{
117 pw_context_connect(m_context.get(),
nullptr,
122 return q23::unexpected(make_error_code(errno));
128 auto connection = PwCoreConnectionHandle{
129 pw_context_connect_fd(m_context.get(), fd,
nullptr,
134 return q23::unexpected(make_error_code(errno));
140 auto instance = std::unique_ptr<QPipeWireInstance>(
new QPipeWireInstance);
141 if (!instance->m_eventLoop || !instance->m_context)
152 int status = m_eventLoop.start();
154 qFatal() <<
"Failed to start event loop" << make_error_code(-status).message();
156 m_context = runWithEventLoopLock([&] {
157 auto applicationName = qApp->applicationName().toUtf8();
158 PwPropertiesHandle props = makeProperties({
159 { PW_KEY_APP_NAME, applicationName.data() },
162 return PwContextHandle{
163 pw_context_new(m_eventLoop.loop(), props.release(), 0),
170 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)