mirror of
https://gitlab.freedesktop.org/pipewire/wireplumber.git
synced 2026-05-08 03:28:02 +02:00
Merge branch 'registry' into 'master'
Registry See merge request gkiagia/wireplumber!12
This commit is contained in:
commit
661010a36b
9 changed files with 278 additions and 297 deletions
|
|
@ -47,9 +47,6 @@ wp_proxy_node_finalize (GObject * object)
|
|||
{
|
||||
WpProxyNode *self = WP_PROXY_NODE(object);
|
||||
|
||||
/* Remove the listener */
|
||||
spa_hook_remove (&self->listener);
|
||||
|
||||
/* Clear the info */
|
||||
if (self->info) {
|
||||
pw_node_info_free(self->info);
|
||||
|
|
|
|||
|
|
@ -77,9 +77,6 @@ wp_proxy_port_finalize (GObject * object)
|
|||
{
|
||||
WpProxyPort *self = WP_PROXY_PORT(object);
|
||||
|
||||
/* Remove the listener */
|
||||
spa_hook_remove (&self->listener);
|
||||
|
||||
/* Clear the indo */
|
||||
if (self->info) {
|
||||
pw_port_info_free(self->info);
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ enum {
|
|||
enum
|
||||
{
|
||||
SIGNAL_DESTROYED,
|
||||
SIGNAL_DONE,
|
||||
LAST_SIGNAL,
|
||||
};
|
||||
|
||||
|
|
@ -63,6 +64,9 @@ proxy_event_done (void *data, int seq)
|
|||
{
|
||||
WpProxyPrivate *self = wp_proxy_get_instance_private (WP_PROXY(data));
|
||||
|
||||
/* Emit the done signal */
|
||||
g_signal_emit (data, wp_proxy_signals[SIGNAL_DONE], 0);
|
||||
|
||||
/* Make sure the task is valid */
|
||||
if (!self->done_task)
|
||||
return;
|
||||
|
|
@ -89,9 +93,6 @@ wp_proxy_finalize (GObject * object)
|
|||
g_debug ("%s:%p destroyed (pw proxy %p)", G_OBJECT_TYPE_NAME (object),
|
||||
object, self->proxy);
|
||||
|
||||
/* Remove the listener */
|
||||
spa_hook_remove (&self->listener);
|
||||
|
||||
/* Destroy the proxy */
|
||||
if (self->proxy) {
|
||||
pw_proxy_destroy (self->proxy);
|
||||
|
|
@ -152,7 +153,7 @@ wp_proxy_init_async (GAsyncInitable *initable, int io_priority,
|
|||
pw_proxy_add_listener (self->proxy, &self->listener, &proxy_events, initable);
|
||||
|
||||
/* Trigger the done callback */
|
||||
pw_proxy_sync(self->proxy, 0);
|
||||
wp_proxy_sync(WP_PROXY(initable));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
@ -199,8 +200,11 @@ wp_proxy_class_init (WpProxyClass * klass)
|
|||
/* Signals */
|
||||
wp_proxy_signals[SIGNAL_DESTROYED] =
|
||||
g_signal_new ("destroyed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (WpProxyClass, destroyed), NULL, NULL,
|
||||
g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
|
||||
G_STRUCT_OFFSET (WpProxyClass, destroyed), NULL, NULL, NULL, G_TYPE_NONE,
|
||||
0);
|
||||
wp_proxy_signals[SIGNAL_DONE] =
|
||||
g_signal_new ("done", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (WpProxyClass, done), NULL, NULL, NULL, G_TYPE_NONE, 0);
|
||||
}
|
||||
|
||||
guint
|
||||
|
|
@ -224,3 +228,15 @@ wp_proxy_get_pw_proxy (WpProxy * self)
|
|||
priv = wp_proxy_get_instance_private (self);
|
||||
return priv->proxy;
|
||||
}
|
||||
|
||||
void wp_proxy_sync (WpProxy * self)
|
||||
{
|
||||
WpProxyPrivate *priv;
|
||||
|
||||
g_return_if_fail (WP_IS_PROXY (self));
|
||||
|
||||
priv = wp_proxy_get_instance_private (self);
|
||||
|
||||
/* Trigger the done callback */
|
||||
pw_proxy_sync(priv->proxy, 0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,11 +24,13 @@ struct _WpProxyClass
|
|||
GObjectClass parent_class;
|
||||
|
||||
/* Signals */
|
||||
void (*destroyed)(WpProxy *wp_proxy);
|
||||
void (*destroyed)(WpProxy *wp_proxy, gpointer data);
|
||||
void (*done)(WpProxy *wp_proxy, gpointer data);
|
||||
};
|
||||
|
||||
guint wp_proxy_get_global_id (WpProxy * self);
|
||||
gpointer wp_proxy_get_pw_proxy (WpProxy * self);
|
||||
void wp_proxy_sync (WpProxy * self);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -26,12 +26,7 @@ gpointer simple_endpoint_link_factory (WpFactory * factory, GType type,
|
|||
struct module_data
|
||||
{
|
||||
WpModule *module;
|
||||
|
||||
/* Registry */
|
||||
struct pw_registry_proxy *registry_proxy;
|
||||
struct spa_hook registry_listener;
|
||||
|
||||
/* Client nodes info */
|
||||
WpRemotePipewire *remote_pipewire;
|
||||
GHashTable *client_nodes_info;
|
||||
};
|
||||
|
||||
|
|
@ -39,7 +34,7 @@ struct endpoint_info
|
|||
{
|
||||
gchar *name;
|
||||
gchar *media_class;
|
||||
const struct pw_proxy *proxy;
|
||||
struct pw_proxy *proxy;
|
||||
};
|
||||
|
||||
struct proxy_info
|
||||
|
|
@ -143,8 +138,8 @@ proxy_port_created(GObject *initable, GAsyncResult *res, gpointer d)
|
|||
{
|
||||
struct proxy_info *pi = d;
|
||||
const struct module_data *data = pi->data;
|
||||
struct endpoint_info *ei = NULL;
|
||||
WpProxyPort *proxy_port = NULL;
|
||||
struct pw_proxy *proxy = NULL;
|
||||
|
||||
/* Get the proxy port */
|
||||
proxy_port = wp_proxy_port_new_finish(initable, res, NULL);
|
||||
|
|
@ -155,19 +150,21 @@ proxy_port_created(GObject *initable, GAsyncResult *res, gpointer d)
|
|||
pi->proxy_port = proxy_port;
|
||||
|
||||
/* Get the node proxy */
|
||||
proxy = pw_registry_proxy_bind (data->registry_proxy, pi->node_id,
|
||||
PW_TYPE_INTERFACE_Node, PW_VERSION_NODE, 0);
|
||||
if (!proxy)
|
||||
ei = g_hash_table_lookup(data->client_nodes_info,
|
||||
GINT_TO_POINTER(pi->node_id));
|
||||
if (!ei)
|
||||
return;
|
||||
|
||||
/* Create the proxy node asynchronically */
|
||||
wp_proxy_node_new(pi->node_id, proxy, proxy_node_created, pi);
|
||||
wp_proxy_node_new(pi->node_id, ei->proxy, proxy_node_created, pi);
|
||||
}
|
||||
|
||||
static void
|
||||
handle_node (struct module_data *data, uint32_t id, uint32_t parent_id,
|
||||
const struct spa_dict * props)
|
||||
handle_node (WpRemotePipewire *rp, guint id, guint parent_id, gconstpointer p,
|
||||
gpointer d)
|
||||
{
|
||||
struct module_data *data = d;
|
||||
const struct spa_dict *props = p;
|
||||
struct endpoint_info *ei = NULL;
|
||||
const gchar *name;
|
||||
const gchar *media_class;
|
||||
|
|
@ -198,9 +195,10 @@ handle_node (struct module_data *data, uint32_t id, uint32_t parent_id,
|
|||
g_debug ("found stream node: id:%u ; name:%s ; media_class:%s", id, name,
|
||||
media_class);
|
||||
|
||||
/* Get the proxy */
|
||||
proxy = pw_registry_proxy_bind (data->registry_proxy, id,
|
||||
PW_TYPE_INTERFACE_Node, PW_VERSION_NODE, 0);
|
||||
/* Bind the proxy */
|
||||
proxy = wp_remote_pipewire_proxy_bind(rp, id, PW_TYPE_INTERFACE_Node);
|
||||
if (!proxy)
|
||||
return;
|
||||
|
||||
/* TODO: Assume all clients have this format for now */
|
||||
format.format = SPA_AUDIO_FORMAT_F32P;
|
||||
|
|
@ -230,9 +228,10 @@ handle_node (struct module_data *data, uint32_t id, uint32_t parent_id,
|
|||
}
|
||||
|
||||
static void
|
||||
handle_port(struct module_data *data, uint32_t id, uint32_t parent_id,
|
||||
const struct spa_dict *props)
|
||||
handle_port(WpRemotePipewire *rp, guint id, guint parent_id, gconstpointer p,
|
||||
gpointer d)
|
||||
{
|
||||
struct module_data *data = d;
|
||||
struct proxy_info *pi = NULL;
|
||||
struct pw_proxy *proxy = NULL;
|
||||
|
||||
|
|
@ -241,9 +240,8 @@ handle_port(struct module_data *data, uint32_t id, uint32_t parent_id,
|
|||
GINT_TO_POINTER (parent_id)))
|
||||
return;
|
||||
|
||||
/* Get the port proxy */
|
||||
proxy = pw_registry_proxy_bind (data->registry_proxy, id,
|
||||
PW_TYPE_INTERFACE_Port, PW_VERSION_PORT, 0);
|
||||
/* Bind the proxy */
|
||||
proxy = wp_remote_pipewire_proxy_bind (rp, id, PW_TYPE_INTERFACE_Port);
|
||||
if (!proxy)
|
||||
return;
|
||||
|
||||
|
|
@ -257,55 +255,18 @@ handle_port(struct module_data *data, uint32_t id, uint32_t parent_id,
|
|||
wp_proxy_port_new(id, proxy, proxy_port_created, pi);
|
||||
}
|
||||
|
||||
static void
|
||||
registry_global(void *d, uint32_t id, uint32_t parent_id,
|
||||
uint32_t permissions, uint32_t type, uint32_t version,
|
||||
const struct spa_dict *props)
|
||||
{
|
||||
struct module_data *data = d;
|
||||
|
||||
switch (type) {
|
||||
case PW_TYPE_INTERFACE_Node:
|
||||
handle_node(data, id, parent_id, props);
|
||||
break;
|
||||
|
||||
case PW_TYPE_INTERFACE_Port:
|
||||
handle_port(data, id, parent_id, props);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct pw_registry_proxy_events registry_events = {
|
||||
PW_VERSION_REGISTRY_PROXY_EVENTS,
|
||||
.global = registry_global,
|
||||
};
|
||||
|
||||
static void
|
||||
on_remote_connected (WpRemote *remote, WpRemoteState state,
|
||||
struct module_data *data)
|
||||
{
|
||||
struct pw_core_proxy *core_proxy;
|
||||
struct pw_remote *pw_remote;
|
||||
|
||||
g_object_get (remote, "pw-remote", &pw_remote, NULL);
|
||||
|
||||
core_proxy = pw_remote_get_core_proxy (pw_remote);
|
||||
data->registry_proxy = pw_core_proxy_get_registry (core_proxy,
|
||||
PW_TYPE_INTERFACE_Registry, PW_VERSION_REGISTRY, 0);
|
||||
pw_registry_proxy_add_listener(data->registry_proxy,
|
||||
&data->registry_listener, ®istry_events, data);
|
||||
}
|
||||
|
||||
static void
|
||||
module_destroy (gpointer d)
|
||||
{
|
||||
struct module_data *data = d;
|
||||
|
||||
/* Set to NULL module and remote pipewire as we don't own the reference */
|
||||
data->module = NULL;
|
||||
data->remote_pipewire = NULL;
|
||||
|
||||
/* Destroy the hash table */
|
||||
g_hash_table_unref (data->client_nodes_info);
|
||||
data->client_nodes_info = NULL;
|
||||
|
||||
/* Clean up */
|
||||
g_slice_free (struct module_data, data);
|
||||
|
|
@ -315,12 +276,13 @@ void
|
|||
wireplumber__module_init (WpModule * module, WpCore * core, GVariant * args)
|
||||
{
|
||||
struct module_data *data;
|
||||
WpRemote *remote;
|
||||
WpRemotePipewire *rp;
|
||||
struct pw_core *pw_core;
|
||||
struct pw_remote *pw_remote;
|
||||
|
||||
remote = wp_core_get_global (core, WP_GLOBAL_REMOTE_PIPEWIRE);
|
||||
if (!remote) {
|
||||
/* Make sure the remote pipewire is valid */
|
||||
rp = wp_core_get_global (core, WP_GLOBAL_REMOTE_PIPEWIRE);
|
||||
if (!rp) {
|
||||
g_critical ("module-pipewire cannot be loaded without a registered "
|
||||
"WpRemotePipewire object");
|
||||
return;
|
||||
|
|
@ -329,20 +291,22 @@ wireplumber__module_init (WpModule * module, WpCore * core, GVariant * args)
|
|||
/* Create the module data */
|
||||
data = g_slice_new0 (struct module_data);
|
||||
data->module = module;
|
||||
data->remote_pipewire = rp;
|
||||
data->client_nodes_info = g_hash_table_new_full (g_direct_hash,
|
||||
g_direct_equal, NULL, endpoint_info_destroy);
|
||||
|
||||
/* Set the module destroy callback */
|
||||
wp_module_set_destroy_callback (module, module_destroy, data);
|
||||
|
||||
g_signal_connect (remote, "state-changed::connected",
|
||||
(GCallback) on_remote_connected, data);
|
||||
/* Register the global addded callbacks */
|
||||
g_signal_connect(rp, "global-added::node", (GCallback)handle_node, data);
|
||||
g_signal_connect(rp, "global-added::port", (GCallback)handle_port, data);
|
||||
|
||||
g_object_get (remote,
|
||||
"pw-core", &pw_core,
|
||||
"pw-remote", &pw_remote,
|
||||
NULL);
|
||||
/* Init remoted endpoint */
|
||||
g_object_get (rp, "pw-core", &pw_core, "pw-remote", &pw_remote, NULL);
|
||||
remote_endpoint_init (core, pw_core, pw_remote);
|
||||
|
||||
/* Register simple-endpoint and simple-endpoint-link */
|
||||
wp_factory_new (core, "pipewire-simple-endpoint", simple_endpoint_factory);
|
||||
wp_factory_new (core, "pipewire-simple-endpoint-link",
|
||||
simple_endpoint_link_factory);
|
||||
|
|
|
|||
|
|
@ -18,15 +18,7 @@
|
|||
struct impl
|
||||
{
|
||||
WpModule *module;
|
||||
|
||||
/* Remote */
|
||||
struct spa_hook remote_listener;
|
||||
|
||||
/* Registry */
|
||||
struct pw_registry_proxy *registry_proxy;
|
||||
struct spa_hook registry_listener;
|
||||
|
||||
/* The alsa node proxies */
|
||||
WpRemotePipewire *remote_pipewire;
|
||||
GHashTable *alsa_nodes_info;
|
||||
};
|
||||
|
||||
|
|
@ -89,8 +81,8 @@ proxy_node_created(GObject *initable, GAsyncResult *res, gpointer data)
|
|||
g_autoptr(WpProxyNode) proxy_node = NULL;
|
||||
struct endpoint_info *ei = NULL;
|
||||
GVariantBuilder b;
|
||||
g_autoptr(GVariant) endpoint_props = NULL;
|
||||
g_autoptr(WpEndpoint) endpoint = NULL;
|
||||
g_autoptr (GVariant) endpoint_props = NULL;
|
||||
g_autoptr (WpEndpoint) endpoint = NULL;
|
||||
|
||||
/* Get the proxy */
|
||||
proxy_node = wp_proxy_node_new_finish(initable, res, NULL);
|
||||
|
|
@ -147,8 +139,8 @@ proxy_port_created(GObject *initable, GAsyncResult *res, gpointer data)
|
|||
pi->proxy_port = proxy_port;
|
||||
|
||||
/* Get the node proxy */
|
||||
proxy = pw_registry_proxy_bind (impl->registry_proxy, pi->node_id,
|
||||
PW_TYPE_INTERFACE_Node, PW_VERSION_NODE, 0);
|
||||
proxy = wp_remote_pipewire_proxy_bind (impl->remote_pipewire, pi->node_id,
|
||||
PW_TYPE_INTERFACE_Node);
|
||||
if (!proxy)
|
||||
return;
|
||||
|
||||
|
|
@ -157,17 +149,16 @@ proxy_port_created(GObject *initable, GAsyncResult *res, gpointer data)
|
|||
}
|
||||
|
||||
static void
|
||||
handle_node(struct impl *impl, uint32_t id, uint32_t parent_id,
|
||||
const struct spa_dict *props)
|
||||
handle_node(WpRemotePipewire *rp, guint id, guint parent_id, gconstpointer p,
|
||||
gpointer d)
|
||||
{
|
||||
struct impl *impl = d;
|
||||
const struct spa_dict *props = p;
|
||||
const gchar *media_class = NULL, *name = NULL;
|
||||
struct endpoint_info *ei = NULL;
|
||||
|
||||
/* Make sure the node has properties */
|
||||
if (!props) {
|
||||
g_warning("node has no properties, skipping...");
|
||||
return;
|
||||
}
|
||||
g_return_if_fail(props);
|
||||
|
||||
/* Get the name and media_class */
|
||||
name = spa_dict_lookup(props, "node.name");
|
||||
|
|
@ -189,9 +180,10 @@ handle_node(struct impl *impl, uint32_t id, uint32_t parent_id,
|
|||
}
|
||||
|
||||
static void
|
||||
handle_port(struct impl *impl, uint32_t id, uint32_t parent_id,
|
||||
const struct spa_dict *props)
|
||||
handle_port(WpRemotePipewire *rp, guint id, guint parent_id, gconstpointer p,
|
||||
gpointer d)
|
||||
{
|
||||
struct impl *impl = d;
|
||||
struct proxy_info *pi = NULL;
|
||||
struct pw_proxy *proxy = NULL;
|
||||
|
||||
|
|
@ -199,13 +191,8 @@ handle_port(struct impl *impl, uint32_t id, uint32_t parent_id,
|
|||
if (!g_hash_table_contains(impl->alsa_nodes_info, GINT_TO_POINTER (parent_id)))
|
||||
return;
|
||||
|
||||
/* Make sure the port has porperties */
|
||||
if (!props)
|
||||
return;
|
||||
|
||||
/* Get the port proxy */
|
||||
proxy = pw_registry_proxy_bind (impl->registry_proxy, id,
|
||||
PW_TYPE_INTERFACE_Port, PW_VERSION_PORT, 0);
|
||||
proxy = wp_remote_pipewire_proxy_bind (rp, id, PW_TYPE_INTERFACE_Port);
|
||||
if (!proxy)
|
||||
return;
|
||||
|
||||
|
|
@ -219,90 +206,48 @@ handle_port(struct impl *impl, uint32_t id, uint32_t parent_id,
|
|||
wp_proxy_port_new(id, proxy, proxy_port_created, pi);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
struct impl *impl = data;
|
||||
|
||||
switch (type) {
|
||||
case PW_TYPE_INTERFACE_Node:
|
||||
handle_node(impl, id, parent_id, props);
|
||||
break;
|
||||
|
||||
case PW_TYPE_INTERFACE_Port:
|
||||
handle_port(impl, id, parent_id, props);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct pw_registry_proxy_events registry_events = {
|
||||
PW_VERSION_REGISTRY_PROXY_EVENTS,
|
||||
.global = registry_global,
|
||||
};
|
||||
|
||||
static void
|
||||
on_connected (WpRemote *remote, WpRemoteState state, struct impl *impl)
|
||||
{
|
||||
struct pw_core_proxy *core_proxy = NULL;
|
||||
struct pw_remote *pw_remote;
|
||||
|
||||
g_object_get (remote, "pw-remote", &pw_remote, NULL);
|
||||
|
||||
core_proxy = pw_remote_get_core_proxy (pw_remote);
|
||||
impl->registry_proxy = pw_core_proxy_get_registry (core_proxy,
|
||||
PW_TYPE_INTERFACE_Registry, PW_VERSION_REGISTRY, 0);
|
||||
pw_registry_proxy_add_listener(impl->registry_proxy,
|
||||
&impl->registry_listener, ®istry_events, impl);
|
||||
}
|
||||
|
||||
static void
|
||||
module_destroy (gpointer data)
|
||||
{
|
||||
struct impl *impl = data;
|
||||
|
||||
/* Set to NULL module and remote pipewire as we don't own the reference */
|
||||
impl->module = NULL;
|
||||
impl->remote_pipewire = NULL;
|
||||
|
||||
/* Destroy the hash table */
|
||||
g_hash_table_unref (impl->alsa_nodes_info);
|
||||
impl->alsa_nodes_info = NULL;
|
||||
|
||||
/* Clean up */
|
||||
g_slice_free (struct impl, impl);
|
||||
}
|
||||
|
||||
struct impl *
|
||||
module_create (WpModule * module, WpCore * core)
|
||||
{
|
||||
struct impl *impl;
|
||||
WpRemote *remote;
|
||||
|
||||
/* Allocate impl */
|
||||
impl = g_new0(struct impl, 1);
|
||||
|
||||
/* Set core */
|
||||
impl->module = module;
|
||||
|
||||
/* Set remote */
|
||||
remote = wp_core_get_global(core, WP_GLOBAL_REMOTE_PIPEWIRE);
|
||||
g_signal_connect (remote, "state-changed::connected",
|
||||
(GCallback) on_connected, impl);
|
||||
|
||||
/* Create the hash table */
|
||||
impl->alsa_nodes_info = g_hash_table_new_full (g_direct_hash,
|
||||
g_direct_equal, NULL, endpoint_info_destroy);
|
||||
|
||||
/* Return the module */
|
||||
return impl;
|
||||
}
|
||||
|
||||
void
|
||||
wireplumber__module_init (WpModule * module, WpCore * core, GVariant * args)
|
||||
{
|
||||
/* Create the impl */
|
||||
struct impl *impl = module_create (module, core);
|
||||
struct impl *impl;
|
||||
WpRemotePipewire *rp;
|
||||
|
||||
/* Make sure the remote pipewire is valid */
|
||||
rp = wp_core_get_global (core, WP_GLOBAL_REMOTE_PIPEWIRE);
|
||||
if (!rp) {
|
||||
g_critical ("module-pw-alsa-udev cannot be loaded without a registered "
|
||||
"WpRemotePipewire object");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Create the module data */
|
||||
impl = g_slice_new0(struct impl);
|
||||
impl->module = module;
|
||||
impl->remote_pipewire = rp;
|
||||
impl->alsa_nodes_info = g_hash_table_new_full (g_direct_hash,
|
||||
g_direct_equal, NULL, endpoint_info_destroy);
|
||||
|
||||
/* Set destroy callback for impl */
|
||||
wp_module_set_destroy_callback (module, module_destroy, impl);
|
||||
|
||||
/* Register the global addded callbacks */
|
||||
g_signal_connect(rp, "global-added::node", (GCallback)handle_node, impl);
|
||||
g_signal_connect(rp, "global-added::port", (GCallback)handle_port, impl);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,17 +26,13 @@ struct _WpPwAudioSoftdspEndpoint
|
|||
{
|
||||
WpEndpoint parent;
|
||||
|
||||
/* The remote pipewire */
|
||||
WpRemotePipewire *remote_pipewire;
|
||||
|
||||
/* temporary method to select which endpoint
|
||||
* is going to be the default input/output */
|
||||
gboolean selected;
|
||||
|
||||
/* Core */
|
||||
struct pw_core_proxy *core_proxy;
|
||||
|
||||
/* Registry */
|
||||
struct pw_registry_proxy *registry_proxy;
|
||||
struct spa_hook registry_listener;
|
||||
|
||||
/* Direction */
|
||||
enum pw_direction direction;
|
||||
|
||||
|
|
@ -132,8 +128,8 @@ on_dsp_running(WpPwAudioSoftdspEndpoint *self)
|
|||
g_debug ("%p linking DSP to node", self);
|
||||
|
||||
/* Create the link */
|
||||
self->link_proxy = pw_core_proxy_create_object(self->core_proxy,
|
||||
"link-factory", PW_TYPE_INTERFACE_Link, PW_VERSION_LINK, &props->dict, 0);
|
||||
self->link_proxy = wp_remote_pipewire_create_object(self->remote_pipewire,
|
||||
"link-factory", PW_TYPE_INTERFACE_Link, &props->dict);
|
||||
|
||||
/* Clean up */
|
||||
pw_properties_free(props);
|
||||
|
|
@ -264,8 +260,8 @@ emit_audio_dsp_node (WpPwAudioSoftdspEndpoint *self)
|
|||
MAX_QUANTUM_SIZE * sizeof(float));
|
||||
|
||||
/* Set the DSP proxy and listener */
|
||||
self->dsp_proxy = pw_core_proxy_create_object(self->core_proxy, "audio-dsp",
|
||||
PW_TYPE_INTERFACE_Node, PW_VERSION_NODE, &props->dict, 0);
|
||||
self->dsp_proxy = wp_remote_pipewire_create_object(self->remote_pipewire,
|
||||
"audio-dsp", PW_TYPE_INTERFACE_Node, &props->dict);
|
||||
pw_node_proxy_add_listener(self->dsp_proxy, &self->dsp_listener,
|
||||
&dsp_node_events, self);
|
||||
pw_node_proxy_enum_params (self->dsp_proxy, 0, SPA_PARAM_Props, 0, -1, NULL);
|
||||
|
|
@ -284,21 +280,69 @@ emit_audio_dsp_node (WpPwAudioSoftdspEndpoint *self)
|
|||
pw_properties_free(props);
|
||||
}
|
||||
|
||||
static void
|
||||
handle_port(WpRemotePipewire *rp, guint id, guint parent_id, gconstpointer p,
|
||||
gpointer d)
|
||||
{
|
||||
WpPwAudioSoftdspEndpoint *self = d;
|
||||
const struct spa_dict *props = p;
|
||||
const char *direction_prop = NULL;
|
||||
enum pw_direction direction;
|
||||
|
||||
/* Make sure the dsp port is not already set*/
|
||||
if (self->dsp_port_id != 0)
|
||||
return;
|
||||
|
||||
/* Make sure the port has porperties */
|
||||
if (!props)
|
||||
return;
|
||||
|
||||
/* Only handle ports owned by this endpoint */
|
||||
if (!self->dsp_info || self->dsp_info->id != parent_id)
|
||||
return;
|
||||
|
||||
/* Get the direction property */
|
||||
direction_prop = spa_dict_lookup(props, "port.direction");
|
||||
if (!direction_prop)
|
||||
return;
|
||||
direction =
|
||||
!strcmp(direction_prop, "out") ? PW_DIRECTION_OUTPUT : PW_DIRECTION_INPUT;
|
||||
|
||||
/* Only handle ports with the oposit direction of the endpoint */
|
||||
if (self->direction == direction)
|
||||
return;
|
||||
|
||||
/* Set the dsp port id */
|
||||
self->dsp_port_id = id;
|
||||
}
|
||||
|
||||
static void
|
||||
endpoint_constructed (GObject * object)
|
||||
{
|
||||
WpPwAudioSoftdspEndpoint *self = WP_PW_AUDIO_SOFTDSP_ENDPOINT (object);
|
||||
g_autoptr (WpCore) core = wp_endpoint_get_core(WP_ENDPOINT(self));
|
||||
const gchar *media_class = wp_endpoint_get_media_class (WP_ENDPOINT (self));
|
||||
GVariantDict d;
|
||||
|
||||
/* Set Remote Pipewire */
|
||||
self->remote_pipewire = wp_core_get_global (core, WP_GLOBAL_REMOTE_PIPEWIRE);
|
||||
if (!self->remote_pipewire)
|
||||
g_critical ("failed to get remote pipewire ");
|
||||
|
||||
/* Register the global-added::port callback in remote pipewire */
|
||||
g_signal_connect(self->remote_pipewire, "global-added::port",
|
||||
(GCallback)handle_port, self);
|
||||
|
||||
/* Set the direction */
|
||||
if (g_str_has_suffix (media_class, "Source")) {
|
||||
if (g_str_has_suffix (media_class, "Source"))
|
||||
self->direction = PW_DIRECTION_INPUT;
|
||||
} else if (g_str_has_suffix (media_class, "Sink")) {
|
||||
else if (g_str_has_suffix (media_class, "Sink"))
|
||||
self->direction = PW_DIRECTION_OUTPUT;
|
||||
} else {
|
||||
else
|
||||
g_critical ("failed to parse direction");
|
||||
}
|
||||
|
||||
/* Emit the audio DSP node */
|
||||
emit_audio_dsp_node(self);
|
||||
|
||||
g_variant_dict_init (&d, NULL);
|
||||
g_variant_dict_insert (&d, "id", "u", 0);
|
||||
|
|
@ -338,6 +382,9 @@ endpoint_finalize (GObject * object)
|
|||
{
|
||||
WpPwAudioSoftdspEndpoint *self = WP_PW_AUDIO_SOFTDSP_ENDPOINT (object);
|
||||
|
||||
/* Set to NULL remote pipewire as we don't own the reference */
|
||||
self->remote_pipewire = NULL;
|
||||
|
||||
/* Unref the proxy node */
|
||||
g_clear_object (&self->proxy_node);
|
||||
|
||||
|
|
@ -500,6 +547,7 @@ endpoint_class_init (WpPwAudioSoftdspEndpointClass * klass)
|
|||
endpoint_class->get_control_value = endpoint_get_control_value;
|
||||
endpoint_class->set_control_value = endpoint_set_control_value;
|
||||
|
||||
/* Instal the properties */
|
||||
g_object_class_install_property (object_class, PROP_NODE_PROXY,
|
||||
g_param_spec_object ("node-proxy", "node-proxy",
|
||||
"Pointer to the node proxy of the device", WP_TYPE_PROXY_NODE,
|
||||
|
|
@ -510,91 +558,22 @@ endpoint_class_init (WpPwAudioSoftdspEndpointClass * klass)
|
|||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
|
||||
}
|
||||
|
||||
static void
|
||||
handle_port(WpPwAudioSoftdspEndpoint *self, uint32_t id, uint32_t parent_id,
|
||||
const struct spa_dict *props)
|
||||
{
|
||||
const char *direction_prop = NULL;
|
||||
enum pw_direction direction;
|
||||
|
||||
/* Make sure the dsp port is not already set*/
|
||||
if (self->dsp_port_id != 0)
|
||||
return;
|
||||
|
||||
/* Make sure the port has porperties */
|
||||
if (!props)
|
||||
return;
|
||||
|
||||
/* Only handle ports owned by this endpoint */
|
||||
if (!self->dsp_info || self->dsp_info->id != parent_id)
|
||||
return;
|
||||
|
||||
/* Get the direction property */
|
||||
direction_prop = spa_dict_lookup(props, "port.direction");
|
||||
if (!direction_prop)
|
||||
return;
|
||||
direction =
|
||||
!strcmp(direction_prop, "out") ? PW_DIRECTION_OUTPUT : PW_DIRECTION_INPUT;
|
||||
|
||||
/* Only handle ports with the oposit direction of the endpoint */
|
||||
if (self->direction == direction)
|
||||
return;
|
||||
|
||||
/* Set the dsp port id */
|
||||
self->dsp_port_id = id;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
WpPwAudioSoftdspEndpoint *self = data;
|
||||
|
||||
switch (type) {
|
||||
case PW_TYPE_INTERFACE_Port:
|
||||
handle_port(self, id, parent_id, props);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct pw_registry_proxy_events registry_events = {
|
||||
PW_VERSION_REGISTRY_PROXY_EVENTS,
|
||||
.global = registry_global,
|
||||
};
|
||||
|
||||
static gpointer
|
||||
endpoint_factory (WpFactory * factory, GType type, GVariant * properties)
|
||||
{
|
||||
g_autoptr (WpCore) wp_core = NULL;
|
||||
WpRemote *remote;
|
||||
struct pw_remote *pw_remote;
|
||||
g_autoptr (WpCore) core = NULL;
|
||||
const gchar *name = NULL;
|
||||
const gchar *media_class = NULL;
|
||||
guint64 proxy_node, proxy_port;
|
||||
|
||||
/* Make sure the type is not the base class type */
|
||||
if (type != WP_TYPE_ENDPOINT)
|
||||
return NULL;
|
||||
/* Make sure the type is correct */
|
||||
g_return_val_if_fail(type == WP_TYPE_ENDPOINT, NULL);
|
||||
|
||||
/* Get the WirePlumber core */
|
||||
wp_core = wp_factory_get_core(factory);
|
||||
if (!wp_core) {
|
||||
g_warning("failed to get wireplumbe core. Skipping...");
|
||||
return NULL;
|
||||
}
|
||||
/* Get the Core */
|
||||
core = wp_factory_get_core(factory);
|
||||
g_return_val_if_fail (core, NULL);
|
||||
|
||||
/* Get the remote */
|
||||
remote = wp_core_get_global(wp_core, WP_GLOBAL_REMOTE_PIPEWIRE);
|
||||
if (!remote) {
|
||||
g_warning("failed to get core remote. Skipping...");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Get the name and media-class */
|
||||
/* Get the properties */
|
||||
if (!g_variant_lookup (properties, "name", "&s", &name))
|
||||
return NULL;
|
||||
if (!g_variant_lookup (properties, "media-class", "&s", &media_class))
|
||||
|
|
@ -604,36 +583,14 @@ endpoint_factory (WpFactory * factory, GType type, GVariant * properties)
|
|||
if (!g_variant_lookup (properties, "proxy-port", "t", &proxy_port))
|
||||
return NULL;
|
||||
|
||||
/* Create the softdsp endpoint object */
|
||||
WpPwAudioSoftdspEndpoint *ep = g_object_new (endpoint_get_type (),
|
||||
"core", wp_core,
|
||||
/* Create and return the softdsp endpoint object */
|
||||
return g_object_new (endpoint_get_type (),
|
||||
"core", core,
|
||||
"name", name,
|
||||
"media-class", media_class,
|
||||
"node-proxy", (gpointer) proxy_node,
|
||||
"port-proxy", (gpointer) proxy_port,
|
||||
NULL);
|
||||
if (!ep)
|
||||
return NULL;
|
||||
|
||||
/* Set the core proxy */
|
||||
g_object_get (remote, "pw-remote", &pw_remote, NULL);
|
||||
ep->core_proxy = pw_remote_get_core_proxy(pw_remote);
|
||||
if (!ep->core_proxy) {
|
||||
g_warning("failed to get core proxy. Skipping...");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Add registry listener */
|
||||
ep->registry_proxy = pw_core_proxy_get_registry (ep->core_proxy,
|
||||
PW_TYPE_INTERFACE_Registry, PW_VERSION_REGISTRY, 0);
|
||||
pw_registry_proxy_add_listener(ep->registry_proxy, &ep->registry_listener,
|
||||
®istry_events, ep);
|
||||
|
||||
/* Emit the audio DSP node */
|
||||
emit_audio_dsp_node(ep);
|
||||
|
||||
/* Return the object */
|
||||
return ep;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue