File indexing completed on 2024-11-10 04:57:06

0001 /*
0002     SPDX-FileCopyrightText: 2018-2020 Red Hat Inc
0003     SPDX-FileCopyrightText: 2020 Aleix Pol Gonzalez <aleixpol@kde.org>
0004     SPDX-FileContributor: Jan Grulich <jgrulich@redhat.com>
0005 
0006     SPDX-License-Identifier: LGPL-2.0-or-later
0007 */
0008 
0009 #include "pipewirecore.h"
0010 #include "kwinscreencast_logging.h"
0011 #include <cerrno>
0012 
0013 #include <KLocalizedString>
0014 
0015 #include <QSocketNotifier>
0016 
0017 namespace KWin
0018 {
0019 
0020 PipeWireCore::PipeWireCore()
0021 {
0022     pw_init(nullptr, nullptr);
0023     pwCoreEvents.version = PW_VERSION_CORE_EVENTS;
0024     pwCoreEvents.error = &PipeWireCore::onCoreError;
0025 }
0026 
0027 PipeWireCore::~PipeWireCore()
0028 {
0029     if (pwMainLoop) {
0030         pw_loop_leave(pwMainLoop);
0031     }
0032 
0033     if (pwCore) {
0034         pw_core_disconnect(pwCore);
0035     }
0036 
0037     if (pwContext) {
0038         pw_context_destroy(pwContext);
0039     }
0040 
0041     if (pwMainLoop) {
0042         pw_loop_destroy(pwMainLoop);
0043     }
0044 }
0045 
0046 void PipeWireCore::onCoreError(void *data, uint32_t id, int seq, int res, const char *message)
0047 {
0048     qCWarning(KWIN_SCREENCAST) << "PipeWire remote error: " << message;
0049     if (id == PW_ID_CORE && res == -EPIPE) {
0050         PipeWireCore *pw = static_cast<PipeWireCore *>(data);
0051         Q_EMIT pw->pipewireFailed(QString::fromUtf8(message));
0052     }
0053 }
0054 
0055 bool PipeWireCore::init()
0056 {
0057     pwMainLoop = pw_loop_new(nullptr);
0058     if (!pwMainLoop) {
0059         qCWarning(KWIN_SCREENCAST, "Failed to create PipeWire loop: %s", strerror(errno));
0060         m_error = i18n("Failed to start main PipeWire loop");
0061         return false;
0062     }
0063     pw_loop_enter(pwMainLoop);
0064 
0065     QSocketNotifier *notifier = new QSocketNotifier(pw_loop_get_fd(pwMainLoop), QSocketNotifier::Read, this);
0066     connect(notifier, &QSocketNotifier::activated, this, [this] {
0067         int result = pw_loop_iterate(pwMainLoop, 0);
0068         if (result < 0) {
0069             qCWarning(KWIN_SCREENCAST) << "pipewire_loop_iterate failed: " << result;
0070         }
0071     });
0072 
0073     pwContext = pw_context_new(pwMainLoop, nullptr, 0);
0074     if (!pwContext) {
0075         qCWarning(KWIN_SCREENCAST) << "Failed to create PipeWire context";
0076         m_error = i18n("Failed to create PipeWire context");
0077         return false;
0078     }
0079 
0080     pwCore = pw_context_connect(pwContext, nullptr, 0);
0081     if (!pwCore) {
0082         qCWarning(KWIN_SCREENCAST) << "Failed to connect PipeWire context";
0083         m_error = i18n("Failed to connect PipeWire context");
0084         return false;
0085     }
0086 
0087     if (pw_loop_iterate(pwMainLoop, 0) < 0) {
0088         qCWarning(KWIN_SCREENCAST) << "Failed to start main PipeWire loop";
0089         m_error = i18n("Failed to start main PipeWire loop");
0090         return false;
0091     }
0092 
0093     pw_core_add_listener(pwCore, &coreListener, &pwCoreEvents, this);
0094     return true;
0095 }
0096 
0097 } // namespace KWin
0098 
0099 #include "moc_pipewirecore.cpp"