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:
George Kiagiadakis
2019-04-17 19:09:39 +03:00
parent 87d60a80aa
commit ce43cf5f0c
21 changed files with 588 additions and 436 deletions

149
lib/wp/core-interfaces.c Normal file
View 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
View 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

View File

@@ -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;

View File

@@ -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);

View File

@@ -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',
]

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -3,6 +3,8 @@ wp_sources = [
'loop-source.c',
'main.c',
'module-loader.c',
'plugin-registry-impl.c',
'proxy-registry-impl.c',
'utils.c',
]

View File

@@ -10,6 +10,7 @@
#include "utils.h"
#include <wp/plugin.h>
#include <gmodule.h>
struct _WpModuleLoader
{

View File

@@ -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
View 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;
}

View 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

View File

@@ -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
View 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