Commit bdce3b4d authored by George Kiagiadakis's avatar George Kiagiadakis

proxy: refactor the proxy class to hide pipewire API and make things easier

parent 19924189
......@@ -6,46 +6,29 @@
* SPDX-License-Identifier: MIT
*/
#include "error.h"
#include "proxy-link.h"
#include <pipewire/pipewire.h>
struct _WpProxyLink
{
WpProxy parent;
/* The task to signal the proxy is initialized */
GTask *init_task;
/* The link proxy listener */
struct spa_hook listener;
/* The link info */
struct pw_link_info *info;
};
static void wp_proxy_link_async_initable_init (gpointer iface,
gpointer iface_data);
G_DEFINE_TYPE_WITH_CODE (WpProxyLink, wp_proxy_link, WP_TYPE_PROXY,
G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE,
wp_proxy_link_async_initable_init))
G_DEFINE_TYPE (WpProxyLink, wp_proxy_link, WP_TYPE_PROXY)
static void
link_event_info(void *data, const struct pw_link_info *info)
{
WpProxyLink *self = data;
/* Make sure the task is valid */
if (!self->init_task)
return;
WpProxy *proxy = WP_PROXY (data);
/* Update the link info */
self->info = pw_link_info_update(self->info, info);
/* Finish the creation of the proxy */
g_task_return_boolean (self->init_task, TRUE);
g_clear_object (&self->init_task);
wp_proxy_update_native_info (proxy, info,
(WpProxyNativeInfoUpdate) pw_link_info_update,
(GDestroyNotify) pw_link_info_free);
wp_proxy_set_feature_ready (proxy, WP_PROXY_FEATURE_INFO);
}
static const struct pw_link_proxy_events link_events = {
......@@ -54,101 +37,22 @@ static const struct pw_link_proxy_events link_events = {
};
static void
wp_proxy_link_finalize (GObject * object)
{
WpProxyLink *self = WP_PROXY_LINK(object);
/* Destroy the init task */
g_clear_object (&self->init_task);
/* Clear the info */
if (self->info) {
pw_link_info_free(self->info);
self->info = NULL;
}
G_OBJECT_CLASS (wp_proxy_link_parent_class)->finalize (object);
}
static void
wp_proxy_link_destroy (WpProxy * proxy)
{
WpProxyLink *self = WP_PROXY_LINK(proxy);
GError *error = NULL;
/* Return error if the pipewire destruction happened while the async creation
* of this proxy link object has not finished */
if (self->init_task) {
g_set_error (&error, WP_DOMAIN_LIBRARY, WP_LIBRARY_ERROR_OPERATION_FAILED,
"pipewire link proxy destroyed before finishing");
g_task_return_error (self->init_task, error);
g_clear_object (&self->init_task);
}
}
static void
wp_proxy_link_init_async (GAsyncInitable *initable, int io_priority,
GCancellable *cancellable, GAsyncReadyCallback callback, gpointer data)
{
WpProxyLink *self = WP_PROXY_LINK(initable);
WpProxy *wp_proxy = WP_PROXY(initable);
struct pw_link_proxy *proxy = NULL;
/* Create the async task */
self->init_task = g_task_new (initable, cancellable, callback, data);
/* Get the proxy from the base class */
proxy = wp_proxy_get_pw_proxy(wp_proxy);
/* Add the link proxy listener */
pw_link_proxy_add_listener(proxy, &self->listener, &link_events, self);
}
static void
wp_proxy_link_async_initable_init (gpointer iface, gpointer iface_data)
wp_proxy_link_init (WpProxyLink * self)
{
GAsyncInitableIface *ai_iface = iface;
/* Only set the init_async */
ai_iface->init_async = wp_proxy_link_init_async;
}
static void
wp_proxy_link_init (WpProxyLink * self)
wp_proxy_link_pw_proxy_created (WpProxy * proxy, struct pw_proxy * pw_proxy)
{
WpProxyLink *self = WP_PROXY_LINK (proxy);
pw_link_proxy_add_listener ((struct pw_link_proxy *) pw_proxy,
&self->listener, &link_events, self);
}
static void
wp_proxy_link_class_init (WpProxyLinkClass * klass)
{
GObjectClass *object_class = (GObjectClass *) klass;
WpProxyClass *proxy_class = (WpProxyClass *) klass;
object_class->finalize = wp_proxy_link_finalize;
proxy_class->destroy = wp_proxy_link_destroy;
}
void
wp_proxy_link_new (guint global_id, gpointer proxy,
GAsyncReadyCallback callback, gpointer user_data)
{
g_async_initable_new_async (
WP_TYPE_PROXY_LINK, G_PRIORITY_DEFAULT, NULL, callback, user_data,
"global-id", global_id,
"pw-proxy", proxy,
NULL);
}
WpProxyLink *
wp_proxy_link_new_finish(GObject *initable, GAsyncResult *res, GError **error)
{
GAsyncInitable *ai = G_ASYNC_INITABLE(initable);
return WP_PROXY_LINK(g_async_initable_new_finish(ai, res, error));
}
const struct pw_link_info *
wp_proxy_link_get_info (WpProxyLink * self)
{
return self->info;
proxy_class->pw_proxy_created = wp_proxy_link_pw_proxy_created;
}
......@@ -9,7 +9,6 @@
#ifndef __WIREPLUMBER_PROXY_LINK_H__
#define __WIREPLUMBER_PROXY_LINK_H__
#include "core.h"
#include "proxy.h"
G_BEGIN_DECLS
......@@ -17,12 +16,12 @@ G_BEGIN_DECLS
#define WP_TYPE_PROXY_LINK (wp_proxy_link_get_type ())
G_DECLARE_FINAL_TYPE (WpProxyLink, wp_proxy_link, WP, PROXY_LINK, WpProxy)
void wp_proxy_link_new (guint global_id, gpointer proxy,
GAsyncReadyCallback callback, gpointer user_data);
WpProxyLink *wp_proxy_link_new_finish(GObject *initable, GAsyncResult *res,
GError **error);
const struct pw_link_info *wp_proxy_link_get_info (WpProxyLink * self);
static inline const struct pw_link_info *
wp_proxy_link_get_info (WpProxyLink * self)
{
return (const struct pw_link_info *)
wp_proxy_get_native_info (WP_PROXY (self));
}
G_END_DECLS
......
......@@ -6,46 +6,29 @@
* SPDX-License-Identifier: MIT
*/
#include "error.h"
#include "proxy-node.h"
#include <pipewire/pipewire.h>
struct _WpProxyNode
{
WpProxy parent;
/* The task to signal the proxy is initialized */
GTask *init_task;
/* The node proxy listener */
struct spa_hook listener;
/* The node info */
struct pw_node_info *info;
};
static void wp_proxy_node_async_initable_init (gpointer iface,
gpointer iface_data);
G_DEFINE_TYPE_WITH_CODE (WpProxyNode, wp_proxy_node, WP_TYPE_PROXY,
G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE,
wp_proxy_node_async_initable_init))
G_DEFINE_TYPE (WpProxyNode, wp_proxy_node, WP_TYPE_PROXY)
static void
node_event_info(void *data, const struct pw_node_info *info)
{
WpProxyNode *self = data;
/* Make sure the task is valid */
if (!self->init_task)
return;
WpProxy *proxy = WP_PROXY (data);
/* Update the node info */
self->info = pw_node_info_update(self->info, info);
/* Finish the creation of the proxy */
g_task_return_boolean (self->init_task, TRUE);
g_clear_object (&self->init_task);
wp_proxy_update_native_info (proxy, info,
(WpProxyNativeInfoUpdate) pw_node_info_update,
(GDestroyNotify) pw_node_info_free);
wp_proxy_set_feature_ready (proxy, WP_PROXY_FEATURE_INFO);
}
static const struct pw_node_proxy_events node_events = {
......@@ -54,101 +37,22 @@ static const struct pw_node_proxy_events node_events = {
};
static void
wp_proxy_node_finalize (GObject * object)
{
WpProxyNode *self = WP_PROXY_NODE(object);
/* Destroy the init task */
g_clear_object (&self->init_task);
/* Clear the info */
if (self->info) {
pw_node_info_free(self->info);
self->info = NULL;
}
G_OBJECT_CLASS (wp_proxy_node_parent_class)->finalize (object);
}
static void
wp_proxy_node_destroy (WpProxy * proxy)
{
WpProxyNode *self = WP_PROXY_NODE(proxy);
GError *error = NULL;
/* Return error if the pipewire destruction happened while the async creation
* of this proxy node object has not finished */
if (self->init_task) {
g_set_error (&error, WP_DOMAIN_LIBRARY, WP_LIBRARY_ERROR_OPERATION_FAILED,
"pipewire node proxy destroyed before finishing");
g_task_return_error (self->init_task, error);
g_clear_object (&self->init_task);
}
}
static void
wp_proxy_node_init_async (GAsyncInitable *initable, int io_priority,
GCancellable *cancellable, GAsyncReadyCallback callback, gpointer data)
{
WpProxyNode *self = WP_PROXY_NODE(initable);
WpProxy *wp_proxy = WP_PROXY(initable);
struct pw_node_proxy *proxy = NULL;
/* Create the async task */
self->init_task = g_task_new (initable, cancellable, callback, data);
/* Get the proxy from the base class */
proxy = wp_proxy_get_pw_proxy(wp_proxy);
/* Add the node proxy listener */
pw_node_proxy_add_listener(proxy, &self->listener, &node_events, self);
}
static void
wp_proxy_node_async_initable_init (gpointer iface, gpointer iface_data)
wp_proxy_node_init (WpProxyNode * self)
{
GAsyncInitableIface *ai_iface = iface;
/* Only set the init_async */
ai_iface->init_async = wp_proxy_node_init_async;
}
static void
wp_proxy_node_init (WpProxyNode * self)
wp_proxy_node_pw_proxy_created (WpProxy * proxy, struct pw_proxy * pw_proxy)
{
WpProxyNode *self = WP_PROXY_NODE (proxy);
pw_node_proxy_add_listener ((struct pw_node_proxy *) pw_proxy,
&self->listener, &node_events, self);
}
static void
wp_proxy_node_class_init (WpProxyNodeClass * klass)
{
GObjectClass *object_class = (GObjectClass *) klass;
WpProxyClass *proxy_class = (WpProxyClass *) klass;
object_class->finalize = wp_proxy_node_finalize;
proxy_class->destroy = wp_proxy_node_destroy;
}
void
wp_proxy_node_new (guint global_id, gpointer proxy,
GAsyncReadyCallback callback, gpointer user_data)
{
g_async_initable_new_async (
WP_TYPE_PROXY_NODE, G_PRIORITY_DEFAULT, NULL, callback, user_data,
"global-id", global_id,
"pw-proxy", proxy,
NULL);
}
WpProxyNode *
wp_proxy_node_new_finish(GObject *initable, GAsyncResult *res, GError **error)
{
GAsyncInitable *ai = G_ASYNC_INITABLE(initable);
return WP_PROXY_NODE(g_async_initable_new_finish(ai, res, error));
}
const struct pw_node_info *
wp_proxy_node_get_info (WpProxyNode * self)
{
return self->info;
proxy_class->pw_proxy_created = wp_proxy_node_pw_proxy_created;
}
......@@ -9,7 +9,6 @@
#ifndef __WIREPLUMBER_PROXY_NODE_H__
#define __WIREPLUMBER_PROXY_NODE_H__
#include "core.h"
#include "proxy.h"
G_BEGIN_DECLS
......@@ -17,12 +16,12 @@ G_BEGIN_DECLS
#define WP_TYPE_PROXY_NODE (wp_proxy_node_get_type ())
G_DECLARE_FINAL_TYPE (WpProxyNode, wp_proxy_node, WP, PROXY_NODE, WpProxy)
void wp_proxy_node_new (guint global_id, gpointer proxy,
GAsyncReadyCallback callback, gpointer user_data);
WpProxyNode *wp_proxy_node_new_finish(GObject *initable, GAsyncResult *res,
GError **error);
const struct pw_node_info *wp_proxy_node_get_info (WpProxyNode * self);
static inline const struct pw_node_info *
wp_proxy_node_get_info (WpProxyNode * self)
{
return (const struct pw_node_info *)
wp_proxy_get_native_info (WP_PROXY (self));
}
G_END_DECLS
......
......@@ -6,8 +6,8 @@
* SPDX-License-Identifier: MIT
*/
#include "error.h"
#include "proxy-port.h"
#include <pipewire/pipewire.h>
#include <spa/param/audio/format-utils.h>
......@@ -15,46 +15,33 @@ struct _WpProxyPort
{
WpProxy parent;
/* The task to signal the proxy is initialized */
GTask *init_task;
/* The port proxy listener */
struct spa_hook listener;
/* The port info */
struct pw_port_info *info;
/* The port format */
uint32_t media_type;
uint32_t media_subtype;
struct spa_audio_info_raw format;
};
static void wp_proxy_port_async_initable_init (gpointer iface,
gpointer iface_data);
G_DEFINE_TYPE_WITH_CODE (WpProxyPort, wp_proxy_port, WP_TYPE_PROXY,
G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE,
wp_proxy_port_async_initable_init))
G_DEFINE_TYPE (WpProxyPort, wp_proxy_port, WP_TYPE_PROXY)
static void
port_event_info(void *data, const struct pw_port_info *info)
{
WpProxyPort *self = data;
WpProxy *proxy = WP_PROXY (data);
/* Update the port info */
self->info = pw_port_info_update(self->info, info);
wp_proxy_update_native_info (proxy, info,
(WpProxyNativeInfoUpdate) pw_port_info_update,
(GDestroyNotify) pw_port_info_free);
wp_proxy_set_feature_ready (proxy, WP_PROXY_FEATURE_INFO);
}
static void
port_event_param(void *data, int seq, uint32_t id, uint32_t index,
uint32_t next, const struct spa_pod *param)
{
WpProxyPort *self = data;
/* Make sure the task is valid */
if (!self->init_task)
return;
WpProxyPort *self = WP_PROXY_PORT (data);
/* Only handle EnumFormat */
if (id != SPA_PARAM_EnumFormat)
......@@ -64,17 +51,14 @@ port_event_param(void *data, int seq, uint32_t id, uint32_t index,
spa_format_parse(param, &self->media_type, &self->media_subtype);
/* Only handle raw audio formats for now */
if (self->media_type != SPA_MEDIA_TYPE_audio ||
self->media_subtype != SPA_MEDIA_SUBTYPE_raw)
return;
/* Parse the raw audio format */
spa_pod_fixate((struct spa_pod*)param);
spa_format_audio_raw_parse(param, &self->format);
if (self->media_type == SPA_MEDIA_TYPE_audio &&
self->media_subtype == SPA_MEDIA_SUBTYPE_raw) {
/* Parse the raw audio format */
spa_pod_fixate ((struct spa_pod *) param);
spa_format_audio_raw_parse (param, &self->format);
}
/* Finish the creation of the proxy */
g_task_return_boolean (self->init_task, TRUE);
g_clear_object (&self->init_task);
wp_proxy_set_feature_ready (WP_PROXY (self), WP_PROXY_PORT_FEATURE_FORMAT);
}
static const struct pw_port_proxy_events port_events = {
......@@ -84,107 +68,40 @@ static const struct pw_port_proxy_events port_events = {
};
static void
wp_proxy_port_finalize (GObject * object)
{
WpProxyPort *self = WP_PROXY_PORT(object);
/* Destroy the init task */
g_clear_object (&self->init_task);
/* Clear the indo */
if (self->info) {
pw_port_info_free(self->info);
self->info = NULL;
}
G_OBJECT_CLASS (wp_proxy_port_parent_class)->finalize (object);
}
static void
wp_proxy_port_destroy (WpProxy * proxy)
wp_proxy_port_init (WpProxyPort * self)
{
WpProxyPort *self = WP_PROXY_PORT(proxy);
GError *error = NULL;
/* Return error if the pipewire destruction happened while the async creation
* of this proxy port object has not finished */
if (self->init_task) {
g_set_error (&error, WP_DOMAIN_LIBRARY, WP_LIBRARY_ERROR_OPERATION_FAILED,
"pipewire port proxy destroyed before finishing");
g_task_return_error (self->init_task, error);
g_clear_object (&self->init_task);
}
}
static void
wp_proxy_port_init_async (GAsyncInitable *initable, int io_priority,
GCancellable *cancellable, GAsyncReadyCallback callback, gpointer data)
wp_proxy_port_augment (WpProxy * proxy, WpProxyFeatures features)
{
WpProxyPort *self = WP_PROXY_PORT(initable);
WpProxy *wp_proxy = WP_PROXY(initable);
struct pw_port_proxy *proxy = NULL;
/* call the default implementation to ensure we have a proxy, if necessary */
WP_PROXY_CLASS (wp_proxy_port_parent_class)->augment (proxy, features);
/* Create the async task */
self->init_task = g_task_new (initable, cancellable, callback, data);
if (features & WP_PROXY_PORT_FEATURE_FORMAT) {
struct pw_proxy *pwp = wp_proxy_get_pw_proxy (proxy);
g_return_if_fail (pwp != NULL);
/* Get the proxy from the base class */
proxy = wp_proxy_get_pw_proxy(wp_proxy);
/* Add the port proxy listener */
pw_port_proxy_add_listener(proxy, &self->listener, &port_events, self);
/* Emit the EnumFormat param */
pw_port_proxy_enum_params((struct pw_port_proxy*)proxy, 0,
SPA_PARAM_EnumFormat, 0, -1, NULL);
}
static void
wp_proxy_port_async_initable_init (gpointer iface, gpointer iface_data)
{
GAsyncInitableIface *ai_iface = iface;
/* Only set the init_async */
ai_iface->init_async = wp_proxy_port_init_async;
pw_port_proxy_enum_params ((struct pw_port_proxy *) pwp, 0,
SPA_PARAM_EnumFormat, 0, -1, NULL);
}
}
static void
wp_proxy_port_init (WpProxyPort * self)
wp_proxy_port_pw_proxy_created (WpProxy * proxy, struct pw_proxy * pw_proxy)
{
WpProxyPort *self = WP_PROXY_PORT (proxy);
pw_port_proxy_add_listener ((struct pw_port_proxy *) pw_proxy,
&self->listener, &port_events, self);
}
static void
wp_proxy_port_class_init (WpProxyPortClass * klass)
{
GObjectClass *object_class = (GObjectClass *) klass;
WpProxyClass *proxy_class = (WpProxyClass *) klass;
object_class->finalize = wp_proxy_port_finalize;
proxy_class->destroy = wp_proxy_port_destroy;
}
void
wp_proxy_port_new (guint global_id, gpointer proxy,
GAsyncReadyCallback callback, gpointer user_data)
{
g_async_initable_new_async (
WP_TYPE_PROXY_PORT, G_PRIORITY_DEFAULT, NULL, callback, user_data,
"global-id", global_id,
"pw-proxy", proxy,
NULL);
}
WpProxyPort *
wp_proxy_port_new_finish(GObject *initable, GAsyncResult *res, GError **error)
{
GAsyncInitable *ai = G_ASYNC_INITABLE(initable);
return WP_PROXY_PORT(g_async_initable_new_finish(ai, res, error));
}
const struct pw_port_info *
wp_proxy_port_get_info (WpProxyPort * self)
{
return self->info;
proxy_class->augment = wp_proxy_port_augment;
proxy_class->pw_proxy_created = wp_proxy_port_pw_proxy_created;
}
const struct spa_audio_info_raw *
......
......@@ -9,20 +9,24 @@
#ifndef __WIREPLUMBER_PROXY_PORT_H__
#define __WIREPLUMBER_PROXY_PORT_H__
#include "core.h"
#include "proxy.h"
G_BEGIN_DECLS
typedef enum { /*< flags >*/
WP_PROXY_PORT_FEATURE_FORMAT = (WP_PROXY_FEATURE_LAST << 0),
} WpProxyPortFeatures;
#define WP_TYPE_PROXY_PORT (wp_proxy_port_get_type ())
G_DECLARE_FINAL_TYPE (WpProxyPort, wp_proxy_port, WP, PROXY_PORT, WpProxy)
void wp_proxy_port_new (guint global_id, gpointer proxy,
GAsyncReadyCallback callback, gpointer user_data);
WpProxyPort *wp_proxy_port_new_finish(GObject *initable, GAsyncResult *res,
GError **error);
static inline const struct pw_port_info *
wp_proxy_port_get_info (WpProxyPort * self)
{
return (const struct pw_port_info *)
wp_proxy_get_native_info (WP_PROXY (self));
}
const struct pw_port_info *wp_proxy_port_get_info (WpProxyPort * self);
const struct spa_audio_info_raw *wp_proxy_port_get_format (WpProxyPort * self);
G_END_DECLS
......
This diff is collapsed.
......@@ -2,6 +2,7 @@
*
* Copyright © 2019 Collabora Ltd.
* @author Julian Bouzas <julian.bouzas@collabora.com>
* @author George Kiagiadakis <george.kiagiadakis@collabora.com>
*
* SPDX-License-Identifier: MIT
*/
......@@ -11,10 +12,20 @@
#include <gio/gio.h>
#include "core.h"
#include "remote.h"
#include "properties.h"
G_BEGIN_DECLS
struct pw_proxy;
typedef enum { /*< flags >*/
WP_PROXY_FEATURE_PW_PROXY = (1 << 0),
WP_PROXY_FEATURE_INFO = (1 << 1),
WP_PROXY_FEATURE_LAST = (1 << 5), /*< skip >*/
} WpProxyFeatures;
#define WP_TYPE_PROXY (wp_proxy_get_type ())
G_DECLARE_DERIVABLE_TYPE (WpProxy, wp_proxy, WP, PROXY, GObject)
......@@ -23,16 +34,53 @@ struct _WpProxyClass
{
GObjectClass parent_class;
/* Methods */
void (*destroy) (WpProxy * self);
void (*augment) (WpProxy *self, WpProxyFeatures features);
/* Signals */
void (*done)(WpProxy *wp_proxy, gpointer data);
void (*pw_proxy_created) (WpProxy * self, struct pw_proxy * proxy);
void (*pw_proxy_destroyed) (WpProxy * self);
};
guint wp_proxy_get_global_id (WpProxy * self);
gpointer wp_proxy_get_pw_proxy (WpProxy * self);
void wp_proxy_sync (WpProxy * self);
WpProxy * wp_proxy_new_global (WpRemote * remote,
guint32 id, guint32 permissions, WpProperties * properties,
guint32 type, guint32 version);
WpProxy * wp_proxy_new_wrap (WpRemote * remote,
struct pw_proxy * proxy, guint32 type, guint32 version);
void wp_proxy_augment (WpProxy *self,
WpProxyFeatures wanted_features, GCancellable * cancellable,
GAsyncReadyCallback callback, gpointer user_data);
gboolean wp_proxy_augment_finish (WpProxy * self, GAsyncResult * res,
GError ** error);
WpProxyFeatures wp_proxy_get_features (WpProxy * self);
WpRemote * wp_proxy_get_remote (WpProxy * self);
gboolean wp_proxy_is_global (WpProxy * self);
guint32 wp_proxy_get_global_id (WpProxy * self);
guint32 wp_proxy_get_global_permissions (WpProxy * self);
WpProperties * wp_proxy_get_global_properties (WpProxy * self);
guint32 wp_proxy_get_interface_type (WpProxy * self);
const gchar * wp_proxy_get_interface_name (WpProxy * self);
GQuark wp_proxy_get_interface_quark (WpProxy * self);
guint32 wp_proxy_get_interface_version (WpProxy * self);
struct pw_proxy * wp_proxy_get_pw_proxy (WpProxy * self);
gconstpointer wp_proxy_get_native_info (WpProxy * self);
/* for subclasses only */
typedef gpointer (*WpProxyNativeInfoUpdate) (gpointer old_info,
gconstpointer new_info);
void wp_proxy_update_native_info (WpProxy * self, gconstpointer info,
WpProxyNativeInfoUpdate update, GDestroyNotify destroy);
void wp_proxy_set_feature_ready (WpProxy * self, WpProxyFeatures feature);
void wp_proxy_augment_error (WpProxy * self, GError * error);
gboolean wp_proxy_bind_global (WpProxy * self);
G_END_DECLS
......
......@@ -7,6 +7,7 @@
*/
#include "remote-pipewire.h"
#include <pipewire/pipewire.h>
/*
......@@ -15,15 +16,6 @@
#define WP_LOOP_SOURCE(x) ((WpLoopSource *) x)
G_DEFINE_QUARK (node, signal_detail_node)
G_DEFINE_QUARK (port, signal_detail_port)
G_DEFINE_QUARK (factory, signal_detail_factory)
G_DEFINE_QUARK (link, signal_detail_link)
G_DEFINE_QUARK (client, signal_detail_client)
G_DEFINE_QUARK (module, signal_detail_module)
G_DEFINE_QUARK (device, signal_detail_device)
G_DEFINE_QUARK (endpoint, signal_detail_endpoint)
typedef struct _WpLoopSource WpLoopSource;
struct _WpLoopSource
{
......@@ -90,6 +82,10 @@ struct _WpRemotePipewire
struct spa_hook registry_listener;
GMainContext *context;
GHashTable *proxies;
GHashTable *default_features;
GQueue created_obj_proxies;
};
enum {
......@@ -113,45 +109,53 @@ static guint signals[LAST_SIGNAL] = { 0 };
G_DEFINE_TYPE (