Skip to content
Snippets Groups Projects
Commit 9d4731d0 authored by George Kiagiadakis's avatar George Kiagiadakis
Browse files

lib: begin working on a library to allow implementing policy plugins

parent 43c44fb7
No related branches found
No related tags found
No related merge requests found
subdir('wp')
/* WirePlumber
*
* Copyright © 2019 Collabora Ltd.
* @author George Kiagiadakis <george.kiagiadakis@collabora.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "error.h"
G_DEFINE_QUARK (wireplumber-library, wp_domain_library);
/* WirePlumber
*
* Copyright © 2019 Collabora Ltd.
* @author George Kiagiadakis <george.kiagiadakis@collabora.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __WP_ERROR_H__
#define __WP_ERROR_H__
#include <glib.h>
G_BEGIN_DECLS
GQuark wp_domain_library_quark (void);
#define WP_DOMAIN_LIBRARY (wp_domain_library_quark ())
typedef enum {
WP_LIBRARY_ERROR_INVARIANT,
} WpLibraryErrorEnum;
G_END_DECLS
#endif
/* WirePlumber
*
* Copyright © 2019 Collabora Ltd.
* @author George Kiagiadakis <george.kiagiadakis@collabora.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "interface-impl.h"
#include "object.h"
typedef struct {
GObject *object;
} WpInterfaceImplPrivate;
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (WpInterfaceImpl, wp_interface_impl, G_TYPE_OBJECT);
static void
wp_interface_impl_init (WpInterfaceImpl * self)
{
}
static void
wp_interface_impl_finalize (GObject * obj)
{
WpInterfaceImpl *self = WP_INTERFACE_IMPL (obj);
WpInterfaceImplPrivate *priv = wp_interface_impl_get_instance_private (self);
g_clear_weak_pointer (&priv->object);
G_OBJECT_CLASS (wp_interface_impl_parent_class)->finalize (obj);
}
static void
wp_interface_impl_class_init (WpInterfaceImplClass * klass)
{
GObjectClass *object_class = (GObjectClass *) klass;
object_class->finalize = wp_interface_impl_finalize;
}
/**
* wp_interface_impl_set_object: (skip)
* @self: the interface implementation instance
* @object: (nullable) (transfer none): the implementor
*/
void
wp_interface_impl_set_object (WpInterfaceImpl * self, GObject * object)
{
WpInterfaceImplPrivate *priv = wp_interface_impl_get_instance_private (self);
g_return_if_fail (WP_IS_INTERFACE_IMPL (self));
g_return_if_fail (WP_IS_OBJECT (object));
g_set_weak_pointer (&priv->object, object);
}
/**
* wp_interface_impl_get_object: (method)
* @self: the interface implementation instance
*
* Returns: (nullable) (transfer none): the object implementing this interface
*/
GObject *
wp_interface_impl_get_object (WpInterfaceImpl * self)
{
WpInterfaceImplPrivate *priv = wp_interface_impl_get_instance_private (self);
g_return_val_if_fail (WP_IS_INTERFACE_IMPL (self), NULL);
return priv->object;
}
/**
* wp_interface_impl_get_sibling: (method)
* @self: the interface implementation instance
* @interface: an interface type
*
* Returns: (nullable) (transfer full): the object implementing @interface
*/
GObject *
wp_interface_impl_get_sibling (WpInterfaceImpl * self, GType interface)
{
WpInterfaceImplPrivate *priv = wp_interface_impl_get_instance_private (self);
GObject *iface = NULL;
g_return_val_if_fail (WP_IS_INTERFACE_IMPL (self), NULL);
g_return_val_if_fail (G_TYPE_IS_INTERFACE (interface), NULL);
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);
}
return iface;
}
/**
* wp_interface_impl_get_prerequisites: (virtual get_prerequisites)
* @self: the interface implementation instance
* @n_prerequisites: (out): the number of elements in the returned array
*
* Returns: (array length=n_prerequisites) (transfer none): the types that are
* required by this interface implementation
*/
GType *
wp_interface_impl_get_prerequisites (WpInterfaceImpl * self,
guint * n_prerequisites)
{
WpInterfaceImplClass * klass = WP_INTERFACE_IMPL_GET_CLASS (self);
g_return_val_if_fail (WP_IS_INTERFACE_IMPL (self), NULL);
g_return_val_if_fail (n_prerequisites != NULL, NULL);
if (klass->get_prerequisites)
return klass->get_prerequisites (self, n_prerequisites);
*n_prerequisites = 0;
return NULL;
}
/* WirePlumber
*
* Copyright © 2019 Collabora Ltd.
* @author George Kiagiadakis <george.kiagiadakis@collabora.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __WP_INTERFACE_IMPL_H__
#define __WP_INTERFACE_IMPL_H__
#include <glib-object.h>
G_BEGIN_DECLS
G_DECLARE_DERIVABLE_TYPE (WpInterfaceImpl, wp_interface_impl, WP, INTERFACE_IMPL, GObject)
struct _WpInterfaceImplClass
{
GObjectClass parent_class;
/**
* get_prerequisites:
* @self: the interface implementation instance
* @n_prerequisites: (out): the number of elements in the returned array
*
* Returns: (array length=n_prerequisites) (transfer none): the types that are
* required by this interface implementation
*/
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,
GType interface);
GType * wp_interface_impl_get_prerequisites (WpInterfaceImpl * self,
guint * n_prerequisites);
G_END_DECLS
#endif
wp_lib_sources = [
'error.c',
'interface-impl.c',
'object.c',
]
wp_lib_headers = [
'error.h',
'interface-impl.h',
'object.h',
]
enums = gnome.mkenums_simple('wpenums', sources: wp_lib_headers)
wp_lib = library('wireplumber-' + wireplumber_api_version,
wp_lib_sources, enums,
c_args : [ '-D_GNU_SOURCE', '-DG_LOG_USE_STRUCTURED' ],
install: true,
dependencies : [gobject_dep, pipewire_dep],
)
gnome.generate_gir(wp_lib,
namespace: 'Wp',
nsversion: wireplumber_api_version,
sources: [wp_lib_sources, wp_lib_headers],
includes: ['GLib-2.0', 'GObject-2.0'],
install: true,
)
/* WirePlumber
*
* Copyright © 2019 Collabora Ltd.
* @author George Kiagiadakis <george.kiagiadakis@collabora.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "object.h"
#include "error.h"
typedef struct {
GArray *iface_objects;
GArray *iface_types;
} WpObjectPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (WpObject, wp_object, G_TYPE_OBJECT);
static void
wp_object_init (WpObject * self)
{
WpObjectPrivate *priv = wp_object_get_instance_private (self);
priv->iface_objects = g_array_new (FALSE, FALSE, sizeof (gpointer));
priv->iface_types = g_array_new (FALSE, FALSE, sizeof (GType));
}
static void
wp_object_finalize (GObject * obj)
{
WpObject *self = WP_OBJECT (obj);
WpObjectPrivate *priv = wp_object_get_instance_private (self);
guint i;
for (i = 0; i < priv->iface_objects->len; i++) {
GObject *obj = g_array_index (priv->iface_objects, GObject*, i);
wp_interface_impl_set_object (WP_INTERFACE_IMPL (obj), NULL);
g_object_unref (obj);
}
g_array_free (priv->iface_objects, TRUE);
g_array_free (priv->iface_types, TRUE);
G_OBJECT_CLASS (wp_object_parent_class)->finalize (obj);
}
static void
wp_object_class_init (WpObjectClass * klass)
{
GObjectClass *object_class = (GObjectClass *) klass;
object_class->finalize = wp_object_finalize;
}
/**
* wp_object_implements_interface: (method)
* @self: the object
* @interface: an interface type
*
* Returns: whether the interface is implemented in this object or not
*/
gboolean
wp_object_implements_interface (WpObject * self, GType interface)
{
WpObjectPrivate *priv = wp_object_get_instance_private (self);
guint i;
g_return_val_if_fail (WP_IS_OBJECT (self), FALSE);
for (i = 0; i < priv->iface_types->len; i++) {
GType t = g_array_index (priv->iface_types, GType, i);
if (t == interface)
return TRUE;
}
return FALSE;
}
/**
* wp_object_get_interface: (method)
* @self: the object
* @interface: an interface type
*
* Returns: (nullable) (transfer full): the object implementing @interface
*/
GObject *
wp_object_get_interface (WpObject * self, GType interface)
{
WpObjectPrivate *priv = wp_object_get_instance_private (self);
guint i;
g_return_val_if_fail (WP_IS_OBJECT (self), FALSE);
for (i = 0; i < priv->iface_objects->len; i++) {
GObject *obj = g_array_index (priv->iface_objects, GObject*, i);
if (g_type_is_a (G_TYPE_FROM_INSTANCE (obj), interface))
return g_object_ref (obj);
}
return NULL;
}
/**
* wp_object_list_interfaces: (method)
* @self: the object
* @n_interfaces: (out): the number of elements in the returned array
*
* Returns: (array length=n_interfaces) (transfer none): the interface types
* that are implemented in this object
*/
GType *
wp_object_list_interfaces (WpObject * self, guint * n_interfaces)
{
WpObjectPrivate *priv = wp_object_get_instance_private (self);
g_return_val_if_fail (WP_IS_OBJECT (self), NULL);
*n_interfaces = priv->iface_types->len;
return (GType *) priv->iface_types->data;
}
/**
* wp_object_attach_interface_impl: (method)
* @self: the object
* @impl: (transfer none): the interface implementation
* @error: (out caller-allocates): a GError to return on failure
*
* Returns: TRUE one success, FALSE on error
*/
gboolean
wp_object_attach_interface_impl (WpObject * self, WpInterfaceImpl * impl,
GError ** error)
{
WpObjectPrivate *priv = wp_object_get_instance_private (self);
GType *new_ifaces;
GType *prerequisites;
guint n_new_ifaces;
guint n_prerequisites, n_satisfied = 0;
guint i, j;
g_return_val_if_fail (WP_IS_OBJECT (self), FALSE);
g_return_val_if_fail (WP_IS_INTERFACE_IMPL (impl), FALSE);
new_ifaces = g_type_interfaces (G_TYPE_FROM_INSTANCE (impl),
&n_new_ifaces);
prerequisites = wp_interface_impl_get_prerequisites (impl, &n_prerequisites);
for (i = 0; i < priv->iface_types->len; i++) {
GType t = g_array_index (priv->iface_types, GType, i);
for (j = 0; j < n_prerequisites; j++) {
if (prerequisites[j] == t)
n_satisfied++;
}
for (j = 0; j < n_new_ifaces; j++) {
if (new_ifaces[j] == t) {
g_set_error (error, WP_DOMAIN_LIBRARY, WP_LIBRARY_ERROR_INVARIANT,
"Interface %s is already provided on object %p",
g_type_name (t), self);
return FALSE;
}
}
}
if (n_satisfied != n_prerequisites) {
g_set_error (error, WP_DOMAIN_LIBRARY, WP_LIBRARY_ERROR_INVARIANT,
"Interface implementation %p has unsatisfied requirements", impl);
return FALSE;
}
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));
return TRUE;
}
/* WirePlumber
*
* Copyright © 2019 Collabora Ltd.
* @author George Kiagiadakis <george.kiagiadakis@collabora.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __WP_OBJECT_H__
#define __WP_OBJECT_H__
#include "interface-impl.h"
G_BEGIN_DECLS
G_DECLARE_DERIVABLE_TYPE (WpObject, wp_object, WP, OBJECT, GObject)
struct _WpObjectClass
{
GObjectClass parent_class;
};
gboolean wp_object_implements_interface (WpObject * self, GType interface);
GObject * 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);
G_END_DECLS
#endif
......@@ -8,7 +8,12 @@ project('wireplumber', ['c'],
]
)
glib_dep = dependency('gobject-2.0')
wireplumber_api_version = '0.1'
gobject_dep = dependency('gobject-2.0')
pipewire_dep = dependency('libpipewire-0.3')
gnome = import('gnome')
subdir('lib')
subdir('src')
......@@ -9,5 +9,5 @@ executable('wireplumber',
wp_sources,
c_args : [ '-D_GNU_SOURCE', '-DG_LOG_USE_STRUCTURED' ],
install: true,
dependencies : [glib_dep, pipewire_dep],
dependencies : [gobject_dep, pipewire_dep],
)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment