refactoring around the registries
* make the registries available as dynamic interfaces of the core * improve a bit the C API of WpObject & WpInterfaceImpl
This commit is contained in:
149
lib/wp/core-interfaces.c
Normal file
149
lib/wp/core-interfaces.c
Normal file
@@ -0,0 +1,149 @@
|
||||
/* WirePlumber
|
||||
*
|
||||
* Copyright © 2019 Collabora Ltd.
|
||||
* @author George Kiagiadakis <george.kiagiadakis@collabora.com>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#include "core-interfaces.h"
|
||||
#include "plugin.h"
|
||||
|
||||
/* WpPluginRegistry */
|
||||
|
||||
G_DEFINE_INTERFACE (WpPluginRegistry, wp_plugin_registry, WP_TYPE_INTERFACE_IMPL)
|
||||
|
||||
static void
|
||||
wp_plugin_registry_default_init (WpPluginRegistryInterface * iface)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* wp_plugin_registry_register_static: (skip)
|
||||
* @plugin_type: the #GType of the #WpPlugin subclass
|
||||
* @metadata: the metadata
|
||||
* @metadata_size: the sizeof (@metadata), to allow ABI-compatible future
|
||||
* expansion of the structure
|
||||
*
|
||||
* Registers a plugin in the registry.
|
||||
* This method is used internally by WP_PLUGIN_REGISTER().
|
||||
* Avoid using it directly.
|
||||
*/
|
||||
void
|
||||
wp_plugin_registry_register_static (WpPluginRegistry * self,
|
||||
GType plugin_type,
|
||||
const WpPluginMetadata * metadata,
|
||||
gsize metadata_size)
|
||||
{
|
||||
WpPluginRegistryInterface *iface = WP_PLUGIN_REGISTRY_GET_IFACE (self);
|
||||
|
||||
g_return_if_fail (WP_IS_PLUGIN_REGISTRY (self));
|
||||
g_return_if_fail (iface->register_plugin != NULL);
|
||||
g_return_if_fail (g_type_is_a (plugin_type, WP_TYPE_PLUGIN));
|
||||
g_return_if_fail (metadata->name != NULL);
|
||||
g_return_if_fail (metadata->description != NULL);
|
||||
g_return_if_fail (metadata->author != NULL);
|
||||
g_return_if_fail (metadata->license != NULL);
|
||||
g_return_if_fail (metadata->version != NULL);
|
||||
g_return_if_fail (metadata->origin != NULL);
|
||||
|
||||
WP_PLUGIN_REGISTRY_GET_IFACE (self)->register_plugin (self, plugin_type,
|
||||
metadata, metadata_size, TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* wp_plugin_registry_register: (method)
|
||||
* @plugin_type: the #GType of the #WpPlugin subclass
|
||||
* @rank: the rank of the plugin
|
||||
* @name: the name of the plugin
|
||||
* @description: plugin description
|
||||
* @author: author <email@domain>, author2 <email@domain>
|
||||
* @license: a SPDX license ID or "Proprietary"
|
||||
* @version: the version of the plugin
|
||||
* @origin: URL or short reference of where this plugin came from
|
||||
*
|
||||
* Registers a plugin in the registry.
|
||||
* This method creates a dynamically allocated #WpPluginMetadata and is meant
|
||||
* to be used by bindings that have no way of representing #WpPluginMetadata.
|
||||
* In C/C++, you should use WP_PLUGIN_REGISTER()
|
||||
*/
|
||||
void
|
||||
wp_plugin_registry_register (WpPluginRegistry * self,
|
||||
GType plugin_type,
|
||||
guint16 rank,
|
||||
const gchar *name,
|
||||
const gchar *description,
|
||||
const gchar *author,
|
||||
const gchar *license,
|
||||
const gchar *version,
|
||||
const gchar *origin)
|
||||
{
|
||||
WpPluginRegistryInterface *iface = WP_PLUGIN_REGISTRY_GET_IFACE (self);
|
||||
WpPluginMetadata metadata = {0};
|
||||
|
||||
g_return_if_fail (WP_IS_PLUGIN_REGISTRY (self));
|
||||
g_return_if_fail (iface->register_plugin != NULL);
|
||||
g_return_if_fail (g_type_is_a (plugin_type, WP_TYPE_PLUGIN));
|
||||
g_return_if_fail (name != NULL);
|
||||
g_return_if_fail (description != NULL);
|
||||
g_return_if_fail (author != NULL);
|
||||
g_return_if_fail (license != NULL);
|
||||
g_return_if_fail (version != NULL);
|
||||
g_return_if_fail (origin != NULL);
|
||||
|
||||
metadata.rank = rank;
|
||||
metadata.name = name;
|
||||
metadata.description = description;
|
||||
metadata.author = author;
|
||||
metadata.license = license;
|
||||
metadata.version = version;
|
||||
metadata.origin = origin;
|
||||
|
||||
WP_PLUGIN_REGISTRY_GET_IFACE (self)->register_plugin (self, plugin_type,
|
||||
&metadata, sizeof (metadata), FALSE);
|
||||
}
|
||||
|
||||
/* WpProxyRegistry */
|
||||
|
||||
G_DEFINE_INTERFACE (WpProxyRegistry, wp_proxy_registry, WP_TYPE_INTERFACE_IMPL)
|
||||
|
||||
static void
|
||||
wp_proxy_registry_default_init (WpProxyRegistryInterface * iface)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
WpProxyRegistryInterface * iface = WP_PROXY_REGISTRY_GET_IFACE (self);
|
||||
|
||||
g_return_val_if_fail (WP_IS_PROXY_REGISTRY (self), NULL);
|
||||
g_return_val_if_fail (iface->get_proxy != NULL, NULL);
|
||||
|
||||
return iface->get_proxy (self, global_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
WpProxyRegistryInterface * iface = WP_PROXY_REGISTRY_GET_IFACE (self);
|
||||
|
||||
g_return_val_if_fail (WP_IS_PROXY_REGISTRY (self), NULL);
|
||||
g_return_val_if_fail (iface->get_pw_registry_proxy != NULL, NULL);
|
||||
|
||||
return iface->get_pw_registry_proxy (self);
|
||||
}
|
73
lib/wp/core-interfaces.h
Normal file
73
lib/wp/core-interfaces.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/* WirePlumber
|
||||
*
|
||||
* Copyright © 2019 Collabora Ltd.
|
||||
* @author George Kiagiadakis <george.kiagiadakis@collabora.com>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#ifndef __WP_CORE_INTERFACES_H__
|
||||
#define __WP_CORE_INTERFACES_H__
|
||||
|
||||
#include "interface-impl.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/* WpPluginRegistry */
|
||||
|
||||
#define WP_TYPE_PLUGIN_REGISTRY (wp_plugin_registry_get_type ())
|
||||
G_DECLARE_INTERFACE (WpPluginRegistry, wp_plugin_registry, WP, PLUGIN_REGISTRY, WpInterfaceImpl)
|
||||
|
||||
typedef struct _WpPluginMetadata WpPluginMetadata;
|
||||
|
||||
struct _WpPluginRegistryInterface
|
||||
{
|
||||
GTypeInterface parent;
|
||||
|
||||
void (*register_plugin) (WpPluginRegistry * self,
|
||||
GType plugin_type,
|
||||
const WpPluginMetadata * metadata,
|
||||
gsize metadata_size,
|
||||
gboolean static_data);
|
||||
};
|
||||
|
||||
void wp_plugin_registry_register_static (WpPluginRegistry * self,
|
||||
GType plugin_type,
|
||||
const WpPluginMetadata * metadata,
|
||||
gsize metadata_size);
|
||||
|
||||
void wp_plugin_registry_register (WpPluginRegistry * self,
|
||||
GType plugin_type,
|
||||
guint16 rank,
|
||||
const gchar *name,
|
||||
const gchar *description,
|
||||
const gchar *author,
|
||||
const gchar *license,
|
||||
const gchar *version,
|
||||
const gchar *origin);
|
||||
|
||||
/* WpProxyRegistry */
|
||||
|
||||
struct pw_registry_proxy;
|
||||
typedef struct _WpProxy WpProxy;
|
||||
|
||||
#define WP_TYPE_PROXY_REGISTRY (wp_proxy_registry_get_type ())
|
||||
G_DECLARE_INTERFACE (WpProxyRegistry, wp_proxy_registry, WP, PROXY_REGISTRY, WpInterfaceImpl)
|
||||
|
||||
struct _WpProxyRegistryInterface
|
||||
{
|
||||
GTypeInterface parent;
|
||||
|
||||
WpProxy * (*get_proxy) (WpProxyRegistry * self, guint32 global_id);
|
||||
struct pw_registry_proxy * (*get_pw_registry_proxy) (WpProxyRegistry * self);
|
||||
};
|
||||
|
||||
WpProxy * wp_proxy_registry_get_proxy (WpProxyRegistry * self,
|
||||
guint32 global_id);
|
||||
|
||||
struct pw_registry_proxy * wp_proxy_registry_get_pw_registry_proxy (
|
||||
WpProxyRegistry * self);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif
|
@@ -10,7 +10,7 @@
|
||||
#include "object.h"
|
||||
|
||||
typedef struct {
|
||||
GObject *object;
|
||||
WpObject *object;
|
||||
} WpInterfaceImplPrivate;
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (WpInterfaceImpl, wp_interface_impl, G_TYPE_OBJECT);
|
||||
@@ -44,7 +44,7 @@ wp_interface_impl_class_init (WpInterfaceImplClass * klass)
|
||||
* @object: (nullable) (transfer none): the implementor
|
||||
*/
|
||||
void
|
||||
wp_interface_impl_set_object (WpInterfaceImpl * self, GObject * object)
|
||||
wp_interface_impl_set_object (WpInterfaceImpl * self, WpObject * object)
|
||||
{
|
||||
WpInterfaceImplPrivate *priv = wp_interface_impl_get_instance_private (self);
|
||||
|
||||
@@ -60,7 +60,7 @@ wp_interface_impl_set_object (WpInterfaceImpl * self, GObject * object)
|
||||
*
|
||||
* Returns: (nullable) (transfer none): the object implementing this interface
|
||||
*/
|
||||
GObject *
|
||||
WpObject *
|
||||
wp_interface_impl_get_object (WpInterfaceImpl * self)
|
||||
{
|
||||
WpInterfaceImplPrivate *priv = wp_interface_impl_get_instance_private (self);
|
||||
@@ -75,9 +75,10 @@ wp_interface_impl_get_object (WpInterfaceImpl * self)
|
||||
* @self: the interface implementation instance
|
||||
* @interface: an interface type
|
||||
*
|
||||
* Returns: (nullable) (transfer full): the object implementing @interface
|
||||
* Returns: (type GObject*) (nullable) (transfer full): the object
|
||||
* implementing @interface
|
||||
*/
|
||||
GObject *
|
||||
gpointer
|
||||
wp_interface_impl_get_sibling (WpInterfaceImpl * self, GType interface)
|
||||
{
|
||||
WpInterfaceImplPrivate *priv = wp_interface_impl_get_instance_private (self);
|
||||
@@ -89,7 +90,7 @@ wp_interface_impl_get_sibling (WpInterfaceImpl * self, GType interface)
|
||||
if (g_type_is_a (G_TYPE_FROM_INSTANCE (self), interface)) {
|
||||
iface = G_OBJECT (g_object_ref (self));
|
||||
} else if (priv->object) {
|
||||
iface = wp_object_get_interface (WP_OBJECT (priv->object), interface);
|
||||
iface = wp_object_get_interface (priv->object, interface);
|
||||
}
|
||||
|
||||
return iface;
|
||||
|
@@ -13,6 +13,9 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _WpObject WpObject;
|
||||
|
||||
#define WP_TYPE_INTERFACE_IMPL (wp_interface_impl_get_type ())
|
||||
G_DECLARE_DERIVABLE_TYPE (WpInterfaceImpl, wp_interface_impl, WP, INTERFACE_IMPL, GObject)
|
||||
|
||||
struct _WpInterfaceImplClass
|
||||
@@ -30,9 +33,9 @@ struct _WpInterfaceImplClass
|
||||
GType *(*get_prerequisites) (WpInterfaceImpl * self, guint * n_prerequisites);
|
||||
};
|
||||
|
||||
void wp_interface_impl_set_object (WpInterfaceImpl * self, GObject * object);
|
||||
GObject * wp_interface_impl_get_object (WpInterfaceImpl * self);
|
||||
GObject * wp_interface_impl_get_sibling (WpInterfaceImpl * self,
|
||||
void wp_interface_impl_set_object (WpInterfaceImpl * self, WpObject * object);
|
||||
WpObject * wp_interface_impl_get_object (WpInterfaceImpl * self);
|
||||
gpointer wp_interface_impl_get_sibling (WpInterfaceImpl * self,
|
||||
GType interface);
|
||||
GType * wp_interface_impl_get_prerequisites (WpInterfaceImpl * self,
|
||||
guint * n_prerequisites);
|
||||
|
@@ -1,20 +1,18 @@
|
||||
wp_lib_sources = [
|
||||
'core-interfaces.c',
|
||||
'error.c',
|
||||
'interface-impl.c',
|
||||
'object.c',
|
||||
'plugin-registry.c',
|
||||
'plugin.c',
|
||||
'proxy-registry.c',
|
||||
'proxy.c',
|
||||
]
|
||||
|
||||
wp_lib_headers = [
|
||||
'core-interfaces.h',
|
||||
'error.h',
|
||||
'interface-impl.h',
|
||||
'object.h',
|
||||
'plugin-registry.h',
|
||||
'plugin.h',
|
||||
'proxy-registry.h',
|
||||
'proxy.h',
|
||||
]
|
||||
|
||||
|
@@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
#include "object.h"
|
||||
#include "interface-impl.h"
|
||||
#include "error.h"
|
||||
|
||||
typedef struct {
|
||||
@@ -80,9 +81,10 @@ wp_object_implements_interface (WpObject * self, GType interface)
|
||||
* @self: the object
|
||||
* @interface: an interface type
|
||||
*
|
||||
* Returns: (nullable) (transfer full): the object implementing @interface
|
||||
* Returns: (type GObject*) (nullable) (transfer full): the object
|
||||
* implementing @interface
|
||||
*/
|
||||
GObject *
|
||||
gpointer
|
||||
wp_object_get_interface (WpObject * self, GType interface)
|
||||
{
|
||||
WpObjectPrivate *priv = wp_object_get_instance_private (self);
|
||||
@@ -121,13 +123,13 @@ wp_object_list_interfaces (WpObject * self, guint * n_interfaces)
|
||||
/**
|
||||
* wp_object_attach_interface_impl: (method)
|
||||
* @self: the object
|
||||
* @impl: (transfer none): the interface implementation
|
||||
* @impl: (type WpInterfaceImpl*) (transfer none): the interface implementation
|
||||
* @error: (out): a GError to return on failure
|
||||
*
|
||||
* Returns: TRUE one success, FALSE on error
|
||||
*/
|
||||
gboolean
|
||||
wp_object_attach_interface_impl (WpObject * self, WpInterfaceImpl * impl,
|
||||
wp_object_attach_interface_impl (WpObject * self, gpointer impl,
|
||||
GError ** error)
|
||||
{
|
||||
WpObjectPrivate *priv = wp_object_get_instance_private (self);
|
||||
@@ -171,6 +173,6 @@ wp_object_attach_interface_impl (WpObject * self, WpInterfaceImpl * impl,
|
||||
g_object_ref (impl);
|
||||
g_array_append_val (priv->iface_objects, impl);
|
||||
g_array_append_vals (priv->iface_types, new_ifaces, n_new_ifaces);
|
||||
wp_interface_impl_set_object (impl, G_OBJECT (self));
|
||||
wp_interface_impl_set_object (WP_INTERFACE_IMPL (impl), self);
|
||||
return TRUE;
|
||||
}
|
||||
|
@@ -9,10 +9,11 @@
|
||||
#ifndef __WP_OBJECT_H__
|
||||
#define __WP_OBJECT_H__
|
||||
|
||||
#include "interface-impl.h"
|
||||
#include <glib-object.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define WP_TYPE_OBJECT (wp_object_get_type ())
|
||||
G_DECLARE_DERIVABLE_TYPE (WpObject, wp_object, WP, OBJECT, GObject)
|
||||
|
||||
struct _WpObjectClass
|
||||
@@ -21,11 +22,11 @@ struct _WpObjectClass
|
||||
};
|
||||
|
||||
gboolean wp_object_implements_interface (WpObject * self, GType interface);
|
||||
GObject * wp_object_get_interface (WpObject * self, GType interface);
|
||||
gpointer wp_object_get_interface (WpObject * self, GType interface);
|
||||
GType * wp_object_list_interfaces (WpObject * self, guint * n_interfaces);
|
||||
|
||||
gboolean wp_object_attach_interface_impl (WpObject * self,
|
||||
WpInterfaceImpl * impl, GError ** error);
|
||||
gboolean wp_object_attach_interface_impl (WpObject * self, gpointer impl,
|
||||
GError ** error);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
@@ -1,227 +0,0 @@
|
||||
/* WirePlumber
|
||||
*
|
||||
* Copyright © 2019 Collabora Ltd.
|
||||
* @author George Kiagiadakis <george.kiagiadakis@collabora.com>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#include "plugin-registry.h"
|
||||
#include "plugin.h"
|
||||
|
||||
typedef struct {
|
||||
gsize block_size;
|
||||
GType gtype;
|
||||
const WpPluginMetadata *metadata;
|
||||
WpPlugin *instance;
|
||||
} PluginData;
|
||||
|
||||
struct _WpPluginRegistry
|
||||
{
|
||||
GObject parent;
|
||||
|
||||
GList *plugins;
|
||||
GStringChunk *metadata_strings;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (WpPluginRegistry, wp_plugin_registry, G_TYPE_OBJECT);
|
||||
|
||||
static void
|
||||
wp_plugin_registry_init (WpPluginRegistry * self)
|
||||
{
|
||||
self->metadata_strings = g_string_chunk_new (200);
|
||||
}
|
||||
|
||||
static void
|
||||
wp_plugin_registry_dispose (GObject * object)
|
||||
{
|
||||
WpPluginRegistry *self = WP_PLUGIN_REGISTRY (object);
|
||||
GList *list;
|
||||
PluginData *plugin_data;
|
||||
|
||||
for (list = self->plugins; list != NULL; list = g_list_next (list)) {
|
||||
plugin_data = list->data;
|
||||
g_clear_object (&plugin_data->instance);
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (wp_plugin_registry_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
plugin_data_free (PluginData *data)
|
||||
{
|
||||
g_slice_free1 (data->block_size, data);
|
||||
}
|
||||
|
||||
static void
|
||||
wp_plugin_registry_finalize (GObject * object)
|
||||
{
|
||||
WpPluginRegistry *self = WP_PLUGIN_REGISTRY (object);
|
||||
|
||||
g_list_free_full (self->plugins, (GDestroyNotify) plugin_data_free);
|
||||
g_string_chunk_free (self->metadata_strings);
|
||||
|
||||
G_OBJECT_CLASS (wp_plugin_registry_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
wp_plugin_registry_class_init (WpPluginRegistryClass * klass)
|
||||
{
|
||||
GObjectClass *object_class = (GObjectClass *) klass;
|
||||
object_class->dispose = wp_plugin_registry_dispose;
|
||||
object_class->finalize = wp_plugin_registry_finalize;
|
||||
}
|
||||
|
||||
/**
|
||||
* wp_plugin_registry_new: (constructor)
|
||||
*
|
||||
* Create a new registry.
|
||||
*/
|
||||
WpPluginRegistry *
|
||||
wp_plugin_registry_new (void)
|
||||
{
|
||||
return g_object_new (wp_plugin_registry_get_type (), NULL);
|
||||
}
|
||||
|
||||
static gint
|
||||
compare_ranks (const WpPluginMetadata * a, const WpPluginMetadata * b)
|
||||
{
|
||||
return (gint) b->rank - (gint) a->rank;
|
||||
}
|
||||
|
||||
/**
|
||||
* wp_plugin_registry_register_with_metadata: (skip)
|
||||
* @plugin_type: the #GType of the #WpPlugin subclass
|
||||
* @metadata: the metadata
|
||||
* @metadata_size: the sizeof (@metadata), to allow ABI-compatible future
|
||||
* expansion of the structure
|
||||
*
|
||||
* Registers a plugin in the registry.
|
||||
* This method is used internally by WP_PLUGIN_REGISTER().
|
||||
* Avoid using it directly.
|
||||
*/
|
||||
void
|
||||
wp_plugin_registry_register_with_metadata (WpPluginRegistry * self,
|
||||
GType plugin_type,
|
||||
const WpPluginMetadata * metadata,
|
||||
gsize metadata_size)
|
||||
{
|
||||
PluginData *data;
|
||||
|
||||
g_return_if_fail (WP_IS_PLUGIN_REGISTRY (self));
|
||||
g_return_if_fail (metadata_size == sizeof (WpPluginMetadata));
|
||||
g_return_if_fail (g_type_is_a (plugin_type, wp_plugin_get_type ()));
|
||||
g_return_if_fail (metadata->name != NULL);
|
||||
g_return_if_fail (metadata->description != NULL);
|
||||
g_return_if_fail (metadata->author != NULL);
|
||||
g_return_if_fail (metadata->license != NULL);
|
||||
g_return_if_fail (metadata->version != NULL);
|
||||
g_return_if_fail (metadata->origin != NULL);
|
||||
|
||||
data = g_slice_alloc (sizeof (PluginData));
|
||||
data->block_size = sizeof (PluginData);
|
||||
data->gtype = plugin_type;
|
||||
data->metadata = metadata;
|
||||
data->instance = NULL;
|
||||
|
||||
self->plugins = g_list_insert_sorted (self->plugins, data,
|
||||
(GCompareFunc) compare_ranks);
|
||||
}
|
||||
|
||||
/**
|
||||
* wp_plugin_registry_register: (method)
|
||||
* @plugin_type: the #GType of the #WpPlugin subclass
|
||||
* @rank: the rank of the plugin
|
||||
* @name: the name of the plugin
|
||||
* @description: plugin description
|
||||
* @author: author <email@domain>, author2 <email@domain>
|
||||
* @license: a SPDX license ID or "Proprietary"
|
||||
* @version: the version of the plugin
|
||||
* @origin: URL or short reference of where this plugin came from
|
||||
*
|
||||
* Registers a plugin in the registry.
|
||||
* This method creates a dynamically allocated #WpPluginMetadata and is meant
|
||||
* to be used by bindings that have no way of representing #WpPluginMetadata.
|
||||
* In C/C++, you should use WP_PLUGIN_REGISTER()
|
||||
*/
|
||||
void
|
||||
wp_plugin_registry_register (WpPluginRegistry * self,
|
||||
GType plugin_type,
|
||||
guint16 rank,
|
||||
const gchar *name,
|
||||
const gchar *description,
|
||||
const gchar *author,
|
||||
const gchar *license,
|
||||
const gchar *version,
|
||||
const gchar *origin)
|
||||
{
|
||||
PluginData *data;
|
||||
WpPluginMetadata *metadata;
|
||||
|
||||
g_return_if_fail (WP_IS_PLUGIN_REGISTRY (self));
|
||||
g_return_if_fail (g_type_is_a (plugin_type, wp_plugin_get_type ()));
|
||||
g_return_if_fail (name != NULL);
|
||||
g_return_if_fail (description != NULL);
|
||||
g_return_if_fail (author != NULL);
|
||||
g_return_if_fail (license != NULL);
|
||||
g_return_if_fail (version != NULL);
|
||||
g_return_if_fail (origin != NULL);
|
||||
|
||||
data = g_slice_alloc (sizeof (PluginData) + sizeof (WpPluginMetadata));
|
||||
data->block_size = sizeof (PluginData) + sizeof (WpPluginMetadata);
|
||||
data->gtype = plugin_type;
|
||||
|
||||
metadata = (WpPluginMetadata *) ((guint8 *) data) + sizeof (PluginData);
|
||||
metadata->rank = rank;
|
||||
metadata->name = g_string_chunk_insert (self->metadata_strings, name);
|
||||
metadata->description = g_string_chunk_insert (self->metadata_strings,
|
||||
description);
|
||||
metadata->author = g_string_chunk_insert (self->metadata_strings, author);
|
||||
metadata->license = g_string_chunk_insert (self->metadata_strings, license);
|
||||
metadata->version = g_string_chunk_insert (self->metadata_strings, version);
|
||||
metadata->origin = g_string_chunk_insert (self->metadata_strings, origin);
|
||||
|
||||
data->metadata = metadata;
|
||||
data->instance = NULL;
|
||||
|
||||
self->plugins = g_list_insert_sorted (self->plugins, data,
|
||||
(GCompareFunc) compare_ranks);
|
||||
}
|
||||
|
||||
static inline void
|
||||
make_plugin (WpPluginRegistry * self, PluginData * plugin_data)
|
||||
{
|
||||
plugin_data->instance = g_object_new (plugin_data->gtype,
|
||||
"registry", self, "metadata", plugin_data->metadata, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* WpPluginFunc: (skip)
|
||||
*/
|
||||
|
||||
/**
|
||||
* wp_plugin_registry_invoke_internal: (skip)
|
||||
* @self: the registry
|
||||
* @func: a vfunc invocation function of #WpPlugin
|
||||
* @data: data to pass to @func
|
||||
*
|
||||
* Used internally only.
|
||||
*/
|
||||
gboolean
|
||||
wp_plugin_registry_invoke_internal (WpPluginRegistry * self, WpPluginFunc func,
|
||||
gpointer data)
|
||||
{
|
||||
GList *list;
|
||||
PluginData *plugin_data;
|
||||
|
||||
for (list = self->plugins; list != NULL; list = g_list_next (list)) {
|
||||
plugin_data = list->data;
|
||||
if (!plugin_data->instance)
|
||||
make_plugin (self, plugin_data);
|
||||
|
||||
if (func (plugin_data->instance, data))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
@@ -1,54 +0,0 @@
|
||||
/* WirePlumber
|
||||
*
|
||||
* Copyright © 2019 Collabora Ltd.
|
||||
* @author George Kiagiadakis <george.kiagiadakis@collabora.com>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#ifndef __WP_PLUGIN_REGISTRY_H__
|
||||
#define __WP_PLUGIN_REGISTRY_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/* declared in plugin.h */
|
||||
typedef struct _WpPluginMetadata WpPluginMetadata;
|
||||
|
||||
G_DECLARE_FINAL_TYPE (WpPluginRegistry, wp_plugin_registry, WP, PLUGIN_REGISTRY, GObject)
|
||||
|
||||
WpPluginRegistry * wp_plugin_registry_new (void);
|
||||
|
||||
void wp_plugin_registry_register_with_metadata (WpPluginRegistry * self,
|
||||
GType plugin_type,
|
||||
const WpPluginMetadata * metadata,
|
||||
gsize metadata_size);
|
||||
|
||||
void wp_plugin_registry_register (WpPluginRegistry * self,
|
||||
GType plugin_type,
|
||||
guint16 rank,
|
||||
const gchar *name,
|
||||
const gchar *description,
|
||||
const gchar *author,
|
||||
const gchar *license,
|
||||
const gchar *version,
|
||||
const gchar *origin);
|
||||
|
||||
|
||||
typedef gboolean (*WpPluginFunc) (gpointer plugin, gpointer data);
|
||||
gboolean wp_plugin_registry_invoke_internal (WpPluginRegistry * self,
|
||||
WpPluginFunc func, gpointer data);
|
||||
|
||||
#define wp_plugin_registry_invoke(r, func, data) \
|
||||
G_STMT_START \
|
||||
if (!(0 ? func ((WpPlugin *) NULL, data) : \
|
||||
wp_plugin_registry_invoke_internal (r, (WpPluginFunc) func, \
|
||||
(gpointer) data))) { \
|
||||
g_warning ("No plugin handled invocation to " ##func); \
|
||||
} \
|
||||
G_STMT_END
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif
|
@@ -11,9 +11,7 @@
|
||||
|
||||
#include "object.h"
|
||||
#include "proxy.h"
|
||||
#include "plugin-registry.h"
|
||||
|
||||
#include <gmodule.h>
|
||||
#include "core-interfaces.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
@@ -66,6 +64,7 @@ struct _WpPluginMetadata
|
||||
const gchar *origin;
|
||||
};
|
||||
|
||||
#define WP_TYPE_PLUGIN (wp_plugin_get_type ())
|
||||
G_DECLARE_DERIVABLE_TYPE (WpPlugin, wp_plugin, WP, PLUGIN, GObject)
|
||||
|
||||
struct _WpPluginClass
|
||||
|
@@ -1,33 +0,0 @@
|
||||
/* 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
|
@@ -10,12 +10,13 @@
|
||||
#define __WP_PROXY_H__
|
||||
|
||||
#include "object.h"
|
||||
#include "proxy-registry.h"
|
||||
#include "core-interfaces.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
struct pw_proxy;
|
||||
|
||||
#define WP_TYPE_PROXY (wp_proxy_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (WpProxy, wp_proxy, WP, PROXY, WpObject)
|
||||
|
||||
guint32 wp_proxy_get_id (WpProxy * self);
|
||||
|
53
src/core.c
53
src/core.c
@@ -9,11 +9,10 @@
|
||||
#include "core.h"
|
||||
#include "loop-source.h"
|
||||
#include "module-loader.h"
|
||||
#include "plugin-registry-impl.h"
|
||||
#include "proxy-registry-impl.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include <wp/plugin-registry.h>
|
||||
#include <wp/proxy-registry.h>
|
||||
|
||||
#include <pipewire/pipewire.h>
|
||||
#include <glib-unix.h>
|
||||
#include <gio/gio.h>
|
||||
@@ -32,13 +31,11 @@ struct _WpCore
|
||||
struct spa_hook remote_listener;
|
||||
|
||||
WpModuleLoader *module_loader;
|
||||
WpPluginRegistry *plugin_registry;
|
||||
WpProxyRegistry *proxy_registry;
|
||||
|
||||
GError *exit_error;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (WpCore, wp_core, G_TYPE_OBJECT);
|
||||
G_DEFINE_TYPE (WpCore, wp_core, WP_TYPE_OBJECT);
|
||||
|
||||
static gboolean
|
||||
signal_handler (gpointer data)
|
||||
@@ -83,6 +80,7 @@ static gboolean
|
||||
wp_core_parse_commands_file (WpCore * self, GInputStream * stream,
|
||||
GError ** error)
|
||||
{
|
||||
g_autoptr (WpPluginRegistry) plugin_registry = NULL;
|
||||
gchar buffer[4096];
|
||||
gssize bytes_read;
|
||||
gchar *cur, *linestart, *saveptr;
|
||||
@@ -90,6 +88,9 @@ wp_core_parse_commands_file (WpCore * self, GInputStream * stream,
|
||||
gint lineno = 1;
|
||||
gboolean eof = FALSE;
|
||||
|
||||
plugin_registry = wp_object_get_interface (WP_OBJECT (self),
|
||||
WP_TYPE_PLUGIN_REGISTRY);
|
||||
|
||||
linestart = cur = buffer;
|
||||
|
||||
do {
|
||||
@@ -126,7 +127,7 @@ wp_core_parse_commands_file (WpCore * self, GInputStream * stream,
|
||||
"expected ABI and MODULE at line %i", lineno);
|
||||
return FALSE;
|
||||
} else if (!wp_module_loader_load (self->module_loader,
|
||||
self->plugin_registry, abi, module, error)) {
|
||||
plugin_registry, abi, module, error)) {
|
||||
return FALSE;
|
||||
}
|
||||
} else {
|
||||
@@ -195,6 +196,9 @@ wp_core_load_commands_file (WpCore * self)
|
||||
static void
|
||||
wp_core_init (WpCore * self)
|
||||
{
|
||||
WpPluginRegistryImpl *plugin_registry;
|
||||
WpProxyRegistryImpl *proxy_registry;
|
||||
|
||||
self->loop = g_main_loop_new (NULL, FALSE);
|
||||
self->source = wp_loop_source_new ();
|
||||
g_source_attach (self->source, NULL);
|
||||
@@ -206,8 +210,31 @@ wp_core_init (WpCore * self)
|
||||
self);
|
||||
|
||||
self->module_loader = wp_module_loader_new ();
|
||||
self->proxy_registry = wp_proxy_registry_new (self->remote);
|
||||
self->plugin_registry = wp_plugin_registry_new ();
|
||||
|
||||
proxy_registry = wp_proxy_registry_impl_new (self->remote);
|
||||
wp_object_attach_interface_impl (WP_OBJECT (self), proxy_registry, NULL);
|
||||
|
||||
plugin_registry = wp_plugin_registry_impl_new ();
|
||||
wp_object_attach_interface_impl (WP_OBJECT (self), plugin_registry, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
wp_core_dispose (GObject * obj)
|
||||
{
|
||||
WpCore *self = WP_CORE (obj);
|
||||
g_autoptr (WpPluginRegistry) plugin_registry = NULL;
|
||||
g_autoptr (WpProxyRegistry) proxy_registry = NULL;
|
||||
|
||||
/* ensure all proxies and plugins are unrefed,
|
||||
* so that the registries can be disposed */
|
||||
|
||||
plugin_registry = wp_object_get_interface (WP_OBJECT (self),
|
||||
WP_TYPE_PLUGIN_REGISTRY);
|
||||
wp_plugin_registry_impl_unload (WP_PLUGIN_REGISTRY_IMPL (plugin_registry));
|
||||
|
||||
proxy_registry = wp_object_get_interface (WP_OBJECT (self),
|
||||
WP_TYPE_PROXY_REGISTRY);
|
||||
wp_proxy_registry_impl_unload (WP_PROXY_REGISTRY_IMPL (proxy_registry));
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -215,13 +242,6 @@ wp_core_finalize (GObject * obj)
|
||||
{
|
||||
WpCore *self = WP_CORE (obj);
|
||||
|
||||
/* ensure all proxies and plugins are unrefed,
|
||||
* so that the registries can be disposed */
|
||||
g_object_run_dispose (G_OBJECT (self->plugin_registry));
|
||||
g_object_run_dispose (G_OBJECT (self->proxy_registry));
|
||||
|
||||
g_clear_object (&self->plugin_registry);
|
||||
g_clear_object (&self->proxy_registry);
|
||||
g_clear_object (&self->module_loader);
|
||||
|
||||
spa_hook_remove (&self->remote_listener);
|
||||
@@ -242,6 +262,7 @@ wp_core_class_init (WpCoreClass * klass)
|
||||
{
|
||||
GObjectClass * object_class = (GObjectClass *) klass;
|
||||
|
||||
object_class->dispose = wp_core_dispose;
|
||||
object_class->finalize = wp_core_finalize;
|
||||
}
|
||||
|
||||
|
@@ -9,11 +9,11 @@
|
||||
#ifndef __WIREPLUMBER_CORE_H__
|
||||
#define __WIREPLUMBER_CORE_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <wp/object.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
G_DECLARE_FINAL_TYPE (WpCore, wp_core, WP, CORE, GObject);
|
||||
G_DECLARE_FINAL_TYPE (WpCore, wp_core, WP, CORE, WpObject);
|
||||
|
||||
WpCore * wp_core_get_instance (void);
|
||||
void wp_core_run (WpCore * self, GError ** error);
|
||||
|
@@ -3,6 +3,8 @@ wp_sources = [
|
||||
'loop-source.c',
|
||||
'main.c',
|
||||
'module-loader.c',
|
||||
'plugin-registry-impl.c',
|
||||
'proxy-registry-impl.c',
|
||||
'utils.c',
|
||||
]
|
||||
|
||||
|
@@ -10,6 +10,7 @@
|
||||
#include "utils.h"
|
||||
|
||||
#include <wp/plugin.h>
|
||||
#include <gmodule.h>
|
||||
|
||||
struct _WpModuleLoader
|
||||
{
|
||||
|
@@ -10,7 +10,7 @@
|
||||
#define __WIREPLUMBER_MODULE_LOADER_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <wp/plugin-registry.h>
|
||||
#include <wp/core-interfaces.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
163
src/plugin-registry-impl.c
Normal file
163
src/plugin-registry-impl.c
Normal file
@@ -0,0 +1,163 @@
|
||||
/* WirePlumber
|
||||
*
|
||||
* Copyright © 2019 Collabora Ltd.
|
||||
* @author George Kiagiadakis <george.kiagiadakis@collabora.com>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#include "plugin-registry-impl.h"
|
||||
#include <wp/plugin.h>
|
||||
|
||||
typedef struct {
|
||||
gsize block_size;
|
||||
GType gtype;
|
||||
const WpPluginMetadata *metadata;
|
||||
WpPlugin *instance;
|
||||
} PluginData;
|
||||
|
||||
struct _WpPluginRegistryImpl
|
||||
{
|
||||
WpInterfaceImpl parent;
|
||||
|
||||
GList *plugins;
|
||||
GStringChunk *metadata_strings;
|
||||
};
|
||||
|
||||
static void wp_plugin_registry_impl_iface_init (WpPluginRegistryInterface * iface);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (WpPluginRegistryImpl, wp_plugin_registry_impl, WP_TYPE_INTERFACE_IMPL,
|
||||
G_IMPLEMENT_INTERFACE (WP_TYPE_PLUGIN_REGISTRY, wp_plugin_registry_impl_iface_init);)
|
||||
|
||||
static void
|
||||
wp_plugin_registry_impl_init (WpPluginRegistryImpl * self)
|
||||
{
|
||||
self->metadata_strings = g_string_chunk_new (200);
|
||||
}
|
||||
|
||||
static void
|
||||
plugin_data_free (PluginData *data)
|
||||
{
|
||||
g_slice_free1 (data->block_size, data);
|
||||
}
|
||||
|
||||
static void
|
||||
wp_plugin_registry_impl_finalize (GObject * object)
|
||||
{
|
||||
WpPluginRegistryImpl *self = WP_PLUGIN_REGISTRY_IMPL (object);
|
||||
|
||||
g_list_free_full (self->plugins, (GDestroyNotify) plugin_data_free);
|
||||
g_string_chunk_free (self->metadata_strings);
|
||||
|
||||
G_OBJECT_CLASS (wp_plugin_registry_impl_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
wp_plugin_registry_impl_class_init (WpPluginRegistryImplClass * klass)
|
||||
{
|
||||
GObjectClass *object_class = (GObjectClass *) klass;
|
||||
object_class->finalize = wp_plugin_registry_impl_finalize;
|
||||
}
|
||||
|
||||
static gint
|
||||
compare_ranks (const WpPluginMetadata * a, const WpPluginMetadata * b)
|
||||
{
|
||||
return (gint) b->rank - (gint) a->rank;
|
||||
}
|
||||
|
||||
static void
|
||||
wp_plugin_registry_impl_register_plugin (WpPluginRegistry * r,
|
||||
GType plugin_type,
|
||||
const WpPluginMetadata * metadata,
|
||||
gsize metadata_size,
|
||||
gboolean static_data)
|
||||
{
|
||||
WpPluginRegistryImpl *self = WP_PLUGIN_REGISTRY_IMPL (r);
|
||||
PluginData *data;
|
||||
|
||||
g_return_if_fail (metadata_size == sizeof (WpPluginMetadata));
|
||||
|
||||
if (static_data) {
|
||||
data = g_slice_alloc (sizeof (PluginData));
|
||||
data->block_size = sizeof (PluginData);
|
||||
} else {
|
||||
data = g_slice_alloc (sizeof (PluginData) + sizeof (WpPluginMetadata));
|
||||
data->block_size = sizeof (PluginData) + sizeof (WpPluginMetadata);
|
||||
}
|
||||
|
||||
data->gtype = plugin_type;
|
||||
data->instance = NULL;
|
||||
|
||||
if (!static_data) {
|
||||
WpPluginMetadata *m;
|
||||
m = (WpPluginMetadata *) ((guint8 *) data) + sizeof (PluginData);
|
||||
m->rank = metadata->rank;
|
||||
m->name = g_string_chunk_insert (self->metadata_strings, metadata->name);
|
||||
m->description = g_string_chunk_insert (self->metadata_strings,
|
||||
metadata->description);
|
||||
m->author = g_string_chunk_insert (self->metadata_strings,
|
||||
metadata->author);
|
||||
m->license = g_string_chunk_insert (self->metadata_strings,
|
||||
metadata->license);
|
||||
m->version = g_string_chunk_insert (self->metadata_strings,
|
||||
metadata->version);
|
||||
m->origin = g_string_chunk_insert (self->metadata_strings,
|
||||
metadata->origin);
|
||||
data->metadata = m;
|
||||
} else {
|
||||
data->metadata = metadata;
|
||||
}
|
||||
|
||||
self->plugins = g_list_insert_sorted (self->plugins, data,
|
||||
(GCompareFunc) compare_ranks);
|
||||
}
|
||||
|
||||
static void
|
||||
wp_plugin_registry_impl_iface_init (WpPluginRegistryInterface * iface)
|
||||
{
|
||||
iface->register_plugin = wp_plugin_registry_impl_register_plugin;
|
||||
}
|
||||
|
||||
WpPluginRegistryImpl *
|
||||
wp_plugin_registry_impl_new (void)
|
||||
{
|
||||
return g_object_new (wp_plugin_registry_impl_get_type (), NULL);
|
||||
}
|
||||
|
||||
void
|
||||
wp_plugin_registry_impl_unload (WpPluginRegistryImpl * self)
|
||||
{
|
||||
GList *list;
|
||||
PluginData *plugin_data;
|
||||
|
||||
for (list = self->plugins; list != NULL; list = g_list_next (list)) {
|
||||
plugin_data = list->data;
|
||||
g_clear_object (&plugin_data->instance);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
make_plugin (WpPluginRegistryImpl * self, PluginData * plugin_data)
|
||||
{
|
||||
plugin_data->instance = g_object_new (plugin_data->gtype,
|
||||
"registry", self, "metadata", plugin_data->metadata, NULL);
|
||||
}
|
||||
|
||||
gboolean
|
||||
wp_plugin_registry_impl_invoke_internal (WpPluginRegistryImpl * self,
|
||||
WpPluginFunc func, gpointer data)
|
||||
{
|
||||
GList *list;
|
||||
PluginData *plugin_data;
|
||||
|
||||
for (list = self->plugins; list != NULL; list = g_list_next (list)) {
|
||||
plugin_data = list->data;
|
||||
if (!plugin_data->instance)
|
||||
make_plugin (self, plugin_data);
|
||||
|
||||
if (func (plugin_data->instance, data))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
39
src/plugin-registry-impl.h
Normal file
39
src/plugin-registry-impl.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/* WirePlumber
|
||||
*
|
||||
* Copyright © 2019 Collabora Ltd.
|
||||
* @author George Kiagiadakis <george.kiagiadakis@collabora.com>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#ifndef __WP_PLUGIN_REGISTRY_IMPL_H__
|
||||
#define __WP_PLUGIN_REGISTRY_IMPL_H__
|
||||
|
||||
#include <wp/core-interfaces.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
G_DECLARE_FINAL_TYPE (WpPluginRegistryImpl, wp_plugin_registry_impl,
|
||||
WP, PLUGIN_REGISTRY_IMPL, WpInterfaceImpl)
|
||||
|
||||
WpPluginRegistryImpl * wp_plugin_registry_impl_new (void);
|
||||
|
||||
void wp_plugin_registry_impl_unload (WpPluginRegistryImpl * self);
|
||||
|
||||
typedef gboolean (*WpPluginFunc) (gpointer plugin, gpointer data);
|
||||
gboolean wp_plugin_registry_impl_invoke_internal (WpPluginRegistryImpl * self,
|
||||
WpPluginFunc func, gpointer data);
|
||||
|
||||
#define wp_plugin_registry_impl_invoke(r, func, data) \
|
||||
G_STMT_START { \
|
||||
if (!(0 ? func ((WpPlugin *) NULL, data) : \
|
||||
wp_plugin_registry_impl_invoke_internal ( \
|
||||
WP_PLUGIN_REGISTRY_IMPL (r), (WpPluginFunc) func, \
|
||||
(gpointer) data))) { \
|
||||
g_warning ("No plugin handled invocation to " ##func); \
|
||||
} \
|
||||
} G_STMT_END
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif
|
@@ -6,14 +6,16 @@
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#include "proxy-registry.h"
|
||||
#include "proxy.h"
|
||||
#include "proxy-registry-impl.h"
|
||||
|
||||
#include <wp/proxy.h>
|
||||
|
||||
#include <pipewire/pipewire.h>
|
||||
#include <pipewire/map.h>
|
||||
|
||||
struct _WpProxyRegistry
|
||||
struct _WpProxyRegistryImpl
|
||||
{
|
||||
GObject parent;
|
||||
WpInterfaceImpl parent;
|
||||
|
||||
struct pw_remote *remote;
|
||||
struct spa_hook remote_listener;
|
||||
@@ -37,7 +39,10 @@ enum {
|
||||
|
||||
static guint signals[N_SIGNALS];
|
||||
|
||||
G_DEFINE_TYPE (WpProxyRegistry, wp_proxy_registry, G_TYPE_OBJECT);
|
||||
static void wp_proxy_registry_impl_iface_init (WpProxyRegistryInterface * iface);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (WpProxyRegistryImpl, wp_proxy_registry_impl, WP_TYPE_INTERFACE_IMPL,
|
||||
G_IMPLEMENT_INTERFACE (WP_TYPE_PROXY_REGISTRY, wp_proxy_registry_impl_iface_init);)
|
||||
|
||||
static gint
|
||||
guint32_compare (const guint32 *a, const guint32 *b)
|
||||
@@ -48,7 +53,7 @@ guint32_compare (const guint32 *a, const guint32 *b)
|
||||
static gboolean
|
||||
idle_notify_new_globals (gpointer data)
|
||||
{
|
||||
WpProxyRegistry *self = WP_PROXY_REGISTRY (data);
|
||||
WpProxyRegistryImpl *self = WP_PROXY_REGISTRY_IMPL (data);
|
||||
guint i;
|
||||
guint32 id;
|
||||
|
||||
@@ -58,7 +63,7 @@ idle_notify_new_globals (gpointer data)
|
||||
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));
|
||||
pw_map_lookup (&self->globals, id));
|
||||
}
|
||||
g_array_remove_range (self->new_globals, 0, self->new_globals->len);
|
||||
|
||||
@@ -79,8 +84,8 @@ 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 (),
|
||||
WpProxyRegistryImpl *self = WP_PROXY_REGISTRY_IMPL (data);
|
||||
WpProxy *proxy = g_object_new (WP_TYPE_PROXY,
|
||||
"id", id,
|
||||
"parent-id", parent_id,
|
||||
"spa-type", type,
|
||||
@@ -101,7 +106,7 @@ registry_global (void * data, uint32_t id, uint32_t parent_id,
|
||||
static void
|
||||
registry_global_remove (void * data, uint32_t id)
|
||||
{
|
||||
WpProxyRegistry *self = WP_PROXY_REGISTRY (data);
|
||||
WpProxyRegistryImpl *self = WP_PROXY_REGISTRY_IMPL (data);
|
||||
GObject *p = pw_map_lookup (&self->globals, id);
|
||||
g_object_unref (p);
|
||||
pw_map_insert_at (&self->globals, id, NULL);
|
||||
@@ -117,7 +122,7 @@ 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);
|
||||
WpProxyRegistryImpl *self = WP_PROXY_REGISTRY_IMPL (data);
|
||||
|
||||
switch (new_state) {
|
||||
case PW_REMOTE_STATE_CONNECTED:
|
||||
@@ -143,39 +148,39 @@ static const struct pw_remote_events remote_events = {
|
||||
};
|
||||
|
||||
static void
|
||||
wp_proxy_registry_init (WpProxyRegistry * self)
|
||||
wp_proxy_registry_impl_init (WpProxyRegistryImpl * 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)
|
||||
wp_proxy_registry_impl_constructed (GObject * obj)
|
||||
{
|
||||
WpProxyRegistry *self = WP_PROXY_REGISTRY (obj);
|
||||
WpProxyRegistryImpl *self = WP_PROXY_REGISTRY_IMPL (obj);
|
||||
|
||||
pw_remote_add_listener (self->remote, &self->remote_listener, &remote_events,
|
||||
self);
|
||||
|
||||
G_OBJECT_CLASS (wp_proxy_registry_parent_class)->constructed (obj);
|
||||
G_OBJECT_CLASS (wp_proxy_registry_impl_parent_class)->constructed (obj);
|
||||
}
|
||||
|
||||
static void
|
||||
wp_proxy_registry_finalize (GObject * obj)
|
||||
wp_proxy_registry_impl_finalize (GObject * obj)
|
||||
{
|
||||
WpProxyRegistry *self = WP_PROXY_REGISTRY (obj);
|
||||
WpProxyRegistryImpl *self = WP_PROXY_REGISTRY_IMPL (obj);
|
||||
|
||||
pw_map_clear (&self->globals);
|
||||
g_array_unref (self->new_globals);
|
||||
|
||||
G_OBJECT_CLASS (wp_proxy_registry_parent_class)->finalize (obj);
|
||||
G_OBJECT_CLASS (wp_proxy_registry_impl_parent_class)->finalize (obj);
|
||||
}
|
||||
|
||||
static void
|
||||
wp_proxy_registry_set_property (GObject * object, guint property_id,
|
||||
wp_proxy_registry_impl_set_property (GObject * object, guint property_id,
|
||||
const GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
WpProxyRegistry *self = WP_PROXY_REGISTRY (object);
|
||||
WpProxyRegistryImpl *self = WP_PROXY_REGISTRY_IMPL (object);
|
||||
|
||||
switch (property_id) {
|
||||
case PROP_REMOTE:
|
||||
@@ -188,10 +193,10 @@ wp_proxy_registry_set_property (GObject * object, guint property_id,
|
||||
}
|
||||
|
||||
static void
|
||||
wp_proxy_registry_get_property (GObject * object, guint property_id,
|
||||
wp_proxy_registry_impl_get_property (GObject * object, guint property_id,
|
||||
GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
WpProxyRegistry *self = WP_PROXY_REGISTRY (object);
|
||||
WpProxyRegistryImpl *self = WP_PROXY_REGISTRY_IMPL (object);
|
||||
|
||||
switch (property_id) {
|
||||
case PROP_REMOTE:
|
||||
@@ -204,14 +209,14 @@ wp_proxy_registry_get_property (GObject * object, guint property_id,
|
||||
}
|
||||
|
||||
static void
|
||||
wp_proxy_registry_class_init (WpProxyRegistryClass * klass)
|
||||
wp_proxy_registry_impl_class_init (WpProxyRegistryImplClass * 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;
|
||||
object_class->constructed = wp_proxy_registry_impl_constructed;
|
||||
object_class->finalize = wp_proxy_registry_impl_finalize;
|
||||
object_class->get_property = wp_proxy_registry_impl_get_property;
|
||||
object_class->set_property = wp_proxy_registry_impl_set_property;
|
||||
|
||||
g_object_class_install_property (object_class, PROP_REMOTE,
|
||||
g_param_spec_pointer ("remote", "remote",
|
||||
@@ -220,64 +225,45 @@ wp_proxy_registry_class_init (WpProxyRegistryClass * klass)
|
||||
|
||||
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 ());
|
||||
G_TYPE_NONE, 1, WP_TYPE_PROXY);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
static WpProxy *
|
||||
wp_proxy_registry_impl_get_proxy (WpProxyRegistry * r, guint32 global_id)
|
||||
{
|
||||
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);
|
||||
WpProxyRegistryImpl *self = WP_PROXY_REGISTRY_IMPL (r);
|
||||
WpProxy *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)
|
||||
static struct pw_registry_proxy *
|
||||
wp_proxy_registry_impl_get_pw_registry_proxy (WpProxyRegistry * r)
|
||||
{
|
||||
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);
|
||||
WpProxyRegistryImpl *self = WP_PROXY_REGISTRY_IMPL (r);
|
||||
return self->reg_proxy;
|
||||
}
|
||||
|
||||
static void
|
||||
wp_proxy_registry_impl_iface_init (WpProxyRegistryInterface * iface)
|
||||
{
|
||||
iface->get_proxy = wp_proxy_registry_impl_get_proxy;
|
||||
iface->get_pw_registry_proxy = wp_proxy_registry_impl_get_pw_registry_proxy;
|
||||
}
|
||||
|
||||
WpProxyRegistryImpl *
|
||||
wp_proxy_registry_impl_new (struct pw_remote * remote)
|
||||
{
|
||||
return g_object_new (wp_proxy_registry_impl_get_type (), "remote", remote,
|
||||
NULL);
|
||||
}
|
||||
|
||||
void
|
||||
wp_proxy_registry_impl_unload (WpProxyRegistryImpl * self)
|
||||
{
|
||||
size_t i, size = pw_map_get_size (&self->globals);
|
||||
for (i = 0; i < size; i++) {
|
||||
g_clear_object (&pw_map_get_item (&self->globals, i)->data);
|
||||
}
|
||||
}
|
27
src/proxy-registry-impl.h
Normal file
27
src/proxy-registry-impl.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/* WirePlumber
|
||||
*
|
||||
* Copyright © 2019 Collabora Ltd.
|
||||
* @author George Kiagiadakis <george.kiagiadakis@collabora.com>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#ifndef __WP_PROXY_REGISTRY_IMPL_H__
|
||||
#define __WP_PROXY_REGISTRY_IMPL_H__
|
||||
|
||||
#include <wp/core-interfaces.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
struct pw_remote;
|
||||
|
||||
G_DECLARE_FINAL_TYPE (WpProxyRegistryImpl, wp_proxy_registry_impl,
|
||||
WP, PROXY_REGISTRY_IMPL, WpInterfaceImpl)
|
||||
|
||||
WpProxyRegistryImpl * wp_proxy_registry_impl_new (struct pw_remote * remote);
|
||||
|
||||
void wp_proxy_registry_impl_unload (WpProxyRegistryImpl * self);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user