From 18dc92eac270a50fb40607602352efb4d3db8207 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Tue, 14 Jan 2020 09:37:09 +0100 Subject: [PATCH] PipeWire: update to 0.3 API (cherry picked from commit a38901e5e7f835efe7b7a06c55790c8c20bc91a2) --- configure.ac | 2 +- src/camera.c | 24 ++++---- src/pipewire.c | 141 +++++++++++++--------------------------------- src/pipewire.h | 10 ++-- src/screen-cast.c | 98 ++++++-------------------------- 5 files changed, 72 insertions(+), 203 deletions(-) diff --git a/configure.ac b/configure.ac index 89902fa..62d7960 100644 --- a/configure.ac +++ b/configure.ac @@ -97,7 +97,7 @@ AC_ARG_ENABLE(pipewire, [AS_HELP_STRING([--enable-pipewire],[Enable PipeWire support. Needed for screen cast portal])], enable_pipewire=$enableval, enable_pipewire=yes) if test x$enable_pipewire = xyes ; then - PKG_CHECK_MODULES(PIPEWIRE, [libpipewire-0.2 >= 0.2.6]) + PKG_CHECK_MODULES(PIPEWIRE, [libpipewire-0.3 >= 0.2.90]) AC_DEFINE([HAVE_PIPEWIRE],[1], [Define to enable PipeWire support]) fi AM_CONDITIONAL([HAVE_PIPEWIRE],[test "$enable_pipewire" = "yes"]) diff --git a/src/camera.c b/src/camera.c index c2b392c..20fe3aa 100644 --- a/src/camera.c +++ b/src/camera.c @@ -141,7 +141,7 @@ open_pipewire_camera_remote (const char *app_id, GError **error) { PipeWireRemote *remote; - struct spa_dict_item permission_items[1]; + struct pw_permission permission_items[2]; struct pw_properties *pipewire_properties; pipewire_properties = @@ -158,12 +158,12 @@ open_pipewire_camera_remote (const char *app_id, * Hide all existing and future nodes by default. PipeWire will use the * permission store to set up permissions. */ - permission_items[0].key = PW_CORE_PROXY_PERMISSIONS_DEFAULT; - permission_items[0].value = "---"; + permission_items[0] = PW_PERMISSION_INIT (PW_ID_CORE, PW_PERM_RWX); + permission_items[1] = PW_PERMISSION_INIT (PW_ID_ANY, 0); - pw_core_proxy_permissions (pw_remote_get_core_proxy (remote->remote), - &SPA_DICT_INIT (permission_items, - G_N_ELEMENTS (permission_items))); + pw_client_update_permissions (pw_core_get_client(remote->core), + G_N_ELEMENTS (permission_items), + permission_items); pipewire_remote_roundtrip (remote); @@ -219,7 +219,7 @@ handle_open_pipewire_remote (XdpCamera *object, } out_fd_list = g_unix_fd_list_new (); - fd = pw_remote_steal_fd (remote->remote); + fd = pw_core_steal_fd (remote->core); fd_id = g_unix_fd_list_append (out_fd_list, fd, &error); close (fd); pipewire_remote_destroy (remote); @@ -250,29 +250,28 @@ camera_iface_init (XdpCameraIface *iface) static void global_added_cb (PipeWireRemote *remote, uint32_t id, - uint32_t type, + const char *type, const struct spa_dict *props, gpointer user_data) { Camera *camera = user_data; - struct pw_type *core_type = pw_core_get_type (remote->core); const struct spa_dict_item *media_class; const struct spa_dict_item *media_role; - if (type != core_type->node) + if (strcmp(type, PW_TYPE_INTERFACE_Node) != 0) return; if (!props) return; - media_class = spa_dict_lookup_item (props, "media.class"); + media_class = spa_dict_lookup_item (props, PW_KEY_MEDIA_CLASS); if (!media_class) return; if (g_strcmp0 (media_class->value, "Video/Source") != 0) return; - media_role = spa_dict_lookup_item (props, "media.role"); + media_role = spa_dict_lookup_item (props, PW_KEY_MEDIA_ROLE); if (!media_role) return; @@ -342,6 +341,7 @@ create_pipewire_remote (Camera *camera, } pipewire_properties = pw_properties_new ("pipewire.access.portal.is_portal", "true", + "portal.monitor", "Camera", NULL); camera->pipewire_remote = pipewire_remote_new_sync (pipewire_properties, global_added_cb, diff --git a/src/pipewire.c b/src/pipewire.c index 793a378..162cd55 100644 --- a/src/pipewire.c +++ b/src/pipewire.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "pipewire.h" @@ -36,27 +37,25 @@ static gboolean is_pipewire_initialized = FALSE; static void registry_event_global (void *user_data, uint32_t id, - uint32_t parent_id, uint32_t permissions, - uint32_t type, + const char *type, uint32_t version, const struct spa_dict *props) { PipeWireRemote *remote = user_data; - struct pw_type *core_type = pw_core_get_type (remote->core); const struct spa_dict_item *factory_object_type; PipeWireGlobal *global; global = g_new0 (PipeWireGlobal, 1); *global = (PipeWireGlobal) { - .parent_id = parent_id, + .parent_id = id, }; g_hash_table_insert (remote->globals, GINT_TO_POINTER (id), global); if (remote->global_added_cb) remote->global_added_cb (remote, id, type, props, remote->user_data); - if (type != core_type->factory) + if (strcmp(type, PW_TYPE_INTERFACE_Factory) != 0) return; factory_object_type = spa_dict_lookup_item (props, "factory.type.name"); @@ -81,8 +80,8 @@ registry_event_global_remove (void *user_data, g_hash_table_remove (remote->globals, GINT_TO_POINTER (id)); } -static const struct pw_registry_proxy_events registry_events = { - PW_VERSION_REGISTRY_PROXY_EVENTS, +static const struct pw_registry_events registry_events = { + PW_VERSION_REGISTRY_EVENTS, .global = registry_event_global, .global_remove = registry_event_global_remove, }; @@ -90,7 +89,7 @@ static const struct pw_registry_proxy_events registry_events = { void pipewire_remote_roundtrip (PipeWireRemote *remote) { - pw_core_proxy_sync (remote->core_proxy, ++remote->sync_seq); + remote->sync_seq = pw_core_sync (remote->core, PW_ID_CORE, remote->sync_seq); pw_main_loop_run (remote->loop); } @@ -98,16 +97,13 @@ static gboolean discover_node_factory_sync (PipeWireRemote *remote, GError **error) { - struct pw_type *core_type = pw_core_get_type (remote->core); - struct pw_registry_proxy *registry_proxy; + struct pw_registry *registry; - registry_proxy = pw_core_proxy_get_registry (remote->core_proxy, - core_type->registry, - PW_VERSION_REGISTRY, 0); - pw_registry_proxy_add_listener (registry_proxy, - &remote->registry_listener, - ®istry_events, - remote); + registry = pw_core_get_registry (remote->core, PW_VERSION_REGISTRY, 0); + pw_registry_add_listener (registry, + &remote->registry_listener, + ®istry_events, + remote); pipewire_remote_roundtrip (remote); @@ -122,59 +118,35 @@ discover_node_factory_sync (PipeWireRemote *remote, } static void -on_state_changed (void *user_data, - enum pw_remote_state old, - enum pw_remote_state state, - const char *error) +core_event_error (void *user_data, + uint32_t id, + int seq, + int res, + const char *message) { PipeWireRemote *remote = user_data; - switch (state) + if (id == PW_ID_CORE) { - case PW_REMOTE_STATE_ERROR: - if (!remote->error) - { - g_set_error (&remote->error, G_IO_ERROR, G_IO_ERROR_FAILED, - "%s", error); - } + g_set_error (&remote->error, G_IO_ERROR, G_IO_ERROR_FAILED, + "%s", message); pw_main_loop_quit (remote->loop); - break; - case PW_REMOTE_STATE_UNCONNECTED: - if (!remote->error) - { - g_set_error (&remote->error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Disconnected"); - } - pw_main_loop_quit (remote->loop); - break; - case PW_REMOTE_STATE_CONNECTING: - break; - case PW_REMOTE_STATE_CONNECTED: - pw_main_loop_quit (remote->loop); - break; - default: - g_warning ("Unknown PipeWire state"); - break; } } -static const struct pw_remote_events remote_events = { - PW_VERSION_REMOTE_EVENTS, - .state_changed = on_state_changed, -}; - static void core_event_done (void *user_data, - uint32_t seq) + uint32_t id, int seq) { PipeWireRemote *remote = user_data; - if (remote->sync_seq == seq) + if (id == PW_ID_CORE && remote->sync_seq == seq) pw_main_loop_quit (remote->loop); } -static const struct pw_core_proxy_events core_events = { - PW_VERSION_CORE_PROXY_EVENTS, +static const struct pw_core_events core_events = { + PW_VERSION_CORE_EVENTS, + .error = core_event_error, .done = core_event_done, }; @@ -237,8 +209,8 @@ void pipewire_remote_destroy (PipeWireRemote *remote) { g_clear_pointer (&remote->globals, g_hash_table_destroy); - g_clear_pointer (&remote->remote, pw_remote_destroy); - g_clear_pointer (&remote->core, pw_core_destroy); + g_clear_pointer (&remote->core, pw_core_disconnect); + g_clear_pointer (&remote->context, pw_context_destroy); g_clear_pointer (&remote->loop, pw_main_loop_destroy); g_clear_error (&remote->error); @@ -307,68 +279,31 @@ pipewire_remote_new_sync (struct pw_properties *pipewire_properties, return NULL; } - remote->core = pw_core_new (pw_main_loop_get_loop (remote->loop), NULL); - if (!remote->core) + remote->context = pw_context_new (pw_main_loop_get_loop (remote->loop), NULL, 0); + if (!remote->context) { pipewire_remote_destroy (remote); pw_properties_free (pipewire_properties); g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Couldn't create PipeWire core"); + "Couldn't create PipeWire context"); return NULL; } - remote->remote = pw_remote_new (remote->core, pipewire_properties, 0); - if (!remote->remote) + remote->core = pw_context_connect (remote->context, pipewire_properties, 0); + if (!remote->core) { pipewire_remote_destroy (remote); g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Couldn't create PipeWire remote"); + "Couldn't connect to PipeWire"); return NULL; } remote->globals = g_hash_table_new_full (NULL, NULL, NULL, g_free); - pw_remote_add_listener (remote->remote, - &remote->remote_listener, - &remote_events, - remote); - - if (pw_remote_connect (remote->remote) != 0) - { - pipewire_remote_destroy (remote); - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Couldn't connect PipeWire remote"); - return NULL; - } - - pw_main_loop_run (remote->loop); - - switch (pw_remote_get_state (remote->remote, NULL)) - { - case PW_REMOTE_STATE_ERROR: - case PW_REMOTE_STATE_UNCONNECTED: - *error = g_steal_pointer (&remote->error); - pipewire_remote_destroy (remote); - return NULL; - case PW_REMOTE_STATE_CONNECTING: - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "PipeWire loop stopped unexpectedly"); - pipewire_remote_destroy (remote); - return NULL; - case PW_REMOTE_STATE_CONNECTED: - break; - default: - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Unexpected PipeWire state"); - pipewire_remote_destroy (remote); - return NULL; - } - - remote->core_proxy = pw_remote_get_core_proxy (remote->remote); - pw_core_proxy_add_listener (remote->core_proxy, - &remote->core_listener, - &core_events, - remote); + pw_core_add_listener (remote->core, + &remote->core_listener, + &core_events, + remote); if (!discover_node_factory_sync (remote, error)) { diff --git a/src/pipewire.h b/src/pipewire.h index 0f1bf54..bf48d5e 100644 --- a/src/pipewire.h +++ b/src/pipewire.h @@ -32,7 +32,7 @@ typedef struct _PipeWireGlobal typedef void (* PipeWireGlobalAddedCallback) (PipeWireRemote *remote, uint32_t id, - uint32_t type, + const char *type, const struct spa_dict *props, gpointer user_data); @@ -43,13 +43,11 @@ typedef void (* PipeWireGlobalRemovedCallback) (PipeWireRemote *remote, struct _PipeWireRemote { struct pw_main_loop *loop; + struct pw_context *context; struct pw_core *core; - struct pw_remote *remote; - struct spa_hook remote_listener; - - struct pw_core_proxy *core_proxy; struct spa_hook core_listener; - uint32_t sync_seq; + + int sync_seq; struct spa_hook registry_listener; diff --git a/src/screen-cast.c b/src/screen-cast.c index 7881ddc..1677050 100644 --- a/src/screen-cast.c +++ b/src/screen-cast.c @@ -31,10 +31,10 @@ #include "xdp-impl-dbus.h" #include "xdp-utils.h" -#define PERMISSION_ITEM(item_key, item_value) \ - ((struct spa_dict_item) { \ - .key = item_key, \ - .value = item_value \ +#define PERMISSION_ITEM(item_id, item_permissions) \ + ((struct pw_permission) { \ + .id = item_id, \ + .permissions = item_permissions \ }) typedef struct _ScreenCast ScreenCast; @@ -517,42 +517,9 @@ screen_cast_stream_get_pipewire_node_id (ScreenCastStream *stream) return stream->id; } -static void -append_parent_permissions (PipeWireRemote *remote, - GArray *permission_items, - GList **string_stash, - PipeWireGlobal *global, - const char *permission) -{ - PipeWireGlobal *parent; - char *parent_permission_value; - - if (global->parent_id == 0) - return; - - parent = g_hash_table_lookup (remote->globals, GINT_TO_POINTER (global->parent_id)); - - if (parent->permission_set) - return; - parent->permission_set = TRUE; - - append_parent_permissions (remote, permission_items, string_stash, - parent, permission); - - parent_permission_value = g_strdup_printf ("%u:%s", - global->parent_id, - permission); - *string_stash = g_list_prepend (*string_stash, parent_permission_value); - - g_array_append_val (permission_items, - PERMISSION_ITEM (PW_CORE_PROXY_PERMISSIONS_GLOBAL, - parent_permission_value)); -} - static void append_stream_permissions (PipeWireRemote *remote, GArray *permission_items, - GList **string_stash, GList *streams) { GList *l; @@ -561,21 +528,10 @@ append_stream_permissions (PipeWireRemote *remote, { ScreenCastStream *stream = l->data; uint32_t stream_id; - PipeWireGlobal *stream_global; - char *stream_permission_value; stream_id = screen_cast_stream_get_pipewire_node_id (stream); - stream_global = g_hash_table_lookup (remote->globals, - GINT_TO_POINTER (stream_id)); - - append_parent_permissions (remote, permission_items, string_stash, - stream_global, "r--"); - - stream_permission_value = g_strdup_printf ("%u:rwx", stream_id); - *string_stash = g_list_prepend (*string_stash, stream_permission_value); g_array_append_val (permission_items, - PERMISSION_ITEM (PW_CORE_PROXY_PERMISSIONS_GLOBAL, - stream_permission_value)); + PERMISSION_ITEM (stream_id, PW_PERM_RWX)); } } @@ -587,9 +543,6 @@ open_pipewire_screen_cast_remote (const char *app_id, struct pw_properties *pipewire_properties; PipeWireRemote *remote; g_autoptr(GArray) permission_items = NULL; - char *node_factory_permission_string; - GList *string_stash = NULL; - struct spa_dict *permission_dict; PipeWireGlobal *node_global; pipewire_properties = pw_properties_new ("pipewire.access.portal.app_id", app_id, @@ -603,48 +556,31 @@ open_pipewire_screen_cast_remote (const char *app_id, permission_items = g_array_new (FALSE, TRUE, sizeof (struct spa_dict_item)); - /* - * Hide all existing and future nodes (except the ones we explicitly list below. - */ - g_array_append_val (permission_items, - PERMISSION_ITEM (PW_CORE_PROXY_PERMISSIONS_EXISTING, - "---")); - g_array_append_val (permission_items, - PERMISSION_ITEM (PW_CORE_PROXY_PERMISSIONS_DEFAULT, - "---")); - /* * PipeWire:Interface:Core * Needs rwx to be able create the sink node using the create-object method */ g_array_append_val (permission_items, - PERMISSION_ITEM (PW_CORE_PROXY_PERMISSIONS_GLOBAL, - "0:rwx")); + PERMISSION_ITEM (PW_ID_CORE, PW_PERM_RWX)); /* * PipeWire:Interface:NodeFactory * Needs r-- so it can be passed to create-object when creating the sink node. */ - node_factory_permission_string = g_strdup_printf ("%d:r--", - remote->node_factory_id); - string_stash = g_list_prepend (string_stash, node_factory_permission_string); g_array_append_val (permission_items, - PERMISSION_ITEM (PW_CORE_PROXY_PERMISSIONS_GLOBAL, - node_factory_permission_string)); - node_global = g_hash_table_lookup (remote->globals, - GINT_TO_POINTER (remote->node_factory_id)); - append_parent_permissions (remote, permission_items, &string_stash, - node_global, "r--"); + PERMISSION_ITEM (remote->node_factory_id, PW_PERM_R)); - append_stream_permissions (remote, permission_items, &string_stash, streams); + append_stream_permissions (remote, permission_items, streams); - permission_dict = - &SPA_DICT_INIT ((struct spa_dict_item *) permission_items->data, - permission_items->len); - pw_core_proxy_permissions (pw_remote_get_core_proxy (remote->remote), - permission_dict); + /* + * Hide all existing and future nodes (except the ones we explicitly list above). + */ + g_array_append_val (permission_items, + PERMISSION_ITEM (PW_ID_ANY, 0)); - g_list_free_full (string_stash, g_free); + pw_client_update_permissions (pw_core_get_client(remote->core), + permission_items->len, + (const struct pw_permission *)permission_items->data); pipewire_remote_roundtrip (remote); @@ -943,7 +879,7 @@ handle_open_pipewire_remote (XdpScreenCast *object, } out_fd_list = g_unix_fd_list_new (); - fd = pw_remote_steal_fd (remote->remote); + fd = pw_core_steal_fd (remote->core); fd_id = g_unix_fd_list_append (out_fd_list, fd, &error); close (fd); pipewire_remote_destroy (remote); -- 2.26.2