pipewire: add support for 0.3 API

Fixes: #369

Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
dev
James Hilliard 4 years ago committed by Daniel Stone
parent c4076ef88a
commit 80b585f8d2
  1. 2
      .gitlab-ci.yml
  2. 16
      .gitlab-ci/debian-install.sh
  3. 26
      pipewire/meson.build
  4. 118
      pipewire/pipewire-plugin.c

@ -20,7 +20,7 @@ stages:
variables: variables:
FDO_DISTRIBUTION_VERSION: buster FDO_DISTRIBUTION_VERSION: buster
FDO_DISTRIBUTION_EXEC: 'bash .gitlab-ci/debian-install.sh' FDO_DISTRIBUTION_EXEC: 'bash .gitlab-ci/debian-install.sh'
FDO_DISTRIBUTION_TAG: '2020-06-24.0' FDO_DISTRIBUTION_TAG: '2020-08-17.0'
container_prep: container_prep:

@ -38,6 +38,8 @@ apt-get -y --no-install-recommends install \
doxygen \ doxygen \
freerdp2-dev \ freerdp2-dev \
git \ git \
libasound2-dev \
libbluetooth-dev \
libcairo2-dev \ libcairo2-dev \
libcolord-dev \ libcolord-dev \
libdbus-1-dev \ libdbus-1-dev \
@ -52,20 +54,23 @@ apt-get -y --no-install-recommends install \
libgstreamer1.0-dev \ libgstreamer1.0-dev \
libgstreamer-plugins-base1.0-dev \ libgstreamer-plugins-base1.0-dev \
libinput-dev \ libinput-dev \
libjack-jackd2-dev \
libjpeg-dev \ libjpeg-dev \
libjpeg-dev \ libjpeg-dev \
liblcms2-dev \ liblcms2-dev \
libmtdev-dev \ libmtdev-dev \
libpam0g-dev \ libpam0g-dev \
libpango1.0-dev \ libpango1.0-dev \
libpipewire-0.2-dev \
libpixman-1-dev \ libpixman-1-dev \
libpng-dev \ libpng-dev \
libpulse-dev \
libsbc-dev \
libsystemd-dev \ libsystemd-dev \
libtool \ libtool \
libudev-dev \ libudev-dev \
libva-dev \ libva-dev \
libvpx-dev \ libvpx-dev \
libvulkan-dev \
libwayland-dev \ libwayland-dev \
libwebp-dev \ libwebp-dev \
libx11-dev \ libx11-dev \
@ -146,5 +151,14 @@ ninja -C build install
cd .. cd ..
rm -rf mesa rm -rf mesa
rm -rf pipewire
git clone --single-branch --branch master https://gitlab.freedesktop.org/pipewire/pipewire.git pipewire
cd pipewire
git checkout -b snapshot db12f47505ddccb257acdc0fa2bb884aceb1b593
meson build
ninja -C build install
cd ..
rm -rf pipewire
apt-get -y --autoremove purge $LINUX_DEV_PKGS apt-get -y --autoremove purge $LINUX_DEV_PKGS
apt-get -y --autoremove purge $MESA_DEV_PKGS apt-get -y --autoremove purge $MESA_DEV_PKGS

@ -5,17 +5,25 @@ if get_option('pipewire')
error('Attempting to build the pipewire plugin without the required DRM backend. ' + user_hint) error('Attempting to build the pipewire plugin without the required DRM backend. ' + user_hint)
endif endif
depnames = [
'libpipewire-0.2', 'libspa-0.1'
]
deps_pipewire = [ dep_libweston_private ] deps_pipewire = [ dep_libweston_private ]
foreach depname : depnames
dep = dependency(depname, required: false) dep_libpipewire = dependency('libpipewire-0.3', required: false)
if not dep.found() if not dep_libpipewire.found()
error('Pipewire plugin requires @0@ which was not found. '.format(depname) + user_hint) dep_libpipewire = dependency('libpipewire-0.2', required: false)
endif
if not dep_libpipewire.found()
error('Pipewire plugin requires libpipewire which was not found. ' + user_hint)
endif
deps_pipewire += dep_libpipewire
dep_libspa = dependency('libspa-0.2', required: false)
if not dep_libspa.found()
dep_libspa = dependency('libspa-0.1', required: false)
endif
if not dep_libspa.found()
error('Pipewire plugin requires libspa which was not found. ' + user_hint)
endif endif
deps_pipewire += dep deps_pipewire += dep_libspa
endforeach
plugin_pipewire = shared_library( plugin_pipewire = shared_library(
'pipewire-plugin', 'pipewire-plugin',

@ -34,20 +34,27 @@
#include <errno.h> #include <errno.h>
#include <unistd.h> #include <unistd.h>
#include <pipewire/pipewire.h>
#include <spa/param/format-utils.h> #include <spa/param/format-utils.h>
#include <spa/param/video/format-utils.h> #include <spa/param/video/format-utils.h>
#include <spa/utils/defs.h> #include <spa/utils/defs.h>
#include <pipewire/pipewire.h> #if PW_CHECK_VERSION(0, 2, 90)
#include <spa/buffer/meta.h>
#include <spa/utils/result.h>
#endif
#define PROP_RANGE(min, max) 2, (min), (max) #define PROP_RANGE(min, max) 2, (min), (max)
#if !PW_CHECK_VERSION(0, 2, 90)
struct type { struct type {
struct spa_type_media_type media_type; struct spa_type_media_type media_type;
struct spa_type_media_subtype media_subtype; struct spa_type_media_subtype media_subtype;
struct spa_type_format_video format_video; struct spa_type_format_video format_video;
struct spa_type_video_format video_format; struct spa_type_video_format video_format;
}; };
#endif
struct weston_pipewire { struct weston_pipewire {
struct weston_compositor *compositor; struct weston_compositor *compositor;
@ -60,12 +67,19 @@ struct weston_pipewire {
struct pw_loop *loop; struct pw_loop *loop;
struct wl_event_source *loop_source; struct wl_event_source *loop_source;
#if PW_CHECK_VERSION(0, 2, 90)
struct pw_context *context;
#endif
struct pw_core *core; struct pw_core *core;
struct pw_type *t; struct pw_type *t;
#if PW_CHECK_VERSION(0, 2, 90)
struct spa_hook core_listener;
#else
struct type type; struct type type;
struct pw_remote *remote; struct pw_remote *remote;
struct spa_hook remote_listener; struct spa_hook remote_listener;
#endif
}; };
struct pipewire_output { struct pipewire_output {
@ -100,6 +114,7 @@ struct pipewire_frame_data {
struct wl_event_source *fence_sync_event_source; struct wl_event_source *fence_sync_event_source;
}; };
#if !PW_CHECK_VERSION(0, 2, 90)
static inline void init_type(struct type *type, struct spa_type_map *map) static inline void init_type(struct type *type, struct spa_type_map *map)
{ {
spa_type_media_type_map(map, &type->media_type); spa_type_media_type_map(map, &type->media_type);
@ -107,6 +122,7 @@ static inline void init_type(struct type *type, struct spa_type_map *map)
spa_type_format_video_map(map, &type->format_video); spa_type_format_video_map(map, &type->format_video);
spa_type_video_format_map(map, &type->video_format); spa_type_video_format_map(map, &type->video_format);
} }
#endif
static void static void
pipewire_debug_impl(struct weston_pipewire *pipewire, pipewire_debug_impl(struct weston_pipewire *pipewire,
@ -141,6 +157,7 @@ pipewire_debug_impl(struct weston_pipewire *pipewire,
free(logstr); free(logstr);
} }
#if !PW_CHECK_VERSION(0, 2, 90)
static void static void
pipewire_debug(struct weston_pipewire *pipewire, const char *fmt, ...) pipewire_debug(struct weston_pipewire *pipewire, const char *fmt, ...)
{ {
@ -150,6 +167,7 @@ pipewire_debug(struct weston_pipewire *pipewire, const char *fmt, ...)
pipewire_debug_impl(pipewire, NULL, fmt, ap); pipewire_debug_impl(pipewire, NULL, fmt, ap);
va_end(ap); va_end(ap);
} }
#endif
static void static void
pipewire_output_debug(struct pipewire_output *output, const char *fmt, ...) pipewire_output_debug(struct pipewire_output *output, const char *fmt, ...)
@ -185,7 +203,9 @@ pipewire_output_handle_frame(struct pipewire_output *output, int fd,
const struct weston_drm_virtual_output_api *api = const struct weston_drm_virtual_output_api *api =
output->pipewire->virtual_output_api; output->pipewire->virtual_output_api;
size_t size = output->output->height * stride; size_t size = output->output->height * stride;
#if !PW_CHECK_VERSION(0, 2, 90)
struct pw_type *t = output->pipewire->t; struct pw_type *t = output->pipewire->t;
#endif
struct pw_buffer *buffer; struct pw_buffer *buffer;
struct spa_buffer *spa_buffer; struct spa_buffer *spa_buffer;
struct spa_meta_header *h; struct spa_meta_header *h;
@ -203,7 +223,12 @@ pipewire_output_handle_frame(struct pipewire_output *output, int fd,
spa_buffer = buffer->buffer; spa_buffer = buffer->buffer;
#if PW_CHECK_VERSION(0, 2, 90)
if ((h = spa_buffer_find_meta_data(spa_buffer, SPA_META_Header,
sizeof(struct spa_meta_header)))) {
#else
if ((h = spa_buffer_find_meta(spa_buffer, t->meta.Header))) { if ((h = spa_buffer_find_meta(spa_buffer, t->meta.Header))) {
#endif
h->pts = -1; h->pts = -1;
h->flags = 0; h->flags = 0;
h->seq = output->seq++; h->seq = output->seq++;
@ -375,18 +400,40 @@ pipewire_set_dpms(struct weston_output *base_output, enum dpms_enum level)
static int static int
pipewire_output_connect(struct pipewire_output *output) pipewire_output_connect(struct pipewire_output *output)
{ {
#if !PW_CHECK_VERSION(0, 2, 90)
struct weston_pipewire *pipewire = output->pipewire; struct weston_pipewire *pipewire = output->pipewire;
struct type *type = &pipewire->type; struct type *type = &pipewire->type;
#endif
uint8_t buffer[1024]; uint8_t buffer[1024];
struct spa_pod_builder builder = struct spa_pod_builder builder =
SPA_POD_BUILDER_INIT(buffer, sizeof(buffer)); SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
const struct spa_pod *params[1]; const struct spa_pod *params[1];
#if !PW_CHECK_VERSION(0, 2, 90)
struct pw_type *t = pipewire->t; struct pw_type *t = pipewire->t;
#endif
int frame_rate = output->output->current_mode->refresh / 1000; int frame_rate = output->output->current_mode->refresh / 1000;
int width = output->output->width; int width = output->output->width;
int height = output->output->height; int height = output->output->height;
int ret; int ret;
#if PW_CHECK_VERSION(0, 2, 90)
params[0] = spa_pod_builder_add_object(&builder,
SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat,
SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_video),
SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw),
SPA_FORMAT_VIDEO_format, SPA_POD_Id(SPA_VIDEO_FORMAT_BGRx),
SPA_FORMAT_VIDEO_size, SPA_POD_Rectangle(&SPA_RECTANGLE(width, height)),
SPA_FORMAT_VIDEO_framerate, SPA_POD_Fraction(&SPA_FRACTION (0, 1)),
SPA_FORMAT_VIDEO_maxFramerate,
SPA_POD_CHOICE_RANGE_Fraction(&SPA_FRACTION(frame_rate, 1),
&SPA_FRACTION(1, 1),
&SPA_FRACTION(frame_rate, 1)));
ret = pw_stream_connect(output->stream, PW_DIRECTION_OUTPUT, SPA_ID_INVALID,
(PW_STREAM_FLAG_DRIVER |
PW_STREAM_FLAG_MAP_BUFFERS),
params, 1);
#else
params[0] = spa_pod_builder_object(&builder, params[0] = spa_pod_builder_object(&builder,
t->param.idEnumFormat, t->spa_format, t->param.idEnumFormat, t->spa_format,
"I", type->media_type.video, "I", type->media_type.video,
@ -406,6 +453,7 @@ pipewire_output_connect(struct pipewire_output *output)
(PW_STREAM_FLAG_DRIVER | (PW_STREAM_FLAG_DRIVER |
PW_STREAM_FLAG_MAP_BUFFERS), PW_STREAM_FLAG_MAP_BUFFERS),
params, 1); params, 1);
#endif
if (ret != 0) { if (ret != 0) {
weston_log("Failed to connect pipewire stream: %s", weston_log("Failed to connect pipewire stream: %s",
spa_strerror(ret)); spa_strerror(ret));
@ -482,26 +530,42 @@ pipewire_output_stream_state_changed(void *data, enum pw_stream_state old,
} }
static void static void
#if PW_CHECK_VERSION(0, 2, 90)
pipewire_output_stream_param_changed(void *data, uint32_t id, const struct spa_pod *format)
#else
pipewire_output_stream_format_changed(void *data, const struct spa_pod *format) pipewire_output_stream_format_changed(void *data, const struct spa_pod *format)
#endif
{ {
struct pipewire_output *output = data; struct pipewire_output *output = data;
#if !PW_CHECK_VERSION(0, 2, 90)
struct weston_pipewire *pipewire = output->pipewire; struct weston_pipewire *pipewire = output->pipewire;
#endif
uint8_t buffer[1024]; uint8_t buffer[1024];
struct spa_pod_builder builder = struct spa_pod_builder builder =
SPA_POD_BUILDER_INIT(buffer, sizeof(buffer)); SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
const struct spa_pod *params[2]; const struct spa_pod *params[2];
#if !PW_CHECK_VERSION(0, 2, 90)
struct pw_type *t = pipewire->t; struct pw_type *t = pipewire->t;
#endif
int32_t width, height, stride, size; int32_t width, height, stride, size;
const int bpp = 4; const int bpp = 4;
if (!format) { if (!format) {
pipewire_output_debug(output, "format = None"); pipewire_output_debug(output, "format = None");
#if PW_CHECK_VERSION(0, 2, 90)
pw_stream_update_params(output->stream, NULL, 0);
#else
pw_stream_finish_format(output->stream, 0, NULL, 0); pw_stream_finish_format(output->stream, 0, NULL, 0);
#endif
return; return;
} }
#if PW_CHECK_VERSION(0, 2, 90)
spa_format_video_raw_parse(format, &output->video_format);
#else
spa_format_video_raw_parse(format, &output->video_format, spa_format_video_raw_parse(format, &output->video_format,
&pipewire->type.format_video); &pipewire->type.format_video);
#endif
width = output->video_format.size.width; width = output->video_format.size.width;
height = output->video_format.size.height; height = output->video_format.size.height;
@ -510,6 +574,21 @@ pipewire_output_stream_format_changed(void *data, const struct spa_pod *format)
pipewire_output_debug(output, "format = %dx%d", width, height); pipewire_output_debug(output, "format = %dx%d", width, height);
#if PW_CHECK_VERSION(0, 2, 90)
params[0] = spa_pod_builder_add_object(&builder,
SPA_TYPE_OBJECT_ParamBuffers, SPA_PARAM_Buffers,
SPA_PARAM_BUFFERS_size, SPA_POD_Int(size),
SPA_PARAM_BUFFERS_stride, SPA_POD_Int(stride),
SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(4, 2, 8),
SPA_PARAM_BUFFERS_align, SPA_POD_Int(16));
params[1] = spa_pod_builder_add_object(&builder,
SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta,
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(output->stream, params, 2);
#else
params[0] = spa_pod_builder_object(&builder, params[0] = spa_pod_builder_object(&builder,
t->param.idBuffers, t->param_buffers.Buffers, t->param.idBuffers, t->param_buffers.Buffers,
":", t->param_buffers.size, ":", t->param_buffers.size,
@ -527,12 +606,17 @@ pipewire_output_stream_format_changed(void *data, const struct spa_pod *format)
":", t->param_meta.size, "i", sizeof(struct spa_meta_header)); ":", t->param_meta.size, "i", sizeof(struct spa_meta_header));
pw_stream_finish_format(output->stream, 0, params, 2); pw_stream_finish_format(output->stream, 0, params, 2);
#endif
} }
static const struct pw_stream_events stream_events = { static const struct pw_stream_events stream_events = {
PW_VERSION_STREAM_EVENTS, PW_VERSION_STREAM_EVENTS,
.state_changed = pipewire_output_stream_state_changed, .state_changed = pipewire_output_stream_state_changed,
#if PW_CHECK_VERSION(0, 2, 90)
.param_changed = pipewire_output_stream_param_changed,
#else
.format_changed = pipewire_output_stream_format_changed, .format_changed = pipewire_output_stream_format_changed,
#endif
}; };
static struct weston_output * static struct weston_output *
@ -560,7 +644,11 @@ pipewire_output_create(struct weston_compositor *c, char *name)
if (!head) if (!head)
goto err; goto err;
#if PW_CHECK_VERSION(0, 2, 90)
output->stream = pw_stream_new(pipewire->core, name, NULL);
#else
output->stream = pw_stream_new(pipewire->remote, name, NULL); output->stream = pw_stream_new(pipewire->remote, name, NULL);
#endif
if (!output->stream) { if (!output->stream) {
weston_log("Cannot initialize pipewire stream\n"); weston_log("Cannot initialize pipewire stream\n");
goto err; goto err;
@ -704,6 +792,14 @@ weston_pipewire_loop_handler(int fd, uint32_t mask, void *data)
return 0; return 0;
} }
#if PW_CHECK_VERSION(0, 2, 90)
static void
weston_pipewire_error(void *data, uint32_t id, int seq, int res,
const char *error)
{
weston_log("pipewire remote error: %s\n", error);
}
#else
static void static void
weston_pipewire_state_changed(void *data, enum pw_remote_state old, weston_pipewire_state_changed(void *data, enum pw_remote_state old,
enum pw_remote_state state, const char *error) enum pw_remote_state state, const char *error)
@ -725,12 +821,20 @@ weston_pipewire_state_changed(void *data, enum pw_remote_state old,
break; break;
} }
} }
#endif
#if PW_CHECK_VERSION(0, 2, 90)
static const struct pw_core_events core_events = {
PW_VERSION_CORE_EVENTS,
.error = weston_pipewire_error,
};
#else
static const struct pw_remote_events remote_events = { static const struct pw_remote_events remote_events = {
PW_VERSION_REMOTE_EVENTS, PW_VERSION_REMOTE_EVENTS,
.state_changed = weston_pipewire_state_changed, .state_changed = weston_pipewire_state_changed,
}; };
#endif
static int static int
weston_pipewire_init(struct weston_pipewire *pipewire) weston_pipewire_init(struct weston_pipewire *pipewire)
@ -745,10 +849,19 @@ weston_pipewire_init(struct weston_pipewire *pipewire)
pw_loop_enter(pipewire->loop); pw_loop_enter(pipewire->loop);
#if PW_CHECK_VERSION(0, 2, 90)
pipewire->context = pw_context_new(pipewire->loop, NULL, 0);
#else
pipewire->core = pw_core_new(pipewire->loop, NULL); pipewire->core = pw_core_new(pipewire->loop, NULL);
pipewire->t = pw_core_get_type(pipewire->core); pipewire->t = pw_core_get_type(pipewire->core);
init_type(&pipewire->type, pipewire->t->map); init_type(&pipewire->type, pipewire->t->map);
#endif
#if PW_CHECK_VERSION(0, 2, 90)
pw_core_add_listener(pipewire->core,
&pipewire->core_listener,
&core_events, pipewire);
#else
pipewire->remote = pw_remote_new(pipewire->core, NULL, 0); pipewire->remote = pw_remote_new(pipewire->core, NULL, 0);
pw_remote_add_listener(pipewire->remote, pw_remote_add_listener(pipewire->remote,
&pipewire->remote_listener, &pipewire->remote_listener,
@ -777,6 +890,7 @@ weston_pipewire_init(struct weston_pipewire *pipewire)
goto err; goto err;
} }
} }
#endif
loop = wl_display_get_event_loop(pipewire->compositor->wl_display); loop = wl_display_get_event_loop(pipewire->compositor->wl_display);
pipewire->loop_source = pipewire->loop_source =
@ -786,12 +900,14 @@ weston_pipewire_init(struct weston_pipewire *pipewire)
pipewire); pipewire);
return 0; return 0;
#if !PW_CHECK_VERSION(0, 2, 90)
err: err:
if (pipewire->remote) if (pipewire->remote)
pw_remote_destroy(pipewire->remote); pw_remote_destroy(pipewire->remote);
pw_loop_leave(pipewire->loop); pw_loop_leave(pipewire->loop);
pw_loop_destroy(pipewire->loop); pw_loop_destroy(pipewire->loop);
return -1; return -1;
#endif
} }
static const struct weston_pipewire_api pipewire_api = { static const struct weston_pipewire_api pipewire_api = {

Loading…
Cancel
Save