221 lines
5.1 KiB
C
221 lines
5.1 KiB
C
/* WirePlumber
|
|
*
|
|
* Copyright © 2019 Collabora Ltd.
|
|
* @author Julian Bouzas <julian.bouzas@collabora.com>
|
|
*
|
|
* SPDX-License-Identifier: MIT
|
|
*/
|
|
|
|
#include <pipewire/pipewire.h>
|
|
|
|
#include "proxy.h"
|
|
|
|
typedef struct _WpProxyPrivate WpProxyPrivate;
|
|
struct _WpProxyPrivate
|
|
{
|
|
/* The core */
|
|
WpCore *core;
|
|
|
|
/* The proxy */
|
|
struct pw_proxy *proxy;
|
|
|
|
/* The proxy listener */
|
|
struct spa_hook listener;
|
|
|
|
/* The done info */
|
|
GTask *done_task;
|
|
};
|
|
|
|
enum {
|
|
PROP_0,
|
|
PROP_CORE,
|
|
PROP_PROXY,
|
|
};
|
|
|
|
static void wp_proxy_async_initable_init (gpointer iface, gpointer iface_data);
|
|
|
|
G_DEFINE_ABSTRACT_TYPE_WITH_CODE (WpProxy, wp_proxy, G_TYPE_OBJECT,
|
|
G_ADD_PRIVATE (WpProxy)
|
|
G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, wp_proxy_async_initable_init))
|
|
|
|
static void
|
|
proxy_event_destroy (void *data)
|
|
{
|
|
WpProxyPrivate *self = wp_proxy_get_instance_private (WP_PROXY(data));
|
|
|
|
/* Set the proxy to NULL */
|
|
self->proxy = NULL;
|
|
|
|
/* Remove the proxy from core */
|
|
wp_core_remove_global (self->core, WP_GLOBAL_PROXY, data);
|
|
}
|
|
|
|
static void
|
|
proxy_event_done (void *data, int seq)
|
|
{
|
|
WpProxyPrivate *self = wp_proxy_get_instance_private (WP_PROXY(data));
|
|
|
|
/* Make sure the task is valid */
|
|
if (!self->done_task)
|
|
return;
|
|
|
|
/* Execute the task */
|
|
g_task_return_boolean (self->done_task, TRUE);
|
|
|
|
/* Clean up */
|
|
g_object_unref (self->done_task);
|
|
self->done_task = NULL;
|
|
}
|
|
|
|
static const struct pw_proxy_events proxy_events = {
|
|
PW_VERSION_PROXY_EVENTS,
|
|
.destroy = proxy_event_destroy,
|
|
.done = proxy_event_done,
|
|
};
|
|
|
|
static void
|
|
wp_proxy_finalize (GObject * object)
|
|
{
|
|
WpProxyPrivate *self = wp_proxy_get_instance_private (WP_PROXY(object));
|
|
|
|
/* Remove the listener */
|
|
spa_hook_remove (&self->listener);
|
|
|
|
/* Destroy the proxy */
|
|
if (self->proxy) {
|
|
pw_proxy_destroy (self->proxy);
|
|
self->proxy = NULL;
|
|
}
|
|
|
|
G_OBJECT_CLASS (wp_proxy_parent_class)->finalize (object);
|
|
}
|
|
|
|
static void
|
|
wp_proxy_set_property (GObject * object, guint property_id,
|
|
const GValue * value, GParamSpec * pspec)
|
|
{
|
|
WpProxyPrivate *self = wp_proxy_get_instance_private (WP_PROXY(object));
|
|
|
|
switch (property_id) {
|
|
case PROP_CORE:
|
|
self->core = g_value_get_pointer (value);
|
|
break;
|
|
case PROP_PROXY:
|
|
self->proxy = g_value_get_pointer (value);
|
|
break;
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
wp_proxy_get_property (GObject * object, guint property_id, GValue * value,
|
|
GParamSpec * pspec)
|
|
{
|
|
WpProxyPrivate *self = wp_proxy_get_instance_private (WP_PROXY(object));
|
|
|
|
switch (property_id) {
|
|
case PROP_CORE:
|
|
g_value_set_pointer (value, self->core);
|
|
break;
|
|
case PROP_PROXY:
|
|
g_value_set_pointer (value, self->proxy);
|
|
break;
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
wp_proxy_init_async (GAsyncInitable *initable, int io_priority,
|
|
GCancellable *cancellable, GAsyncReadyCallback callback, gpointer data)
|
|
{
|
|
WpProxyPrivate *self = wp_proxy_get_instance_private (WP_PROXY(initable));
|
|
|
|
/* Create the async task */
|
|
self->done_task = g_task_new (initable, cancellable, callback, data);
|
|
|
|
/* Add the event listener */
|
|
pw_proxy_add_listener (self->proxy, &self->listener, &proxy_events, initable);
|
|
|
|
/* Trigger the done callback */
|
|
pw_proxy_sync(self->proxy, 0);
|
|
}
|
|
|
|
static gboolean
|
|
wp_proxy_init_finish (GAsyncInitable *initable, GAsyncResult *result,
|
|
GError **error)
|
|
{
|
|
g_return_val_if_fail (g_task_is_valid (result, initable), FALSE);
|
|
|
|
return g_task_propagate_boolean (G_TASK (result), error);
|
|
}
|
|
|
|
static void
|
|
wp_proxy_async_initable_init (gpointer iface, gpointer iface_data)
|
|
{
|
|
GAsyncInitableIface *ai_iface = iface;
|
|
|
|
ai_iface->init_async = wp_proxy_init_async;
|
|
ai_iface->init_finish = wp_proxy_init_finish;
|
|
}
|
|
|
|
static void
|
|
wp_proxy_init (WpProxy * self)
|
|
{
|
|
}
|
|
|
|
static void
|
|
wp_proxy_class_init (WpProxyClass * klass)
|
|
{
|
|
GObjectClass *object_class = (GObjectClass *) klass;
|
|
|
|
object_class->finalize = wp_proxy_finalize;
|
|
object_class->get_property = wp_proxy_get_property;
|
|
object_class->set_property = wp_proxy_set_property;
|
|
|
|
/* Install the properties */
|
|
g_object_class_install_property (object_class, PROP_CORE,
|
|
g_param_spec_pointer ("core", "core", "The wireplumber core",
|
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
|
|
g_object_class_install_property (object_class, PROP_PROXY,
|
|
g_param_spec_pointer ("pw-proxy", "pw-proxy", "The pipewire proxy",
|
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
|
|
}
|
|
|
|
void
|
|
wp_proxy_register(WpProxy * self)
|
|
{
|
|
WpProxyPrivate *priv;
|
|
|
|
g_return_if_fail (WP_IS_PROXY (self));
|
|
|
|
priv = wp_proxy_get_instance_private (self);
|
|
wp_core_register_global (priv->core, WP_GLOBAL_PROXY, g_object_ref (self),
|
|
g_object_unref);
|
|
}
|
|
|
|
WpCore *
|
|
wp_proxy_get_core (WpProxy * self)
|
|
{
|
|
WpProxyPrivate *priv;
|
|
|
|
g_return_val_if_fail (WP_IS_PROXY (self), NULL);
|
|
|
|
priv = wp_proxy_get_instance_private (self);
|
|
return priv->core;
|
|
}
|
|
|
|
gpointer
|
|
wp_proxy_get_pw_proxy (WpProxy * self)
|
|
{
|
|
WpProxyPrivate *priv;
|
|
|
|
g_return_val_if_fail (WP_IS_PROXY (self), NULL);
|
|
|
|
priv = wp_proxy_get_instance_private (self);
|
|
return priv->proxy;
|
|
}
|