diff --git a/cmake/modules/FindPipeWire.cmake b/cmake/modules/FindPipeWire.cmake index 9717ac0..2a5e154 100644 --- a/cmake/modules/FindPipeWire.cmake +++ b/cmake/modules/FindPipeWire.cmake @@ -62,8 +62,8 @@ # in the FIND_PATH() and FIND_LIBRARY() calls find_package(PkgConfig QUIET) -pkg_search_module(PKG_PipeWire QUIET libpipewire-0.3 libpipewire-0.2) -pkg_search_module(PKG_Spa QUIET libspa-0.2 libspa-0.1) +pkg_search_module(PKG_PipeWire QUIET libpipewire-0.3) +pkg_search_module(PKG_Spa QUIET libspa-0.2) set(PipeWire_DEFINITIONS "${PKG_PipeWire_CFLAGS}" "${PKG_Spa_CFLAGS}") set(PipeWire_VERSION "${PKG_PipeWire_VERSION}") @@ -76,6 +76,13 @@ find_path(PipeWire_INCLUDE_DIRS ${PKG_PipeWire_INCLUDE_DIRS}/pipewire-0.3 ) +find_library(PipeWire_LIBRARIES + NAMES + pipewire-0.3 + HINTS + ${PKG_PipeWire_LIBRARY_DIRS} +) + find_path(Spa_INCLUDE_DIRS NAMES spa/param/props.h @@ -84,14 +91,6 @@ find_path(Spa_INCLUDE_DIRS ${PKG_Spa_INCLUDE_DIRS}/spa-0.2 ) -find_library(PipeWire_LIBRARIES - NAMES - pipewire-0.3 - pipewire-0.2 - HINTS - ${PKG_PipeWire_LIBRARY_DIRS} -) - include(FindPackageHandleStandardArgs) find_package_handle_standard_args(PipeWire FOUND_VAR diff --git a/framebuffers/pipewire/pw_framebuffer.cpp b/framebuffers/pipewire/pw_framebuffer.cpp index 5be74cc..404b473 100644 --- a/framebuffers/pipewire/pw_framebuffer.cpp +++ b/framebuffers/pipewire/pw_framebuffer.cpp @@ -1,6 +1,6 @@ /* This file is part of the KDE project + Copyright (C) 2018-2021 Jan Grulich Copyright (C) 2018 Oleg Chernovskiy - Copyright (C) 2018 Jan Grulich This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public @@ -23,19 +23,15 @@ #endif // pipewire -#include - -#if PW_CHECK_VERSION(0, 2, 90) -#include #ifdef HAVE_LINUX_DMABUF_H #include #endif #include -#endif #include #include #include +#include #include @@ -71,19 +67,6 @@ const QDBusArgument &operator >> (const QDBusArgument &arg, PWFrameBuffer::Strea return arg; } -#if !PW_CHECK_VERSION(0, 2, 90) -/** - * @brief The PwType class - helper class to contain pointers to raw C pipewire media mappings - */ -class PwType { -public: - spa_type_media_type media_type; - spa_type_media_subtype media_subtype; - spa_type_format_video format_video; - spa_type_video_format video_format; -}; -#endif - /** * @brief The PWFrameBuffer::Private class - private counterpart of PWFramebuffer class. This is the entity where * whole logic resides, for more info search for "d-pointer pattern" information. @@ -96,21 +79,13 @@ public: private: friend class PWFrameBuffer; -#if PW_CHECK_VERSION(0, 2, 90) static void onCoreError(void *data, uint32_t id, int seq, int res, const char *message); static void onStreamParamChanged(void *data, uint32_t id, const struct spa_pod *format); -#else - static void onStateChanged(void *data, pw_remote_state old, pw_remote_state state, const char *error); - static void onStreamFormatChanged(void *data, const struct spa_pod *format); -#endif static void onStreamStateChanged(void *data, pw_stream_state old, pw_stream_state state, const char *error_message); static void onStreamProcess(void *data); void initDbus(); void initPw(); -#if !PW_CHECK_VERSION(0, 2, 90) - void initializePwTypes(); -#endif // dbus handling void handleSessionCreated(quint32 &code, QVariantMap &results); @@ -126,7 +101,6 @@ private: PWFrameBuffer *q; // pipewire stuff -#if PW_CHECK_VERSION(0, 2, 90) struct pw_context *pwContext = nullptr; struct pw_core *pwCore = nullptr; struct pw_stream *pwStream = nullptr; @@ -140,22 +114,6 @@ private: // event handlers pw_core_events pwCoreEvents = {}; pw_stream_events pwStreamEvents = {}; -#else - pw_core *pwCore = nullptr; - pw_loop *pwLoop = nullptr; - pw_thread_loop *pwMainLoop = nullptr; - pw_stream *pwStream = nullptr; - pw_remote *pwRemote = nullptr; - pw_type *pwCoreType = nullptr; - PwType *pwType = nullptr; - - spa_hook remoteListener = {}; - spa_hook streamListener = {}; - - // event handlers - pw_remote_events pwRemoteEvents = {}; - pw_stream_events pwStreamEvents = {}; -#endif uint pwStreamNodeId = 0; @@ -187,7 +145,6 @@ private: PWFrameBuffer::Private::Private(PWFrameBuffer *q) : q(q) { -#if PW_CHECK_VERSION(0, 2, 90) pwCoreEvents.version = PW_VERSION_CORE_EVENTS; pwCoreEvents.error = &onCoreError; @@ -195,16 +152,6 @@ PWFrameBuffer::Private::Private(PWFrameBuffer *q) : q(q) pwStreamEvents.state_changed = &onStreamStateChanged; pwStreamEvents.param_changed = &onStreamParamChanged; pwStreamEvents.process = &onStreamProcess; -#else - // initialize event handlers, remote end and stream-related - pwRemoteEvents.version = PW_VERSION_REMOTE_EVENTS; - pwRemoteEvents.state_changed = &onStateChanged; - - pwStreamEvents.version = PW_VERSION_STREAM_EVENTS; - pwStreamEvents.state_changed = &onStreamStateChanged; - pwStreamEvents.format_changed = &onStreamFormatChanged; - pwStreamEvents.process = &onStreamProcess; -#endif } /** @@ -463,7 +410,6 @@ void PWFrameBuffer::Private::initPw() { // init pipewire (required) pw_init(nullptr, nullptr); // args are not used anyways -#if PW_CHECK_VERSION(0, 2, 90) pwMainLoop = pw_thread_loop_new("pipewire-main-loop", nullptr); pwContext = pw_context_new(pw_thread_loop_get_loop(pwMainLoop), nullptr, 0); if (!pwContext) { @@ -484,22 +430,6 @@ void PWFrameBuffer::Private::initPw() { qCWarning(KRFB_FB_PIPEWIRE) << "Failed to create PipeWire stream"; return; } -#else - // initialize our source - pwLoop = pw_loop_new(nullptr); - pwMainLoop = pw_thread_loop_new(pwLoop, "pipewire-main-loop"); - // create PipeWire core object (required) - pwCore = pw_core_new(pwLoop, nullptr); - pwCoreType = pw_core_get_type(pwCore); - - initializePwTypes(); - - // pw_remote should be initialized before type maps or connection error will happen - pwRemote = pw_remote_new(pwCore, nullptr, 0); - // init PipeWire remote, add listener to handle events - pw_remote_add_listener(pwRemote, &remoteListener, &pwRemoteEvents, this); - pw_remote_connect_fd(pwRemote, pipewireFd.fileDescriptor()); -#endif if (pw_thread_loop_start(pwMainLoop) < 0) { qCWarning(KRFB_FB_PIPEWIRE) << "Failed to start main PipeWire loop"; @@ -507,26 +437,6 @@ void PWFrameBuffer::Private::initPw() { } } -#if !PW_CHECK_VERSION(0, 2, 90) -/** - * @brief PWFrameBuffer::Private::initializePwTypes - helper method to initialize and map all needed - * Pipewire types from core to type structure. - */ -void PWFrameBuffer::Private::initializePwTypes() -{ - // raw C-like PipeWire type map - spa_type_map *map = pwCoreType->map; - pwType = new PwType(); - - spa_type_media_type_map(map, &pwType->media_type); - spa_type_media_subtype_map(map, &pwType->media_subtype); - spa_type_format_video_map(map, &pwType->format_video); - spa_type_video_format_map(map, &pwType->video_format); -} -#endif - - -#if PW_CHECK_VERSION(0, 2, 90) void PWFrameBuffer::Private::onCoreError(void *data, uint32_t id, int seq, int res, const char *message) { Q_UNUSED(data); @@ -536,32 +446,6 @@ void PWFrameBuffer::Private::onCoreError(void *data, uint32_t id, int seq, int r qInfo() << "core error: " << message; } -#else -/** - * @brief PWFrameBuffer::Private::onStateChanged - global state tracking for pipewire connection - * @param data pointer that you have set in pw_remote_add_listener call's last argument - * @param state new state that connection has changed to - * @param error optional error message, is set to non-null if state is error - */ -void PWFrameBuffer::Private::onStateChanged(void *data, pw_remote_state /*old*/, pw_remote_state state, const char *error) -{ - qInfo() << "remote state: " << pw_remote_state_as_string(state); - - auto d = static_cast(data); - - switch (state) { - case PW_REMOTE_STATE_ERROR: - qCWarning(KRFB_FB_PIPEWIRE) << "remote error: " << error; - break; - case PW_REMOTE_STATE_CONNECTED: - d->pwStream = d->createReceivingStream(); - break; - default: - qInfo() << "remote state: " << pw_remote_state_as_string(state); - break; - } -} -#endif /** * @brief PWFrameBuffer::Private::onStreamStateChanged - called whenever stream state changes on pipewire server @@ -575,7 +459,6 @@ void PWFrameBuffer::Private::onStreamStateChanged(void *data, pw_stream_state /* auto *d = static_cast(data); -#if PW_CHECK_VERSION(0, 2, 90) switch (state) { case PW_STREAM_STATE_ERROR: qCWarning(KRFB_FB_PIPEWIRE) << "pipewire stream error: " << error_message; @@ -588,18 +471,6 @@ void PWFrameBuffer::Private::onStreamStateChanged(void *data, pw_stream_state /* case PW_STREAM_STATE_CONNECTING: break; } -#else - switch (state) { - case PW_STREAM_STATE_ERROR: - qCWarning(KRFB_FB_PIPEWIRE) << "pipewire stream error: " << error_message; - break; - case PW_STREAM_STATE_CONFIGURE: - pw_stream_set_active(d->pwStream, true); - break; - default: - break; - } -#endif } /** @@ -608,32 +479,19 @@ void PWFrameBuffer::Private::onStreamStateChanged(void *data, pw_stream_state /* * @param data pointer that you have set in pw_stream_add_listener call's last argument * @param format format that's being proposed */ -#if PW_CHECK_VERSION(0, 2, 90) void PWFrameBuffer::Private::onStreamParamChanged(void *data, uint32_t id, const struct spa_pod *format) -#else -void PWFrameBuffer::Private::onStreamFormatChanged(void *data, const struct spa_pod *format) -#endif { qInfo() << "Stream format changed"; auto *d = static_cast(data); const int bpp = 4; -#if PW_CHECK_VERSION(0, 2, 90) if (!format || id != SPA_PARAM_Format) { -#else - if (!format) { - pw_stream_finish_format(d->pwStream, 0, nullptr, 0); -#endif return; } d->videoFormat = new spa_video_info_raw(); -#if PW_CHECK_VERSION(0, 2, 90) spa_format_video_raw_parse(format, d->videoFormat); -#else - spa_format_video_raw_parse(format, d->videoFormat, &d->pwType->format_video); -#endif auto width = d->videoFormat->size.width; auto height = d->videoFormat->size.height; auto stride = SPA_ROUND_UP_N(width * bpp, 4); @@ -645,7 +503,6 @@ void PWFrameBuffer::Private::onStreamFormatChanged(void *data, const struct spa_ // setup buffers and meta header for new format const struct spa_pod *params[2]; -#if PW_CHECK_VERSION(0, 2, 90) params[0] = reinterpret_cast(spa_pod_builder_add_object(&builder, SPA_TYPE_OBJECT_ParamBuffers, SPA_PARAM_Buffers, SPA_PARAM_BUFFERS_size, SPA_POD_Int(size), @@ -658,19 +515,6 @@ void PWFrameBuffer::Private::onStreamFormatChanged(void *data, const struct spa_ SPA_PARAM_META_type, SPA_POD_Id(SPA_META_Header), SPA_PARAM_META_size, SPA_POD_Int(sizeof(struct spa_meta_header)))); pw_stream_update_params(d->pwStream, params, 2); -#else - params[0] = reinterpret_cast(spa_pod_builder_object(&builder, - d->pwCoreType->param.idBuffers, d->pwCoreType->param_buffers.Buffers, - ":", d->pwCoreType->param_buffers.size, "i", size, - ":", d->pwCoreType->param_buffers.stride, "i", stride, - ":", d->pwCoreType->param_buffers.buffers, "iru", 8, SPA_POD_PROP_MIN_MAX(1, 32), - ":", d->pwCoreType->param_buffers.align, "i", 16)); - params[1] = reinterpret_cast(spa_pod_builder_object(&builder, - d->pwCoreType->param.idMeta, d->pwCoreType->param_meta.Meta, - ":", d->pwCoreType->param_meta.type, "I", d->pwCoreType->meta.Header, - ":", d->pwCoreType->param_meta.size, "i", sizeof(struct spa_meta_header))); - pw_stream_finish_format(d->pwStream, 0, params, 2); -#endif } /** @@ -692,7 +536,7 @@ void PWFrameBuffer::Private::onStreamProcess(void *data) pw_stream_queue_buffer(d->pwStream, buf); } -#if PW_CHECK_VERSION(0, 2, 90) && defined(HAVE_LINUX_DMABUF_H) +#if defined(HAVE_LINUX_DMABUF_H) static void syncDmaBuf(int fd, uint64_t start_or_end) { struct dma_buf_sync sync = { 0 }; @@ -718,17 +562,14 @@ void PWFrameBuffer::Private::handleFrame(pw_buffer *pwBuffer) auto *spaBuffer = pwBuffer->buffer; void *src = spaBuffer->datas[0].data; -#if PW_CHECK_VERSION(0, 2, 90) if (!src && spaBuffer->datas->type != SPA_DATA_DmaBuf) { qCDebug(KRFB_FB_PIPEWIRE) << "discarding null buffer"; return; } -#endif const quint32 maxSize = spaBuffer->datas[0].maxsize; std::function cleanup; -#if PW_CHECK_VERSION(0, 2, 90) #ifdef HAVE_LINUX_DMABUF_H if (spaBuffer->datas->type == SPA_DATA_DmaBuf) { const int fd = spaBuffer->datas[0].fd; @@ -764,7 +605,6 @@ void PWFrameBuffer::Private::handleFrame(pw_buffer *pwBuffer) munmap(map, spaBuffer->datas->maxsize + spaBuffer->datas->mapoffset); }; } -#endif const qint32 srcStride = spaBuffer->datas[0].chunk->stride; if (srcStride != q->paddedWidth()) { @@ -776,7 +616,6 @@ void PWFrameBuffer::Private::handleFrame(pw_buffer *pwBuffer) std::memcpy(q->fb, src, maxSize); cleanup(); -#if PW_CHECK_VERSION(0, 2, 90) if (videoFormat->format == SPA_VIDEO_FORMAT_BGRA || videoFormat->format == SPA_VIDEO_FORMAT_BGRx) { for (uint y = 0; y < videoFormat->size.height; y++) { for (uint x = 0; x < videoFormat->size.width; x++) { @@ -792,7 +631,6 @@ void PWFrameBuffer::Private::handleFrame(pw_buffer *pwBuffer) QImage img((uchar*) q->fb, videoFormat->size.width, videoFormat->size.height, spaBuffer->datas->chunk->stride, format); img.convertTo(QImage::Format_RGB888); } -#endif } /** @@ -808,23 +646,16 @@ pw_stream *PWFrameBuffer::Private::createReceivingStream() spa_fraction pwFramerateMin = SPA_FRACTION(0, 1); spa_fraction pwFramerateMax = SPA_FRACTION(60, 1); -#if PW_CHECK_VERSION(0, 2, 90) auto stream = pw_stream_new_simple(pw_thread_loop_get_loop(pwMainLoop), "krfb-fb-consume-stream", pw_properties_new(PW_KEY_MEDIA_TYPE, "Video", PW_KEY_MEDIA_CATEGORY, "Capture", PW_KEY_MEDIA_ROLE, "Screen", nullptr), &pwStreamEvents, this); - -#else - auto reuseProps = pw_properties_new("pipewire.client.reuse", "1", nullptr); // null marks end of varargs - auto stream = pw_stream_new(pwRemote, "krfb-fb-consume-stream", reuseProps); -#endif uint8_t buffer[1024] = {}; const spa_pod *params[1]; auto builder = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer)); -#if PW_CHECK_VERSION(0, 2, 90) params[0] = reinterpret_cast(spa_pod_builder_add_object(&builder, SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat, SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_video), @@ -836,24 +667,9 @@ pw_stream *PWFrameBuffer::Private::createReceivingStream() SPA_FORMAT_VIDEO_size, SPA_POD_CHOICE_RANGE_Rectangle(&pwMaxScreenBounds, &pwMinScreenBounds, &pwMaxScreenBounds), SPA_FORMAT_VIDEO_framerate, SPA_POD_Fraction(&pwFramerateMin), SPA_FORMAT_VIDEO_maxFramerate, SPA_POD_CHOICE_RANGE_Fraction(&pwFramerateMax, &pwFramerateMin, &pwFramerateMax))); -#else - params[0] = reinterpret_cast(spa_pod_builder_object(&builder, - pwCoreType->param.idEnumFormat, pwCoreType->spa_format, - "I", pwType->media_type.video, - "I", pwType->media_subtype.raw, - ":", pwType->format_video.format, "I", pwType->video_format.RGBx, - ":", pwType->format_video.size, "Rru", &pwMaxScreenBounds, SPA_POD_PROP_MIN_MAX(&pwMinScreenBounds, &pwMaxScreenBounds), - ":", pwType->format_video.framerate, "F", &pwFramerateMin, - ":", pwType->format_video.max_framerate, "Fru", &pwFramerateMax, 2, &pwFramerateMin, &pwFramerateMax)); - pw_stream_add_listener(stream, &streamListener, &pwStreamEvents, this); -#endif auto flags = static_cast(PW_STREAM_FLAG_AUTOCONNECT | PW_STREAM_FLAG_INACTIVE | PW_STREAM_FLAG_MAP_BUFFERS); -#if PW_CHECK_VERSION(0, 2, 90) if (pw_stream_connect(stream, PW_DIRECTION_INPUT, PW_ID_ANY, flags, params, 1) != 0) { -#else - if (pw_stream_connect(stream, PW_DIRECTION_INPUT, nullptr, flags, params, 1) != 0) { -#endif qCWarning(KRFB_FB_PIPEWIRE) << "Could not connect receiving stream"; isValid = false; } @@ -867,23 +683,10 @@ PWFrameBuffer::Private::~Private() pw_thread_loop_stop(pwMainLoop); } -#if !PW_CHECK_VERSION(0, 2, 9) - if (pwType) { - delete pwType; - } -#endif - if (pwStream) { pw_stream_destroy(pwStream); } -#if !PW_CHECK_VERSION(0, 2, 90) - if (pwRemote) { - pw_remote_destroy(pwRemote); - } -#endif - -#if PW_CHECK_VERSION(0, 2, 90) if (pwCore) { pw_core_disconnect(pwCore); } @@ -891,22 +694,10 @@ PWFrameBuffer::Private::~Private() if (pwContext) { pw_context_destroy(pwContext); } -#else - if (pwCore) { - pw_core_destroy(pwCore); - } -#endif if (pwMainLoop) { pw_thread_loop_destroy(pwMainLoop); } - -#if !PW_CHECK_VERSION(0, 2, 90) - if (pwLoop) { - pw_loop_leave(pwLoop); - pw_loop_destroy(pwLoop); - } -#endif } PWFrameBuffer::PWFrameBuffer(WId winid, QObject *parent)