Commit 789194b5 authored by George Kiagiadakis's avatar George Kiagiadakis

Merge remote-tracking branch 'origin/master' into proxy-refactoring

parents a5e86717 dcbf823a
......@@ -93,6 +93,7 @@ struct _WpEndpointPrivate
{
gchar *name;
gchar media_class[40];
guint direction;
GPtrArray *streams;
GPtrArray *controls;
GPtrArray *links;
......@@ -104,6 +105,7 @@ enum {
PROP_CORE,
PROP_NAME,
PROP_MEDIA_CLASS,
PROP_DIRECTION,
};
enum {
......@@ -211,6 +213,9 @@ wp_endpoint_set_property (GObject * object, guint property_id,
strncpy (priv->media_class, g_value_get_string (value),
sizeof (priv->media_class) - 1);
break;
case PROP_DIRECTION:
priv->direction = g_value_get_uint(value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
......@@ -234,6 +239,9 @@ wp_endpoint_get_property (GObject * object, guint property_id, GValue * value,
case PROP_MEDIA_CLASS:
g_value_set_string (value, priv->media_class);
break;
case PROP_DIRECTION:
g_value_set_uint (value, priv->direction);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
......@@ -281,6 +289,15 @@ wp_endpoint_class_init (WpEndpointClass * klass)
signals[SIGNAL_NOTIFY_CONTROL_VALUE] = g_signal_new ("notify-control-value",
G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL,
G_TYPE_NONE, 1, G_TYPE_UINT);
/**
* WpEndpoint::direction:
* The direction of the endpoint: input = 0, output = 1.
*/
g_object_class_install_property (object_class, PROP_DIRECTION,
g_param_spec_uint ("direction", "direction",
"The direction of the endpoint", 0, 1, 0,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
}
/**
......@@ -465,6 +482,17 @@ wp_endpoint_get_media_class (WpEndpoint * self)
return priv->media_class;
}
guint
wp_endpoint_get_direction (WpEndpoint * self)
{
WpEndpointPrivate *priv;
g_return_val_if_fail (WP_IS_ENDPOINT (self), -1);
priv = wp_endpoint_get_instance_private (self);
return priv->direction;
}
/**
* wp_endpoint_register_stream:
* @self: the endpoint
......
......@@ -48,6 +48,7 @@ GPtrArray * wp_endpoint_find (WpCore * core, const gchar * media_class_lookup);
WpCore *wp_endpoint_get_core (WpEndpoint * self);
const gchar * wp_endpoint_get_name (WpEndpoint * self);
const gchar * wp_endpoint_get_media_class (WpEndpoint * self);
guint wp_endpoint_get_direction (WpEndpoint * self);
void wp_endpoint_register_stream (WpEndpoint * self, GVariant * stream);
GVariant * wp_endpoint_get_stream (WpEndpoint * self, guint32 stream_id);
......
......@@ -42,9 +42,6 @@ struct _WpPipewireSimpleEndpoint
/* Handler */
gulong proxy_node_done_handler_id;
/* Direction */
enum pw_direction direction;
/* Proxies */
WpProxyNode *proxy_node;
struct spa_hook node_proxy_listener;
......@@ -230,6 +227,7 @@ on_port_added(WpRemotePipewire *rp, guint id, gconstpointer p, gpointer d)
static void
emit_endpoint_ports(WpPipewireSimpleEndpoint *self)
{
enum pw_direction direction = wp_endpoint_get_direction (WP_ENDPOINT (self));
struct pw_node_proxy* node_proxy = NULL;
struct spa_audio_info_raw format = { 0, };
struct spa_pod *param;
......@@ -252,7 +250,7 @@ emit_endpoint_ports(WpPipewireSimpleEndpoint *self)
param = spa_format_audio_raw_build(&pod_builder, SPA_PARAM_Format, &format);
param = spa_pod_builder_add_object(&pod_builder,
SPA_TYPE_OBJECT_ParamPortConfig, SPA_PARAM_PortConfig,
SPA_PARAM_PORT_CONFIG_direction, SPA_POD_Id(self->direction),
SPA_PARAM_PORT_CONFIG_direction, SPA_POD_Id(direction),
SPA_PARAM_PORT_CONFIG_mode, SPA_POD_Id(SPA_PARAM_PORT_CONFIG_MODE_dsp),
SPA_PARAM_PORT_CONFIG_format, SPA_POD_Pod(param));
......@@ -323,7 +321,6 @@ wp_simple_endpoint_init_async (GAsyncInitable *initable, int io_priority,
{
WpPipewireSimpleEndpoint *self = WP_PIPEWIRE_SIMPLE_ENDPOINT (initable);
g_autoptr (WpCore) core = wp_endpoint_get_core(WP_ENDPOINT(self));
const gchar *media_class = wp_endpoint_get_media_class (WP_ENDPOINT (self));
struct pw_node_proxy *node_proxy = NULL;
/* Create the async task */
......@@ -332,14 +329,6 @@ wp_simple_endpoint_init_async (GAsyncInitable *initable, int io_priority,
/* Init the proxies_port array */
self->proxies_port = g_ptr_array_new_full(2, (GDestroyNotify)g_object_unref);
/* Set the direction */
if (g_str_has_prefix (media_class, "Stream/Input"))
self->direction = PW_DIRECTION_INPUT;
else if (g_str_has_prefix (media_class, "Stream/Output"))
self->direction = PW_DIRECTION_OUTPUT;
else
g_critical ("failed to parse direction");
/* Register a port_added callback */
self->remote_pipewire = wp_core_get_global (core, WP_GLOBAL_REMOTE_PIPEWIRE);
g_return_if_fail(self->remote_pipewire);
......@@ -579,6 +568,7 @@ simple_endpoint_factory (WpFactory * factory, GType type,
{
g_autoptr (WpCore) core = NULL;
const gchar *name, *media_class;
guint direction;
guint global_id;
/* Make sure the type is correct */
......@@ -593,6 +583,8 @@ simple_endpoint_factory (WpFactory * factory, GType type,
return;
if (!g_variant_lookup (properties, "media-class", "&s", &media_class))
return;
if (!g_variant_lookup (properties, "direction", "u", &direction))
return;
if (!g_variant_lookup (properties, "global-id", "u", &global_id))
return;
......@@ -601,6 +593,7 @@ simple_endpoint_factory (WpFactory * factory, GType type,
"core", core,
"name", name,
"media-class", media_class,
"direction", direction,
"global-id", global_id,
NULL);
}
......@@ -96,6 +96,7 @@ on_node_added(WpRemotePipewire *rp, guint id, gconstpointer p, gpointer 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 (GVariant) endpoint_props = NULL;
......@@ -116,12 +117,28 @@ on_node_added(WpRemotePipewire *rp, guint id, gconstpointer p, gpointer d)
if (!name)
name = spa_dict_lookup (props, "node.name");
/* Don't handle bluetooth nodes */
if (g_str_has_prefix (name, "api.bluez5"))
return;
/* Get the direction */
if (g_str_has_prefix (media_class, "Audio/Sink")) {
direction = PW_DIRECTION_INPUT;
} else if (g_str_has_prefix (media_class, "Audio/Source")) {
direction = PW_DIRECTION_OUTPUT;
} else {
g_critical ("failed to parse direction");
return;
}
/* Set the properties */
g_variant_builder_init (&b, G_VARIANT_TYPE_VARDICT);
g_variant_builder_add (&b, "{sv}",
"name", g_variant_new_string (name));
g_variant_builder_add (&b, "{sv}",
"media-class", g_variant_new_string (media_class));
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));
g_variant_builder_add (&b, "{sv}",
......
......@@ -57,6 +57,7 @@ on_node_added (WpRemotePipewire *rp, guint id, gconstpointer p, gpointer 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;
......@@ -70,6 +71,16 @@ on_node_added (WpRemotePipewire *rp, guint id, gconstpointer p, gpointer d)
if (!g_str_has_prefix (media_class, "Stream/"))
return;
/* Get the direction */
if (g_str_has_prefix (media_class, "Stream/Input")) {
direction = PW_DIRECTION_INPUT;
} else if (g_str_has_prefix (media_class, "Stream/Output")) {
direction = PW_DIRECTION_OUTPUT;
} else {
g_critical ("failed to parse direction");
return;
}
/* Get the name */
name = spa_dict_lookup (props, "media.name");
if (!name)
......@@ -83,6 +94,8 @@ on_node_added (WpRemotePipewire *rp, guint id, gconstpointer p, gpointer d)
g_variant_new_take_string (g_strdup_printf ("Stream %u", id)));
g_variant_builder_add (&b, "{sv}",
"media-class", g_variant_new_string (media_class));
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));
endpoint_props = g_variant_builder_end (&b);
......
......@@ -42,9 +42,6 @@ struct _WpPwAudioSoftdspEndpoint
GTask *init_task;
gboolean init_abort;
/* Direction */
enum pw_direction direction;
/* Audio Streams */
WpAudioStream *adapter;
GPtrArray *converters;
......@@ -162,6 +159,7 @@ on_audio_adapter_created(GObject *initable, GAsyncResult *res,
gpointer data)
{
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_autofree gchar *name = NULL;
const struct pw_node_info *adapter_info = NULL;
......@@ -193,8 +191,8 @@ on_audio_adapter_created(GObject *initable, GAsyncResult *res,
/* 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, self->direction,
adapter_info, on_audio_convert_created, self);
wp_audio_convert_new (WP_ENDPOINT(self), i, stream, direction, adapter_info,
on_audio_convert_created, self);
/* Register the stream */
g_variant_dict_init (&d, NULL);
......@@ -316,24 +314,16 @@ wp_endpoint_init_async (GAsyncInitable *initable, int io_priority,
GCancellable *cancellable, GAsyncReadyCallback callback, gpointer data)
{
WpPwAudioSoftdspEndpoint *self = WP_PW_AUDIO_SOFTDSP_ENDPOINT (initable);
enum pw_direction direction = wp_endpoint_get_direction(WP_ENDPOINT(self));
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;
/* Create the async task */
self->init_task = g_task_new (initable, cancellable, callback, data);
/* Set the direction */
if (g_str_has_suffix (media_class, "Source"))
self->direction = PW_DIRECTION_OUTPUT;
else if (g_str_has_suffix (media_class, "Sink"))
self->direction = PW_DIRECTION_INPUT;
else
g_critical ("failed to parse direction");
/* Create the adapter proxy */
wp_audio_adapter_new (WP_ENDPOINT(self), WP_STREAM_ID_NONE, "master",
self->direction, self->global_id, FALSE, on_audio_adapter_created, self);
direction, self->global_id, FALSE, on_audio_adapter_created, self);
/* Register the selected control */
self->selected = FALSE;
......@@ -401,6 +391,7 @@ endpoint_factory (WpFactory * factory, GType type, GVariant * properties,
{
g_autoptr (WpCore) core = NULL;
const gchar *name, *media_class;
guint direction;
guint global_id;
g_autoptr (GVariant) streams = NULL;
......@@ -416,6 +407,8 @@ endpoint_factory (WpFactory * factory, GType type, GVariant * properties,
return;
if (!g_variant_lookup (properties, "media-class", "&s", &media_class))
return;
if (!g_variant_lookup (properties, "direction", "u", &direction))
return;
if (!g_variant_lookup (properties, "global-id", "u", &global_id))
return;
if (!(streams = g_variant_lookup_value (properties, "streams",
......@@ -428,6 +421,7 @@ endpoint_factory (WpFactory * factory, GType type, GVariant * properties,
"core", core,
"name", name,
"media-class", media_class,
"direction", direction,
"global-id", global_id,
"streams", streams,
NULL);
......
......@@ -26,6 +26,7 @@ struct _WpAudioAdapter
/* The task to signal the proxy is initialized */
GTask *init_task;
gboolean init_abort;
gboolean ports_done;
/* Props */
guint adapter_id;
......@@ -79,9 +80,45 @@ on_audio_adapter_done(WpProxy *proxy, gpointer data)
{
WpAudioAdapter *self = data;
/* Emit the ports if not done and sync again */
if (!self->ports_done) {
enum pw_direction direction =
wp_audio_stream_get_direction ( WP_AUDIO_STREAM (self));
struct pw_node_proxy *pw_proxy = NULL;
uint8_t buf[1024];
struct spa_pod_builder pod_builder = SPA_POD_BUILDER_INIT(buf, sizeof(buf));
struct spa_pod *param;
/* Emit the props param */
pw_proxy = wp_proxy_get_pw_proxy(WP_PROXY(self->proxy));
pw_node_proxy_enum_params (pw_proxy, 0, SPA_PARAM_Props, 0, -1, NULL);
/* Emit the ports */
if (self->convert) {
param = spa_pod_builder_add_object(&pod_builder,
SPA_TYPE_OBJECT_ParamPortConfig, SPA_PARAM_PortConfig,
SPA_PARAM_PORT_CONFIG_direction, SPA_POD_Id(direction),
SPA_PARAM_PORT_CONFIG_mode, SPA_POD_Id(SPA_PARAM_PORT_CONFIG_MODE_convert));
} else {
struct spa_audio_info_raw format = *wp_proxy_node_get_format (self->proxy);
param = spa_format_audio_raw_build(&pod_builder, SPA_PARAM_Format, &format);
param = spa_pod_builder_add_object(&pod_builder,
SPA_TYPE_OBJECT_ParamPortConfig, SPA_PARAM_PortConfig,
SPA_PARAM_PORT_CONFIG_direction, SPA_POD_Id(direction),
SPA_PARAM_PORT_CONFIG_mode, SPA_POD_Id(SPA_PARAM_PORT_CONFIG_MODE_dsp),
SPA_PARAM_PORT_CONFIG_format, SPA_POD_Pod(param));
}
pw_node_proxy_set_param(pw_proxy, SPA_PARAM_PortConfig, 0, param);
/* Sync */
self->ports_done = TRUE;
wp_proxy_sync (WP_PROXY(self->proxy));
return;
}
/* Don't do anything if the audio adapter has already been initialized */
if (!self->init_task)
return;
return;
/* Finish the creation of the audio adapter */
g_task_return_boolean (self->init_task, TRUE);
......@@ -93,12 +130,6 @@ on_audio_adapter_proxy_created(GObject *initable, GAsyncResult *res,
gpointer data)
{
WpAudioAdapter *self = data;
enum pw_direction direction =
wp_audio_stream_get_direction ( WP_AUDIO_STREAM (self));
struct pw_node_proxy *pw_proxy = NULL;
uint8_t buf[1024];
struct spa_pod_builder pod_builder = SPA_POD_BUILDER_INIT(buf, sizeof(buf));
struct spa_pod *param;
/* Get the adapter proxy */
self->proxy = WP_PROXY_NODE (object_safe_new_finish (self, initable,
......@@ -106,39 +137,10 @@ on_audio_adapter_proxy_created(GObject *initable, GAsyncResult *res,
if (!self->proxy)
return;
/* Get the pipewire proxy */
pw_proxy = wp_proxy_get_pw_proxy(WP_PROXY(self->proxy));
g_return_if_fail (pw_proxy);
/* Emit the props param */
pw_node_proxy_enum_params (pw_proxy, 0, SPA_PARAM_Props, 0, -1, NULL);
/* Emit the ports */
if (self->convert) {
param = spa_pod_builder_add_object(&pod_builder,
SPA_TYPE_OBJECT_ParamPortConfig, SPA_PARAM_PortConfig,
SPA_PARAM_PORT_CONFIG_direction, SPA_POD_Id(direction),
SPA_PARAM_PORT_CONFIG_mode, SPA_POD_Id(SPA_PARAM_PORT_CONFIG_MODE_convert));
pw_node_proxy_set_param(pw_proxy, SPA_PARAM_PortConfig, 0, param);
} else {
struct spa_audio_info_raw format;
spa_zero(format);
format.format = SPA_AUDIO_FORMAT_F32P;
format.flags = 1;
format.rate = 48000;
format.channels = 2;
format.position[0] = SPA_AUDIO_CHANNEL_FL;
format.position[1] = SPA_AUDIO_CHANNEL_FR;
param = spa_format_audio_raw_build(&pod_builder, SPA_PARAM_Format, &format);
param = spa_pod_builder_add_object(&pod_builder,
SPA_TYPE_OBJECT_ParamPortConfig, SPA_PARAM_PortConfig,
SPA_PARAM_PORT_CONFIG_direction, SPA_POD_Id(direction),
SPA_PARAM_PORT_CONFIG_mode, SPA_POD_Id(SPA_PARAM_PORT_CONFIG_MODE_dsp),
SPA_PARAM_PORT_CONFIG_format, SPA_POD_Pod(param));
pw_node_proxy_set_param(pw_proxy, SPA_PARAM_PortConfig, 0, param);
}
/* Emit the EnumFormat param */
wp_proxy_node_enum_params (self->proxy, 0, SPA_PARAM_EnumFormat, 0, -1, NULL);
/* Register a callback to know when all the adapter ports have been emitted */
/* Register the done callback */
g_signal_connect_object(self->proxy, "done", (GCallback)on_audio_adapter_done,
self, 0);
wp_proxy_sync (WP_PROXY(self->proxy));
......@@ -248,6 +250,7 @@ static void
wp_audio_adapter_init (WpAudioAdapter * self)
{
self->init_abort = FALSE;
self->ports_done = FALSE;
}
static void
......
......@@ -25,6 +25,7 @@ struct monitor {
struct impl {
WpModule *module;
WpRemotePipewire *remote_pipewire;
GHashTable *registered_endpoints;
/* The bluez monitor */
struct monitor monitor;
......@@ -57,6 +58,107 @@ struct node {
struct pw_proxy *proxy;
};
static void
on_endpoint_created(GObject *initable, GAsyncResult *res, gpointer d)
{
struct impl *data = d;
WpEndpoint *endpoint = 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 */
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_debug ("Created bluetooth 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);
}
static void
on_node_added (WpRemotePipewire *rp, guint id, gconstpointer p, gpointer d)
{
struct impl *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);
/* Get the media_class */
media_class = spa_dict_lookup(props, "media.class");
/* Get the name */
name = spa_dict_lookup (props, "media.name");
if (!name)
name = spa_dict_lookup (props, "node.name");
/* Only handle bluetooth nodes */
if (!g_str_has_prefix (name, "api.bluez5"))
return;
/* Get the direction */
if (g_str_has_prefix (media_class, "Audio/Sink")) {
direction = PW_DIRECTION_INPUT;
} else if (g_str_has_prefix (media_class, "Audio/Source")) {
direction = PW_DIRECTION_OUTPUT;
} else {
g_critical ("failed to parse direction");
return;
}
/* Set the properties */
g_variant_builder_init (&b, G_VARIANT_TYPE_VARDICT);
g_variant_builder_add (&b, "{sv}",
"name", name ?
g_variant_new_take_string (g_strdup_printf ("Stream %u (%s)", id, name)) :
g_variant_new_take_string (g_strdup_printf ("Stream %u", id)));
g_variant_builder_add (&b, "{sv}",
"media-class", g_variant_new_string (media_class));
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));
endpoint_props = g_variant_builder_end (&b);
/* Create the endpoint async */
wp_factory_make (core, "pipewire-simple-endpoint", WP_TYPE_ENDPOINT,
endpoint_props, on_endpoint_created, data);
}
static void
on_global_removed (WpRemotePipewire *rp, guint id, gpointer d)
{
struct impl *data = d;
WpEndpoint *endpoint = NULL;
/* Get the endpoint */
endpoint = g_hash_table_lookup (data->registered_endpoints,
GUINT_TO_POINTER(id));
if (!endpoint)
return;
/* Unregister the endpoint and remove it from the table */
wp_endpoint_unregister (endpoint);
g_hash_table_remove (data->registered_endpoints, GUINT_TO_POINTER(id));
}
static struct node *
create_node(struct impl *impl, struct device *dev, uint32_t id,
const struct spa_device_object_info *info)
......@@ -343,6 +445,10 @@ module_destroy (gpointer data)
impl->module = NULL;
impl->remote_pipewire = NULL;
/* Destroy the registered endpoints table */
g_hash_table_unref(impl->registered_endpoints);
impl->registered_endpoints = NULL;
/* Clean up */
g_slice_free (struct impl, impl);
}
......@@ -365,6 +471,8 @@ wireplumber__module_init (WpModule * module, WpCore * core, GVariant * args)
impl = g_slice_new0(struct impl);
impl->module = module;
impl->remote_pipewire = rp;
impl->registered_endpoints = g_hash_table_new_full (g_direct_hash,
g_direct_equal, NULL, (GDestroyNotify)g_object_unref);
/* Set destroy callback for impl */
wp_module_set_destroy_callback (module, module_destroy, impl);
......@@ -374,4 +482,8 @@ wireplumber__module_init (WpModule * module, WpCore * core, GVariant * args)
/* Start the monitor when the connected callback is triggered */
g_signal_connect(rp, "state-changed::connected", (GCallback)start_monitor, impl);
/* Register the global added/removed callbacks */
g_signal_connect(rp, "global-added::node", (GCallback)on_node_added, impl);
g_signal_connect(rp, "global-removed", (GCallback)on_global_removed, impl);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment