mirror of
https://gitlab.freedesktop.org/pipewire/wireplumber.git
synced 2026-05-09 07:28:41 +02:00
modules: refactor config-endpoint to use the new session item API
This commit is contained in:
parent
20708b28c7
commit
288f1f091b
14 changed files with 405 additions and 491 deletions
|
|
@ -14,6 +14,8 @@
|
|||
#include "parser-streams.h"
|
||||
#include "context.h"
|
||||
|
||||
G_DEFINE_QUARK (wp-module-config-endpoint-context-session, session);
|
||||
|
||||
struct _WpConfigEndpointContext
|
||||
{
|
||||
GObject parent;
|
||||
|
|
@ -21,8 +23,9 @@ struct _WpConfigEndpointContext
|
|||
/* Props */
|
||||
GWeakRef core;
|
||||
|
||||
WpObjectManager *om;
|
||||
GHashTable *registered_endpoints;
|
||||
WpObjectManager *sessions_om;
|
||||
WpObjectManager *nodes_om;
|
||||
GHashTable *endpoints;
|
||||
};
|
||||
|
||||
enum {
|
||||
|
|
@ -40,63 +43,52 @@ static guint signals[N_SIGNALS];
|
|||
G_DEFINE_TYPE (WpConfigEndpointContext, wp_config_endpoint_context,
|
||||
G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
on_endpoint_created (GObject *initable, GAsyncResult *res, gpointer d)
|
||||
{
|
||||
WpConfigEndpointContext *self = d;
|
||||
g_autoptr (WpBaseEndpoint) endpoint = NULL;
|
||||
g_autoptr (WpProxy) proxy = NULL;
|
||||
guint global_id = 0;
|
||||
GError *error = NULL;
|
||||
|
||||
/* Get the endpoint */
|
||||
endpoint = wp_base_endpoint_new_finish (initable, res, &error);
|
||||
if (error) {
|
||||
g_warning ("Failed to create endpoint: %s", error->message);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get the endpoint global id */
|
||||
g_object_get (endpoint, "node", &proxy, NULL);
|
||||
global_id = wp_proxy_get_bound_id (proxy);
|
||||
|
||||
/* Register the endpoint and add it to the table */
|
||||
wp_base_endpoint_register (endpoint);
|
||||
g_hash_table_insert (self->registered_endpoints, GUINT_TO_POINTER (global_id),
|
||||
g_object_ref (endpoint));
|
||||
|
||||
/* Emit the endpoint-created signal */
|
||||
g_signal_emit (self, signals[SIGNAL_ENDPOINT_CREATED], 0, endpoint);
|
||||
}
|
||||
|
||||
static GVariant *
|
||||
create_streams_variant (WpConfiguration *config, const char *streams)
|
||||
static const struct WpParserStreamsData *
|
||||
get_streams_data (WpConfiguration *config, const char *file_name)
|
||||
{
|
||||
g_autoptr (WpConfigParser) parser = NULL;
|
||||
const struct WpParserStreamsData *streams_data = NULL;
|
||||
g_autoptr (GVariantBuilder) ba = NULL;
|
||||
|
||||
if (!streams || !config)
|
||||
return NULL;
|
||||
g_return_val_if_fail (config, 0);
|
||||
g_return_val_if_fail (file_name, 0);
|
||||
|
||||
/* Get the streams parser */
|
||||
parser = wp_configuration_get_parser (config, WP_PARSER_STREAMS_EXTENSION);
|
||||
if (!parser)
|
||||
return NULL;
|
||||
return 0;
|
||||
|
||||
/* Get the streams data */
|
||||
streams_data = wp_config_parser_get_matched_data (parser, (gpointer)streams);
|
||||
if (!streams_data || streams_data->n_streams <= 0)
|
||||
return NULL;
|
||||
return wp_config_parser_get_matched_data (parser, (gpointer)file_name);
|
||||
}
|
||||
|
||||
/* Build the variant array with the stream name and priority */
|
||||
ba = g_variant_builder_new (G_VARIANT_TYPE ("a(su)"));
|
||||
g_variant_builder_init (ba, G_VARIANT_TYPE_ARRAY);
|
||||
for (guint i = 0; i < streams_data->n_streams; i++)
|
||||
g_variant_builder_add (ba, "(su)", streams_data->streams[i].name,
|
||||
streams_data->streams[i].priority);
|
||||
static void
|
||||
endpoint_export_finish_cb (WpSessionItem * ep, GAsyncResult * res,
|
||||
WpConfigEndpointContext * self)
|
||||
{
|
||||
g_autoptr (GError) error = NULL;
|
||||
gboolean export_ret = wp_session_item_export_finish (ep, res, &error);
|
||||
g_return_if_fail (error == NULL);
|
||||
g_return_if_fail (export_ret);
|
||||
|
||||
return g_variant_new ("a(su)", ba);
|
||||
/* Emit the signal */
|
||||
g_signal_emit (self, signals[SIGNAL_ENDPOINT_CREATED], 0, ep);
|
||||
}
|
||||
|
||||
static void
|
||||
endpoint_activate_finish_cb (WpSessionItem * ep, GAsyncResult * res,
|
||||
WpConfigEndpointContext * self)
|
||||
{
|
||||
WpSession * session = NULL;
|
||||
g_autoptr (GError) error = NULL;
|
||||
gboolean activate_ret = wp_session_item_activate_finish (ep, res, &error);
|
||||
g_return_if_fail (error == NULL);
|
||||
g_return_if_fail (activate_ret);
|
||||
|
||||
/* Get the session */
|
||||
session = g_object_get_qdata (G_OBJECT (ep), session_quark ());
|
||||
g_return_if_fail (session);
|
||||
|
||||
wp_session_item_export (ep, WP_SESSION (session),
|
||||
(GAsyncReadyCallback) endpoint_export_finish_cb, self);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -106,74 +98,141 @@ on_node_added (WpObjectManager *om, WpProxy *proxy, gpointer d)
|
|||
g_autoptr (WpCore) core = g_weak_ref_get (&self->core);
|
||||
g_autoptr (WpConfiguration) config = wp_configuration_get_instance (core);
|
||||
g_autoptr (WpProperties) props = wp_proxy_get_properties (proxy);
|
||||
g_autoptr (WpSessionItem) ep = NULL;
|
||||
g_autoptr (WpSessionItem) streams_ep = NULL;
|
||||
g_autoptr (WpSession) session = NULL;
|
||||
g_autoptr (WpConfigParser) parser = NULL;
|
||||
const struct WpParserEndpointData *endpoint_data = NULL;
|
||||
GVariantBuilder b;
|
||||
g_autoptr (GVariant) endpoint_props = NULL;
|
||||
const char *media_class = NULL, *name = NULL;
|
||||
g_autoptr (GVariant) streams_variant = NULL;
|
||||
const struct WpParserStreamsData *streams_data = NULL;
|
||||
|
||||
/* Skip nodes with no media class (JACK Clients) */
|
||||
media_class = wp_properties_get (props, PW_KEY_MEDIA_CLASS);
|
||||
if (!media_class)
|
||||
if (!wp_properties_get (props, PW_KEY_MEDIA_CLASS))
|
||||
return;
|
||||
|
||||
/* Get the linked and ep streams data */
|
||||
/* Get the endpoint configuration data */
|
||||
parser = wp_configuration_get_parser (config, WP_PARSER_ENDPOINT_EXTENSION);
|
||||
endpoint_data = wp_config_parser_get_matched_data (parser, proxy);
|
||||
if (!endpoint_data)
|
||||
return;
|
||||
|
||||
/* Set the name if it is null */
|
||||
name = endpoint_data->e.name;
|
||||
if (!name)
|
||||
name = wp_properties_get (props, PW_KEY_NODE_NAME);
|
||||
/* Get the session */
|
||||
session = wp_object_manager_lookup (self->sessions_om, WP_TYPE_SESSION,
|
||||
WP_CONSTRAINT_TYPE_PW_PROPERTY, "session.name", "=s",
|
||||
endpoint_data->e.session, NULL);
|
||||
if (!session) {
|
||||
wp_warning_object (self, "could not find session for endpoint");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set the media class if it is null */
|
||||
if (endpoint_data->e.media_class)
|
||||
media_class = endpoint_data->e.media_class;
|
||||
/* Get the streams data */
|
||||
streams_data = endpoint_data->e.streams ?
|
||||
get_streams_data (config, endpoint_data->e.streams) : NULL;
|
||||
|
||||
/* Create the streams variant */
|
||||
streams_variant = create_streams_variant (config, endpoint_data->e.streams);
|
||||
/* Create the endpoint */
|
||||
ep = wp_session_item_make (core, endpoint_data->e.type);
|
||||
if (!ep) {
|
||||
wp_warning_object (self, "could not create endpoint of type %s",
|
||||
endpoint_data->e.type);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set the properties */
|
||||
g_variant_builder_init (&b, G_VARIANT_TYPE_VARDICT);
|
||||
g_variant_builder_add (&b, "{sv}",
|
||||
"name", g_variant_new_take_string (g_strdup_printf ("%s", 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 (endpoint_data->e.direction));
|
||||
g_variant_builder_add (&b, "{sv}",
|
||||
"priority", g_variant_new_uint32 (endpoint_data->e.priority));
|
||||
g_variant_builder_add (&b, "{sv}",
|
||||
"node", g_variant_new_uint64 ((guint64) proxy));
|
||||
if (streams_variant)
|
||||
g_variant_builder_add (&b, "{sv}", "streams",
|
||||
g_steal_pointer (&streams_variant));
|
||||
endpoint_props = g_variant_builder_end (&b);
|
||||
/* Configure the endpoint */
|
||||
{
|
||||
g_auto (GVariantBuilder) b =
|
||||
G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE_VARDICT);
|
||||
g_variant_builder_add (&b, "{sv}", "node",
|
||||
g_variant_new_uint64 ((guint64) proxy));
|
||||
|
||||
/* Create the endpoint async */
|
||||
wp_factory_make (core, endpoint_data->e.type, WP_TYPE_BASE_ENDPOINT,
|
||||
endpoint_props, on_endpoint_created, self);
|
||||
if (endpoint_data->e.c.name)
|
||||
g_variant_builder_add (&b, "{sv}", "name",
|
||||
g_variant_new_string (endpoint_data->e.c.name));
|
||||
|
||||
if (endpoint_data->e.c.media_class)
|
||||
g_variant_builder_add (&b, "{sv}", "media-class",
|
||||
g_variant_new_string (endpoint_data->e.c.media_class));
|
||||
|
||||
if (endpoint_data->e.c.role)
|
||||
g_variant_builder_add (&b, "{sv}", "role",
|
||||
g_variant_new_string (endpoint_data->e.c.role));
|
||||
|
||||
g_variant_builder_add (&b, "{sv}", "priority",
|
||||
g_variant_new_uint32 (endpoint_data->e.c.priority));
|
||||
|
||||
g_variant_builder_add (&b, "{sv}", "enable-control-port",
|
||||
g_variant_new_boolean (endpoint_data->e.c.enable_control_port));
|
||||
|
||||
g_variant_builder_add (&b, "{sv}", "enable-monitor",
|
||||
g_variant_new_boolean (endpoint_data->e.c.enable_monitor));
|
||||
|
||||
wp_session_item_configure (ep, g_variant_builder_end (&b));
|
||||
}
|
||||
|
||||
/* TODO: for now we always create softdsp audio endpoints if streams data is
|
||||
* valid. However, this will need to change once we have video endpoints. */
|
||||
if (streams_data) {
|
||||
/* Create the steams endpoint */
|
||||
streams_ep = wp_session_item_make (core, "si-audio-softdsp-endpoint");
|
||||
|
||||
/* Configure the streams endpoint */
|
||||
{
|
||||
g_auto (GVariantBuilder) b =
|
||||
G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE_VARDICT);
|
||||
g_variant_builder_add (&b, "{sv}", "adapter",
|
||||
g_variant_new_uint64 ((guint64) ep));
|
||||
wp_session_item_configure (streams_ep, g_variant_builder_end (&b));
|
||||
}
|
||||
|
||||
/* Add the streams */
|
||||
for (guint i = 0; i < streams_data->n_streams; i++) {
|
||||
const struct WpParserStreamsStreamData *sd = streams_data->streams + i;
|
||||
g_autoptr (WpSessionItem) stream =
|
||||
wp_session_item_make (core, "si-convert");
|
||||
{
|
||||
g_auto (GVariantBuilder) b =
|
||||
G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE_VARDICT);
|
||||
g_variant_builder_add (&b, "{sv}", "target",
|
||||
g_variant_new_uint64 ((guint64) ep));
|
||||
g_variant_builder_add (&b, "{sv}", "name",
|
||||
g_variant_new_string (sd->name));
|
||||
g_variant_builder_add (&b, "{sv}", "enable-control-port",
|
||||
g_variant_new_boolean (sd->enable_control_port));
|
||||
wp_session_item_configure (stream, g_variant_builder_end (&b));
|
||||
}
|
||||
|
||||
wp_session_bin_add (WP_SESSION_BIN (streams_ep), g_steal_pointer (&stream));
|
||||
}
|
||||
}
|
||||
|
||||
/* Activate endpoint */
|
||||
g_object_set_qdata_full (
|
||||
G_OBJECT (streams_data ? streams_ep : ep), session_quark (),
|
||||
g_steal_pointer (&session), g_object_unref);
|
||||
wp_session_item_activate (streams_data ? streams_ep : ep,
|
||||
(GAsyncReadyCallback) endpoint_activate_finish_cb, self);
|
||||
|
||||
/* Insert the endpoint */
|
||||
g_hash_table_insert (self->endpoints, proxy,
|
||||
streams_data ? g_steal_pointer (&streams_ep) : g_steal_pointer (&ep));
|
||||
}
|
||||
|
||||
static void
|
||||
on_node_removed (WpObjectManager *om, WpProxy *proxy, gpointer d)
|
||||
on_sessions_changed (WpObjectManager *om, gpointer d)
|
||||
{
|
||||
WpConfigEndpointContext *self = d;
|
||||
WpBaseEndpoint *endpoint = NULL;
|
||||
guint32 id = wp_proxy_get_bound_id (proxy);
|
||||
g_autoptr (WpCore) core = g_weak_ref_get (&self->core);
|
||||
g_return_if_fail (core);
|
||||
|
||||
/* Get the endpoint */
|
||||
endpoint = g_hash_table_lookup (self->registered_endpoints,
|
||||
GUINT_TO_POINTER(id));
|
||||
if (!endpoint)
|
||||
return;
|
||||
/* Handle node-added signal and install the nodes object manager */
|
||||
wp_object_manager_add_interest_1 (self->nodes_om, WP_TYPE_NODE, NULL);
|
||||
wp_object_manager_request_proxy_features (self->nodes_om, WP_TYPE_NODE,
|
||||
WP_PROXY_FEATURES_STANDARD);
|
||||
g_signal_connect_object (self->nodes_om, "object-added",
|
||||
G_CALLBACK (on_node_added), self, 0);
|
||||
wp_core_install_object_manager (core, self->nodes_om);
|
||||
|
||||
/* Unregister the endpoint and remove it from the table */
|
||||
wp_base_endpoint_unregister (endpoint);
|
||||
g_hash_table_remove (self->registered_endpoints, GUINT_TO_POINTER(id));
|
||||
/* Remove handler */
|
||||
g_signal_handlers_disconnect_by_func (self->sessions_om,
|
||||
on_sessions_changed, d);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -195,8 +254,13 @@ wp_config_endpoint_context_constructed (GObject * object)
|
|||
wp_configuration_reload (config, WP_PARSER_ENDPOINT_EXTENSION);
|
||||
wp_configuration_reload (config, WP_PARSER_STREAMS_EXTENSION);
|
||||
|
||||
/* Install the object manager */
|
||||
wp_core_install_object_manager (core, self->om);
|
||||
/* Handle sessions-changed signal and install the session object manager */
|
||||
wp_object_manager_add_interest_1 (self->sessions_om, WP_TYPE_SESSION, NULL);
|
||||
wp_object_manager_request_proxy_features (self->sessions_om, WP_TYPE_SESSION,
|
||||
WP_PROXY_FEATURES_STANDARD);
|
||||
g_signal_connect_object (self->sessions_om, "objects-changed",
|
||||
G_CALLBACK (on_sessions_changed), self, 0);
|
||||
wp_core_install_object_manager (core, self->sessions_om);
|
||||
|
||||
G_OBJECT_CLASS (wp_config_endpoint_context_parent_class)->constructed (object);
|
||||
}
|
||||
|
|
@ -246,8 +310,9 @@ wp_config_endpoint_context_finalize (GObject *object)
|
|||
}
|
||||
g_weak_ref_clear (&self->core);
|
||||
|
||||
g_clear_object (&self->om);
|
||||
g_clear_pointer (&self->registered_endpoints, g_hash_table_unref);
|
||||
g_clear_pointer (&self->endpoints, g_hash_table_unref);
|
||||
g_clear_object (&self->sessions_om);
|
||||
g_clear_object (&self->nodes_om);
|
||||
|
||||
G_OBJECT_CLASS (wp_config_endpoint_context_parent_class)->finalize (object);
|
||||
}
|
||||
|
|
@ -255,20 +320,10 @@ wp_config_endpoint_context_finalize (GObject *object)
|
|||
static void
|
||||
wp_config_endpoint_context_init (WpConfigEndpointContext *self)
|
||||
{
|
||||
self->om = wp_object_manager_new ();
|
||||
self->registered_endpoints = g_hash_table_new_full (g_direct_hash,
|
||||
g_direct_equal, NULL, (GDestroyNotify) g_object_unref);
|
||||
|
||||
/* Only handle augmented nodes with info set */
|
||||
wp_object_manager_add_interest_1 (self->om, WP_TYPE_NODE, NULL);
|
||||
wp_object_manager_request_proxy_features (self->om, WP_TYPE_NODE,
|
||||
WP_PROXY_FEATURES_STANDARD);
|
||||
|
||||
/* Register the global added/removed callbacks */
|
||||
g_signal_connect(self->om, "object-added",
|
||||
(GCallback) on_node_added, self);
|
||||
g_signal_connect(self->om, "object-removed",
|
||||
(GCallback) on_node_removed, self);
|
||||
self->nodes_om = wp_object_manager_new ();
|
||||
self->sessions_om = wp_object_manager_new ();
|
||||
self->endpoints = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
|
||||
(GDestroyNotify) g_object_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -290,7 +345,7 @@ wp_config_endpoint_context_class_init (WpConfigEndpointContextClass *klass)
|
|||
/* Signals */
|
||||
signals[SIGNAL_ENDPOINT_CREATED] = g_signal_new ("endpoint-created",
|
||||
G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 1, WP_TYPE_ENDPOINT);
|
||||
G_TYPE_NONE, 1, WP_TYPE_SESSION_ITEM);
|
||||
}
|
||||
|
||||
WpConfigEndpointContext *
|
||||
|
|
@ -300,10 +355,3 @@ wp_config_endpoint_context_new (WpCore *core)
|
|||
"core", core,
|
||||
NULL);
|
||||
}
|
||||
|
||||
guint
|
||||
wp_config_endpoint_context_get_length (WpConfigEndpointContext *self)
|
||||
{
|
||||
g_return_val_if_fail (WP_IS_CONFIG_ENDPOINT_CONTEXT (self), 0);
|
||||
return g_hash_table_size (self->registered_endpoints);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,8 +19,6 @@ G_DECLARE_FINAL_TYPE (WpConfigEndpointContext, wp_config_endpoint_context,
|
|||
|
||||
WpConfigEndpointContext * wp_config_endpoint_context_new (WpCore *core);
|
||||
|
||||
guint wp_config_endpoint_context_get_length (WpConfigEndpointContext *self);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -32,14 +32,14 @@ wp_parser_endpoint_data_destroy (gpointer p)
|
|||
{
|
||||
struct WpParserEndpointData *data = p;
|
||||
|
||||
/* Free the strings */
|
||||
g_clear_pointer (&data->filename, g_free);
|
||||
g_clear_pointer (&data->mn.props, wp_properties_unref);
|
||||
g_clear_pointer (&data->e.name, g_free);
|
||||
g_clear_pointer (&data->e.media_class, g_free);
|
||||
g_clear_pointer (&data->e.props, wp_properties_unref);
|
||||
g_clear_pointer (&data->e.session, g_free);
|
||||
g_clear_pointer (&data->e.type, g_free);
|
||||
g_clear_pointer (&data->e.streams, g_free);
|
||||
g_clear_pointer (&data->e.c.name, g_free);
|
||||
g_clear_pointer (&data->e.c.media_class, g_free);
|
||||
g_clear_pointer (&data->e.c.role, g_free);
|
||||
|
||||
g_slice_free (struct WpParserEndpointData, data);
|
||||
}
|
||||
|
|
@ -76,25 +76,12 @@ parse_properties (WpTomlTable *table, const char *name)
|
|||
return props;
|
||||
}
|
||||
|
||||
static guint
|
||||
parse_endpoint_direction (const char *direction)
|
||||
{
|
||||
if (g_strcmp0 (direction, "sink") == 0)
|
||||
return PW_DIRECTION_INPUT;
|
||||
else if (g_strcmp0 (direction, "source") == 0)
|
||||
return PW_DIRECTION_OUTPUT;
|
||||
|
||||
g_return_val_if_reached (PW_DIRECTION_INPUT);
|
||||
}
|
||||
|
||||
static struct WpParserEndpointData *
|
||||
wp_parser_endpoint_data_new (const gchar *location)
|
||||
{
|
||||
g_autoptr (WpTomlFile) file = NULL;
|
||||
g_autoptr (WpTomlTable) table = NULL, mn = NULL, e = NULL;
|
||||
g_autoptr (WpTomlArray) streams = NULL;
|
||||
g_autoptr (WpTomlTable) table = NULL, mn = NULL, e = NULL, c = NULL;
|
||||
struct WpParserEndpointData *res = NULL;
|
||||
g_autofree char *direction = NULL;
|
||||
|
||||
/* File format:
|
||||
* ------------
|
||||
|
|
@ -102,13 +89,17 @@ wp_parser_endpoint_data_new (const gchar *location)
|
|||
* properties (WpProperties)
|
||||
*
|
||||
* [endpoint]
|
||||
* name (string)
|
||||
* media_class (string)
|
||||
* direction (string)
|
||||
* priority (uint32)
|
||||
* properties (WpProperties)
|
||||
* session (string)
|
||||
* type (string)
|
||||
* streams (string)
|
||||
*
|
||||
* [endpoint.config]
|
||||
* name (string)
|
||||
* media_class (string)
|
||||
* role (string)
|
||||
* priority (uint32)
|
||||
* enable_control_port (bool)
|
||||
* enable_monitor (bool)
|
||||
*/
|
||||
|
||||
/* Get the TOML file */
|
||||
|
|
@ -140,33 +131,33 @@ wp_parser_endpoint_data_new (const gchar *location)
|
|||
if (!e)
|
||||
goto error;
|
||||
|
||||
/* Get the name from the endpoint table */
|
||||
res->e.name = wp_toml_table_get_string (e, "name");
|
||||
|
||||
/* Get the media class from the endpoint table */
|
||||
res->e.media_class = wp_toml_table_get_string (e, "media_class");
|
||||
|
||||
/* Get the direction from the endpoint table */
|
||||
direction = wp_toml_table_get_string (e, "direction");
|
||||
if (!direction)
|
||||
/* Get the endpoint session */
|
||||
res->e.session = wp_toml_table_get_string (e, "session");
|
||||
if (!res->e.session)
|
||||
goto error;
|
||||
res->e.direction = parse_endpoint_direction (direction);
|
||||
|
||||
/* Get the priority from the endpoint table */
|
||||
res->e.priority = 0;
|
||||
wp_toml_table_get_uint32 (e, "priority", &res->e.priority);
|
||||
|
||||
/* Get the endpoint properties */
|
||||
res->e.props = parse_properties (e, "properties");
|
||||
|
||||
/* Get the endpoint type */
|
||||
res->e.type = wp_toml_table_get_string (e, "type");
|
||||
if (!res->e.type)
|
||||
goto error;
|
||||
|
||||
/* Get the endpoint streams */
|
||||
/* Get the optional streams */
|
||||
res->e.streams = wp_toml_table_get_string (e, "streams");
|
||||
|
||||
/* Get the optional endpoint config table */
|
||||
c = wp_toml_table_get_table (e, "config");
|
||||
if (c) {
|
||||
res->e.c.name = wp_toml_table_get_string (c, "name");
|
||||
res->e.c.media_class = wp_toml_table_get_string (c, "media_class");
|
||||
res->e.c.role = wp_toml_table_get_string (c, "role");
|
||||
res->e.c.priority = 0;
|
||||
wp_toml_table_get_uint32 (c, "priority", &res->e.c.priority);
|
||||
res->e.c.enable_control_port = FALSE;
|
||||
wp_toml_table_get_boolean (c, "enable-control-port", &res->e.c.enable_control_port);
|
||||
res->e.c.enable_monitor = FALSE;
|
||||
wp_toml_table_get_boolean (c, "enable-monitor", &res->e.c.enable_monitor);
|
||||
}
|
||||
|
||||
return res;
|
||||
|
||||
error:
|
||||
|
|
@ -193,7 +184,7 @@ wp_parser_endpoint_add_file (WpConfigParser *parser,
|
|||
/* Parse the file */
|
||||
data = wp_parser_endpoint_data_new (name);
|
||||
if (!data) {
|
||||
g_warning ("Failed to parse configuration file '%s'", name);
|
||||
wp_warning_object (parser, "Failed to parse configuration file '%s'", name);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,13 +21,18 @@ struct WpParserEndpointData {
|
|||
WpProperties *props;
|
||||
} mn;
|
||||
struct Endpoint {
|
||||
char *name;
|
||||
char *media_class;
|
||||
guint direction;
|
||||
guint priority;
|
||||
WpProperties *props;
|
||||
char *session;
|
||||
char *type;
|
||||
char *streams;
|
||||
struct Config {
|
||||
char *name;
|
||||
char *media_class;
|
||||
char *role;
|
||||
guint priority;
|
||||
gboolean enable_control_port;
|
||||
gboolean enable_monitor;
|
||||
guint direction;
|
||||
} c;
|
||||
} e;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -97,6 +97,11 @@ streams_for_each (const WpTomlTable *table, gpointer user_data)
|
|||
stream->priority = 0;
|
||||
wp_toml_table_get_uint32 (table, "priority", &stream->priority);
|
||||
|
||||
/* Parse the optional enable_control_port */
|
||||
stream->enable_control_port = FALSE;
|
||||
wp_toml_table_get_boolean (table, "enable_control_port",
|
||||
&stream->enable_control_port);
|
||||
|
||||
/* Increment the number of streams */
|
||||
data->n_streams++;
|
||||
}
|
||||
|
|
@ -115,6 +120,7 @@ wp_parser_streams_data_new (const gchar *location)
|
|||
* [[streams]]
|
||||
* name (string)
|
||||
* priority (uint32)
|
||||
* enable_control_port (bool)
|
||||
*/
|
||||
|
||||
/* Get the TOML file */
|
||||
|
|
@ -152,7 +158,7 @@ wp_parser_streams_add_file (WpConfigParser *parser,
|
|||
/* Parse the file */
|
||||
data = wp_parser_streams_data_new (name);
|
||||
if (!data) {
|
||||
g_warning ("Failed to parse configuration file '%s'", name);
|
||||
wp_warning_object (parser, "Failed to parse configuration file '%s'", name);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ G_BEGIN_DECLS
|
|||
struct WpParserStreamsStreamData {
|
||||
char *name;
|
||||
guint priority;
|
||||
gboolean enable_control_port;
|
||||
};
|
||||
|
||||
struct WpParserStreamsData {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@
|
|||
*/
|
||||
|
||||
#include "../common/base-test-fixture.h"
|
||||
#include "config-endpoint/endpoint-audiotestsrc.h"
|
||||
#include "../../modules/module-config-endpoint/context.h"
|
||||
|
||||
typedef struct {
|
||||
|
|
@ -15,64 +14,183 @@ typedef struct {
|
|||
} TestConfigEndpointFixture;
|
||||
|
||||
static void
|
||||
config_endpoint_setup (TestConfigEndpointFixture *self, gconstpointer data)
|
||||
config_endpoint_setup (TestConfigEndpointFixture *f, gconstpointer data)
|
||||
{
|
||||
wp_base_test_fixture_setup (&self->base, 0);
|
||||
wp_base_test_fixture_setup (&f->base, 0);
|
||||
|
||||
/* load audiotestsrc */
|
||||
pw_thread_loop_lock (self->base.server.thread_loop);
|
||||
pw_context_add_spa_lib (self->base.server.context, "audiotestsrc",
|
||||
"audiotestsrc/libspa-audiotestsrc");
|
||||
if (!pw_context_load_module (self->base.server.context,
|
||||
"libpipewire-module-spa-node", "audiotestsrc", NULL)) {
|
||||
pw_thread_loop_unlock (self->base.server.thread_loop);
|
||||
g_test_skip ("audiotestsrc SPA plugin is not installed");
|
||||
return;
|
||||
/* load modules */
|
||||
{
|
||||
g_autoptr (WpTestServerLocker) lock =
|
||||
wp_test_server_locker_new (&f->base.server);
|
||||
|
||||
g_assert_cmpint (pw_context_add_spa_lib (f->base.server.context,
|
||||
"audiotestsrc", "audiotestsrc/libspa-audiotestsrc"), ==, 0);
|
||||
g_assert_nonnull (pw_context_load_module (f->base.server.context,
|
||||
"libpipewire-module-spa-node-factory", NULL, NULL));
|
||||
g_assert_nonnull (pw_context_load_module (f->base.server.context,
|
||||
"libpipewire-module-adapter", NULL, NULL));
|
||||
}
|
||||
{
|
||||
g_autoptr (GError) error = NULL;
|
||||
WpModule *module = wp_module_load (f->base.core, "C",
|
||||
"libwireplumber-module-si-simple-node-endpoint", NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert_nonnull (module);
|
||||
}
|
||||
{
|
||||
g_autoptr (GError) error = NULL;
|
||||
WpModule *module = wp_module_load (f->base.core, "C",
|
||||
"libwireplumber-module-si-adapter", NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert_nonnull (module);
|
||||
}
|
||||
{
|
||||
g_autoptr (GError) error = NULL;
|
||||
WpModule *module = wp_module_load (f->base.core, "C",
|
||||
"libwireplumber-module-si-convert", NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert_nonnull (module);
|
||||
}
|
||||
{
|
||||
g_autoptr (GError) error = NULL;
|
||||
WpModule *module = wp_module_load (f->base.core, "C",
|
||||
"libwireplumber-module-si-audio-softdsp-endpoint", NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert_nonnull (module);
|
||||
}
|
||||
pw_thread_loop_unlock (self->base.server.thread_loop);
|
||||
|
||||
/* Register the wp-endpoint-audiotestsrc */
|
||||
wp_factory_new (self->base.core, "wp-endpoint-audiotestsrc",
|
||||
wp_endpoint_audiotestsrc_factory);
|
||||
}
|
||||
|
||||
static void
|
||||
config_endpoint_teardown (TestConfigEndpointFixture *self, gconstpointer data)
|
||||
config_endpoint_teardown (TestConfigEndpointFixture *f, gconstpointer data)
|
||||
{
|
||||
wp_base_test_fixture_teardown (&self->base);
|
||||
wp_base_test_fixture_teardown (&f->base);
|
||||
}
|
||||
|
||||
static void
|
||||
on_audiotestsrc_created (WpConfigEndpointContext *ctx, WpEndpoint *ep,
|
||||
on_default_session_exported (WpProxy * session, GAsyncResult * res,
|
||||
TestConfigEndpointFixture *f)
|
||||
{
|
||||
g_assert_nonnull (ep);
|
||||
g_autoptr (GError) error = NULL;
|
||||
g_assert_true (wp_proxy_augment_finish (session, res, &error));
|
||||
g_assert_no_error (error);
|
||||
g_assert_true (WP_IS_IMPL_SESSION (session));
|
||||
g_main_loop_quit (f->base.loop);
|
||||
}
|
||||
|
||||
static void
|
||||
basic (TestConfigEndpointFixture *f, gconstpointer data)
|
||||
on_audiotestsrc_simple_endpoint_created (WpConfigEndpointContext *ctx,
|
||||
WpSessionItem *ep, TestConfigEndpointFixture *f)
|
||||
{
|
||||
g_autoptr (WpNode) node = NULL;
|
||||
g_autoptr (WpProperties) props = NULL;
|
||||
g_assert_nonnull (ep);
|
||||
|
||||
g_autoptr (GVariant) v = wp_session_item_get_configuration (ep);
|
||||
const gchar *str;
|
||||
guint32 prio;
|
||||
g_assert_true (g_variant_lookup (v, "name", "&s", &str));
|
||||
g_assert_cmpstr (str, ==, "audiotestsrc-endpoint");
|
||||
g_assert_true (g_variant_lookup (v, "media-class", "&s", &str));
|
||||
g_assert_cmpstr (str, ==, "Audio/Source");
|
||||
g_assert_true (g_variant_lookup (v, "role", "&s", &str));
|
||||
g_assert_cmpstr (str, ==, "Multimedia");
|
||||
g_assert_true (g_variant_lookup (v, "priority", "u", &prio));
|
||||
g_assert_cmpuint (prio, ==, 0);
|
||||
|
||||
g_main_loop_quit (f->base.loop);
|
||||
}
|
||||
|
||||
static void
|
||||
on_audiotestsrc_streams_endpoint_created (WpConfigEndpointContext *ctx,
|
||||
WpSessionItem *ep, TestConfigEndpointFixture *f)
|
||||
{
|
||||
g_assert_nonnull (ep);
|
||||
g_assert_cmpuint (5, ==, wp_session_bin_get_n_children (WP_SESSION_BIN (ep)));
|
||||
|
||||
g_autoptr (GVariant) v = wp_session_item_get_configuration (ep);
|
||||
guint64 p_i;
|
||||
g_assert_true (g_variant_lookup (v, "adapter", "t", &p_i));
|
||||
g_assert_nonnull ((gpointer)p_i);
|
||||
|
||||
g_autoptr (GVariant) v2 = wp_session_item_get_configuration ((gpointer)p_i);
|
||||
const gchar *str;
|
||||
guint32 prio;
|
||||
g_assert_true (g_variant_lookup (v2, "name", "&s", &str));
|
||||
g_assert_cmpstr (str, ==, "audiotestsrc-endpoint");
|
||||
g_assert_true (g_variant_lookup (v2, "media-class", "&s", &str));
|
||||
g_assert_cmpstr (str, ==, "Audio/Source");
|
||||
g_assert_true (g_variant_lookup (v2, "role", "&s", &str));
|
||||
g_assert_cmpstr (str, ==, "Multimedia");
|
||||
g_assert_true (g_variant_lookup (v2, "priority", "u", &prio));
|
||||
g_assert_cmpuint (prio, ==, 0);
|
||||
|
||||
g_main_loop_quit (f->base.loop);
|
||||
}
|
||||
|
||||
static void
|
||||
simple (TestConfigEndpointFixture *f, gconstpointer data)
|
||||
{
|
||||
/* Set the configuration path */
|
||||
g_autoptr (WpConfiguration) config = wp_configuration_get_instance (f->base.core);
|
||||
g_assert_nonnull (config);
|
||||
wp_configuration_add_path (config, "config-endpoint/basic");
|
||||
wp_configuration_add_path (config, "config-endpoint/simple");
|
||||
|
||||
/* Create the context and handle the endpoint-created callback */
|
||||
/* Create the endpoint context and handle the endpoint-created callback */
|
||||
g_autoptr (WpConfigEndpointContext) ctx =
|
||||
wp_config_endpoint_context_new (f->base.core);
|
||||
g_assert_nonnull (ctx);
|
||||
g_assert_cmpint (wp_config_endpoint_context_get_length (ctx), ==, 0);
|
||||
|
||||
/* Add a handler to stop the main loop when the endpoint is created */
|
||||
g_signal_connect (ctx, "endpoint-created",
|
||||
(GCallback) on_audiotestsrc_created, f);
|
||||
(GCallback) on_audiotestsrc_simple_endpoint_created, f);
|
||||
|
||||
/* Run the main loop */
|
||||
/* Create and export the default session */
|
||||
g_autoptr (WpImplSession) session = wp_impl_session_new (f->base.core);
|
||||
wp_impl_session_set_property (session, "session.name", "default");
|
||||
wp_proxy_augment (WP_PROXY (session), WP_PROXY_FEATURE_BOUND, NULL,
|
||||
(GAsyncReadyCallback) on_default_session_exported, f);
|
||||
g_main_loop_run (f->base.loop);
|
||||
|
||||
/* Check if the endpoint was created */
|
||||
g_assert_cmpint (wp_config_endpoint_context_get_length (ctx), ==, 1);
|
||||
/* Create the audiotestsrc node and run until the endpoint is created */
|
||||
g_autoptr (WpNode) node = wp_node_new_from_factory (f->base.core,
|
||||
"spa-node-factory",
|
||||
wp_properties_new (
|
||||
"factory.name", "audiotestsrc",
|
||||
"node.name", "audiotestsrc0",
|
||||
NULL));
|
||||
g_assert_nonnull (node);
|
||||
g_main_loop_run (f->base.loop);
|
||||
}
|
||||
|
||||
static void
|
||||
streams (TestConfigEndpointFixture *f, gconstpointer data)
|
||||
{
|
||||
/* Set the configuration path */
|
||||
g_autoptr (WpConfiguration) config = wp_configuration_get_instance (f->base.core);
|
||||
g_assert_nonnull (config);
|
||||
wp_configuration_add_path (config, "config-endpoint/streams");
|
||||
|
||||
/* Create the endpoint context and handle the endpoint-created callback */
|
||||
g_autoptr (WpConfigEndpointContext) ctx =
|
||||
wp_config_endpoint_context_new (f->base.core);
|
||||
g_assert_nonnull (ctx);
|
||||
g_signal_connect (ctx, "endpoint-created",
|
||||
(GCallback) on_audiotestsrc_streams_endpoint_created, f);
|
||||
|
||||
/* Create and export the default session */
|
||||
g_autoptr (WpImplSession) session = wp_impl_session_new (f->base.core);
|
||||
wp_impl_session_set_property (session, "session.name", "default");
|
||||
wp_proxy_augment (WP_PROXY (session), WP_PROXY_FEATURE_BOUND, NULL,
|
||||
(GAsyncReadyCallback) on_default_session_exported, f);
|
||||
g_main_loop_run (f->base.loop);
|
||||
|
||||
/* create audiotestsrc adapter node and run until the endpoint is created */
|
||||
g_autoptr (WpNode) node = wp_node_new_from_factory (f->base.core,
|
||||
"adapter",
|
||||
wp_properties_new (
|
||||
"factory.name", "audiotestsrc",
|
||||
"node.name", "adapter-audiotestsrc0",
|
||||
NULL));
|
||||
g_assert_nonnull (node);
|
||||
g_main_loop_run (f->base.loop);
|
||||
}
|
||||
|
||||
int
|
||||
|
|
@ -82,8 +200,10 @@ main (int argc, char *argv[])
|
|||
pw_init (NULL, NULL);
|
||||
g_log_set_writer_func (wp_log_writer_default, NULL, NULL);
|
||||
|
||||
g_test_add ("/modules/config-endpoint/basic", TestConfigEndpointFixture,
|
||||
NULL, config_endpoint_setup, basic, config_endpoint_teardown);
|
||||
g_test_add ("/modules/config-endpoint/simple", TestConfigEndpointFixture,
|
||||
NULL, config_endpoint_setup, simple, config_endpoint_teardown);
|
||||
g_test_add ("/modules/config-endpoint/streams", TestConfigEndpointFixture,
|
||||
NULL, config_endpoint_setup, streams, config_endpoint_teardown);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +0,0 @@
|
|||
[match-node]
|
||||
properties = [
|
||||
{ name = "media.class", value = "Audio/Source" },
|
||||
]
|
||||
|
||||
[endpoint]
|
||||
direction = "source"
|
||||
type = "wp-endpoint-audiotestsrc"
|
||||
streams = "default.streams"
|
||||
|
|
@ -1,254 +0,0 @@
|
|||
/* WirePlumber
|
||||
*
|
||||
* Copyright © 2019 Collabora Ltd.
|
||||
* @author Julian Bouzas <julian.bouzas@collabora.com>
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include <wp/wp.h>
|
||||
|
||||
#include "endpoint-audiotestsrc.h"
|
||||
|
||||
struct _WpEndpointAudiotestsrc
|
||||
{
|
||||
WpBaseEndpoint parent;
|
||||
GTask *init_task;
|
||||
guint id;
|
||||
|
||||
/* Props */
|
||||
WpNode *node;
|
||||
GVariant *streams;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_PROXY_NODE,
|
||||
PROP_STREAMS,
|
||||
};
|
||||
|
||||
static GAsyncInitableIface *wp_endpoint_audiotestsrc_parent_interface = NULL;
|
||||
static void wp_endpoint_audiotestsrc_async_initable_init (gpointer iface,
|
||||
gpointer iface_data);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (WpEndpointAudiotestsrc, wp_endpoint_audiotestsrc,
|
||||
WP_TYPE_BASE_ENDPOINT,
|
||||
G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE,
|
||||
wp_endpoint_audiotestsrc_async_initable_init))
|
||||
|
||||
static WpProperties *
|
||||
wp_endpoint_audiotestsrc_get_properties (WpBaseEndpoint * ep)
|
||||
{
|
||||
WpEndpointAudiotestsrc *self = WP_ENDPOINT_AUDIOTESTSRC (ep);
|
||||
return wp_proxy_get_properties (WP_PROXY (self->node));
|
||||
}
|
||||
|
||||
static const char *
|
||||
wp_endpoint_audiotestsrc_get_role (WpBaseEndpoint * ep)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static guint32
|
||||
wp_endpoint_audiotestsrc_get_global_id (WpBaseEndpoint * ep)
|
||||
{
|
||||
WpEndpointAudiotestsrc *self = WP_ENDPOINT_AUDIOTESTSRC (ep);
|
||||
return self->id;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
wp_endpoint_audiotestsrc_prepare_link (WpBaseEndpoint * ep, guint32 stream_id,
|
||||
WpBaseEndpointLink * link, GVariant ** properties, GError ** error)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static const char *
|
||||
wp_endpoint_audiotestsrc_get_endpoint_link_factory (WpBaseEndpoint * ep)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
wp_endpoint_audiotestsrc_constructed (GObject * object)
|
||||
{
|
||||
WpEndpointAudiotestsrc *self = WP_ENDPOINT_AUDIOTESTSRC (object);
|
||||
GVariantDict d;
|
||||
GVariantIter iter;
|
||||
const gchar *stream;
|
||||
guint priority;
|
||||
int i;
|
||||
|
||||
if (self->streams) {
|
||||
g_variant_iter_init (&iter, self->streams);
|
||||
for (i = 0; g_variant_iter_next (&iter, "(&su)", &stream, &priority); i++) {
|
||||
g_variant_dict_init (&d, NULL);
|
||||
g_variant_dict_insert (&d, "id", "u", i);
|
||||
g_variant_dict_insert (&d, "name", "s", stream);
|
||||
g_variant_dict_insert (&d, "priority", "u", priority);
|
||||
wp_base_endpoint_register_stream (WP_BASE_ENDPOINT (self), g_variant_dict_end (&d));
|
||||
}
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (wp_endpoint_audiotestsrc_parent_class)->constructed (object);
|
||||
}
|
||||
|
||||
static void
|
||||
wp_endpoint_audiotestsrc_set_property (GObject * object, guint property_id,
|
||||
const GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
WpEndpointAudiotestsrc *self = WP_ENDPOINT_AUDIOTESTSRC (object);
|
||||
|
||||
switch (property_id) {
|
||||
case PROP_PROXY_NODE:
|
||||
self->node = g_value_dup_object (value);
|
||||
break;
|
||||
case PROP_STREAMS:
|
||||
self->streams = g_value_dup_variant(value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
wp_endpoint_audiotestsrc_get_property (GObject * object, guint property_id,
|
||||
GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
WpEndpointAudiotestsrc *self = WP_ENDPOINT_AUDIOTESTSRC (object);
|
||||
|
||||
switch (property_id) {
|
||||
case PROP_PROXY_NODE:
|
||||
g_value_set_object (value, self->node);
|
||||
break;
|
||||
case PROP_STREAMS:
|
||||
g_value_set_variant (value, self->streams);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
wp_endpoint_audiotestsrc_finalize (GObject * object)
|
||||
{
|
||||
WpEndpointAudiotestsrc *self = WP_ENDPOINT_AUDIOTESTSRC (object);
|
||||
|
||||
g_clear_object(&self->node);
|
||||
g_clear_pointer(&self->streams, g_variant_unref);
|
||||
|
||||
G_OBJECT_CLASS (wp_endpoint_audiotestsrc_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
wp_endpoint_audiotestsrc_finish_creation (WpCore *core, GAsyncResult *res,
|
||||
WpEndpointAudiotestsrc *self)
|
||||
{
|
||||
g_task_return_boolean (self->init_task, TRUE);
|
||||
g_clear_object (&self->init_task);
|
||||
}
|
||||
|
||||
static void
|
||||
wp_endpoint_audiotestsrc_init_async (GAsyncInitable *initable, int io_priority,
|
||||
GCancellable *cancellable, GAsyncReadyCallback callback, gpointer data)
|
||||
{
|
||||
WpEndpointAudiotestsrc *self = WP_ENDPOINT_AUDIOTESTSRC (initable);
|
||||
|
||||
self->init_task = g_task_new (initable, cancellable, callback, data);
|
||||
|
||||
wp_endpoint_audiotestsrc_parent_interface->init_async (initable, io_priority,
|
||||
cancellable, callback, data);
|
||||
|
||||
g_autoptr (WpCore) core = wp_base_endpoint_get_core (WP_BASE_ENDPOINT(self));
|
||||
g_return_if_fail (core);
|
||||
|
||||
wp_core_sync (core, NULL,
|
||||
(GAsyncReadyCallback) wp_endpoint_audiotestsrc_finish_creation, self);
|
||||
}
|
||||
|
||||
static void
|
||||
wp_endpoint_audiotestsrc_async_initable_init (gpointer iface,
|
||||
gpointer iface_data)
|
||||
{
|
||||
GAsyncInitableIface *ai_iface = iface;
|
||||
wp_endpoint_audiotestsrc_parent_interface =
|
||||
g_type_interface_peek_parent (iface);
|
||||
ai_iface->init_async = wp_endpoint_audiotestsrc_init_async;
|
||||
}
|
||||
|
||||
static void
|
||||
wp_endpoint_audiotestsrc_init (WpEndpointAudiotestsrc * self)
|
||||
{
|
||||
static guint id = 0;
|
||||
self->id = id++;
|
||||
}
|
||||
|
||||
static void
|
||||
wp_endpoint_audiotestsrc_class_init (WpEndpointAudiotestsrcClass * klass)
|
||||
{
|
||||
GObjectClass *object_class = (GObjectClass *) klass;
|
||||
WpBaseEndpointClass *endpoint_class = (WpBaseEndpointClass *) klass;
|
||||
|
||||
object_class->constructed = wp_endpoint_audiotestsrc_constructed;
|
||||
object_class->finalize = wp_endpoint_audiotestsrc_finalize;
|
||||
object_class->set_property = wp_endpoint_audiotestsrc_set_property;
|
||||
object_class->get_property = wp_endpoint_audiotestsrc_get_property;
|
||||
|
||||
endpoint_class->get_properties = wp_endpoint_audiotestsrc_get_properties;
|
||||
endpoint_class->get_role = wp_endpoint_audiotestsrc_get_role;
|
||||
endpoint_class->get_global_id = wp_endpoint_audiotestsrc_get_global_id;
|
||||
endpoint_class->prepare_link = wp_endpoint_audiotestsrc_prepare_link;
|
||||
endpoint_class->get_endpoint_link_factory =
|
||||
wp_endpoint_audiotestsrc_get_endpoint_link_factory;
|
||||
|
||||
g_object_class_install_property (object_class, PROP_PROXY_NODE,
|
||||
g_param_spec_object ("node", "node",
|
||||
"The node this endpoint refers to", WP_TYPE_NODE,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_property (object_class, PROP_STREAMS,
|
||||
g_param_spec_variant ("streams", "streams",
|
||||
"The stream names for the streams to register",
|
||||
G_VARIANT_TYPE ("a(su)"), NULL,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
|
||||
}
|
||||
|
||||
void
|
||||
wp_endpoint_audiotestsrc_factory (WpFactory * factory, GType type,
|
||||
GVariant * properties, GAsyncReadyCallback ready, gpointer data)
|
||||
{
|
||||
g_autoptr (WpCore) core = NULL;
|
||||
const gchar *name, *media_class;
|
||||
guint direction, priority;
|
||||
guint64 node;
|
||||
g_autoptr (GVariant) streams = NULL;
|
||||
|
||||
core = wp_factory_get_core(factory);
|
||||
g_return_if_fail (core);
|
||||
|
||||
if (!g_variant_lookup (properties, "name", "&s", &name))
|
||||
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, "priority", "u", &priority))
|
||||
return;
|
||||
if (!g_variant_lookup (properties, "node", "t", &node))
|
||||
return;
|
||||
streams = g_variant_lookup_value (properties, "streams",
|
||||
G_VARIANT_TYPE ("a(su)"));
|
||||
|
||||
g_async_initable_new_async (wp_endpoint_audiotestsrc_get_type (),
|
||||
G_PRIORITY_DEFAULT, NULL, ready, data,
|
||||
"core", core,
|
||||
"name", name,
|
||||
"media-class", media_class,
|
||||
"direction", direction,
|
||||
"priority", priority,
|
||||
"node", (gpointer) node,
|
||||
"streams", streams,
|
||||
NULL);
|
||||
}
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
/* WirePlumber
|
||||
*
|
||||
* Copyright © 2019 Collabora Ltd.
|
||||
* @author Julian Bouzas <julian.bouzas@collabora.com>
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#ifndef __WIREPLUMBER_ENDPOINT_AUDIOTESTSRC_H__
|
||||
#define __WIREPLUMBER_ENDPOINT_AUDIOTESTSRC_H__
|
||||
|
||||
#include <wp/wp.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
G_DECLARE_FINAL_TYPE (WpEndpointAudiotestsrc, wp_endpoint_audiotestsrc, WP,
|
||||
ENDPOINT_AUDIOTESTSRC, WpBaseEndpoint)
|
||||
|
||||
void wp_endpoint_audiotestsrc_factory (WpFactory * factory, GType type,
|
||||
GVariant * properties, GAsyncReadyCallback ready, gpointer data);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif
|
||||
14
tests/modules/config-endpoint/simple/audio-source.endpoint
Normal file
14
tests/modules/config-endpoint/simple/audio-source.endpoint
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
[match-node]
|
||||
properties = [
|
||||
{ name = "media.class", value = "Audio/Source" },
|
||||
]
|
||||
|
||||
[endpoint]
|
||||
session = "default"
|
||||
type = "si-simple-node-endpoint"
|
||||
|
||||
[endpoint.config]
|
||||
name = "audiotestsrc-endpoint"
|
||||
media_class = "Audio/Source"
|
||||
role = "Multimedia"
|
||||
priority = 0
|
||||
15
tests/modules/config-endpoint/streams/audio-source.endpoint
Normal file
15
tests/modules/config-endpoint/streams/audio-source.endpoint
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
[match-node]
|
||||
properties = [
|
||||
{ name = "media.class", value = "Audio/Source" },
|
||||
]
|
||||
|
||||
[endpoint]
|
||||
session = "default"
|
||||
type = "si-adapter"
|
||||
streams = "default.streams"
|
||||
|
||||
[endpoint.config]
|
||||
name = "audiotestsrc-endpoint"
|
||||
media_class = "Audio/Source"
|
||||
role = "Multimedia"
|
||||
priority = 0
|
||||
|
|
@ -1,15 +1,19 @@
|
|||
[[streams]]
|
||||
name = "0"
|
||||
priority = 0
|
||||
enable_control_port = false
|
||||
|
||||
[[streams]]
|
||||
name = "2"
|
||||
priority = 2
|
||||
enable_control_port = false
|
||||
|
||||
[[streams]]
|
||||
name = "3"
|
||||
priority = 3
|
||||
enable_control_port = false
|
||||
|
||||
[[streams]]
|
||||
name = "4"
|
||||
priority = 4
|
||||
enable_control_port = false
|
||||
|
|
@ -38,7 +38,6 @@ test(
|
|||
executable('test-config-endpoint',
|
||||
[
|
||||
'config-endpoint.c',
|
||||
'config-endpoint/endpoint-audiotestsrc.c',
|
||||
'../../modules/module-config-endpoint/parser-endpoint.c',
|
||||
'../../modules/module-config-endpoint/parser-streams.c',
|
||||
'../../modules/module-config-endpoint/context.c',
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue