Skip to content
Snippets Groups Projects
Commit 661010a3 authored by George Kiagiadakis's avatar George Kiagiadakis
Browse files

Merge branch 'registry' into 'master'

Registry

See merge request gkiagia/wireplumber!12
parents 1f82868e d2b83370
No related branches found
No related tags found
No related merge requests found
......@@ -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,
&registry_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, &registry_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, &registry_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)
void
wireplumber__module_init (WpModule * module, WpCore * core, GVariant * args)
{
struct impl *impl;
WpRemote *remote;
WpRemotePipewire *rp;
/* Allocate impl */
impl = g_new0(struct impl, 1);
/* 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;
}
/* Set core */
/* Create the module data */
impl = g_slice_new0(struct impl);
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->remote_pipewire = rp;
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);
/* 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 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 Core */
core = wp_factory_get_core(factory);
g_return_val_if_fail (core, 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,
&registry_events, ep);
/* Emit the audio DSP node */
emit_audio_dsp_node(ep);
/* Return the object */
return ep;
}
void
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment