proxy: add methods to get info & enum params
This commit is contained in:
@@ -28,14 +28,14 @@ wp_lib = library('wireplumber-' + wireplumber_api_version,
|
|||||||
'-DG_LOG_DOMAIN="libwireplumber"'
|
'-DG_LOG_DOMAIN="libwireplumber"'
|
||||||
],
|
],
|
||||||
install: true,
|
install: true,
|
||||||
dependencies : [gobject_dep, pipewire_dep],
|
dependencies : [gobject_dep, pipewire_dep, gio_dep],
|
||||||
)
|
)
|
||||||
|
|
||||||
gnome.generate_gir(wp_lib,
|
gnome.generate_gir(wp_lib,
|
||||||
namespace: 'Wp',
|
namespace: 'Wp',
|
||||||
nsversion: wireplumber_api_version,
|
nsversion: wireplumber_api_version,
|
||||||
sources: [wp_lib_sources, wp_lib_headers],
|
sources: [wp_lib_sources, wp_lib_headers],
|
||||||
includes: ['GLib-2.0', 'GObject-2.0'],
|
includes: ['GLib-2.0', 'GObject-2.0', 'Gio-2.0'],
|
||||||
install: true,
|
install: true,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
248
lib/wp/proxy.c
248
lib/wp/proxy.c
@@ -7,8 +7,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "proxy.h"
|
#include "proxy.h"
|
||||||
|
#include "error.h"
|
||||||
#include <pipewire/pipewire.h>
|
#include <pipewire/pipewire.h>
|
||||||
#include <spa/debug/types.h>
|
#include <spa/debug/types.h>
|
||||||
|
#include <spa/pod/builder.h>
|
||||||
|
|
||||||
struct _WpProxy
|
struct _WpProxy
|
||||||
{
|
{
|
||||||
@@ -29,6 +31,19 @@ struct _WpProxy
|
|||||||
const struct spa_dict *initial_properties;
|
const struct spa_dict *initial_properties;
|
||||||
struct pw_properties *properties;
|
struct pw_properties *properties;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
union {
|
||||||
|
gpointer info;
|
||||||
|
struct pw_node_info *node_info;
|
||||||
|
struct pw_port_info *port_info;
|
||||||
|
struct pw_factory_info *factory_info;
|
||||||
|
struct pw_link_info *link_info;
|
||||||
|
struct pw_client_info *client_info;
|
||||||
|
struct pw_module_info *module_info;
|
||||||
|
struct pw_device_info *device_info;
|
||||||
|
};
|
||||||
|
|
||||||
|
GList *tasks;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@@ -49,6 +64,7 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static guint signals[N_SIGNALS];
|
static guint signals[N_SIGNALS];
|
||||||
|
static int global_seq = 0;
|
||||||
|
|
||||||
static void wp_proxy_pw_properties_init (WpPipewirePropertiesInterface * iface);
|
static void wp_proxy_pw_properties_init (WpPipewirePropertiesInterface * iface);
|
||||||
|
|
||||||
@@ -56,75 +72,114 @@ G_DEFINE_TYPE_WITH_CODE (WpProxy, wp_proxy, WP_TYPE_OBJECT,
|
|||||||
G_IMPLEMENT_INTERFACE (WP_TYPE_PIPEWIRE_PROPERTIES, wp_proxy_pw_properties_init);
|
G_IMPLEMENT_INTERFACE (WP_TYPE_PIPEWIRE_PROPERTIES, wp_proxy_pw_properties_init);
|
||||||
)
|
)
|
||||||
|
|
||||||
static void
|
struct task_data {
|
||||||
node_event_info (void *object, const struct pw_node_info *info)
|
guint32 seq;
|
||||||
{
|
GPtrArray *result;
|
||||||
WpProxy *self = WP_PROXY (object);
|
};
|
||||||
|
|
||||||
if (info->change_mask & PW_NODE_CHANGE_MASK_PROPS) {
|
static gint
|
||||||
g_clear_pointer (&self->properties, pw_properties_free);
|
find_task (gconstpointer t, gconstpointer s)
|
||||||
self->properties = pw_properties_new_dict (info->props);
|
{
|
||||||
}
|
GTask *task = (GTask *) t;
|
||||||
g_signal_emit (self, signals[SIGNAL_CHANGED], 0);
|
int seq = GPOINTER_TO_INT (s);
|
||||||
|
struct task_data *data = g_task_get_task_data (task);
|
||||||
|
|
||||||
|
return data->seq - seq;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Updates the info structure while copying the properties into self->properties
|
||||||
|
* and avoiding making a second copy of the properties dict in info->props */
|
||||||
|
#define PROXY_INFO_FUNC(TYPE, type) \
|
||||||
|
static void \
|
||||||
|
type##_event_info (void *object, const struct pw_##type##_info *info) \
|
||||||
|
{ \
|
||||||
|
WpProxy *self = WP_PROXY (object); \
|
||||||
|
\
|
||||||
|
if (info->change_mask & PW_##TYPE##_CHANGE_MASK_PROPS) { \
|
||||||
|
g_clear_pointer (&self->properties, pw_properties_free); \
|
||||||
|
self->properties = pw_properties_new_dict (info->props); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
{ \
|
||||||
|
uint64_t change_mask = info->change_mask; \
|
||||||
|
((struct pw_##type##_info *)info)->change_mask &= ~PW_##TYPE##_CHANGE_MASK_PROPS; \
|
||||||
|
self->type##_info = pw_##type##_info_update (self->type##_info, info); \
|
||||||
|
self->type##_info->props = &self->properties->dict; \
|
||||||
|
((struct pw_##type##_info *)info)->change_mask = change_mask; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
g_signal_emit (self, signals[SIGNAL_CHANGED], 0); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PROXY_PARAM_FUNC(type) \
|
||||||
|
static void \
|
||||||
|
type##_event_param(void *object, int seq, uint32_t id, uint32_t index, \
|
||||||
|
uint32_t next, const struct spa_pod *param) \
|
||||||
|
{ \
|
||||||
|
WpProxy *self = WP_PROXY (object); \
|
||||||
|
GList *l; \
|
||||||
|
struct task_data *data; \
|
||||||
|
\
|
||||||
|
l = g_list_find_custom (self->tasks, GINT_TO_POINTER (seq), find_task); \
|
||||||
|
g_return_if_fail (l != NULL); \
|
||||||
|
\
|
||||||
|
data = g_task_get_task_data (G_TASK (l->data)); \
|
||||||
|
g_ptr_array_add (data->result, spa_pod_copy (param)); \
|
||||||
|
}
|
||||||
|
|
||||||
|
PROXY_INFO_FUNC (NODE, node)
|
||||||
|
PROXY_PARAM_FUNC(node)
|
||||||
|
|
||||||
static const struct pw_node_proxy_events node_events = {
|
static const struct pw_node_proxy_events node_events = {
|
||||||
PW_VERSION_NODE_PROXY_EVENTS,
|
PW_VERSION_NODE_PROXY_EVENTS,
|
||||||
.info = node_event_info
|
.info = node_event_info,
|
||||||
|
.param = node_event_param,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
PROXY_INFO_FUNC (PORT, port)
|
||||||
link_event_info (void *object, const struct pw_link_info *info)
|
PROXY_PARAM_FUNC(port)
|
||||||
{
|
|
||||||
WpProxy *self = WP_PROXY (object);
|
|
||||||
|
|
||||||
if (info->change_mask & PW_LINK_CHANGE_MASK_PROPS) {
|
static const struct pw_port_proxy_events port_events = {
|
||||||
g_clear_pointer (&self->properties, pw_properties_free);
|
PW_VERSION_PORT_PROXY_EVENTS,
|
||||||
self->properties = pw_properties_new_dict (info->props);
|
.info = port_event_info,
|
||||||
}
|
.param = port_event_param,
|
||||||
|
};
|
||||||
|
|
||||||
g_signal_emit (self, signals[SIGNAL_CHANGED], 0);
|
PROXY_INFO_FUNC (FACTORY, factory)
|
||||||
}
|
|
||||||
|
static const struct pw_factory_proxy_events factory_events = {
|
||||||
|
PW_VERSION_FACTORY_PROXY_EVENTS,
|
||||||
|
.info = factory_event_info
|
||||||
|
};
|
||||||
|
|
||||||
|
PROXY_INFO_FUNC (LINK, link)
|
||||||
|
|
||||||
static const struct pw_link_proxy_events link_events = {
|
static const struct pw_link_proxy_events link_events = {
|
||||||
PW_VERSION_LINK_PROXY_EVENTS,
|
PW_VERSION_LINK_PROXY_EVENTS,
|
||||||
.info = link_event_info
|
.info = link_event_info
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
PROXY_INFO_FUNC (CLIENT, client)
|
||||||
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) {
|
|
||||||
g_clear_pointer (&self->properties, pw_properties_free);
|
|
||||||
self->properties = pw_properties_new_dict (info->props);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_signal_emit (self, signals[SIGNAL_CHANGED], 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct pw_client_proxy_events client_events = {
|
static const struct pw_client_proxy_events client_events = {
|
||||||
PW_VERSION_CLIENT_PROXY_EVENTS,
|
PW_VERSION_CLIENT_PROXY_EVENTS,
|
||||||
.info = client_event_info
|
.info = client_event_info
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
PROXY_INFO_FUNC (MODULE, module)
|
||||||
device_event_info (void *object, const struct pw_device_info *info)
|
|
||||||
{
|
|
||||||
WpProxy *self = WP_PROXY (object);
|
|
||||||
|
|
||||||
if (info->change_mask & PW_DEVICE_CHANGE_MASK_PROPS) {
|
static const struct pw_module_proxy_events module_events = {
|
||||||
g_clear_pointer (&self->properties, pw_properties_free);
|
PW_VERSION_MODULE_PROXY_EVENTS,
|
||||||
self->properties = pw_properties_new_dict (info->props);
|
.info = module_event_info
|
||||||
}
|
};
|
||||||
|
|
||||||
g_signal_emit (self, signals[SIGNAL_CHANGED], 0);
|
PROXY_INFO_FUNC (DEVICE, device)
|
||||||
}
|
PROXY_PARAM_FUNC (device)
|
||||||
|
|
||||||
static const struct pw_device_proxy_events device_events = {
|
static const struct pw_device_proxy_events device_events = {
|
||||||
PW_VERSION_DEVICE_PROXY_EVENTS,
|
PW_VERSION_DEVICE_PROXY_EVENTS,
|
||||||
.info = device_event_info
|
.info = device_event_info,
|
||||||
|
.param = device_event_param,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -138,9 +193,25 @@ proxy_event_destroy (void *object)
|
|||||||
g_signal_emit (self, signals[SIGNAL_DESTROYED], 0);
|
g_signal_emit (self, signals[SIGNAL_DESTROYED], 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
proxy_event_done (void *object, int seq)
|
||||||
|
{
|
||||||
|
WpProxy *self = WP_PROXY (object);
|
||||||
|
GList *l;
|
||||||
|
struct task_data *data;
|
||||||
|
|
||||||
|
l = g_list_find_custom (self->tasks, GINT_TO_POINTER (seq), find_task);
|
||||||
|
g_return_if_fail (l != NULL);
|
||||||
|
|
||||||
|
data = g_task_get_task_data (G_TASK (l->data));
|
||||||
|
g_task_return_pointer (G_TASK (l->data), g_ptr_array_ref (data->result),
|
||||||
|
(GDestroyNotify) g_ptr_array_unref);
|
||||||
|
}
|
||||||
|
|
||||||
static const struct pw_proxy_events proxy_events = {
|
static const struct pw_proxy_events proxy_events = {
|
||||||
PW_VERSION_PROXY_EVENTS,
|
PW_VERSION_PROXY_EVENTS,
|
||||||
.destroy = proxy_event_destroy
|
.destroy = proxy_event_destroy,
|
||||||
|
.done = proxy_event_done,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -167,6 +238,14 @@ wp_proxy_constructed (GObject * object)
|
|||||||
events = &node_events;
|
events = &node_events;
|
||||||
ver = PW_VERSION_NODE;
|
ver = PW_VERSION_NODE;
|
||||||
break;
|
break;
|
||||||
|
case PW_TYPE_INTERFACE_Port:
|
||||||
|
events = &port_events;
|
||||||
|
ver = PW_VERSION_PORT;
|
||||||
|
break;
|
||||||
|
case PW_TYPE_INTERFACE_Factory:
|
||||||
|
events = &factory_events;
|
||||||
|
ver = PW_VERSION_FACTORY;
|
||||||
|
break;
|
||||||
case PW_TYPE_INTERFACE_Link:
|
case PW_TYPE_INTERFACE_Link:
|
||||||
events = &link_events;
|
events = &link_events;
|
||||||
ver = PW_VERSION_LINK;
|
ver = PW_VERSION_LINK;
|
||||||
@@ -175,6 +254,10 @@ wp_proxy_constructed (GObject * object)
|
|||||||
events = &client_events;
|
events = &client_events;
|
||||||
ver = PW_VERSION_CLIENT;
|
ver = PW_VERSION_CLIENT;
|
||||||
break;
|
break;
|
||||||
|
case PW_TYPE_INTERFACE_Module:
|
||||||
|
events = &module_events;
|
||||||
|
ver = PW_VERSION_MODULE;
|
||||||
|
break;
|
||||||
case PW_TYPE_INTERFACE_Device:
|
case PW_TYPE_INTERFACE_Device:
|
||||||
events = &device_events;
|
events = &device_events;
|
||||||
ver = PW_VERSION_DEVICE;
|
ver = PW_VERSION_DEVICE;
|
||||||
@@ -443,3 +526,80 @@ wp_proxy_get_pw_proxy (WpProxy * self)
|
|||||||
g_return_val_if_fail (WP_IS_PROXY (self), NULL);
|
g_return_val_if_fail (WP_IS_PROXY (self), NULL);
|
||||||
return self->proxy;
|
return self->proxy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gconstpointer
|
||||||
|
wp_proxy_get_info_native (WpProxy * self)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (WP_IS_PROXY (self), NULL);
|
||||||
|
return self->info;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
task_data_free (struct task_data * data)
|
||||||
|
{
|
||||||
|
g_ptr_array_unref (data->result);
|
||||||
|
g_slice_free (struct task_data, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
wp_proxy_enum_params (WpProxy * self, guint32 id,
|
||||||
|
GAsyncReadyCallback callback, gpointer user_data)
|
||||||
|
{
|
||||||
|
g_autoptr (GTask) task = NULL;
|
||||||
|
int seq;
|
||||||
|
struct task_data *data;
|
||||||
|
|
||||||
|
g_return_if_fail (WP_IS_PROXY (self));
|
||||||
|
g_return_if_fail (callback != NULL);
|
||||||
|
|
||||||
|
task = g_task_new (self, NULL, callback, user_data);
|
||||||
|
g_task_set_source_tag (task, wp_proxy_enum_params);
|
||||||
|
|
||||||
|
data = g_slice_new0 (struct task_data);
|
||||||
|
data->seq = seq = global_seq++;
|
||||||
|
data->result = g_ptr_array_new_with_free_func (free);
|
||||||
|
g_task_set_task_data (task, data, (GDestroyNotify) task_data_free);
|
||||||
|
|
||||||
|
self->tasks = g_list_append (self->tasks, task);
|
||||||
|
|
||||||
|
switch (self->type) {
|
||||||
|
case PW_TYPE_INTERFACE_Node:
|
||||||
|
pw_node_proxy_enum_params ((struct pw_node_proxy *) self->proxy,
|
||||||
|
seq, id, 0, -1, NULL);
|
||||||
|
pw_proxy_sync (self->proxy, seq);
|
||||||
|
break;
|
||||||
|
case PW_TYPE_INTERFACE_Port:
|
||||||
|
pw_port_proxy_enum_params ((struct pw_port_proxy *) self->proxy,
|
||||||
|
seq, id, 0, -1, NULL);
|
||||||
|
pw_proxy_sync (self->proxy, seq);
|
||||||
|
break;
|
||||||
|
case PW_TYPE_INTERFACE_Device:
|
||||||
|
pw_device_proxy_enum_params ((struct pw_device_proxy *) self->proxy,
|
||||||
|
seq, id, 0, -1, NULL);
|
||||||
|
pw_proxy_sync (self->proxy, seq);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_task_return_new_error (task, WP_DOMAIN_LIBRARY,
|
||||||
|
WP_LIBRARY_ERROR_INVARIANT,
|
||||||
|
"Proxy interface does not have an enum_params method");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wp_proxy_enum_params_finish:
|
||||||
|
*
|
||||||
|
* Returns: (transfer full) (element-type spa_pod*): the params
|
||||||
|
*/
|
||||||
|
GPtrArray *
|
||||||
|
wp_proxy_enum_params_finish (WpProxy * self,
|
||||||
|
GAsyncResult * res, GError ** err)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (g_task_is_valid (res, self), NULL);
|
||||||
|
g_return_val_if_fail (g_async_result_is_tagged (res, wp_proxy_enum_params),
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
self->tasks = g_list_remove (self->tasks, res);
|
||||||
|
|
||||||
|
return g_task_propagate_pointer (G_TASK (res), err);
|
||||||
|
}
|
||||||
|
@@ -12,6 +12,8 @@
|
|||||||
#include "object.h"
|
#include "object.h"
|
||||||
#include "core-interfaces.h"
|
#include "core-interfaces.h"
|
||||||
|
|
||||||
|
#include <gio/gio.h>
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
struct pw_proxy;
|
struct pw_proxy;
|
||||||
@@ -29,6 +31,13 @@ WpObject * wp_proxy_get_core (WpProxy *self);
|
|||||||
gboolean wp_proxy_is_destroyed (WpProxy * self);
|
gboolean wp_proxy_is_destroyed (WpProxy * self);
|
||||||
struct pw_proxy * wp_proxy_get_pw_proxy (WpProxy * self);
|
struct pw_proxy * wp_proxy_get_pw_proxy (WpProxy * self);
|
||||||
|
|
||||||
|
gconstpointer wp_proxy_get_info_native (WpProxy * self);
|
||||||
|
|
||||||
|
void wp_proxy_enum_params (WpProxy * self, guint32 id,
|
||||||
|
GAsyncReadyCallback callback, gpointer data);
|
||||||
|
GPtrArray * wp_proxy_enum_params_finish (WpProxy * self,
|
||||||
|
GAsyncResult * res, GError ** err);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Reference in New Issue
Block a user