| From cc08737e3fd174ec3c4c208ea4f2a3a6a9e8af3e Mon Sep 17 00:00:00 2001 |
| From: James Hilliard <james.hilliard1@gmail.com> |
| Date: Mon, 6 Jul 2020 00:58:02 -0600 |
| Subject: [PATCH] pipewire: add support for 0.3 API |
| |
| Fixes: #369 |
| |
| Signed-off-by: James Hilliard <james.hilliard1@gmail.com> |
| [james.hilliard1@gmail.com: backport from upstream commit |
| 80b585f8d2a31e780b4de41fbd187a742bea7e1a] |
| --- |
| .gitlab-ci.yml | 2 +- |
| .gitlab-ci/debian-install.sh | 16 ++++- |
| pipewire/meson.build | 28 ++++++--- |
| pipewire/pipewire-plugin.c | 118 ++++++++++++++++++++++++++++++++++- |
| 4 files changed, 151 insertions(+), 13 deletions(-) |
| |
| diff --git a/pipewire/meson.build b/pipewire/meson.build |
| index 3d3374b8..e30a0b62 100644 |
| --- a/pipewire/meson.build |
| +++ b/pipewire/meson.build |
| @@ -5,17 +5,25 @@ if get_option('pipewire') |
| error('Attempting to build the pipewire plugin without the required DRM backend. ' + user_hint) |
| endif |
| |
| - depnames = [ |
| - 'libpipewire-0.2', 'libspa-0.1' |
| - ] |
| deps_pipewire = [ dep_libweston_private ] |
| - foreach depname : depnames |
| - dep = dependency(depname, required: false) |
| - if not dep.found() |
| - error('Pipewire plugin requires @0@ which was not found. '.format(depname) + user_hint) |
| - endif |
| - deps_pipewire += dep |
| - endforeach |
| + |
| + dep_libpipewire = dependency('libpipewire-0.3', required: false) |
| + if not dep_libpipewire.found() |
| + 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 |
| + deps_pipewire += dep_libspa |
| |
| plugin_pipewire = shared_library( |
| 'pipewire-plugin', |
| diff --git a/pipewire/pipewire-plugin.c b/pipewire/pipewire-plugin.c |
| index 6f892574..ce70ea63 100644 |
| --- a/pipewire/pipewire-plugin.c |
| +++ b/pipewire/pipewire-plugin.c |
| @@ -34,20 +34,27 @@ |
| #include <errno.h> |
| #include <unistd.h> |
| |
| +#include <pipewire/pipewire.h> |
| + |
| #include <spa/param/format-utils.h> |
| #include <spa/param/video/format-utils.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) |
| |
| +#if !PW_CHECK_VERSION(0, 2, 90) |
| struct type { |
| struct spa_type_media_type media_type; |
| struct spa_type_media_subtype media_subtype; |
| struct spa_type_format_video format_video; |
| struct spa_type_video_format video_format; |
| }; |
| +#endif |
| |
| struct weston_pipewire { |
| struct weston_compositor *compositor; |
| @@ -60,12 +67,19 @@ struct weston_pipewire { |
| struct pw_loop *loop; |
| struct wl_event_source *loop_source; |
| |
| +#if PW_CHECK_VERSION(0, 2, 90) |
| + struct pw_context *context; |
| +#endif |
| struct pw_core *core; |
| struct pw_type *t; |
| +#if PW_CHECK_VERSION(0, 2, 90) |
| + struct spa_hook core_listener; |
| +#else |
| struct type type; |
| |
| struct pw_remote *remote; |
| struct spa_hook remote_listener; |
| +#endif |
| }; |
| |
| struct pipewire_output { |
| @@ -100,6 +114,7 @@ struct pipewire_frame_data { |
| 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) |
| { |
| 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_video_format_map(map, &type->video_format); |
| } |
| +#endif |
| |
| static void |
| pipewire_debug_impl(struct weston_pipewire *pipewire, |
| @@ -141,6 +157,7 @@ pipewire_debug_impl(struct weston_pipewire *pipewire, |
| free(logstr); |
| } |
| |
| +#if !PW_CHECK_VERSION(0, 2, 90) |
| static void |
| 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); |
| va_end(ap); |
| } |
| +#endif |
| |
| static void |
| 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 = |
| output->pipewire->virtual_output_api; |
| size_t size = output->output->height * stride; |
| +#if !PW_CHECK_VERSION(0, 2, 90) |
| struct pw_type *t = output->pipewire->t; |
| +#endif |
| struct pw_buffer *buffer; |
| struct spa_buffer *spa_buffer; |
| struct spa_meta_header *h; |
| @@ -203,7 +223,12 @@ pipewire_output_handle_frame(struct pipewire_output *output, int fd, |
| |
| 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))) { |
| +#endif |
| h->pts = -1; |
| h->flags = 0; |
| h->seq = output->seq++; |
| @@ -375,18 +400,40 @@ pipewire_set_dpms(struct weston_output *base_output, enum dpms_enum level) |
| static int |
| pipewire_output_connect(struct pipewire_output *output) |
| { |
| +#if !PW_CHECK_VERSION(0, 2, 90) |
| struct weston_pipewire *pipewire = output->pipewire; |
| struct type *type = &pipewire->type; |
| +#endif |
| uint8_t buffer[1024]; |
| struct spa_pod_builder builder = |
| SPA_POD_BUILDER_INIT(buffer, sizeof(buffer)); |
| const struct spa_pod *params[1]; |
| +#if !PW_CHECK_VERSION(0, 2, 90) |
| struct pw_type *t = pipewire->t; |
| +#endif |
| int frame_rate = output->output->current_mode->refresh / 1000; |
| int width = output->output->width; |
| int height = output->output->height; |
| 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, |
| t->param.idEnumFormat, t->spa_format, |
| "I", type->media_type.video, |
| @@ -406,6 +453,7 @@ pipewire_output_connect(struct pipewire_output *output) |
| (PW_STREAM_FLAG_DRIVER | |
| PW_STREAM_FLAG_MAP_BUFFERS), |
| params, 1); |
| +#endif |
| if (ret != 0) { |
| weston_log("Failed to connect pipewire stream: %s", |
| spa_strerror(ret)); |
| @@ -482,26 +530,42 @@ pipewire_output_stream_state_changed(void *data, enum pw_stream_state old, |
| } |
| |
| 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) |
| +#endif |
| { |
| struct pipewire_output *output = data; |
| +#if !PW_CHECK_VERSION(0, 2, 90) |
| struct weston_pipewire *pipewire = output->pipewire; |
| +#endif |
| uint8_t buffer[1024]; |
| struct spa_pod_builder builder = |
| SPA_POD_BUILDER_INIT(buffer, sizeof(buffer)); |
| const struct spa_pod *params[2]; |
| +#if !PW_CHECK_VERSION(0, 2, 90) |
| struct pw_type *t = pipewire->t; |
| +#endif |
| int32_t width, height, stride, size; |
| const int bpp = 4; |
| |
| if (!format) { |
| 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); |
| +#endif |
| 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, |
| &pipewire->type.format_video); |
| +#endif |
| |
| width = output->video_format.size.width; |
| 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); |
| |
| +#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, |
| t->param.idBuffers, t->param_buffers.Buffers, |
| ":", 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)); |
| |
| pw_stream_finish_format(output->stream, 0, params, 2); |
| +#endif |
| } |
| |
| static const struct pw_stream_events stream_events = { |
| PW_VERSION_STREAM_EVENTS, |
| .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, |
| +#endif |
| }; |
| |
| static struct weston_output * |
| @@ -560,7 +644,11 @@ pipewire_output_create(struct weston_compositor *c, char *name) |
| if (!head) |
| 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); |
| +#endif |
| if (!output->stream) { |
| weston_log("Cannot initialize pipewire stream\n"); |
| goto err; |
| @@ -704,6 +792,14 @@ weston_pipewire_loop_handler(int fd, uint32_t mask, void *data) |
| 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 |
| weston_pipewire_state_changed(void *data, enum pw_remote_state old, |
| enum pw_remote_state state, const char *error) |
| @@ -725,12 +821,20 @@ weston_pipewire_state_changed(void *data, enum pw_remote_state old, |
| 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 = { |
| PW_VERSION_REMOTE_EVENTS, |
| .state_changed = weston_pipewire_state_changed, |
| }; |
| +#endif |
| |
| static int |
| weston_pipewire_init(struct weston_pipewire *pipewire) |
| @@ -745,10 +849,19 @@ weston_pipewire_init(struct weston_pipewire *pipewire) |
| |
| 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->t = pw_core_get_type(pipewire->core); |
| 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); |
| pw_remote_add_listener(pipewire->remote, |
| &pipewire->remote_listener, |
| @@ -777,6 +890,7 @@ weston_pipewire_init(struct weston_pipewire *pipewire) |
| goto err; |
| } |
| } |
| +#endif |
| |
| loop = wl_display_get_event_loop(pipewire->compositor->wl_display); |
| pipewire->loop_source = |
| @@ -786,12 +900,14 @@ weston_pipewire_init(struct weston_pipewire *pipewire) |
| pipewire); |
| |
| return 0; |
| +#if !PW_CHECK_VERSION(0, 2, 90) |
| err: |
| if (pipewire->remote) |
| pw_remote_destroy(pipewire->remote); |
| pw_loop_leave(pipewire->loop); |
| pw_loop_destroy(pipewire->loop); |
| return -1; |
| +#endif |
| } |
| |
| static const struct weston_pipewire_api pipewire_api = { |
| -- |
| 2.25.1 |
| |