mirror of
https://gitlab.freedesktop.org/pipewire/wireplumber.git
synced 2026-02-05 04:20:27 +01:00
lib: implement proxy & proxy-registry
This commit is contained in:
parent
aa34eaae97
commit
f1bb4e3588
5 changed files with 706 additions and 20 deletions
|
|
@ -4,6 +4,7 @@ wp_lib_sources = [
|
|||
'object.c',
|
||||
'plugin-registry.c',
|
||||
'plugin.c',
|
||||
'proxy-registry.c',
|
||||
'proxy.c',
|
||||
]
|
||||
|
||||
|
|
@ -13,6 +14,7 @@ wp_lib_headers = [
|
|||
'object.h',
|
||||
'plugin-registry.h',
|
||||
'plugin.h',
|
||||
'proxy-registry.h',
|
||||
'proxy.h',
|
||||
]
|
||||
|
||||
|
|
|
|||
283
lib/wp/proxy-registry.c
Normal file
283
lib/wp/proxy-registry.c
Normal file
|
|
@ -0,0 +1,283 @@
|
|||
/* WirePlumber
|
||||
*
|
||||
* Copyright © 2019 Collabora Ltd.
|
||||
* @author George Kiagiadakis <george.kiagiadakis@collabora.com>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#include "proxy-registry.h"
|
||||
#include "proxy.h"
|
||||
#include <pipewire/pipewire.h>
|
||||
#include <pipewire/map.h>
|
||||
|
||||
struct _WpProxyRegistry
|
||||
{
|
||||
GObject parent;
|
||||
|
||||
struct pw_remote *remote;
|
||||
struct spa_hook remote_listener;
|
||||
|
||||
struct pw_registry_proxy *reg_proxy;
|
||||
struct spa_hook reg_proxy_listener;
|
||||
|
||||
struct pw_map globals;
|
||||
GArray *new_globals;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_REMOTE,
|
||||
};
|
||||
|
||||
enum {
|
||||
SIGNAL_NEW_PROXY_AVAILABLE,
|
||||
N_SIGNALS
|
||||
};
|
||||
|
||||
static guint signals[N_SIGNALS];
|
||||
|
||||
G_DEFINE_TYPE (WpProxyRegistry, wp_proxy_registry, G_TYPE_OBJECT);
|
||||
|
||||
static gint
|
||||
guint32_compare (const guint32 *a, const guint32 *b)
|
||||
{
|
||||
return (gint) ((gint64)*a - (gint64)*b);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
idle_notify_new_globals (gpointer data)
|
||||
{
|
||||
WpProxyRegistry *self = WP_PROXY_REGISTRY (data);
|
||||
guint i;
|
||||
guint32 id;
|
||||
|
||||
// TODO verify these globals still exist
|
||||
|
||||
g_array_sort (self->new_globals, (GCompareFunc) guint32_compare);
|
||||
for (i = 0; i < self->new_globals->len; i++) {
|
||||
id = g_array_index (self->new_globals, guint32, i);
|
||||
g_signal_emit (self, signals[SIGNAL_NEW_PROXY_AVAILABLE], 0,
|
||||
wp_proxy_registry_get_proxy (self, id));
|
||||
}
|
||||
g_array_remove_range (self->new_globals, 0, self->new_globals->len);
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static inline void
|
||||
map_insert (struct pw_map *map, guint32 id, gpointer obj)
|
||||
{
|
||||
size_t size = pw_map_get_size (map);
|
||||
while (id > size)
|
||||
pw_map_insert_at (map, size++, NULL);
|
||||
pw_map_insert_at (map, id, obj);
|
||||
}
|
||||
|
||||
static void
|
||||
registry_global (void * data, uint32_t id, uint32_t parent_id,
|
||||
uint32_t permissions, uint32_t type, uint32_t version,
|
||||
const struct spa_dict * props)
|
||||
{
|
||||
WpProxyRegistry *self = WP_PROXY_REGISTRY (data);
|
||||
WpProxy *proxy = g_object_new (wp_proxy_get_type (),
|
||||
"id", id,
|
||||
"parent-id", parent_id,
|
||||
"spa-type", type,
|
||||
"initial-properties", props,
|
||||
NULL);
|
||||
map_insert (&self->globals, id, proxy);
|
||||
|
||||
/*
|
||||
* defer notifications until we return to the main loop;
|
||||
* this allows the pipewire event loop to finish emitting
|
||||
* all new available globals before we use them
|
||||
*/
|
||||
if (self->new_globals->len == 0)
|
||||
g_idle_add (idle_notify_new_globals, self);
|
||||
g_array_append_val (self->new_globals, id);
|
||||
}
|
||||
|
||||
static void
|
||||
registry_global_remove (void * data, uint32_t id)
|
||||
{
|
||||
WpProxyRegistry *self = WP_PROXY_REGISTRY (data);
|
||||
GObject *p = pw_map_lookup (&self->globals, id);
|
||||
g_object_unref (p);
|
||||
pw_map_insert_at (&self->globals, id, NULL);
|
||||
}
|
||||
|
||||
static const struct pw_registry_proxy_events registry_events = {
|
||||
PW_VERSION_REGISTRY_PROXY_EVENTS,
|
||||
.global = registry_global,
|
||||
.global_remove = registry_global_remove,
|
||||
};
|
||||
|
||||
static void
|
||||
remote_state_changed (void * data, enum pw_remote_state old_state,
|
||||
enum pw_remote_state new_state, const char * error)
|
||||
{
|
||||
WpProxyRegistry *self = WP_PROXY_REGISTRY (data);
|
||||
|
||||
switch (new_state) {
|
||||
case PW_REMOTE_STATE_CONNECTED:
|
||||
self->reg_proxy = pw_core_proxy_get_registry (
|
||||
pw_remote_get_core_proxy (self->remote),
|
||||
PW_TYPE_INTERFACE_Registry, PW_VERSION_REGISTRY, 0);
|
||||
pw_registry_proxy_add_listener (self->reg_proxy,
|
||||
&self->reg_proxy_listener, ®istry_events, self);
|
||||
break;
|
||||
|
||||
case PW_REMOTE_STATE_UNCONNECTED:
|
||||
self->reg_proxy = NULL;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct pw_remote_events remote_events = {
|
||||
PW_VERSION_REMOTE_EVENTS,
|
||||
.state_changed = remote_state_changed,
|
||||
};
|
||||
|
||||
static void
|
||||
wp_proxy_registry_init (WpProxyRegistry * self)
|
||||
{
|
||||
pw_map_init (&self->globals, 64, 64);
|
||||
self->new_globals = g_array_sized_new (FALSE, FALSE, sizeof (guint32), 64);
|
||||
}
|
||||
|
||||
static void
|
||||
wp_proxy_registry_constructed (GObject * obj)
|
||||
{
|
||||
WpProxyRegistry *self = WP_PROXY_REGISTRY (obj);
|
||||
|
||||
pw_remote_add_listener (self->remote, &self->remote_listener, &remote_events,
|
||||
self);
|
||||
|
||||
G_OBJECT_CLASS (wp_proxy_registry_parent_class)->constructed (obj);
|
||||
}
|
||||
|
||||
static void
|
||||
wp_proxy_registry_finalize (GObject * obj)
|
||||
{
|
||||
WpProxyRegistry *self = WP_PROXY_REGISTRY (obj);
|
||||
|
||||
pw_map_clear (&self->globals);
|
||||
g_array_unref (self->new_globals);
|
||||
|
||||
G_OBJECT_CLASS (wp_proxy_registry_parent_class)->finalize (obj);
|
||||
}
|
||||
|
||||
static void
|
||||
wp_proxy_registry_set_property (GObject * object, guint property_id,
|
||||
const GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
WpProxyRegistry *self = WP_PROXY_REGISTRY (object);
|
||||
|
||||
switch (property_id) {
|
||||
case PROP_REMOTE:
|
||||
self->remote = g_value_get_pointer (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
wp_proxy_registry_get_property (GObject * object, guint property_id,
|
||||
GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
WpProxyRegistry *self = WP_PROXY_REGISTRY (object);
|
||||
|
||||
switch (property_id) {
|
||||
case PROP_REMOTE:
|
||||
g_value_set_pointer (value, self->remote);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
wp_proxy_registry_class_init (WpProxyRegistryClass * klass)
|
||||
{
|
||||
GObjectClass * object_class = (GObjectClass *) klass;
|
||||
|
||||
object_class->constructed = wp_proxy_registry_constructed;
|
||||
object_class->finalize = wp_proxy_registry_finalize;
|
||||
object_class->get_property = wp_proxy_registry_get_property;
|
||||
object_class->set_property = wp_proxy_registry_set_property;
|
||||
|
||||
g_object_class_install_property (object_class, PROP_REMOTE,
|
||||
g_param_spec_pointer ("remote", "remote",
|
||||
"The underlying struct pw_remote *",
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
signals[SIGNAL_NEW_PROXY_AVAILABLE] = g_signal_new ("new-proxy-available",
|
||||
G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 1, wp_proxy_get_type ());
|
||||
}
|
||||
|
||||
/**
|
||||
* wp_proxy_registry_new: (constructor)
|
||||
* @remote: the `pw_remote` on which to bind
|
||||
*
|
||||
* Returns: (transfer full): the new #WpProxyRegistry
|
||||
*/
|
||||
WpProxyRegistry *
|
||||
wp_proxy_registry_new (struct pw_remote * remote)
|
||||
{
|
||||
return g_object_new (wp_proxy_registry_get_type (), "remote", remote, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* wp_proxy_registry_get_proxy: (method)
|
||||
* @self: the registry
|
||||
* @global_id: the ID of the pw_global that is represented by the proxy
|
||||
*
|
||||
* Returns: (transfer full): the #WpProxy that represents the global with
|
||||
* @global_id
|
||||
*/
|
||||
WpProxy *
|
||||
wp_proxy_registry_get_proxy (WpProxyRegistry * self, guint32 global_id)
|
||||
{
|
||||
WpProxy *p;
|
||||
|
||||
g_return_val_if_fail (WP_IS_PROXY_REGISTRY (self), NULL);
|
||||
|
||||
p = pw_map_lookup (&self->globals, global_id);
|
||||
if (p)
|
||||
g_object_ref (p);
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* wp_proxy_registry_get_pw_remote: (skip)
|
||||
* @self: the registry
|
||||
*
|
||||
* Returns: the underlying `pw_remote`
|
||||
*/
|
||||
struct pw_remote *
|
||||
wp_proxy_registry_get_pw_remote (WpProxyRegistry * self)
|
||||
{
|
||||
g_return_val_if_fail (WP_IS_PROXY_REGISTRY (self), NULL);
|
||||
return self->remote;
|
||||
}
|
||||
|
||||
/**
|
||||
* wp_proxy_registry_get_pw_registry_proxy: (skip)
|
||||
* @self: the registry
|
||||
*
|
||||
* Returns: the underlying `pw_registry_proxy`
|
||||
*/
|
||||
struct pw_registry_proxy *
|
||||
wp_proxy_registry_get_pw_registry_proxy (WpProxyRegistry * self)
|
||||
{
|
||||
g_return_val_if_fail (WP_IS_PROXY_REGISTRY (self), NULL);
|
||||
return self->reg_proxy;
|
||||
}
|
||||
33
lib/wp/proxy-registry.h
Normal file
33
lib/wp/proxy-registry.h
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
/* WirePlumber
|
||||
*
|
||||
* Copyright © 2019 Collabora Ltd.
|
||||
* @author George Kiagiadakis <george.kiagiadakis@collabora.com>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#ifndef __WP_PROXY_REGISTRY_H__
|
||||
#define __WP_PROXY_REGISTRY_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
struct pw_remote;
|
||||
struct pw_registry_proxy;
|
||||
typedef struct _WpProxy WpProxy;
|
||||
|
||||
G_DECLARE_FINAL_TYPE (WpProxyRegistry, wp_proxy_registry, WP, PROXY_REGISTRY, GObject)
|
||||
|
||||
WpProxyRegistry * wp_proxy_registry_new (struct pw_remote * remote);
|
||||
|
||||
WpProxy * wp_proxy_registry_get_proxy (WpProxyRegistry * self,
|
||||
guint32 global_id);
|
||||
|
||||
struct pw_remote * wp_proxy_registry_get_pw_remote (WpProxyRegistry * self);
|
||||
struct pw_registry_proxy * wp_proxy_registry_get_pw_registry_proxy (
|
||||
WpProxyRegistry * self);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif
|
||||
398
lib/wp/proxy.c
398
lib/wp/proxy.c
|
|
@ -8,29 +8,227 @@
|
|||
|
||||
#include "proxy.h"
|
||||
#include <pipewire/pipewire.h>
|
||||
#include <spa/debug/types.h>
|
||||
|
||||
struct _WpProxy
|
||||
{
|
||||
GObject parent;
|
||||
|
||||
WpProxyRegistry *registry;
|
||||
|
||||
struct pw_proxy *proxy;
|
||||
guint32 id;
|
||||
guint32 parent_id;
|
||||
guint32 type;
|
||||
const gchar *type_string;
|
||||
|
||||
struct spa_hook proxy_listener;
|
||||
struct spa_hook proxy_proxy_listener;
|
||||
|
||||
union {
|
||||
const struct spa_dict *initial_properties;
|
||||
GHashTable *properties;
|
||||
};
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_PROXY,
|
||||
PROP_ID,
|
||||
PROP_PARENT_ID,
|
||||
PROP_SPA_TYPE,
|
||||
PROP_SPA_TYPE_STRING,
|
||||
PROP_INITIAL_PROPERTIES,
|
||||
PROP_REGISTRY,
|
||||
PROP_PROXY,
|
||||
};
|
||||
|
||||
enum {
|
||||
SIGNAL_DESTROYED,
|
||||
SIGNAL_CHANGED,
|
||||
N_SIGNALS
|
||||
};
|
||||
|
||||
static guint signals[N_SIGNALS];
|
||||
|
||||
G_DEFINE_TYPE (WpProxy, wp_proxy, G_TYPE_OBJECT);
|
||||
|
||||
static void
|
||||
spa_dict_to_hashtable (const struct spa_dict * dict, GHashTable * htable)
|
||||
{
|
||||
const struct spa_dict_item *item;
|
||||
spa_dict_for_each (item, dict) {
|
||||
g_hash_table_insert (htable,
|
||||
GUINT_TO_POINTER (g_quark_from_string (item->key)),
|
||||
g_strdup (item->value));
|
||||
}
|
||||
}
|
||||
|
||||
#define UPDATE_PROP(name, lvalue) \
|
||||
{ \
|
||||
static GQuark _quark = 0; \
|
||||
if (!_quark) \
|
||||
g_quark_from_static_string (name); \
|
||||
g_hash_table_insert (self->properties, GUINT_TO_POINTER (_quark), lvalue); \
|
||||
}
|
||||
|
||||
#define STATIC_PROP(name, lvalue) \
|
||||
{ \
|
||||
static GQuark _quark = 0; \
|
||||
if (!_quark) \
|
||||
g_quark_from_static_string (name); \
|
||||
if (!g_hash_table_contains (self->properties, GUINT_TO_POINTER (_quark))) { \
|
||||
g_hash_table_insert (self->properties, GUINT_TO_POINTER (_quark), lvalue); \
|
||||
} \
|
||||
}
|
||||
|
||||
static void
|
||||
node_event_info (void *object, const struct pw_node_info *info)
|
||||
{
|
||||
WpProxy *self = WP_PROXY (object);
|
||||
|
||||
if (info->change_mask & PW_NODE_CHANGE_MASK_NAME) {
|
||||
UPDATE_PROP ("node-info.name", g_strdup (info->name));
|
||||
}
|
||||
if (info->change_mask & PW_NODE_CHANGE_MASK_INPUT_PORTS) {
|
||||
UPDATE_PROP ("node-info.n-input-ports",
|
||||
g_strdup_printf ("%u", info->n_input_ports));
|
||||
UPDATE_PROP ("node-info.max-input-ports",
|
||||
g_strdup_printf ("%u", info->max_input_ports));
|
||||
}
|
||||
if (info->change_mask & PW_NODE_CHANGE_MASK_OUTPUT_PORTS) {
|
||||
UPDATE_PROP ("node-info.n-output-ports",
|
||||
g_strdup_printf ("%u", info->n_output_ports));
|
||||
UPDATE_PROP ("node-info.max-output-ports",
|
||||
g_strdup_printf ("%u", info->max_output_ports));
|
||||
}
|
||||
if (info->change_mask & PW_NODE_CHANGE_MASK_STATE) {
|
||||
UPDATE_PROP ("node-info.state",
|
||||
g_strdup (pw_node_state_as_string (info->state)));
|
||||
UPDATE_PROP ("node-info.error", g_strdup (info->error));
|
||||
}
|
||||
if (info->change_mask & PW_NODE_CHANGE_MASK_PROPS) {
|
||||
spa_dict_to_hashtable (info->props, self->properties);
|
||||
}
|
||||
// TODO: PW_NODE_CHANGE_MASK_PARAMS
|
||||
|
||||
g_signal_emit (self, signals[SIGNAL_CHANGED], 0);
|
||||
}
|
||||
|
||||
static const struct pw_node_proxy_events node_events = {
|
||||
PW_VERSION_NODE_PROXY_EVENTS,
|
||||
.info = node_event_info
|
||||
};
|
||||
|
||||
static void
|
||||
port_event_info (void *object, const struct pw_port_info *info)
|
||||
{
|
||||
WpProxy *self = WP_PROXY (object);
|
||||
|
||||
STATIC_PROP ("port-info.direction",
|
||||
g_strdup (pw_direction_as_string (info->direction)));
|
||||
|
||||
if (info->change_mask & PW_PORT_CHANGE_MASK_PROPS) {
|
||||
spa_dict_to_hashtable (info->props, self->properties);
|
||||
}
|
||||
// TODO: PW_PORT_CHANGE_MASK_PARAMS
|
||||
|
||||
g_signal_emit (self, signals[SIGNAL_CHANGED], 0);
|
||||
}
|
||||
|
||||
static const struct pw_port_proxy_events port_events = {
|
||||
PW_VERSION_PORT_PROXY_EVENTS,
|
||||
.info = port_event_info
|
||||
};
|
||||
|
||||
static void
|
||||
link_event_info (void *object, const struct pw_link_info *info)
|
||||
{
|
||||
WpProxy *self = WP_PROXY (object);
|
||||
|
||||
if (info->change_mask & PW_LINK_CHANGE_MASK_OUTPUT) {
|
||||
UPDATE_PROP ("link-info.output-node-id",
|
||||
g_strdup_printf ("%u", info->output_node_id));
|
||||
UPDATE_PROP ("link-info.output-port-id",
|
||||
g_strdup_printf ("%u", info->output_port_id));
|
||||
}
|
||||
if (info->change_mask & PW_LINK_CHANGE_MASK_INPUT) {
|
||||
UPDATE_PROP ("link-info.input-node-id",
|
||||
g_strdup_printf ("%u", info->input_node_id));
|
||||
UPDATE_PROP ("link-info.input-port-id",
|
||||
g_strdup_printf ("%u", info->input_port_id));
|
||||
}
|
||||
if (info->change_mask & PW_LINK_CHANGE_MASK_STATE) {
|
||||
UPDATE_PROP ("link-info.state",
|
||||
g_strdup (pw_link_state_as_string (info->state)));
|
||||
UPDATE_PROP ("link-info.error", g_strdup (info->error));
|
||||
}
|
||||
//TODO: PW_LINK_CHANGE_MASK_FORMAT
|
||||
|
||||
if (info->change_mask & PW_LINK_CHANGE_MASK_PROPS) {
|
||||
spa_dict_to_hashtable (info->props, self->properties);
|
||||
}
|
||||
|
||||
g_signal_emit (self, signals[SIGNAL_CHANGED], 0);
|
||||
}
|
||||
|
||||
static const struct pw_link_proxy_events link_events = {
|
||||
PW_VERSION_LINK_PROXY_EVENTS,
|
||||
.info = link_event_info
|
||||
};
|
||||
|
||||
static void
|
||||
client_event_info (void *object, const struct pw_client_info *info)
|
||||
{
|
||||
WpProxy *self = WP_PROXY (object);
|
||||
|
||||
if (info->change_mask & PW_CLIENT_CHANGE_MASK_PROPS) {
|
||||
spa_dict_to_hashtable (info->props, self->properties);
|
||||
}
|
||||
|
||||
g_signal_emit (self, signals[SIGNAL_CHANGED], 0);
|
||||
}
|
||||
|
||||
static const struct pw_client_proxy_events client_events = {
|
||||
PW_VERSION_CLIENT_PROXY_EVENTS,
|
||||
.info = client_event_info
|
||||
};
|
||||
|
||||
static void
|
||||
device_event_info (void *object, const struct pw_device_info *info)
|
||||
{
|
||||
WpProxy *self = WP_PROXY (object);
|
||||
|
||||
STATIC_PROP ("device-info.name", g_strdup (info->name));
|
||||
|
||||
if (info->change_mask & PW_DEVICE_CHANGE_MASK_PROPS) {
|
||||
spa_dict_to_hashtable (info->props, self->properties);
|
||||
}
|
||||
//TODO: PW_DEVICE_CHANGE_MASK_PARAMS
|
||||
|
||||
g_signal_emit (self, signals[SIGNAL_CHANGED], 0);
|
||||
}
|
||||
|
||||
static const struct pw_device_proxy_events device_events = {
|
||||
PW_VERSION_DEVICE_PROXY_EVENTS,
|
||||
.info = device_event_info
|
||||
};
|
||||
|
||||
static void
|
||||
proxy_event_destroy (void *object)
|
||||
{
|
||||
WpProxy *self = WP_PROXY (object);
|
||||
|
||||
g_debug ("proxy %u destroyed", self->id);
|
||||
|
||||
self->proxy = NULL;
|
||||
g_signal_emit (self, signals[SIGNAL_DESTROYED], 0);
|
||||
}
|
||||
|
||||
static const struct pw_proxy_events proxy_events = {
|
||||
PW_VERSION_PROXY_EVENTS,
|
||||
.destroy = proxy_event_destroy
|
||||
};
|
||||
|
||||
static void
|
||||
wp_proxy_init (WpProxy * self)
|
||||
{
|
||||
|
|
@ -40,16 +238,63 @@ static void
|
|||
wp_proxy_constructed (GObject * object)
|
||||
{
|
||||
WpProxy *self = WP_PROXY (object);
|
||||
const struct spa_type_info *info = pw_type_info ();
|
||||
GHashTable *properties;
|
||||
struct pw_registry_proxy *reg_proxy;
|
||||
const void *events = NULL;
|
||||
uint32_t ver = 0;
|
||||
|
||||
while (info->type) {
|
||||
if (info->type == self->type) {
|
||||
self->type_string = info->name;
|
||||
self->type_string = spa_debug_type_find_name (pw_type_info (), self->type);
|
||||
|
||||
g_debug ("added id %u, parent %u, type %s", self->id, self->parent_id,
|
||||
self->type_string);
|
||||
|
||||
switch (self->type) {
|
||||
case PW_TYPE_INTERFACE_Node:
|
||||
events = &node_events;
|
||||
ver = PW_VERSION_NODE;
|
||||
break;
|
||||
case PW_TYPE_INTERFACE_Port:
|
||||
events = &port_events;
|
||||
ver = PW_VERSION_PORT;
|
||||
break;
|
||||
case PW_TYPE_INTERFACE_Link:
|
||||
events = &link_events;
|
||||
ver = PW_VERSION_LINK;
|
||||
break;
|
||||
case PW_TYPE_INTERFACE_Client:
|
||||
events = &client_events;
|
||||
ver = PW_VERSION_CLIENT;
|
||||
break;
|
||||
case PW_TYPE_INTERFACE_Device:
|
||||
events = &device_events;
|
||||
ver = PW_VERSION_DEVICE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
info++;
|
||||
}
|
||||
|
||||
reg_proxy = wp_proxy_registry_get_pw_registry_proxy (self->registry);
|
||||
g_warn_if_fail (reg_proxy != NULL);
|
||||
|
||||
self->proxy = pw_registry_proxy_bind (reg_proxy, self->id, self->type, ver, 0);
|
||||
pw_proxy_add_listener (self->proxy, &self->proxy_listener, &proxy_events,
|
||||
self);
|
||||
|
||||
if (events)
|
||||
pw_proxy_add_proxy_listener(self->proxy, &self->proxy_proxy_listener,
|
||||
events, self);
|
||||
|
||||
/*
|
||||
* initial_properties is a stack-allocated const spa_dict *
|
||||
* that is not safe to access beyond the scope of the g_object_new()
|
||||
* call, so we replace it with a GHashTable
|
||||
*/
|
||||
properties = g_hash_table_new_full (g_direct_hash, g_direct_equal,
|
||||
NULL, g_free);
|
||||
if (self->initial_properties)
|
||||
spa_dict_to_hashtable (self->initial_properties, properties);
|
||||
self->properties = properties;
|
||||
|
||||
G_OBJECT_CLASS (wp_proxy_parent_class)->constructed (object);
|
||||
}
|
||||
|
||||
|
|
@ -58,6 +303,9 @@ wp_proxy_finalize (GObject * object)
|
|||
{
|
||||
WpProxy *self = WP_PROXY (object);
|
||||
|
||||
g_hash_table_unref (self->properties);
|
||||
g_clear_object (&self->registry);
|
||||
|
||||
G_OBJECT_CLASS (wp_proxy_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
|
|
@ -68,9 +316,6 @@ wp_proxy_set_property (GObject * object, guint property_id,
|
|||
WpProxy *self = WP_PROXY (object);
|
||||
|
||||
switch (property_id) {
|
||||
case PROP_PROXY:
|
||||
self->proxy = g_value_get_pointer (value);
|
||||
break;
|
||||
case PROP_ID:
|
||||
self->id = g_value_get_uint (value);
|
||||
break;
|
||||
|
|
@ -80,6 +325,12 @@ wp_proxy_set_property (GObject * object, guint property_id,
|
|||
case PROP_SPA_TYPE:
|
||||
self->type = g_value_get_uint (value);
|
||||
break;
|
||||
case PROP_INITIAL_PROPERTIES:
|
||||
self->initial_properties = g_value_get_pointer (value);
|
||||
break;
|
||||
case PROP_REGISTRY:
|
||||
self->registry = g_value_get_object (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
|
|
@ -93,9 +344,6 @@ wp_proxy_get_property (GObject * object, guint property_id, GValue * value,
|
|||
WpProxy *self = WP_PROXY (object);
|
||||
|
||||
switch (property_id) {
|
||||
case PROP_PROXY:
|
||||
g_value_set_pointer (value, self->proxy);
|
||||
break;
|
||||
case PROP_ID:
|
||||
g_value_set_uint (value, self->id);
|
||||
break;
|
||||
|
|
@ -106,7 +354,13 @@ wp_proxy_get_property (GObject * object, guint property_id, GValue * value,
|
|||
g_value_set_uint (value, self->type);
|
||||
break;
|
||||
case PROP_SPA_TYPE_STRING:
|
||||
g_value_set_string (value, wp_proxy_get_spa_type_string (self));
|
||||
g_value_set_string (value, self->type_string);
|
||||
break;
|
||||
case PROP_REGISTRY:
|
||||
g_value_set_object (value, self->registry);
|
||||
break;
|
||||
case PROP_PROXY:
|
||||
g_value_set_pointer (value, self->proxy);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
|
|
@ -124,11 +378,6 @@ wp_proxy_class_init (WpProxyClass * klass)
|
|||
object_class->get_property = wp_proxy_get_property;
|
||||
object_class->set_property = wp_proxy_set_property;
|
||||
|
||||
g_object_class_install_property (object_class, PROP_PROXY,
|
||||
g_param_spec_pointer ("proxy", "proxy",
|
||||
"The underlying struct pw_proxy *",
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_property (object_class, PROP_ID,
|
||||
g_param_spec_uint ("id", "id",
|
||||
"The global ID of the object", 0, G_MAXUINT, 0,
|
||||
|
|
@ -148,28 +397,139 @@ wp_proxy_class_init (WpProxyClass * klass)
|
|||
g_param_spec_string ("spa-type-string", "spa-type-string",
|
||||
"The string representation of the SPA type of the object", NULL,
|
||||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_property (object_class, PROP_INITIAL_PROPERTIES,
|
||||
g_param_spec_pointer ("initial-properties", "initial-properties",
|
||||
"The initial set of properties of the proxy",
|
||||
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_property (object_class, PROP_REGISTRY,
|
||||
g_param_spec_object ("registry", "registry",
|
||||
"The WpProxyRegistry that owns this proxy",
|
||||
wp_proxy_registry_get_type (),
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_property (object_class, PROP_PROXY,
|
||||
g_param_spec_pointer ("proxy", "proxy",
|
||||
"The underlying struct pw_proxy *",
|
||||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
signals[SIGNAL_DESTROYED] = g_signal_new ("destroyed",
|
||||
G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 0);
|
||||
signals[SIGNAL_CHANGED] = g_signal_new ("changed",
|
||||
G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* wp_proxy_get_id: (method)
|
||||
* @self: the proxy
|
||||
*
|
||||
* Returns: the global ID of the remote object
|
||||
*/
|
||||
guint32
|
||||
wp_proxy_get_id (WpProxy * self)
|
||||
{
|
||||
g_return_val_if_fail (WP_IS_PROXY (self), -1);
|
||||
return self->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* wp_proxy_get_parent_id: (method)
|
||||
* @self: the proxy
|
||||
*
|
||||
* Returns: the global ID of the parent remote object
|
||||
*/
|
||||
guint32
|
||||
wp_proxy_get_parent_id (WpProxy * self)
|
||||
{
|
||||
g_return_val_if_fail (WP_IS_PROXY (self), -1);
|
||||
return self->parent_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* wp_proxy_get_spa_type: (method)
|
||||
* @self: the proxy
|
||||
*
|
||||
* Returns: the SPA type of the remote object
|
||||
*/
|
||||
guint32
|
||||
wp_proxy_get_spa_type (WpProxy * self)
|
||||
{
|
||||
g_return_val_if_fail (WP_IS_PROXY (self), -1);
|
||||
return self->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* wp_proxy_get_spa_type_string: (method)
|
||||
* @self: the proxy
|
||||
*
|
||||
* Returns: (transfer none): the string that describes the SPA type of
|
||||
* the remote object
|
||||
*/
|
||||
const gchar *
|
||||
wp_proxy_get_spa_type_string (WpProxy * self)
|
||||
{
|
||||
g_return_val_if_fail (WP_IS_PROXY (self), NULL);
|
||||
return self->type_string;
|
||||
}
|
||||
|
||||
/**
|
||||
* wp_proxy_get_registry: (method)
|
||||
* @self: the proxy
|
||||
*
|
||||
* Returns: (transfer full): the #WpProxyRegistry
|
||||
*/
|
||||
WpProxyRegistry *
|
||||
wp_proxy_get_registry (WpProxy *self)
|
||||
{
|
||||
g_return_val_if_fail (WP_IS_PROXY (self), NULL);
|
||||
return g_object_ref (self->registry);
|
||||
}
|
||||
|
||||
/**
|
||||
* wp_proxy_is_destroyed: (method)
|
||||
* @self: the proxy
|
||||
*
|
||||
* Returns: TRUE if the proxy has been destroyed
|
||||
*/
|
||||
gboolean
|
||||
wp_proxy_is_destroyed (WpProxy * self)
|
||||
{
|
||||
g_return_val_if_fail (WP_IS_PROXY (self), TRUE);
|
||||
return (self->proxy == NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* wp_proxy_get_pw_proxy: (skip)
|
||||
* @self: the proxy
|
||||
*
|
||||
* Returns: the pw_proxy pointer or %NULL if the proxy is destroyed
|
||||
*/
|
||||
struct pw_proxy *
|
||||
wp_proxy_get_pw_proxy (WpProxy * self)
|
||||
{
|
||||
g_return_val_if_fail (WP_IS_PROXY (self), NULL);
|
||||
return self->proxy;
|
||||
}
|
||||
|
||||
/**
|
||||
* wp_proxy_get_pw_property: (method)
|
||||
* @self: the proxy
|
||||
* @property: (transfer none): the name of the property to lookup
|
||||
*
|
||||
* Returns: (transfer none): the value or %NULL
|
||||
*/
|
||||
const gchar *
|
||||
wp_proxy_get_pw_property (WpProxy * self, const gchar * property)
|
||||
{
|
||||
GQuark quark = 0;
|
||||
|
||||
g_return_val_if_fail (WP_IS_PROXY (self), NULL);
|
||||
g_return_val_if_fail (property != NULL, NULL);
|
||||
|
||||
quark = g_quark_try_string (property);
|
||||
return quark ?
|
||||
g_hash_table_lookup (self->properties, GUINT_TO_POINTER (quark)) : NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
#ifndef __WP_PROXY_H__
|
||||
#define __WP_PROXY_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
#include "proxy-registry.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
|
@ -22,6 +22,14 @@ guint32 wp_proxy_get_parent_id (WpProxy * self);
|
|||
guint32 wp_proxy_get_spa_type (WpProxy * self);
|
||||
const gchar * wp_proxy_get_spa_type_string (WpProxy * self);
|
||||
|
||||
WpProxyRegistry * wp_proxy_get_registry (WpProxy *self);
|
||||
|
||||
gboolean wp_proxy_is_destroyed (WpProxy * self);
|
||||
struct pw_proxy * wp_proxy_get_pw_proxy (WpProxy * self);
|
||||
|
||||
const gchar * wp_proxy_get_pw_property (WpProxy * self, const gchar * property);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue