diff --git a/lib/wp/remote-pipewire.c b/lib/wp/remote-pipewire.c index 66bb09c5b52bc9eb9256afeb914092ded1a0d5e6..023190c065d3cb917fdb2e1432a8dc8ebd6844c9 100644 --- a/lib/wp/remote-pipewire.c +++ b/lib/wp/remote-pipewire.c @@ -15,6 +15,9 @@ #define WP_LOOP_SOURCE(x) ((WpLoopSource *) x) +G_DEFINE_QUARK (node, signal_detail_node) +G_DEFINE_QUARK (port, signal_detail_port) + typedef struct _WpLoopSource WpLoopSource; struct _WpLoopSource { @@ -74,6 +77,11 @@ struct _WpRemotePipewire struct pw_core *core; struct pw_remote *remote; struct spa_hook remote_listener; + struct pw_core_proxy *core_proxy; + + /* Registry */ + struct pw_registry_proxy *registry_proxy; + struct spa_hook registry_listener; GMainContext *context; }; @@ -87,8 +95,61 @@ enum { PROP_CONTEXT, }; +enum +{ + SIGNAL_GLOBAL_ADDED, + SIGNAL_GLOBAL_REMOVED, + LAST_SIGNAL, +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + G_DEFINE_TYPE (WpRemotePipewire, wp_remote_pipewire, WP_TYPE_REMOTE) +static void +registry_global(void *data, uint32_t id, uint32_t parent_id, + uint32_t permissions, uint32_t type, uint32_t version, + const struct spa_dict *props) +{ + switch (type) { + case PW_TYPE_INTERFACE_Node: + g_signal_emit (data, signals[SIGNAL_GLOBAL_ADDED], + signal_detail_node_quark (), id, parent_id, props); + break; + case PW_TYPE_INTERFACE_Port: + g_signal_emit (data, signals[SIGNAL_GLOBAL_ADDED], + signal_detail_port_quark (), id, parent_id, props); + break; + default: + break; + } +} + +static void +registry_global_remove (void *data, uint32_t id) +{ + g_signal_emit (data, signals[SIGNAL_GLOBAL_REMOVED], 0, id); +} + +static const struct pw_registry_proxy_events registry_proxy_events = { + PW_VERSION_REGISTRY_PROXY_EVENTS, + .global = registry_global, + .global_remove = registry_global_remove, +}; + +static void +registry_init (WpRemotePipewire *self) +{ + /* Get the core proxy */ + self->core_proxy = pw_remote_get_core_proxy (self->remote); + + /* Registry */ + self->registry_proxy = pw_core_proxy_get_registry (self->core_proxy, + PW_TYPE_INTERFACE_Registry, PW_VERSION_REGISTRY, 0); + pw_registry_proxy_add_listener(self->registry_proxy, &self->registry_listener, + ®istry_proxy_events, self); +} + static void on_remote_state_changed (void *d, enum pw_remote_state old_state, enum pw_remote_state new_state, const char *error) @@ -99,6 +160,10 @@ on_remote_state_changed (void *d, enum pw_remote_state old_state, pw_remote_state_as_string (old_state), pw_remote_state_as_string (new_state)); + /* Init the registry when connected */ + if (!self->registry_proxy && new_state == PW_REMOTE_STATE_CONNECTED) + registry_init (self); + g_object_notify (G_OBJECT (self), "state"); } @@ -138,6 +203,8 @@ wp_remote_pipewire_finalize (GObject *object) pw_remote_destroy (self->remote); pw_core_destroy (self->core); g_clear_pointer (&self->context, g_main_context_unref); + self->core_proxy= NULL; + self->registry_proxy = NULL; G_OBJECT_CLASS (wp_remote_pipewire_parent_class)->finalize (object); } @@ -242,6 +309,15 @@ wp_remote_pipewire_class_init (WpRemotePipewireClass *klass) g_object_class_install_property (object_class, PROP_PW_REMOTE, g_param_spec_pointer ("pw-remote", "pw-remote", "The pipewire remote", G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + /* Signals */ + signals[SIGNAL_GLOBAL_ADDED] = g_signal_new ("global-added", + G_TYPE_FROM_CLASS (klass), G_SIGNAL_DETAILED | G_SIGNAL_RUN_LAST, + 0, NULL, NULL, NULL, G_TYPE_NONE, 3, G_TYPE_UINT, G_TYPE_UINT, + G_TYPE_POINTER); + signals[SIGNAL_GLOBAL_REMOVED] = g_signal_new ("global-removed", + G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, + 0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_UINT); } WpRemote * @@ -260,3 +336,25 @@ wp_remote_pipewire_new (WpCore *core, GMainContext *context) return remote; } + +gpointer +wp_remote_pipewire_proxy_bind (WpRemotePipewire *self, guint global_id, + guint global_type) +{ + g_return_val_if_fail (WP_IS_REMOTE_PIPEWIRE(self), NULL); + g_return_val_if_fail (self->registry_proxy, NULL); + + return pw_registry_proxy_bind (self->registry_proxy, global_id, global_type, + 0, 0); +} + +gpointer +wp_remote_pipewire_create_object (WpRemotePipewire *self, + const char *factory_name, guint global_type, gconstpointer props) +{ + g_return_val_if_fail (WP_IS_REMOTE_PIPEWIRE(self), NULL); + g_return_val_if_fail (self->core_proxy, NULL); + + return pw_core_proxy_create_object(self->core_proxy, factory_name, + global_type, 0, props, 0); +} diff --git a/lib/wp/remote-pipewire.h b/lib/wp/remote-pipewire.h index d7da043df3aefcc7efdd965a9852808f9b378ee2..347ffae0fb99ca101033c2389f2172463d882a07 100644 --- a/lib/wp/remote-pipewire.h +++ b/lib/wp/remote-pipewire.h @@ -19,6 +19,11 @@ G_DECLARE_FINAL_TYPE (WpRemotePipewire, wp_remote_pipewire, WpRemote *wp_remote_pipewire_new (WpCore *core, GMainContext *context); +gpointer wp_remote_pipewire_proxy_bind (WpRemotePipewire *self, guint global_id, + guint global_type); +gpointer wp_remote_pipewire_create_object (WpRemotePipewire *self, + const char *factory_name, guint global_type, gconstpointer props); + G_END_DECLS #endif