2019-12-09 16:35:15 +02:00
|
|
|
/* WirePlumber
|
|
|
|
|
*
|
|
|
|
|
* Copyright © 2019 Collabora Ltd.
|
|
|
|
|
* @author George Kiagiadakis <george.kiagiadakis@collabora.com>
|
|
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: MIT
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "endpoint.h"
|
|
|
|
|
#include "private.h"
|
2020-02-12 11:28:07 +02:00
|
|
|
#include "error.h"
|
2019-12-09 16:35:15 +02:00
|
|
|
#include "wpenums.h"
|
|
|
|
|
|
|
|
|
|
#include <pipewire/pipewire.h>
|
|
|
|
|
#include <pipewire/extensions/session-manager.h>
|
|
|
|
|
#include <spa/pod/builder.h>
|
|
|
|
|
#include <spa/pod/parser.h>
|
|
|
|
|
|
|
|
|
|
enum {
|
|
|
|
|
SIGNAL_CONTROL_CHANGED,
|
|
|
|
|
N_SIGNALS,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static guint32 signals[N_SIGNALS] = {0};
|
|
|
|
|
|
|
|
|
|
/* helpers */
|
|
|
|
|
|
|
|
|
|
static struct pw_endpoint_info *
|
|
|
|
|
endpoint_info_update (struct pw_endpoint_info *info,
|
|
|
|
|
WpProperties ** props_storage,
|
|
|
|
|
const struct pw_endpoint_info *update)
|
|
|
|
|
{
|
|
|
|
|
if (update == NULL)
|
|
|
|
|
return info;
|
|
|
|
|
|
|
|
|
|
if (info == NULL) {
|
|
|
|
|
info = calloc(1, sizeof(struct pw_endpoint_info));
|
|
|
|
|
if (info == NULL)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
info->id = update->id;
|
|
|
|
|
info->name = g_strdup(update->name);
|
|
|
|
|
info->media_class = g_strdup(update->media_class);
|
|
|
|
|
info->direction = update->direction;
|
|
|
|
|
info->flags = update->flags;
|
|
|
|
|
}
|
|
|
|
|
info->change_mask = update->change_mask;
|
|
|
|
|
|
|
|
|
|
if (update->change_mask & PW_ENDPOINT_CHANGE_MASK_STREAMS)
|
|
|
|
|
info->n_streams = update->n_streams;
|
|
|
|
|
|
|
|
|
|
if (update->change_mask & PW_ENDPOINT_CHANGE_MASK_SESSION)
|
|
|
|
|
info->session_id = update->session_id;
|
|
|
|
|
|
|
|
|
|
if (update->change_mask & PW_ENDPOINT_CHANGE_MASK_PROPS) {
|
|
|
|
|
if (*props_storage)
|
|
|
|
|
wp_properties_unref (*props_storage);
|
|
|
|
|
*props_storage = wp_properties_new_copy_dict (update->props);
|
|
|
|
|
info->props = (struct spa_dict *) wp_properties_peek_dict (*props_storage);
|
|
|
|
|
}
|
|
|
|
|
if (update->change_mask & PW_ENDPOINT_CHANGE_MASK_PARAMS) {
|
|
|
|
|
info->n_params = update->n_params;
|
|
|
|
|
free((void *) info->params);
|
|
|
|
|
if (update->params) {
|
|
|
|
|
size_t size = info->n_params * sizeof(struct spa_param_info);
|
|
|
|
|
info->params = malloc(size);
|
|
|
|
|
memcpy(info->params, update->params, size);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
info->params = NULL;
|
|
|
|
|
}
|
|
|
|
|
return info;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
endpoint_info_free (struct pw_endpoint_info *info)
|
|
|
|
|
{
|
|
|
|
|
g_free(info->name);
|
|
|
|
|
g_free(info->media_class);
|
|
|
|
|
free((void *) info->params);
|
|
|
|
|
free(info);
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-12 11:28:07 +02:00
|
|
|
/* WpEndpoint */
|
2019-12-09 16:35:15 +02:00
|
|
|
|
2020-02-12 11:28:07 +02:00
|
|
|
typedef struct _WpEndpointPrivate WpEndpointPrivate;
|
|
|
|
|
struct _WpEndpointPrivate
|
2019-12-09 16:35:15 +02:00
|
|
|
{
|
|
|
|
|
WpProperties *properties;
|
|
|
|
|
WpSpaProps spa_props;
|
|
|
|
|
struct pw_endpoint_info *info;
|
|
|
|
|
struct spa_hook listener;
|
|
|
|
|
};
|
|
|
|
|
|
2020-02-12 11:28:07 +02:00
|
|
|
G_DEFINE_TYPE_WITH_PRIVATE (WpEndpoint, wp_endpoint, WP_TYPE_PROXY)
|
2019-12-09 16:35:15 +02:00
|
|
|
|
|
|
|
|
static void
|
2020-02-12 11:28:07 +02:00
|
|
|
wp_endpoint_init (WpEndpoint * self)
|
2019-12-09 16:35:15 +02:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2020-02-12 11:28:07 +02:00
|
|
|
wp_endpoint_finalize (GObject * object)
|
2019-12-09 16:35:15 +02:00
|
|
|
{
|
2020-02-12 11:28:07 +02:00
|
|
|
WpEndpoint *self = WP_ENDPOINT (object);
|
|
|
|
|
WpEndpointPrivate *priv = wp_endpoint_get_instance_private (self);
|
2019-12-09 16:35:15 +02:00
|
|
|
|
2020-02-12 11:28:07 +02:00
|
|
|
g_clear_pointer (&priv->info, endpoint_info_free);
|
|
|
|
|
g_clear_pointer (&priv->properties, wp_properties_unref);
|
|
|
|
|
wp_spa_props_clear (&priv->spa_props);
|
2019-12-09 16:35:15 +02:00
|
|
|
|
2020-02-12 11:28:07 +02:00
|
|
|
G_OBJECT_CLASS (wp_endpoint_parent_class)->finalize (object);
|
2019-12-09 16:35:15 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2020-02-12 11:28:07 +02:00
|
|
|
wp_endpoint_augment (WpProxy * proxy, WpProxyFeatures features)
|
2019-12-09 16:35:15 +02:00
|
|
|
{
|
2020-01-22 10:34:56 +02:00
|
|
|
/* call the parent impl first to ensure we have a pw proxy if necessary */
|
2020-02-12 11:28:07 +02:00
|
|
|
WP_PROXY_CLASS (wp_endpoint_parent_class)->augment (proxy, features);
|
2019-12-09 16:35:15 +02:00
|
|
|
|
2020-02-12 11:28:07 +02:00
|
|
|
if (features & WP_ENDPOINT_FEATURE_CONTROLS) {
|
2020-01-22 10:34:56 +02:00
|
|
|
struct pw_endpoint *pw_proxy = NULL;
|
|
|
|
|
uint32_t ids[] = { SPA_PARAM_Props };
|
|
|
|
|
|
|
|
|
|
pw_proxy = (struct pw_endpoint *) wp_proxy_get_pw_proxy (proxy);
|
|
|
|
|
if (!pw_proxy)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
pw_endpoint_enum_params (pw_proxy, 0, SPA_PARAM_PropInfo, 0, -1, NULL);
|
|
|
|
|
pw_endpoint_subscribe_params (pw_proxy, ids, SPA_N_ELEMENTS (ids));
|
2019-12-09 16:35:15 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-22 10:34:56 +02:00
|
|
|
static gconstpointer
|
2020-02-12 11:28:07 +02:00
|
|
|
wp_endpoint_get_info (WpProxy * proxy)
|
2020-01-22 10:34:56 +02:00
|
|
|
{
|
2020-02-12 11:28:07 +02:00
|
|
|
WpEndpoint *self = WP_ENDPOINT (proxy);
|
|
|
|
|
WpEndpointPrivate *priv = wp_endpoint_get_instance_private (self);
|
|
|
|
|
|
|
|
|
|
return priv->info;
|
2020-01-22 10:34:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static WpProperties *
|
2020-02-12 11:28:07 +02:00
|
|
|
wp_endpoint_get_properties (WpProxy * proxy)
|
2020-01-22 10:34:56 +02:00
|
|
|
{
|
2020-02-12 11:28:07 +02:00
|
|
|
WpEndpoint *self = WP_ENDPOINT (proxy);
|
|
|
|
|
WpEndpointPrivate *priv = wp_endpoint_get_instance_private (self);
|
|
|
|
|
|
|
|
|
|
return wp_properties_ref (priv->properties);
|
2020-01-22 10:34:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gint
|
2020-02-12 11:28:07 +02:00
|
|
|
wp_endpoint_enum_params (WpProxy * self, guint32 id, guint32 start,
|
2020-01-22 10:34:56 +02:00
|
|
|
guint32 num, const struct spa_pod *filter)
|
|
|
|
|
{
|
|
|
|
|
struct pw_endpoint *pwp;
|
|
|
|
|
int endpoint_enum_params_result;
|
|
|
|
|
|
|
|
|
|
pwp = (struct pw_endpoint *) wp_proxy_get_pw_proxy (self);
|
|
|
|
|
endpoint_enum_params_result = pw_endpoint_enum_params (pwp, 0, id, start, num,
|
|
|
|
|
filter);
|
|
|
|
|
g_warn_if_fail (endpoint_enum_params_result >= 0);
|
|
|
|
|
|
|
|
|
|
return endpoint_enum_params_result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gint
|
2020-02-12 11:28:07 +02:00
|
|
|
wp_endpoint_subscribe_params (WpProxy * self, guint32 n_ids, guint32 *ids)
|
2020-01-22 10:34:56 +02:00
|
|
|
{
|
|
|
|
|
struct pw_endpoint *pwp;
|
|
|
|
|
int endpoint_subscribe_params_result;
|
|
|
|
|
|
|
|
|
|
pwp = (struct pw_endpoint *) wp_proxy_get_pw_proxy (self);
|
|
|
|
|
endpoint_subscribe_params_result = pw_endpoint_subscribe_params (pwp, ids,
|
|
|
|
|
n_ids);
|
|
|
|
|
g_warn_if_fail (endpoint_subscribe_params_result >= 0);
|
|
|
|
|
|
|
|
|
|
return endpoint_subscribe_params_result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gint
|
2020-02-12 11:28:07 +02:00
|
|
|
wp_endpoint_set_param (WpProxy * self, guint32 id, guint32 flags,
|
2020-01-22 10:34:56 +02:00
|
|
|
const struct spa_pod *param)
|
|
|
|
|
{
|
|
|
|
|
struct pw_endpoint *pwp;
|
|
|
|
|
int endpoint_set_param_result;
|
|
|
|
|
|
|
|
|
|
pwp = (struct pw_endpoint *) wp_proxy_get_pw_proxy (self);
|
|
|
|
|
endpoint_set_param_result = pw_endpoint_set_param (pwp, id, flags, param);
|
|
|
|
|
g_warn_if_fail (endpoint_set_param_result >= 0);
|
|
|
|
|
|
|
|
|
|
return endpoint_set_param_result;
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-09 16:35:15 +02:00
|
|
|
static void
|
|
|
|
|
endpoint_event_info (void *data, const struct pw_endpoint_info *info)
|
|
|
|
|
{
|
2020-02-12 11:28:07 +02:00
|
|
|
WpEndpoint *self = WP_ENDPOINT (data);
|
|
|
|
|
WpEndpointPrivate *priv = wp_endpoint_get_instance_private (self);
|
2019-12-09 16:35:15 +02:00
|
|
|
|
2020-02-12 11:28:07 +02:00
|
|
|
priv->info = endpoint_info_update (priv->info, &priv->properties, info);
|
2020-01-30 17:41:25 +02:00
|
|
|
wp_proxy_set_feature_ready (WP_PROXY (self), WP_PROXY_FEATURE_INFO);
|
|
|
|
|
|
2019-12-09 16:35:15 +02:00
|
|
|
g_object_notify (G_OBJECT (self), "info");
|
|
|
|
|
|
|
|
|
|
if (info->change_mask & PW_ENDPOINT_CHANGE_MASK_PROPS)
|
|
|
|
|
g_object_notify (G_OBJECT (self), "properties");
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-22 10:34:56 +02:00
|
|
|
static const struct pw_endpoint_events endpoint_events = {
|
|
|
|
|
PW_VERSION_ENDPOINT_EVENTS,
|
|
|
|
|
.info = endpoint_event_info,
|
|
|
|
|
.param = wp_proxy_handle_event_param,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static void
|
2020-02-12 11:28:07 +02:00
|
|
|
wp_endpoint_pw_proxy_created (WpProxy * proxy, struct pw_proxy * pw_proxy)
|
2020-01-22 10:34:56 +02:00
|
|
|
{
|
2020-02-12 11:28:07 +02:00
|
|
|
WpEndpoint *self = WP_ENDPOINT (proxy);
|
|
|
|
|
WpEndpointPrivate *priv = wp_endpoint_get_instance_private (self);
|
|
|
|
|
|
2020-01-22 10:34:56 +02:00
|
|
|
pw_endpoint_add_listener ((struct pw_endpoint *) pw_proxy,
|
2020-02-12 11:28:07 +02:00
|
|
|
&priv->listener, &endpoint_events, self);
|
2020-01-22 10:34:56 +02:00
|
|
|
}
|
|
|
|
|
|
2019-12-09 16:35:15 +02:00
|
|
|
static void
|
2020-02-12 11:28:07 +02:00
|
|
|
wp_endpoint_param (WpProxy * proxy, gint seq, guint32 id, guint32 index,
|
2020-01-22 10:34:56 +02:00
|
|
|
guint32 next, const struct spa_pod *param)
|
2019-12-09 16:35:15 +02:00
|
|
|
{
|
2020-02-12 11:28:07 +02:00
|
|
|
WpEndpoint *self = WP_ENDPOINT (proxy);
|
|
|
|
|
WpEndpointPrivate *priv = wp_endpoint_get_instance_private (self);
|
2019-12-09 16:35:15 +02:00
|
|
|
g_autoptr (GArray) changed_ids = NULL;
|
|
|
|
|
guint32 prop_id;
|
|
|
|
|
|
|
|
|
|
switch (id) {
|
|
|
|
|
case SPA_PARAM_PropInfo:
|
2020-02-12 11:28:07 +02:00
|
|
|
wp_spa_props_register_from_prop_info (&priv->spa_props, param);
|
2019-12-09 16:35:15 +02:00
|
|
|
break;
|
|
|
|
|
case SPA_PARAM_Props:
|
|
|
|
|
changed_ids = g_array_new (FALSE, FALSE, sizeof (uint32_t));
|
2020-02-12 11:28:07 +02:00
|
|
|
wp_spa_props_store_from_props (&priv->spa_props, param, changed_ids);
|
2019-12-09 16:35:15 +02:00
|
|
|
|
|
|
|
|
for (guint i = 0; i < changed_ids->len; i++) {
|
|
|
|
|
prop_id = g_array_index (changed_ids, uint32_t, i);
|
|
|
|
|
g_signal_emit (self, signals[SIGNAL_CONTROL_CHANGED], 0, prop_id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
wp_proxy_set_feature_ready (WP_PROXY (self),
|
2020-02-12 11:28:07 +02:00
|
|
|
WP_ENDPOINT_FEATURE_CONTROLS);
|
2019-12-09 16:35:15 +02:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-22 10:34:56 +02:00
|
|
|
static const gchar *
|
2020-02-12 11:28:07 +02:00
|
|
|
get_name (WpEndpoint * self)
|
2019-12-11 23:43:13 +02:00
|
|
|
{
|
2020-02-12 11:28:07 +02:00
|
|
|
WpEndpointPrivate *priv = wp_endpoint_get_instance_private (self);
|
|
|
|
|
return priv->info->name;
|
2019-12-11 23:43:13 +02:00
|
|
|
}
|
|
|
|
|
|
2020-01-22 10:34:56 +02:00
|
|
|
static const gchar *
|
2020-02-12 11:28:07 +02:00
|
|
|
get_media_class (WpEndpoint * self)
|
2019-12-11 23:43:13 +02:00
|
|
|
{
|
2020-02-12 11:28:07 +02:00
|
|
|
WpEndpointPrivate *priv = wp_endpoint_get_instance_private (self);
|
|
|
|
|
return priv->info->media_class;
|
2019-12-11 23:43:13 +02:00
|
|
|
}
|
|
|
|
|
|
2020-01-22 10:34:56 +02:00
|
|
|
static WpDirection
|
2020-02-12 11:28:07 +02:00
|
|
|
get_direction (WpEndpoint * self)
|
2019-12-11 23:43:13 +02:00
|
|
|
{
|
2020-02-12 11:28:07 +02:00
|
|
|
WpEndpointPrivate *priv = wp_endpoint_get_instance_private (self);
|
|
|
|
|
return priv->info->direction;
|
2019-12-11 23:43:13 +02:00
|
|
|
}
|
|
|
|
|
|
2019-12-09 16:35:15 +02:00
|
|
|
static const struct spa_pod *
|
2020-02-12 11:28:07 +02:00
|
|
|
get_control (WpEndpoint * self, guint32 control_id)
|
2019-12-09 16:35:15 +02:00
|
|
|
{
|
2020-02-12 11:28:07 +02:00
|
|
|
WpEndpointPrivate *priv = wp_endpoint_get_instance_private (self);
|
|
|
|
|
return wp_spa_props_get_stored (&priv->spa_props, control_id);
|
2019-12-09 16:35:15 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
2020-02-12 11:28:07 +02:00
|
|
|
set_control (WpEndpoint * self, guint32 control_id,
|
2019-12-09 16:35:15 +02:00
|
|
|
const struct spa_pod * pod)
|
|
|
|
|
{
|
|
|
|
|
char buf[1024];
|
|
|
|
|
struct spa_pod_builder b = SPA_POD_BUILDER_INIT (buf, sizeof (buf));
|
2020-01-09 12:39:45 -05:00
|
|
|
struct pw_endpoint *pw_proxy = NULL;
|
2019-12-09 16:35:15 +02:00
|
|
|
|
|
|
|
|
/* set the default endpoint id as a property param on the endpoint;
|
|
|
|
|
our spa_props will be updated by the param event */
|
|
|
|
|
|
2020-01-09 12:39:45 -05:00
|
|
|
pw_proxy = (struct pw_endpoint *) wp_proxy_get_pw_proxy (WP_PROXY (self));
|
2019-12-12 20:08:41 +02:00
|
|
|
if (!pw_proxy)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
2020-01-09 12:39:45 -05:00
|
|
|
pw_endpoint_set_param (pw_proxy,
|
2019-12-09 16:35:15 +02:00
|
|
|
SPA_PARAM_Props, 0,
|
|
|
|
|
spa_pod_builder_add_object (&b,
|
|
|
|
|
SPA_TYPE_OBJECT_Props, SPA_PARAM_Props,
|
|
|
|
|
control_id, SPA_POD_Pod (pod)));
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2020-02-12 11:28:07 +02:00
|
|
|
wp_endpoint_class_init (WpEndpointClass * klass)
|
2019-12-09 16:35:15 +02:00
|
|
|
{
|
|
|
|
|
GObjectClass *object_class = (GObjectClass *) klass;
|
|
|
|
|
WpProxyClass *proxy_class = (WpProxyClass *) klass;
|
|
|
|
|
|
2020-02-12 11:28:07 +02:00
|
|
|
object_class->finalize = wp_endpoint_finalize;
|
2019-12-09 16:35:15 +02:00
|
|
|
|
2020-01-30 17:41:25 +02:00
|
|
|
proxy_class->pw_iface_type = PW_TYPE_INTERFACE_Endpoint;
|
|
|
|
|
proxy_class->pw_iface_version = PW_VERSION_ENDPOINT;
|
|
|
|
|
|
2020-02-12 11:28:07 +02:00
|
|
|
proxy_class->augment = wp_endpoint_augment;
|
|
|
|
|
proxy_class->get_info = wp_endpoint_get_info;
|
|
|
|
|
proxy_class->get_properties = wp_endpoint_get_properties;
|
|
|
|
|
proxy_class->enum_params = wp_endpoint_enum_params;
|
|
|
|
|
proxy_class->subscribe_params = wp_endpoint_subscribe_params;
|
|
|
|
|
proxy_class->set_param = wp_endpoint_set_param;
|
|
|
|
|
|
|
|
|
|
proxy_class->pw_proxy_created = wp_endpoint_pw_proxy_created;
|
|
|
|
|
proxy_class->param = wp_endpoint_param;
|
|
|
|
|
|
|
|
|
|
klass->get_name = get_name;
|
|
|
|
|
klass->get_media_class = get_media_class;
|
|
|
|
|
klass->get_direction = get_direction;
|
|
|
|
|
klass->get_control = get_control;
|
|
|
|
|
klass->set_control = set_control;
|
2019-12-09 16:35:15 +02:00
|
|
|
|
2020-02-12 11:28:07 +02:00
|
|
|
signals[SIGNAL_CONTROL_CHANGED] = g_signal_new (
|
|
|
|
|
"control-changed", G_TYPE_FROM_CLASS (klass),
|
|
|
|
|
G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_UINT);
|
2019-12-09 16:35:15 +02:00
|
|
|
}
|
|
|
|
|
|
2020-02-12 11:28:07 +02:00
|
|
|
const gchar *
|
|
|
|
|
wp_endpoint_get_name (WpEndpoint * self)
|
2019-12-09 16:35:15 +02:00
|
|
|
{
|
2020-02-12 11:28:07 +02:00
|
|
|
g_return_val_if_fail (WP_IS_ENDPOINT (self), NULL);
|
|
|
|
|
g_return_val_if_fail (WP_ENDPOINT_GET_CLASS (self)->get_name, NULL);
|
|
|
|
|
|
|
|
|
|
return WP_ENDPOINT_GET_CLASS (self)->get_name (self);
|
2019-12-09 16:35:15 +02:00
|
|
|
}
|
|
|
|
|
|
2020-02-12 11:28:07 +02:00
|
|
|
const gchar *
|
|
|
|
|
wp_endpoint_get_media_class (WpEndpoint * self)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (WP_IS_ENDPOINT (self), NULL);
|
|
|
|
|
g_return_val_if_fail (WP_ENDPOINT_GET_CLASS (self)->get_media_class, NULL);
|
|
|
|
|
|
|
|
|
|
return WP_ENDPOINT_GET_CLASS (self)->get_media_class (self);
|
|
|
|
|
}
|
2019-12-09 16:35:15 +02:00
|
|
|
|
2020-02-12 11:28:07 +02:00
|
|
|
WpDirection
|
|
|
|
|
wp_endpoint_get_direction (WpEndpoint * self)
|
2019-12-09 16:35:15 +02:00
|
|
|
{
|
2020-02-12 11:28:07 +02:00
|
|
|
g_return_val_if_fail (WP_IS_ENDPOINT (self), 0);
|
|
|
|
|
g_return_val_if_fail (WP_ENDPOINT_GET_CLASS (self)->get_direction, 0);
|
|
|
|
|
|
|
|
|
|
return WP_ENDPOINT_GET_CLASS (self)->get_direction (self);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const struct spa_pod *
|
|
|
|
|
wp_endpoint_get_control (WpEndpoint * self, guint32 control_id)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (WP_IS_ENDPOINT (self), NULL);
|
|
|
|
|
g_return_val_if_fail (WP_ENDPOINT_GET_CLASS (self)->get_control, NULL);
|
|
|
|
|
|
|
|
|
|
return WP_ENDPOINT_GET_CLASS (self)->get_control (self, control_id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
|
wp_endpoint_get_control_boolean (WpEndpoint * self, guint32 control_id,
|
|
|
|
|
gboolean * value)
|
|
|
|
|
{
|
|
|
|
|
const struct spa_pod *pod = wp_endpoint_get_control (self, control_id);
|
|
|
|
|
bool val;
|
|
|
|
|
if (pod && spa_pod_get_bool (pod, &val) == 0) {
|
|
|
|
|
*value = val;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
|
wp_endpoint_get_control_int (WpEndpoint * self, guint32 control_id,
|
|
|
|
|
gint * value)
|
|
|
|
|
{
|
|
|
|
|
const struct spa_pod *pod = wp_endpoint_get_control (self, control_id);
|
|
|
|
|
return (pod && spa_pod_get_int (pod, value) == 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
|
wp_endpoint_get_control_float (WpEndpoint * self, guint32 control_id,
|
|
|
|
|
gfloat * value)
|
|
|
|
|
{
|
|
|
|
|
const struct spa_pod *pod = wp_endpoint_get_control (self, control_id);
|
|
|
|
|
return (pod && spa_pod_get_float (pod, value) == 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
|
wp_endpoint_set_control (WpEndpoint * self, guint32 control_id,
|
|
|
|
|
const struct spa_pod * value)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (WP_IS_ENDPOINT (self), FALSE);
|
|
|
|
|
g_return_val_if_fail (WP_ENDPOINT_GET_CLASS (self)->set_control, FALSE);
|
|
|
|
|
|
|
|
|
|
return WP_ENDPOINT_GET_CLASS (self)->set_control (self, control_id, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
|
wp_endpoint_set_control_boolean (WpEndpoint * self, guint32 control_id,
|
|
|
|
|
gboolean value)
|
|
|
|
|
{
|
|
|
|
|
gchar buffer[512];
|
|
|
|
|
return wp_endpoint_set_control (self, control_id, wp_spa_props_build_pod (
|
|
|
|
|
buffer, sizeof (buffer), SPA_POD_Bool (value), 0));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
|
wp_endpoint_set_control_int (WpEndpoint * self, guint32 control_id,
|
|
|
|
|
gint value)
|
|
|
|
|
{
|
|
|
|
|
gchar buffer[512];
|
|
|
|
|
return wp_endpoint_set_control (self, control_id, wp_spa_props_build_pod (
|
|
|
|
|
buffer, sizeof (buffer), SPA_POD_Int (value), 0));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
|
wp_endpoint_set_control_float (WpEndpoint * self, guint32 control_id,
|
|
|
|
|
gfloat value)
|
|
|
|
|
{
|
|
|
|
|
gchar buffer[512];
|
|
|
|
|
return wp_endpoint_set_control (self, control_id, wp_spa_props_build_pod (
|
|
|
|
|
buffer, sizeof (buffer), SPA_POD_Float (value), 0));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* WpImplEndpoint */
|
|
|
|
|
|
|
|
|
|
typedef struct _WpImplEndpointPrivate WpImplEndpointPrivate;
|
|
|
|
|
struct _WpImplEndpointPrivate
|
|
|
|
|
{
|
|
|
|
|
WpEndpointPrivate *pp;
|
2019-12-09 16:35:15 +02:00
|
|
|
struct pw_endpoint_info info;
|
|
|
|
|
struct spa_param_info param_info[2];
|
|
|
|
|
};
|
|
|
|
|
|
2020-02-12 11:28:07 +02:00
|
|
|
G_DEFINE_TYPE_WITH_PRIVATE (WpImplEndpoint, wp_impl_endpoint, WP_TYPE_ENDPOINT)
|
2019-12-09 16:35:15 +02:00
|
|
|
|
|
|
|
|
static void
|
2020-02-12 11:28:07 +02:00
|
|
|
wp_impl_endpoint_init (WpImplEndpoint * self)
|
2019-12-09 16:35:15 +02:00
|
|
|
{
|
2020-02-12 11:28:07 +02:00
|
|
|
WpImplEndpointPrivate *priv = wp_impl_endpoint_get_instance_private (self);
|
2019-12-09 16:35:15 +02:00
|
|
|
|
2020-02-12 11:28:07 +02:00
|
|
|
/* store a pointer to the parent's private; we use that structure
|
|
|
|
|
as well to optimize memory usage and to be able to re-use some of the
|
|
|
|
|
parent's methods without reimplementing them */
|
|
|
|
|
priv->pp = wp_endpoint_get_instance_private (WP_ENDPOINT (self));
|
|
|
|
|
|
|
|
|
|
priv->pp->properties = wp_properties_new_empty ();
|
2019-12-09 16:35:15 +02:00
|
|
|
|
|
|
|
|
priv->param_info[0] = SPA_PARAM_INFO (SPA_PARAM_Props, SPA_PARAM_INFO_READWRITE);
|
|
|
|
|
priv->param_info[1] = SPA_PARAM_INFO (SPA_PARAM_PropInfo, SPA_PARAM_INFO_READ);
|
|
|
|
|
|
|
|
|
|
priv->info.version = PW_VERSION_ENDPOINT_INFO;
|
2020-02-12 11:28:07 +02:00
|
|
|
priv->info.props =
|
|
|
|
|
(struct spa_dict *) wp_properties_peek_dict (priv->pp->properties);
|
2019-12-09 16:35:15 +02:00
|
|
|
priv->info.params = priv->param_info;
|
|
|
|
|
priv->info.n_params = SPA_N_ELEMENTS (priv->param_info);
|
2020-02-12 11:28:07 +02:00
|
|
|
priv->pp->info = &priv->info;
|
|
|
|
|
wp_proxy_set_feature_ready (WP_PROXY (self), WP_PROXY_FEATURE_INFO);
|
|
|
|
|
wp_proxy_set_feature_ready (WP_PROXY (self), WP_ENDPOINT_FEATURE_CONTROLS);
|
2019-12-09 16:35:15 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2020-02-12 11:28:07 +02:00
|
|
|
wp_impl_endpoint_finalize (GObject * object)
|
2019-12-09 16:35:15 +02:00
|
|
|
{
|
2020-02-12 11:28:07 +02:00
|
|
|
WpImplEndpointPrivate *priv =
|
|
|
|
|
wp_impl_endpoint_get_instance_private (WP_IMPL_ENDPOINT (object));
|
2019-12-09 16:35:15 +02:00
|
|
|
|
2020-02-12 11:28:07 +02:00
|
|
|
/* set to NULL to prevent parent's finalize from calling free() on it */
|
|
|
|
|
priv->pp->info = NULL;
|
2019-12-09 18:31:43 +02:00
|
|
|
g_free (priv->info.name);
|
|
|
|
|
g_free (priv->info.media_class);
|
2019-12-09 16:35:15 +02:00
|
|
|
|
2020-02-12 11:28:07 +02:00
|
|
|
G_OBJECT_CLASS (wp_impl_endpoint_parent_class)->finalize (object);
|
2019-12-09 16:35:15 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2020-02-12 11:28:07 +02:00
|
|
|
client_endpoint_update (WpImplEndpoint * self, guint32 change_mask,
|
2019-12-09 16:35:15 +02:00
|
|
|
guint32 info_change_mask)
|
|
|
|
|
{
|
2020-02-12 11:28:07 +02:00
|
|
|
WpImplEndpointPrivate *priv = wp_impl_endpoint_get_instance_private (self);
|
2019-12-09 16:35:15 +02:00
|
|
|
char buf[1024];
|
|
|
|
|
struct spa_pod_builder b = SPA_POD_BUILDER_INIT (buf, sizeof (buf));
|
2020-01-09 12:39:45 -05:00
|
|
|
struct pw_client_endpoint *pw_proxy = NULL;
|
2019-12-09 16:35:15 +02:00
|
|
|
struct pw_endpoint_info *info = NULL;
|
|
|
|
|
g_autoptr (GPtrArray) params = NULL;
|
|
|
|
|
|
2020-02-12 11:28:07 +02:00
|
|
|
pw_proxy = (struct pw_client_endpoint *) wp_proxy_get_pw_proxy (WP_PROXY (self));
|
2019-12-09 16:35:15 +02:00
|
|
|
|
|
|
|
|
if (change_mask & PW_CLIENT_ENDPOINT_UPDATE_PARAMS) {
|
2020-02-12 11:28:07 +02:00
|
|
|
params = wp_spa_props_build_all_pods (&priv->pp->spa_props, &b);
|
2019-12-09 16:35:15 +02:00
|
|
|
}
|
|
|
|
|
if (change_mask & PW_CLIENT_ENDPOINT_UPDATE_INFO) {
|
|
|
|
|
info = &priv->info;
|
|
|
|
|
info->change_mask = info_change_mask;
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-09 12:39:45 -05:00
|
|
|
pw_client_endpoint_update (pw_proxy,
|
2019-12-09 16:35:15 +02:00
|
|
|
change_mask,
|
|
|
|
|
params ? params->len : 0,
|
|
|
|
|
(const struct spa_pod **) (params ? params->pdata : NULL),
|
|
|
|
|
info);
|
|
|
|
|
|
|
|
|
|
if (info)
|
|
|
|
|
info->change_mask = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
client_endpoint_set_param (void *object,
|
|
|
|
|
uint32_t id, uint32_t flags, const struct spa_pod *param)
|
|
|
|
|
{
|
2020-02-12 11:28:07 +02:00
|
|
|
WpImplEndpoint *self = WP_IMPL_ENDPOINT (object);
|
|
|
|
|
WpImplEndpointPrivate *priv = wp_impl_endpoint_get_instance_private (self);
|
2019-12-09 16:35:15 +02:00
|
|
|
g_autoptr (GArray) changed_ids = NULL;
|
|
|
|
|
guint32 prop_id;
|
|
|
|
|
|
|
|
|
|
if (id != SPA_PARAM_Props)
|
|
|
|
|
return -ENOENT;
|
|
|
|
|
|
|
|
|
|
changed_ids = g_array_new (FALSE, FALSE, sizeof (guint32));
|
2020-02-12 11:28:07 +02:00
|
|
|
wp_spa_props_store_from_props (&priv->pp->spa_props, param, changed_ids);
|
2019-12-09 16:35:15 +02:00
|
|
|
|
|
|
|
|
for (guint i = 0; i < changed_ids->len; i++) {
|
|
|
|
|
prop_id = g_array_index (changed_ids, guint32, i);
|
|
|
|
|
g_signal_emit (self, signals[SIGNAL_CONTROL_CHANGED], 0, prop_id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
client_endpoint_update (self, PW_CLIENT_ENDPOINT_UPDATE_PARAMS, 0);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-09 12:39:45 -05:00
|
|
|
static struct pw_client_endpoint_events client_endpoint_events = {
|
|
|
|
|
PW_VERSION_CLIENT_ENDPOINT_EVENTS,
|
2019-12-09 16:35:15 +02:00
|
|
|
.set_param = client_endpoint_set_param,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static void
|
2020-02-12 11:28:07 +02:00
|
|
|
wp_impl_endpoint_augment (WpProxy * proxy, WpProxyFeatures features)
|
|
|
|
|
{
|
|
|
|
|
WpImplEndpoint *self = WP_IMPL_ENDPOINT (proxy);
|
|
|
|
|
WpImplEndpointPrivate *priv = wp_impl_endpoint_get_instance_private (self);
|
|
|
|
|
|
|
|
|
|
/* if any of the default features is requested, make sure BOUND
|
|
|
|
|
is also requested, as they all depend on binding the endpoint */
|
|
|
|
|
if (features & WP_PROXY_FEATURES_STANDARD)
|
|
|
|
|
features |= WP_PROXY_FEATURE_BOUND;
|
|
|
|
|
|
|
|
|
|
if (features & WP_PROXY_FEATURE_BOUND) {
|
|
|
|
|
g_autoptr (WpCore) core = wp_proxy_get_core (proxy);
|
|
|
|
|
struct pw_core *pw_core = wp_core_get_pw_core (core);
|
|
|
|
|
struct pw_proxy *pw_proxy = NULL;
|
|
|
|
|
|
|
|
|
|
/* no pw_core -> we are not connected */
|
|
|
|
|
if (!pw_core) {
|
|
|
|
|
wp_proxy_augment_error (proxy, g_error_new (WP_DOMAIN_LIBRARY,
|
|
|
|
|
WP_LIBRARY_ERROR_OPERATION_FAILED,
|
|
|
|
|
"The WirePlumber core is not connected; "
|
|
|
|
|
"object cannot be exported to PipeWire"));
|
|
|
|
|
return;
|
|
|
|
|
}
|
2019-12-09 16:35:15 +02:00
|
|
|
|
2020-02-12 11:28:07 +02:00
|
|
|
/* make sure these props are not present; they are added by the server */
|
|
|
|
|
wp_properties_set (priv->pp->properties, PW_KEY_OBJECT_ID, NULL);
|
|
|
|
|
wp_properties_set (priv->pp->properties, PW_KEY_CLIENT_ID, NULL);
|
|
|
|
|
wp_properties_set (priv->pp->properties, PW_KEY_FACTORY_ID, NULL);
|
2019-12-09 16:35:15 +02:00
|
|
|
|
2020-02-12 11:28:07 +02:00
|
|
|
/* add must-have global properties */
|
|
|
|
|
wp_properties_set (priv->pp->properties,
|
|
|
|
|
PW_KEY_ENDPOINT_NAME, priv->info.name);
|
|
|
|
|
wp_properties_set (priv->pp->properties,
|
|
|
|
|
PW_KEY_MEDIA_CLASS, priv->info.media_class);
|
2019-12-09 16:35:15 +02:00
|
|
|
|
2020-02-12 11:28:07 +02:00
|
|
|
pw_proxy = pw_core_create_object (pw_core, "client-endpoint",
|
|
|
|
|
PW_TYPE_INTERFACE_ClientEndpoint, PW_VERSION_CLIENT_ENDPOINT,
|
|
|
|
|
wp_properties_peek_dict (priv->pp->properties), 0);
|
|
|
|
|
wp_proxy_set_pw_proxy (proxy, pw_proxy);
|
2019-12-11 23:43:13 +02:00
|
|
|
|
2020-02-12 11:28:07 +02:00
|
|
|
pw_client_endpoint_add_listener (pw_proxy, &priv->pp->listener,
|
|
|
|
|
&client_endpoint_events, self);
|
2019-12-11 23:43:13 +02:00
|
|
|
|
2020-02-12 11:28:07 +02:00
|
|
|
client_endpoint_update (WP_IMPL_ENDPOINT (self),
|
|
|
|
|
PW_CLIENT_ENDPOINT_UPDATE_PARAMS | PW_CLIENT_ENDPOINT_UPDATE_INFO,
|
|
|
|
|
PW_ENDPOINT_CHANGE_MASK_ALL);
|
|
|
|
|
}
|
2019-12-11 23:43:13 +02:00
|
|
|
}
|
|
|
|
|
|
2020-02-12 11:28:07 +02:00
|
|
|
static gint
|
|
|
|
|
wp_impl_endpoint_set_param (WpProxy * self, guint32 id, guint32 flags,
|
|
|
|
|
const struct spa_pod *param)
|
2019-12-09 16:35:15 +02:00
|
|
|
{
|
2020-02-12 11:28:07 +02:00
|
|
|
return client_endpoint_set_param (self, id, flags, param);
|
2019-12-09 16:35:15 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
2020-02-12 11:28:07 +02:00
|
|
|
wp_impl_endpoint_set_control (WpEndpoint * endpoint, guint32 control_id,
|
2019-12-09 16:35:15 +02:00
|
|
|
const struct spa_pod * pod)
|
|
|
|
|
{
|
2020-02-12 11:28:07 +02:00
|
|
|
WpImplEndpointPrivate *priv =
|
|
|
|
|
wp_impl_endpoint_get_instance_private (WP_IMPL_ENDPOINT (endpoint));
|
2019-12-09 16:35:15 +02:00
|
|
|
|
2020-02-12 11:28:07 +02:00
|
|
|
if (wp_spa_props_store_pod (&priv->pp->spa_props, control_id, pod) < 0)
|
2019-12-09 16:35:15 +02:00
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
g_signal_emit (endpoint, signals[SIGNAL_CONTROL_CHANGED], 0, control_id);
|
|
|
|
|
|
|
|
|
|
/* update only after the endpoint has been exported */
|
2020-02-12 11:28:07 +02:00
|
|
|
if (wp_proxy_get_features (WP_PROXY (endpoint)) & WP_PROXY_FEATURE_BOUND) {
|
|
|
|
|
client_endpoint_update (WP_IMPL_ENDPOINT (endpoint),
|
|
|
|
|
PW_CLIENT_ENDPOINT_UPDATE_PARAMS, 0);
|
2019-12-09 16:35:15 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2020-02-12 11:28:07 +02:00
|
|
|
wp_impl_endpoint_class_init (WpImplEndpointClass * klass)
|
2019-12-09 16:35:15 +02:00
|
|
|
{
|
|
|
|
|
GObjectClass *object_class = (GObjectClass *) klass;
|
2020-02-12 11:28:07 +02:00
|
|
|
WpProxyClass *proxy_class = (WpProxyClass *) klass;
|
|
|
|
|
WpEndpointClass *endpoint_class = (WpEndpointClass *) klass;
|
2019-12-09 16:35:15 +02:00
|
|
|
|
2020-02-12 11:28:07 +02:00
|
|
|
object_class->finalize = wp_impl_endpoint_finalize;
|
2020-01-22 10:34:56 +02:00
|
|
|
|
2020-02-12 11:28:07 +02:00
|
|
|
proxy_class->augment = wp_impl_endpoint_augment;
|
|
|
|
|
proxy_class->enum_params = NULL;
|
|
|
|
|
proxy_class->subscribe_params = NULL;
|
|
|
|
|
proxy_class->set_param = wp_impl_endpoint_set_param;
|
2020-01-22 10:34:56 +02:00
|
|
|
|
2020-02-12 11:28:07 +02:00
|
|
|
proxy_class->pw_proxy_created = NULL;
|
|
|
|
|
proxy_class->param = NULL;
|
2019-12-09 16:35:15 +02:00
|
|
|
|
2020-02-12 11:28:07 +02:00
|
|
|
endpoint_class->set_control = wp_impl_endpoint_set_control;
|
2019-12-09 16:35:15 +02:00
|
|
|
}
|
|
|
|
|
|
2020-02-12 11:28:07 +02:00
|
|
|
WpImplEndpoint *
|
|
|
|
|
wp_impl_endpoint_new (WpCore * core)
|
2019-12-09 16:35:15 +02:00
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (WP_IS_CORE (core), NULL);
|
|
|
|
|
|
2020-02-12 11:28:07 +02:00
|
|
|
return g_object_new (WP_TYPE_IMPL_ENDPOINT,
|
2019-12-09 16:35:15 +02:00
|
|
|
"core", core,
|
|
|
|
|
NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2020-02-12 11:28:07 +02:00
|
|
|
wp_impl_endpoint_set_property (WpImplEndpoint * self,
|
2019-12-09 16:35:15 +02:00
|
|
|
const gchar * key, const gchar * value)
|
|
|
|
|
{
|
2020-02-12 11:28:07 +02:00
|
|
|
WpImplEndpointPrivate *priv;
|
2019-12-09 16:35:15 +02:00
|
|
|
|
2020-02-12 11:28:07 +02:00
|
|
|
g_return_if_fail (WP_IS_IMPL_ENDPOINT (self));
|
|
|
|
|
priv = wp_impl_endpoint_get_instance_private (self);
|
2019-12-09 16:35:15 +02:00
|
|
|
|
2020-02-12 11:28:07 +02:00
|
|
|
wp_properties_set (priv->pp->properties, key, value);
|
2019-12-09 16:35:15 +02:00
|
|
|
|
|
|
|
|
g_object_notify (G_OBJECT (self), "properties");
|
|
|
|
|
|
|
|
|
|
/* update only after the endpoint has been exported */
|
2020-02-12 11:28:07 +02:00
|
|
|
if (wp_proxy_get_features (WP_PROXY (self)) & WP_PROXY_FEATURE_BOUND) {
|
|
|
|
|
client_endpoint_update (self, PW_CLIENT_ENDPOINT_UPDATE_INFO,
|
|
|
|
|
PW_ENDPOINT_CHANGE_MASK_PROPS);
|
2019-12-09 16:35:15 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2020-02-12 11:28:07 +02:00
|
|
|
wp_impl_endpoint_update_properties (WpImplEndpoint * self,
|
2019-12-09 16:35:15 +02:00
|
|
|
WpProperties * updates)
|
|
|
|
|
{
|
2020-02-12 11:28:07 +02:00
|
|
|
WpImplEndpointPrivate *priv;
|
2019-12-09 16:35:15 +02:00
|
|
|
|
2020-02-12 11:28:07 +02:00
|
|
|
g_return_if_fail (WP_IS_IMPL_ENDPOINT (self));
|
|
|
|
|
priv = wp_impl_endpoint_get_instance_private (self);
|
2019-12-09 16:35:15 +02:00
|
|
|
|
2020-02-12 11:28:07 +02:00
|
|
|
wp_properties_update_from_dict (priv->pp->properties,
|
2019-12-09 16:35:15 +02:00
|
|
|
wp_properties_peek_dict (updates));
|
|
|
|
|
|
|
|
|
|
g_object_notify (G_OBJECT (self), "properties");
|
|
|
|
|
|
|
|
|
|
/* update only after the endpoint has been exported */
|
2020-02-12 11:28:07 +02:00
|
|
|
if (wp_proxy_get_features (WP_PROXY (self)) & WP_PROXY_FEATURE_BOUND) {
|
|
|
|
|
client_endpoint_update (self, PW_CLIENT_ENDPOINT_UPDATE_INFO,
|
|
|
|
|
PW_ENDPOINT_CHANGE_MASK_PROPS);
|
2019-12-09 16:35:15 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-09 18:31:43 +02:00
|
|
|
void
|
2020-02-12 11:28:07 +02:00
|
|
|
wp_impl_endpoint_set_name (WpImplEndpoint * self, const gchar * name)
|
2019-12-09 18:31:43 +02:00
|
|
|
{
|
2020-02-12 11:28:07 +02:00
|
|
|
WpImplEndpointPrivate *priv;
|
2019-12-09 18:31:43 +02:00
|
|
|
|
2020-02-12 11:28:07 +02:00
|
|
|
g_return_if_fail (WP_IS_IMPL_ENDPOINT (self));
|
|
|
|
|
priv = wp_impl_endpoint_get_instance_private (self);
|
2019-12-09 18:31:43 +02:00
|
|
|
|
|
|
|
|
g_free (priv->info.name);
|
|
|
|
|
priv->info.name = g_strdup (name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2020-02-12 11:28:07 +02:00
|
|
|
wp_impl_endpoint_set_media_class (WpImplEndpoint * self,
|
2019-12-09 18:31:43 +02:00
|
|
|
const gchar * media_class)
|
|
|
|
|
{
|
2020-02-12 11:28:07 +02:00
|
|
|
WpImplEndpointPrivate *priv;
|
2019-12-09 18:31:43 +02:00
|
|
|
|
2020-02-12 11:28:07 +02:00
|
|
|
g_return_if_fail (WP_IS_IMPL_ENDPOINT (self));
|
|
|
|
|
priv = wp_impl_endpoint_get_instance_private (self);
|
2019-12-09 18:31:43 +02:00
|
|
|
|
|
|
|
|
g_free (priv->info.media_class);
|
|
|
|
|
priv->info.media_class = g_strdup (media_class);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2020-02-12 11:28:07 +02:00
|
|
|
wp_impl_endpoint_set_direction (WpImplEndpoint * self, WpDirection dir)
|
2019-12-09 18:31:43 +02:00
|
|
|
{
|
2020-02-12 11:28:07 +02:00
|
|
|
WpImplEndpointPrivate *priv;
|
2019-12-09 18:31:43 +02:00
|
|
|
|
2020-02-12 11:28:07 +02:00
|
|
|
g_return_if_fail (WP_IS_IMPL_ENDPOINT (self));
|
|
|
|
|
priv = wp_impl_endpoint_get_instance_private (self);
|
2019-12-09 18:31:43 +02:00
|
|
|
|
|
|
|
|
priv->info.direction = (enum pw_direction) dir;
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-09 16:35:15 +02:00
|
|
|
void
|
2020-02-12 11:28:07 +02:00
|
|
|
wp_impl_endpoint_register_control (WpImplEndpoint * self,
|
2019-12-09 16:35:15 +02:00
|
|
|
WpEndpointControl control)
|
|
|
|
|
{
|
2020-02-12 11:28:07 +02:00
|
|
|
WpImplEndpointPrivate *priv;
|
2019-12-09 16:35:15 +02:00
|
|
|
|
2020-02-12 11:28:07 +02:00
|
|
|
g_return_if_fail (WP_IS_IMPL_ENDPOINT (self));
|
|
|
|
|
priv = wp_impl_endpoint_get_instance_private (self);
|
2019-12-09 16:35:15 +02:00
|
|
|
|
|
|
|
|
switch (control) {
|
|
|
|
|
case WP_ENDPOINT_CONTROL_VOLUME:
|
2020-02-12 11:28:07 +02:00
|
|
|
wp_spa_props_register (&priv->pp->spa_props, control,
|
2019-12-09 16:35:15 +02:00
|
|
|
"Volume", SPA_POD_CHOICE_RANGE_Float (1.0, 0.0, 10.0));
|
|
|
|
|
break;
|
|
|
|
|
case WP_ENDPOINT_CONTROL_MUTE:
|
2020-02-12 11:28:07 +02:00
|
|
|
wp_spa_props_register (&priv->pp->spa_props, control,
|
2019-12-09 16:35:15 +02:00
|
|
|
"Mute", SPA_POD_CHOICE_Bool (false));
|
|
|
|
|
break;
|
|
|
|
|
case WP_ENDPOINT_CONTROL_CHANNEL_VOLUMES:
|
2020-02-12 11:28:07 +02:00
|
|
|
wp_spa_props_register (&priv->pp->spa_props, control,
|
2019-12-09 16:35:15 +02:00
|
|
|
"Channel Volumes", SPA_POD_CHOICE_RANGE_Float (1.0, 0.0, 10.0));
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
g_warning ("Unknown endpoint control: 0x%x", control);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|