diff --git a/lib/wp/meson.build b/lib/wp/meson.build index 9c88bd3fd4eba430cc9dc688e2029b25c26518f4..40d64b4d98ae9d648a227c6cd040badc26b50a33 100644 --- a/lib/wp/meson.build +++ b/lib/wp/meson.build @@ -15,6 +15,7 @@ wp_lib_sources = files( 'node.c', 'object-interest.c', 'object-manager.c', + 'plugin.c', 'port.c', 'properties.c', 'proxy.c', @@ -48,6 +49,7 @@ wp_lib_headers = files( 'node.h', 'object-interest.h', 'object-manager.h', + 'plugin.h', 'port.h', 'properties.h', 'proxy.h', diff --git a/lib/wp/module.c b/lib/wp/module.c index f6036ef3fa2856b8715e53cfd35195ac404f2110..05f4746a0ad3784ecf628ebaee3ac3a71f1a939c 100644 --- a/lib/wp/module.c +++ b/lib/wp/module.c @@ -191,6 +191,7 @@ wp_module_load (WpCore * core, const gchar * abi, const gchar * module_name, GVariant * wp_module_get_properties (WpModule * self) { + g_return_val_if_fail (WP_IS_MODULE (self), NULL); return self->properties; } @@ -203,6 +204,7 @@ wp_module_get_properties (WpModule * self) WpCore * wp_module_get_core (WpModule * self) { + g_return_val_if_fail (WP_IS_MODULE (self), NULL); return g_weak_ref_get (&self->core); } diff --git a/lib/wp/plugin.c b/lib/wp/plugin.c new file mode 100644 index 0000000000000000000000000000000000000000..ddd6c77ddd0a3fb10b7e50107ff0e59ea916fdb8 --- /dev/null +++ b/lib/wp/plugin.c @@ -0,0 +1,200 @@ +/* WirePlumber + * + * Copyright © 2020 Collabora Ltd. + * @author George Kiagiadakis <george.kiagiadakis@collabora.com> + * + * SPDX-License-Identifier: MIT + */ + +/** + * SECTION: plugin + * @title: WirePlumber Daemon Plugins + */ + +#define G_LOG_DOMAIN "wp-plugin" + +#include "plugin.h" +#include "private.h" + +enum { + PROP_0, + PROP_MODULE, +}; + +typedef struct _WpPluginPrivate WpPluginPrivate; +struct _WpPluginPrivate +{ + GWeakRef module; +}; + +/** + * WpPlugin: + * + * #WpPlugin is a base class for objects that provide functionality to the + * WirePlumber daemon. + * + * Typically, a plugin is created within a module and then registered to + * make it available for use by the daemon. The daemon is responsible for + * calling #WpPluginClass.activate() after all modules have been loaded, + * the core is connected and the initial discovery of global objects is + * done. + */ +G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (WpPlugin, wp_plugin, G_TYPE_OBJECT) + +static void +wp_plugin_init (WpPlugin * self) +{ + WpPluginPrivate *priv = wp_plugin_get_instance_private (self); + g_weak_ref_init (&priv->module, NULL); +} + +static void +wp_plugin_dispose (GObject * object) +{ + WpPlugin *self = WP_PLUGIN (object); + + wp_plugin_deactivate (self); + + G_OBJECT_CLASS (wp_plugin_parent_class)->dispose (object); +} + +static void +wp_plugin_finalize (GObject * object) +{ + WpPlugin *self = WP_PLUGIN (object); + WpPluginPrivate *priv = wp_plugin_get_instance_private (self); + + g_weak_ref_clear (&priv->module); + + G_OBJECT_CLASS (wp_plugin_parent_class)->finalize (object); +} + +static void +wp_plugin_set_property (GObject * object, guint property_id, + const GValue * value, GParamSpec * pspec) +{ + WpPlugin *self = WP_PLUGIN (object); + WpPluginPrivate *priv = wp_plugin_get_instance_private (self); + + switch (property_id) { + case PROP_MODULE: + g_weak_ref_set (&priv->module, g_value_get_object (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +wp_plugin_get_property (GObject * object, guint property_id, + GValue * value, GParamSpec * pspec) +{ + WpPlugin *self = WP_PLUGIN (object); + WpPluginPrivate *priv = wp_plugin_get_instance_private (self); + + switch (property_id) { + case PROP_MODULE: + g_value_take_object (value, g_weak_ref_get (&priv->module)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +wp_plugin_class_init (WpPluginClass * klass) +{ + GObjectClass * object_class = (GObjectClass *) klass; + + object_class->dispose = wp_plugin_dispose; + object_class->finalize = wp_plugin_finalize; + object_class->set_property = wp_plugin_set_property; + object_class->get_property = wp_plugin_get_property; + + /** + * WpPlugin:module: + * The module that created this plugin. + * Implementations should initialize this in the constructor. + */ + g_object_class_install_property (object_class, PROP_MODULE, + g_param_spec_object ("module", "module", + "The module that owns this plugin", WP_TYPE_MODULE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); +} + +/** + * wp_plugin_register: + * @plugin: (transfer full): the plugin + * + * Registers the plugin to its associated core, making it available for use + */ +void +wp_plugin_register (WpPlugin * plugin) +{ + g_autoptr (WpCore) core = wp_plugin_get_core (plugin); + g_return_if_fail (WP_IS_CORE (core)); + + wp_registry_register_object (wp_core_get_registry (core), plugin); +} + +/** + * wp_plugin_get_module: + * @self: the plugin + * + * Returns: (transfer full): the module associated with this plugin + */ +WpModule * +wp_plugin_get_module (WpPlugin * self) +{ + g_return_val_if_fail (WP_IS_PLUGIN (self), NULL); + + WpPluginPrivate *priv = wp_plugin_get_instance_private (self); + return g_weak_ref_get (&priv->module); +} + +/** + * wp_plugin_get_core: + * @self: the plugin + * + * Returns: (transfer full): the core associated with this plugin + */ +WpCore * +wp_plugin_get_core (WpPlugin * self) +{ + g_autoptr (WpModule) module = wp_plugin_get_module (self); + return module ? wp_module_get_core (module) : NULL; +} + +/** + * wp_plugin_activate: (virtual activate) + * @self: the plugin + * + * Activates the plugin. The plugin is required to start any operations only + * when this method is called and not before. + */ +void +wp_plugin_activate (WpPlugin * self) +{ + g_return_if_fail (WP_IS_PLUGIN (self)); + g_return_if_fail (WP_PLUGIN_GET_CLASS (self)->activate); + + WP_PLUGIN_GET_CLASS (self)->activate (self); +} + +/** + * wp_plugin_deactivate: (virtual deactivate) + * @self: the plugin + * + * Deactivates the plugin. The plugin is required to stop all operations and + * release all resources associated with it. + */ +void +wp_plugin_deactivate (WpPlugin * self) +{ + g_return_if_fail (WP_IS_PLUGIN (self)); + g_return_if_fail (WP_PLUGIN_GET_CLASS (self)->deactivate); + + WP_PLUGIN_GET_CLASS (self)->deactivate (self); +} diff --git a/lib/wp/plugin.h b/lib/wp/plugin.h new file mode 100644 index 0000000000000000000000000000000000000000..97180f10b16a79845fff3b921e4e53a0e7df2847 --- /dev/null +++ b/lib/wp/plugin.h @@ -0,0 +1,55 @@ +/* WirePlumber + * + * Copyright © 2020 Collabora Ltd. + * @author George Kiagiadakis <george.kiagiadakis@collabora.com> + * + * SPDX-License-Identifier: MIT + */ + +#ifndef __WIREPLUMBER_PLUGIN_H__ +#define __WIREPLUMBER_PLUGIN_H__ + +#include "module.h" + +G_BEGIN_DECLS + +/** + * WP_TYPE_PLUGIN: + * + * The #WpPlugin #GType + */ +#define WP_TYPE_PLUGIN (wp_plugin_get_type ()) +WP_API +G_DECLARE_DERIVABLE_TYPE (WpPlugin, wp_plugin, WP, PLUGIN, GObject) + +/** + * WpPluginClass: + * @activate: See wp_plugin_activate() + * @deactivate: See wp_plugin_deactivate() + */ +struct _WpPluginClass +{ + GObjectClass parent_class; + + void (*activate) (WpPlugin * self); + void (*deactivate) (WpPlugin * self); +}; + +WP_API +void wp_plugin_register (WpPlugin * plugin); + +WP_API +WpModule * wp_plugin_get_module (WpPlugin * self); + +WP_API +WpCore * wp_plugin_get_core (WpPlugin * self); + +WP_API +void wp_plugin_activate (WpPlugin * self); + +WP_API +void wp_plugin_deactivate (WpPlugin * self); + +G_END_DECLS + +#endif diff --git a/lib/wp/wp.h b/lib/wp/wp.h index 50d9762d55ae59a7a6c54c68edefce303f1af4cc..df6af38bac0b467968f549005cd56bc2b4ee0a17 100644 --- a/lib/wp/wp.h +++ b/lib/wp/wp.h @@ -25,6 +25,7 @@ #include "node.h" #include "object-interest.h" #include "object-manager.h" +#include "plugin.h" #include "port.h" #include "properties.h" #include "proxy.h"