Commit ac7086d1 authored by George Kiagiadakis's avatar George Kiagiadakis

modules: port to new WpProxy API

parent ff59fc06
......@@ -389,8 +389,8 @@ wp_remote_pipewire_create_object (WpRemotePipewire *self,
g_return_val_if_fail (self->core_proxy, NULL);
pw_proxy = pw_core_proxy_create_object (self->core_proxy, factory_name,
interface_type, interface_version, wp_properties_peek_dict (properties),
0);
interface_type, interface_version,
properties ? wp_properties_peek_dict (properties) : NULL, 0);
return wp_proxy_new_wrap (WP_REMOTE (self), pw_proxy, interface_type,
interface_version);
}
......
......@@ -33,6 +33,6 @@ gnome = import('gnome')
wp_lib_include_dir = include_directories('lib')
subdir('lib')
#subdir('modules')
subdir('modules')
subdir('src')
subdir('tests')
......@@ -9,111 +9,22 @@
#include <wp/wp.h>
#include <pipewire/pipewire.h>
struct client_data
{
union {
struct pw_proxy *proxy;
struct pw_client_proxy *client_proxy;
};
struct spa_hook proxy_listener;
struct spa_hook client_listener;
gboolean done;
};
static gboolean
do_free_client_data (gpointer data)
{
g_rc_box_release (data);
return G_SOURCE_REMOVE;
}
static void
proxy_destroy (void *data)
{
struct client_data *d = data;
d->proxy = NULL;
/* destroy later because we can't free the memory of the proxy_listener
* while we are running in one of its callbacks */
g_idle_add (do_free_client_data, data);
}
static gboolean
do_destroy_proxy (gpointer data)
{
struct client_data *d = data;
if (d->proxy) {
g_debug ("Destroying client proxy %p", d->proxy);
pw_proxy_destroy (d->proxy);
}
return G_SOURCE_REMOVE;
}
static void
proxy_done (void *data, int seq)
{
struct client_data *d = data;
/* the proxy is not useful to keep around once we have changed permissions.
* take an extra ref on the client data because the proxy may
* disappear on its own if the client disconnects in the meantime */
if (d->done)
g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, do_destroy_proxy,
g_rc_box_acquire (d), g_rc_box_release);
}
static const struct pw_proxy_events proxy_events = {
PW_VERSION_PROXY_EVENTS,
.destroy = proxy_destroy,
.done = proxy_done,
};
static void
client_info (void *object, const struct pw_client_info *info)
client_added (WpRemote * remote, WpProxyClient *client, gpointer data)
{
struct client_data *d = object;
g_autoptr (WpProperties) properties = NULL;
const char *access;
guint32 id = wp_proxy_get_global_id (WP_PROXY (client));
if (!(info->change_mask & PW_CLIENT_CHANGE_MASK_PROPS))
return;
g_debug ("Client added: %d", id);
g_return_if_fail (info->props);
access = spa_dict_lookup (info->props, "pipewire.access");
properties = wp_proxy_client_get_properties (client);
access = wp_properties_get (properties, PW_KEY_ACCESS);
/* grant full permissions to restricted or security confined apps
TODO: we should eventually build a system where we can use the role
and the client's security label to grant access only to specific nodes
and endpoints in the graph */
if (!g_strcmp0 (access, "flatpak") || !g_strcmp0 (access, "restricted")) {
const struct pw_permission perm = PW_PERMISSION_INIT(-1, PW_PERM_RWX);
g_debug ("Granting full access to client %d (%p)", info->id, d->proxy);
pw_client_proxy_update_permissions (d->client_proxy, 1, &perm);
g_debug ("Granting full access to client %d", id);
wp_proxy_client_update_permissions (client, 1, -1, PW_PERM_RWX);
}
d->done = TRUE;
pw_proxy_sync (d->proxy, 123456);
}
static const struct pw_client_proxy_events client_events = {
PW_VERSION_CLIENT_PROXY_EVENTS,
.info = client_info,
};
static void
client_added (WpRemotePipewire * remote, guint32 id,
const struct spa_dict *properties, gpointer data)
{
struct client_data *d;
d = g_rc_box_new0 (struct client_data);
d->proxy = wp_remote_pipewire_proxy_bind (remote, id,
PW_TYPE_INTERFACE_Client);
pw_proxy_add_listener (d->proxy, &d->proxy_listener, &proxy_events, d);
pw_client_proxy_add_listener (d->client_proxy, &d->client_listener,
&client_events, d);
g_debug ("Bound to client %d (%p)", id, d->proxy);
}
void
......@@ -122,6 +33,9 @@ wireplumber__module_init (WpModule * module, WpCore * core, GVariant * args)
WpRemote *remote = wp_core_get_global (core, WP_GLOBAL_REMOTE_PIPEWIRE);
g_return_if_fail (remote != NULL);
wp_remote_pipewire_set_default_features (WP_REMOTE_PIPEWIRE (remote),
WP_TYPE_PROXY_CLIENT, WP_PROXY_FEATURE_PW_PROXY | WP_PROXY_FEATURE_INFO);
g_signal_connect(remote, "global-added::client", (GCallback) client_added,
NULL);
}
......@@ -102,16 +102,8 @@ simple_endpoint_link_finalize (GObject * object)
{
WpPipewireSimpleEndpointLink *self = WP_PIPEWIRE_SIMPLE_ENDPOINT_LINK(object);
/* Destroy the init task */
g_clear_object(&self->init_task);
/* Destroy the proxies port */
if (self->link_proxies) {
g_ptr_array_free(self->link_proxies, TRUE);
self->link_proxies = NULL;
}
/* Clear the core weak reference */
g_clear_object (&self->init_task);
g_clear_pointer (&self->link_proxies, g_ptr_array_unref);
g_weak_ref_clear (&self->core);
}
......@@ -150,34 +142,23 @@ simple_endpoint_link_get_property (GObject * object, guint property_id,
}
static void
finish_simple_endpoint_link_creation(WpPipewireSimpleEndpointLink *self)
{
/* Don't do anything if the link has already been initialized */
if (!self->init_task)
return;
/* Finish the creation of the audio dsp */
g_task_return_boolean (self->init_task, TRUE);
g_clear_object(&self->init_task);
}
static void
on_proxy_link_created(GObject *initable, GAsyncResult *res, gpointer data)
on_proxy_link_augmented (WpProxy *proxy, GAsyncResult *res, gpointer data)
{
WpPipewireSimpleEndpointLink *self = data;
WpProxyLink *proxy_link = NULL;
/* Get the link */
proxy_link = wp_proxy_link_new_finish(initable, res, NULL);
g_return_if_fail (proxy_link);
g_autoptr (GError) error = NULL;
/* Add the proxy link to the array */
g_ptr_array_add(self->link_proxies, proxy_link);
self->link_count--;
wp_proxy_augment_finish (proxy, res, &error);
if (error && self->init_task) {
g_task_return_error (self->init_task, g_steal_pointer (&error));
g_clear_object (&self->init_task);
return;
}
/* Finish the simple endpoint link creation if all links have been created */
if (self->link_count == 0)
finish_simple_endpoint_link_creation (self);
if (--self->link_count == 0 && self->init_task) {
g_task_return_boolean (self->init_task, TRUE);
g_clear_object(&self->init_task);
}
}
static gboolean
......@@ -185,15 +166,18 @@ simple_endpoint_link_create (WpEndpointLink * epl, GVariant * src_data,
GVariant * sink_data, GError ** error)
{
WpPipewireSimpleEndpointLink *self = WP_PIPEWIRE_SIMPLE_ENDPOINT_LINK(epl);
g_autoptr (WpCore) core = g_weak_ref_get (&self->core);
g_autoptr (WpCore) core = NULL;
WpRemotePipewire *remote_pipewire;
struct pw_properties *props;
guint32 output_node_id, input_node_id;
GVariant *src_ports, *sink_ports;
GVariantIter *out_iter, *in_iter;
guint64 out_ptr, in_ptr;
GHashTable *linked_ports = NULL;
struct pw_proxy *proxy;
g_autoptr (GHashTable) linked_ports = NULL;
g_autoptr (WpProperties) props = NULL;
WpProxy *proxy = NULL;
core = g_weak_ref_get (&self->core);
g_return_val_if_fail (core, FALSE);
/* Get the remote pipewire */
remote_pipewire = wp_core_get_global (core, WP_GLOBAL_REMOTE_PIPEWIRE);
......@@ -230,40 +214,37 @@ simple_endpoint_link_create (WpEndpointLink * epl, GVariant * src_data,
continue;
/* Skip the ports if they are already linked */
if (g_hash_table_contains (linked_ports, GUINT_TO_POINTER(in_id)))
continue;
if (g_hash_table_contains (linked_ports, GUINT_TO_POINTER(out_id)))
if (g_hash_table_contains (linked_ports, GUINT_TO_POINTER(in_id)) ||
g_hash_table_contains (linked_ports, GUINT_TO_POINTER(out_id)))
continue;
/* Create the properties */
props = pw_properties_new(NULL, NULL);
pw_properties_setf(props, PW_KEY_LINK_OUTPUT_NODE, "%d", output_node_id);
pw_properties_setf(props, PW_KEY_LINK_OUTPUT_PORT, "%d", out_id);
pw_properties_setf(props, PW_KEY_LINK_INPUT_NODE, "%d", input_node_id);
pw_properties_setf(props, PW_KEY_LINK_INPUT_PORT, "%d", in_id);
props = wp_properties_new_empty ();
wp_properties_setf(props, PW_KEY_LINK_OUTPUT_NODE, "%d", output_node_id);
wp_properties_setf(props, PW_KEY_LINK_OUTPUT_PORT, "%d", out_id);
wp_properties_setf(props, PW_KEY_LINK_INPUT_NODE, "%d", input_node_id);
wp_properties_setf(props, PW_KEY_LINK_INPUT_PORT, "%d", in_id);
/* Create the link */
proxy = wp_remote_pipewire_create_object(remote_pipewire, "link-factory",
PW_TYPE_INTERFACE_Link, &props->dict);
PW_TYPE_INTERFACE_Link, PW_VERSION_LINK_PROXY, props);
g_return_val_if_fail (proxy, FALSE);
wp_proxy_link_new (pw_proxy_get_id(proxy), proxy, on_proxy_link_created,
self);
g_ptr_array_add(self->link_proxies, proxy);
/* Wait for the link to be created on the server side
by waiting for the info event, which will be signaled anyway */
self->link_count++;
wp_proxy_augment (proxy, WP_PROXY_FEATURE_INFO, NULL,
(GAsyncReadyCallback) on_proxy_link_augmented, self);
/* Insert the port ids in the hash tables to know they are linked */
g_hash_table_insert (linked_ports, GUINT_TO_POINTER(in_id), NULL);
g_hash_table_insert (linked_ports, GUINT_TO_POINTER(out_id), NULL);
/* Clean up */
pw_properties_free(props);
g_hash_table_add (linked_ports, GUINT_TO_POINTER(in_id));
g_hash_table_add (linked_ports, GUINT_TO_POINTER(out_id));
}
g_variant_iter_free (in_iter);
}
g_variant_iter_free (out_iter);
/* Clean up */
g_hash_table_unref(linked_ports);
return TRUE;
}
......@@ -272,11 +253,7 @@ simple_endpoint_link_destroy (WpEndpointLink * epl)
{
WpPipewireSimpleEndpointLink *self = WP_PIPEWIRE_SIMPLE_ENDPOINT_LINK(epl);
/* Destroy the proxies port */
if (self->link_proxies) {
g_ptr_array_free(self->link_proxies, TRUE);
self->link_proxies = NULL;
}
g_clear_pointer (&self->link_proxies, g_ptr_array_unref);
}
static void
......
This diff is collapsed.
......@@ -54,9 +54,7 @@ struct node {
struct spa_list link;
uint32_t id;
struct pw_properties *props;
struct pw_proxy *proxy;
WpProxy *proxy;
struct spa_node *node;
};
......@@ -64,47 +62,45 @@ static void
on_endpoint_created(GObject *initable, GAsyncResult *res, gpointer d)
{
struct impl *impl = d;
WpEndpoint *endpoint = NULL;
g_autoptr (WpEndpoint) endpoint = NULL;
g_autoptr (WpProxy) proxy = NULL;
guint global_id = 0;
GError *error = NULL;
/* Get the endpoint */
endpoint = wp_endpoint_new_finish(initable, res, NULL);
g_return_if_fail (endpoint);
/* Check for error */
endpoint = wp_endpoint_new_finish(initable, res, &error);
if (error) {
g_clear_object (&endpoint);
g_warning ("Failed to create alsa endpoint: %s", error->message);
return;
}
/* Get the endpoint global id */
g_object_get (endpoint, "global-id", &global_id, NULL);
g_object_get (endpoint, "proxy-node", &proxy, NULL);
global_id = wp_proxy_get_global_id (proxy);
g_debug ("Created alsa endpoint for global id %d", global_id);
/* Register the endpoint and add it to the table */
wp_endpoint_register (endpoint);
g_hash_table_insert (impl->registered_endpoints, GUINT_TO_POINTER(global_id),
endpoint);
g_steal_pointer (&endpoint));
}
static void
on_node_added(WpRemotePipewire *rp, guint id, gconstpointer p, gpointer d)
on_node_added(WpRemotePipewire *rp, WpProxy *proxy, struct impl *impl)
{
struct impl *impl = d;
const struct spa_dict *props = p;
g_autoptr (WpCore) core = wp_module_get_core (impl->module);
const gchar *media_class, *name;
enum pw_direction direction;
GVariantBuilder b;
g_autoptr (WpProperties) props = NULL;
g_autoptr (GVariant) endpoint_props = NULL;
/* Make sure the node has properties */
props = wp_proxy_get_global_properties (proxy);
g_return_if_fail(props);
/* Get the media_class */
media_class = spa_dict_lookup(props, "media.class");
media_class = wp_properties_get (props, PW_KEY_MEDIA_CLASS);
/* Make sure the media class is non-convert audio */
if (!g_str_has_prefix (media_class, "Audio/"))
......@@ -113,9 +109,9 @@ on_node_added(WpRemotePipewire *rp, guint id, gconstpointer p, gpointer d)
return;
/* Get the name */
name = spa_dict_lookup (props, "media.name");
name = wp_properties_get (props, PW_KEY_MEDIA_NAME);
if (!name)
name = spa_dict_lookup (props, "node.name");
name = wp_properties_get (props, PW_KEY_NODE_NAME);
/* Don't handle bluetooth nodes */
if (g_str_has_prefix (name, "api.bluez5"))
......@@ -140,7 +136,7 @@ on_node_added(WpRemotePipewire *rp, guint id, gconstpointer p, gpointer d)
g_variant_builder_add (&b, "{sv}",
"direction", g_variant_new_uint32 (direction));
g_variant_builder_add (&b, "{sv}",
"global-id", g_variant_new_uint32 (id));
"proxy-node", g_variant_new_uint64 ((guint64) proxy));
g_variant_builder_add (&b, "{sv}",
"streams", impl->streams);
endpoint_props = g_variant_builder_end (&b);
......@@ -151,10 +147,10 @@ on_node_added(WpRemotePipewire *rp, guint id, gconstpointer p, gpointer d)
}
static void
on_global_removed (WpRemotePipewire *rp, guint id, gpointer d)
on_global_removed (WpRemotePipewire *rp, WpProxy *proxy, struct impl *impl)
{
struct impl *impl = d;
WpEndpoint *endpoint = NULL;
guint32 id = wp_proxy_get_global_id (proxy);
/* Get the endpoint */
endpoint = g_hash_table_lookup (impl->registered_endpoints,
......@@ -173,6 +169,7 @@ create_node(struct impl *impl, struct device *dev, uint32_t id,
{
struct node *node;
const char *str;
g_autoptr (WpProperties) props = NULL;
/* Check if the type is a node */
if (info->type != SPA_TYPE_INTERFACE_Node)
......@@ -182,25 +179,27 @@ create_node(struct impl *impl, struct device *dev, uint32_t id,
node = g_slice_new0(struct node);
/* Set the node properties */
node->props = pw_properties_copy(dev->props);
pw_properties_update(node->props, info->props);
str = pw_properties_get(dev->props, SPA_KEY_DEVICE_NICK);
props = wp_properties_new_copy (dev->props);
str = wp_properties_get (props, SPA_KEY_DEVICE_NICK);
if (str == NULL)
str = pw_properties_get(dev->props, SPA_KEY_DEVICE_NAME);
str = wp_properties_get (props, SPA_KEY_DEVICE_NAME);
if (str == NULL)
str = pw_properties_get(dev->props, SPA_KEY_DEVICE_ALIAS);
str = wp_properties_get (props, SPA_KEY_DEVICE_ALIAS);
if (str == NULL)
str = "alsa-device";
pw_properties_set(node->props, PW_KEY_NODE_NAME, str);
pw_properties_set(node->props, "factory.name", info->factory_name);
pw_properties_set(node->props, "merger.monitor", "1");
wp_properties_update_from_dict (props, info->props);
wp_properties_set(props, PW_KEY_NODE_NAME, str);
wp_properties_set(props, "factory.name", info->factory_name);
wp_properties_set(props, "merger.monitor", "1");
/* Set the node info */
node->impl = impl;
node->device = dev;
node->id = id;
node->proxy = wp_remote_pipewire_create_object(impl->remote_pipewire,
"adapter", PW_TYPE_INTERFACE_Node, &node->props->dict);
node->proxy = wp_remote_pipewire_create_object (impl->remote_pipewire,
"adapter", PW_TYPE_INTERFACE_Node, PW_VERSION_NODE_PROXY, props);
if (!node->proxy) {
g_slice_free (struct node, node);
return NULL;
......@@ -216,8 +215,6 @@ static void
update_node(struct impl *impl, struct device *dev, struct node *node,
const struct spa_device_object_info *info)
{
/* Just update the properties */
pw_properties_update(node->props, info->props);
}
static void destroy_node(struct impl *impl, struct device *dev, struct node *node)
......@@ -226,7 +223,7 @@ static void destroy_node(struct impl *impl, struct device *dev, struct node *nod
spa_list_remove(&node->link);
/* Destroy the proxy node */
pw_proxy_destroy(node->proxy);
g_clear_object (&node->proxy);
/* Destroy the node */
g_slice_free (struct node, node);
......
......@@ -25,47 +25,44 @@ static void
on_endpoint_created(GObject *initable, GAsyncResult *res, gpointer d)
{
struct module_data *data = d;
WpEndpoint *endpoint = NULL;
g_autoptr (WpEndpoint) endpoint = NULL;
g_autoptr (WpProxy) proxy = NULL;
guint global_id = 0;
GError *error = NULL;
/* Get the endpoint */
endpoint = wp_endpoint_new_finish(initable, res, NULL);
g_return_if_fail (endpoint);
/* Check for error */
endpoint = wp_endpoint_new_finish(initable, res, &error);
if (error) {
g_clear_object (&endpoint);
g_warning ("Failed to create client endpoint: %s", error->message);
return;
}
/* Get the endpoint global id */
g_object_get (endpoint, "global-id", &global_id, NULL);
g_object_get (endpoint, "proxy-node", &proxy, NULL);
global_id = wp_proxy_get_global_id (proxy);
g_debug ("Created client endpoint for global id %d", global_id);
/* Register the endpoint and add it to the table */
wp_endpoint_register (endpoint);
g_hash_table_insert (data->registered_endpoints, GUINT_TO_POINTER(global_id),
endpoint);
g_steal_pointer (&endpoint));
}
static void
on_node_added (WpRemotePipewire *rp, guint id, gconstpointer p, gpointer d)
on_node_added (WpRemotePipewire *rp, WpProxy *proxy, gpointer d)
{
struct module_data *data = d;
const struct spa_dict *props = p;
g_autoptr (WpCore) core = wp_module_get_core (data->module);
const gchar *name, *media_class;
enum pw_direction direction;
GVariantBuilder b;
g_autoptr (GVariant) endpoint_props = NULL;
/* Make sure the node has properties */
g_return_if_fail(props);
guint32 id = wp_proxy_get_global_id (proxy);
g_autoptr (WpProperties) props = wp_proxy_get_global_properties (proxy);
/* Get the media_class */
media_class = spa_dict_lookup(props, "media.class");
media_class = wp_properties_get (props, PW_KEY_MEDIA_CLASS);
/* Only handle client Stream nodes */
if (!g_str_has_prefix (media_class, "Stream/"))
......@@ -82,9 +79,9 @@ on_node_added (WpRemotePipewire *rp, guint id, gconstpointer p, gpointer d)
}
/* Get the name */
name = spa_dict_lookup (props, "media.name");
name = wp_properties_get (props, PW_KEY_MEDIA_NAME);
if (!name)
name = spa_dict_lookup (props, "node.name");
name = wp_properties_get (props, PW_KEY_NODE_NAME);
/* Set the properties */
g_variant_builder_init (&b, G_VARIANT_TYPE_VARDICT);
......@@ -97,7 +94,7 @@ on_node_added (WpRemotePipewire *rp, guint id, gconstpointer p, gpointer d)
g_variant_builder_add (&b, "{sv}",
"direction", g_variant_new_uint32 (direction));
g_variant_builder_add (&b, "{sv}",
"global-id", g_variant_new_uint32 (id));
"proxy-node", g_variant_new_uint64 ((guint64) proxy));
endpoint_props = g_variant_builder_end (&b);
/* Create the endpoint async */
......@@ -106,10 +103,11 @@ on_node_added (WpRemotePipewire *rp, guint id, gconstpointer p, gpointer d)
}
static void
on_global_removed (WpRemotePipewire *rp, guint id, gpointer d)
on_global_removed (WpRemotePipewire *rp, WpProxy *proxy, gpointer d)
{
struct module_data *data = d;
WpEndpoint *endpoint = NULL;
guint32 id = wp_proxy_get_global_id (proxy);
/* Get the endpoint */
endpoint = g_hash_table_lookup (data->registered_endpoints,
......@@ -132,8 +130,7 @@ module_destroy (gpointer d)
data->remote_pipewire = NULL;
/* Destroy the registered endpoints table */
g_hash_table_unref(data->registered_endpoints);
data->registered_endpoints = NULL;
g_clear_pointer (&data->registered_endpoints, g_hash_table_unref);
/* Clean up */
g_slice_free (struct module_data, data);
......
......@@ -32,7 +32,7 @@ struct _WpPwAudioSoftdspEndpoint
WpEndpoint parent;
/* Properties */
guint global_id;
WpProxyNode *proxy_node;
GVariant *streams;
guint stream_count;
......@@ -40,7 +40,6 @@ struct _WpPwAudioSoftdspEndpoint
/* The task to signal the endpoint is initialized */
GTask *init_task;
gboolean init_abort;
/* Audio Streams */
WpAudioStream *adapter;
......@@ -49,7 +48,7 @@ struct _WpPwAudioSoftdspEndpoint
enum {
PROP_0,
PROP_GLOBAL_ID,
PROP_PROXY_NODE,
PROP_STREAMS,
};
......@@ -71,28 +70,23 @@ static GObject *
object_safe_new_finish(WpPwAudioSoftdspEndpoint * self, GObject *initable,
GAsyncResult *res, WpObjectNewFinishFunc new_finish_func)
{
GObject *object = NULL;
g_autoptr (GObject) object = NULL;
GError *error = NULL;
/* Return NULL if we are already aborting */
if (self->init_abort)
if (!self->init_task)
return NULL;
/* Get the object */
object = G_OBJECT (new_finish_func (initable, res, &error));
g_return_val_if_fail (object, NULL);
/* Check for error */
if (error) {
g_clear_object (&object);
g_warning ("WpPwAudioSoftdspEndpoint:%p Aborting construction", self);
self->init_abort = TRUE;
g_task_return_error (self->init_task, error);
g_clear_object (&self->init_task);
return NULL;
}
return object;
return g_steal_pointer (&object);
}
static gboolean
......@@ -161,8 +155,8 @@ on_audio_adapter_created(GObject *initable, GAsyncResult *res,
WpPwAudioSoftdspEndpoint *self = data;
enum pw_direction direction = wp_endpoint_get_direction(WP_ENDPOINT(self));
g_autoptr (WpCore) core = wp_endpoint_get_core(WP_ENDPOINT(self));
g_autoptr (WpProperties) props = NULL;
g_autofree gchar *name = NULL;
const struct pw_node_info *adapter_info = NULL;
GVariantDict d;
GVariantIter iter;
const gchar *stream;
......@@ -174,25 +168,23 @@ on_audio_adapter_created(GObject *initable, GAsyncResult *res,
if (!self->adapter)
return;
/* Get the adapter info */
adapter_info = wp_audio_stream_get_info (self->adapter);
g_return_if_fail (adapter_info);
props = wp_proxy_node_get_properties (self->proxy_node);
/* Give a proper name to this endpoint based on adapter properties */
if (0 == g_strcmp0(spa_dict_lookup (adapter_info->props, "device.api"), "alsa")) {
name = g_strdup_printf ("%s on %s (%s / node %d)",
spa_dict_lookup (adapter_info->props, "api.alsa.pcm.name"),
spa_dict_lookup (adapter_info->props, "api.alsa.card.name"),
spa_dict_lookup (adapter_info->props, "api.alsa.path"),
adapter_info->id);
if (0 == g_strcmp0(wp_properties_get (props, "device.api"), "alsa")) {
name = g_strdup_printf ("%s on %s (%s / node %s)",
wp_properties_get (props, "api.alsa.pcm.name"),
wp_properties_get (props, "api.alsa.card.name"),
wp_properties_get (props, "api.alsa.path"),
wp_properties_get (props, PW_KEY_NODE_ID));
g_object_set (self, "name", name, NULL);
}
/* Create the audio converters */
g_variant_iter_init (&iter, self->streams);
for (i = 0; g_variant_iter_next (&iter, "&s", &stream); i++) {
wp_audio_convert_new (WP_ENDPOINT(self), i, stream, direction, adapter_info,
on_audio_convert_created, self);
wp_audio_convert_new (WP_ENDPOINT(self), i, stream, direction,
self->proxy_node, on_audio_convert_created, self);
/* Register the stream */
g_variant_dict_init (&d, NULL);
......@@ -219,6 +211,8 @@ endpoint_finalize (GObject * object)
/* Destroy the done task */
g_clear_object(&self->init_task);
g_clear_object(&self->proxy_node);
G_OBJECT_CLASS (endpoint_parent_class)->finalize (object);
}
......@@ -229,8 +223,8 @@ endpoint_set_property (GObject * object, guint property_id,
WpPwAudioSoftdspEndpoint *self = WP_PW_AUDIO_SOFTDSP_ENDPOINT (object);
switch (property_id) {
case PROP_GLOBAL_ID:
self->global_id = g_value_get_uint(value);
case PROP_PROXY_NODE:
self->proxy_node = g_value_dup_object (value);
break;
case PROP_STREAMS:
self->streams = g_value_dup_variant(value);
......@@ -248,8 +242,8 @@ endpoint_get_property (GObject * object, guint property_id,
WpPwAudioSoftdspEndpoint *self = WP_PW_AUDIO_SOFTDSP_ENDPOINT (object);
switch (property_id) {
case PROP_GLOBAL_ID:
g_value_set_uint (value, self->global_id);
case PROP_PROXY_NODE:
g_value_set_object (value, self->proxy_node);
break;
case PROP_STREAMS:
g_value_set_variant (value, self->streams);
......@@ -323,7 +317,7 @@ wp_endpoint_init_async (GAsyncInitable *initable, int io_priority,
/* Create the adapter proxy */
wp_audio_adapter_new (WP_ENDPOINT(self), WP_STREAM_ID_NONE, "master",
direction, self->global_id, FALSE, on_audio_adapter_created, self);
direction, self->proxy_node, FALSE, on_audio_adapter_created, self);
/* Register the selected control */
self->se