Commit 0d072874 authored by George Kiagiadakis's avatar George Kiagiadakis
Browse files

lib: introduce WpComponentLoader and remove WpModule

The component loader is a more generic and extensible mechanism
of loading components; modules are one type of component...
The idea is to make scripts and config files also be components,
loaded by plugins that inherit WpComponentLoader
parent f61e2929
/* WirePlumber
*
* Copyright © 2021 Collabora Ltd.
* @author George Kiagiadakis <george.kiagiadakis@collabora.com>
*
* SPDX-License-Identifier: MIT
*/
/**
* SECTION: component-loader
* @title: Components
*/
#define G_LOG_DOMAIN "wp-comp-loader"
#include "component-loader.h"
#include "error.h"
#include "private/registry.h"
#include <pipewire/impl.h>
#define WP_MODULE_INIT_SYMBOL "wireplumber__module_init"
typedef gboolean (*WpModuleInitFunc) (WpCore *, GVariant *, GError **);
G_DEFINE_ABSTRACT_TYPE (WpComponentLoader, wp_component_loader, WP_TYPE_PLUGIN)
static void
wp_component_loader_init (WpComponentLoader * self)
{
}
static void
wp_component_loader_class_init (WpComponentLoaderClass * klass)
{
}
static const gchar *
get_module_dir (void)
{
static const gchar *module_dir = NULL;
if (!module_dir) {
module_dir = g_getenv ("WIREPLUMBER_MODULE_DIR");
if (!module_dir)
module_dir = WIREPLUMBER_DEFAULT_MODULE_DIR;
}
return module_dir;
}
static gboolean
load_module (WpCore * core, const gchar * module_name,
GVariant * args, GError ** error)
{
g_autofree gchar *module_path = NULL;
GModule *gmodule;
gpointer module_init;
module_path = g_module_build_path (get_module_dir (), module_name);
gmodule = g_module_open (module_path, G_MODULE_BIND_LOCAL);
if (!gmodule) {
g_set_error (error, WP_DOMAIN_LIBRARY, WP_LIBRARY_ERROR_OPERATION_FAILED,
"Failed to open module %s: %s", module_path, g_module_error ());
return FALSE;
}
if (!g_module_symbol (gmodule, WP_MODULE_INIT_SYMBOL, &module_init)) {
g_set_error (error, WP_DOMAIN_LIBRARY, WP_LIBRARY_ERROR_OPERATION_FAILED,
"Failed to locate symbol " WP_MODULE_INIT_SYMBOL " in %s",
module_path);
g_module_close (gmodule);
return FALSE;
}
return ((WpModuleInitFunc) module_init) (core, args, error);
}
static gboolean
load_pw_module (WpCore * core, const gchar * module_name,
GVariant * args, GError ** error)
{
const gchar *args_str = NULL;
if (args) {
if (g_variant_is_of_type (args, G_VARIANT_TYPE_STRING))
args_str = g_variant_get_string (args, NULL);
//TODO if it proves to be useful
//else if (g_variant_is_of_type (args, G_VARIANT_TYPE_DICTIONARY))
}
struct pw_impl_module *module = pw_context_load_module (
wp_core_get_pw_context (core), module_name, args_str, NULL);
if (!module) {
int res = errno;
g_set_error (error, WP_DOMAIN_LIBRARY, WP_LIBRARY_ERROR_OPERATION_FAILED,
"Failed to load pipewire module: %s", g_strerror (res));
return FALSE;
}
return TRUE;
}
static gboolean
find_component_loader_func (gpointer cl, gpointer type)
{
if (WP_IS_COMPONENT_LOADER (cl) &&
(WP_COMPONENT_LOADER_GET_CLASS (cl)->supports_type (
WP_COMPONENT_LOADER (cl), (const gchar *) type)))
return TRUE;
return FALSE;
}
static WpComponentLoader *
wp_component_loader_find (WpCore * core, const gchar * type)
{
g_return_val_if_fail (WP_IS_CORE (core), NULL);
GObject *c = wp_registry_find_object (wp_core_get_registry (core),
(GEqualFunc) find_component_loader_func, type);
return c ? WP_COMPONENT_LOADER (c) : NULL;
}
static gboolean
wp_component_loader_load (WpComponentLoader * self, const gchar * component,
const gchar * type, GVariant * args, GError ** error)
{
g_return_val_if_fail (WP_IS_COMPONENT_LOADER (self), FALSE);
return WP_COMPONENT_LOADER_GET_CLASS (self)->load (self, component, type,
args, error);
}
/**
* wp_core_load_component:
* @self: the core
* @component: the module name or file name
* @type: the type of the component
* @args: (transfer floating)(nullable): additional arguments for the component,
* usually a dict or a string
* @error: (out) (optional): return location for errors, or NULL to ignore
*
* Returns: %TRUE if loaded, %FALSE if there was an error
*/
gboolean
wp_core_load_component (WpCore * self, const gchar * component,
const gchar * type, GVariant * args, GError ** error)
{
g_autoptr (GVariant) args_ref = args ? g_variant_ref_sink (args) : NULL;
if (!g_strcmp0 (type, "module"))
return load_module (self, component, args_ref, error);
else if (!g_strcmp0 (type, "pw_module"))
return load_pw_module (self, component, args_ref, error);
else {
g_autoptr (WpComponentLoader) c = wp_component_loader_find (self, type);
if (c)
return wp_component_loader_load (c, component, type, args, error);
else {
g_set_error (error, WP_DOMAIN_LIBRARY, WP_LIBRARY_ERROR_INVALID_ARGUMENT,
"No component loader was found for components of type '%s'", type);
return FALSE;
}
}
}
/* WirePlumber
*
* Copyright © 2021 Collabora Ltd.
* @author George Kiagiadakis <george.kiagiadakis@collabora.com>
*
* SPDX-License-Identifier: MIT
*/
#ifndef __WIREPLUMBER_COMPONENT_LOADER_H__
#define __WIREPLUMBER_COMPONENT_LOADER_H__
#include "plugin.h"
G_BEGIN_DECLS
/**
* WP_TYPE_COMPONENT_LOADER:
*
* The #WpComponentLoader #GType
*/
#define WP_TYPE_COMPONENT_LOADER (wp_component_loader_get_type ())
WP_API
G_DECLARE_DERIVABLE_TYPE (WpComponentLoader, wp_component_loader,
WP, COMPONENT_LOADER, WpPlugin)
struct _WpComponentLoaderClass
{
WpPluginClass parent_class;
gboolean (*supports_type) (WpComponentLoader * self, const gchar * type);
gboolean (*load) (WpComponentLoader * self, const gchar * component,
const gchar * type, GVariant * args, GError ** error);
};
G_END_DECLS
#endif
......@@ -40,6 +40,10 @@ struct pw_context * wp_core_get_pw_context (WpCore * self);
WP_API
struct pw_core * wp_core_get_pw_core (WpCore * self);
WP_API
gboolean wp_core_load_component (WpCore * self, const gchar * component,
const gchar * type, GVariant * args, GError ** error);
/* Connection */
WP_API
......
wp_lib_sources = files(
'private/pipewire-object-mixin.c',
'client.c',
'component-loader.c',
'configuration.c',
'core.c',
'debug.c',
......@@ -13,7 +14,6 @@ wp_lib_sources = files(
'iterator.c',
'link.c',
'metadata.c',
'module.c',
'node.c',
'object.c',
'object-interest.c',
......@@ -37,6 +37,7 @@ wp_lib_sources = files(
wp_lib_headers = files(
'client.h',
'component-loader.h',
'configuration.h',
'core.h',
'debug.h',
......@@ -50,7 +51,6 @@ wp_lib_headers = files(
'iterator.h',
'link.h',
'metadata.h',
'module.h',
'node.h',
'object.h',
'object-interest.h',
......
......@@ -10,6 +10,7 @@
#define __WIREPLUMBER_WP_H__
#include "client.h"
#include "component-loader.h"
#include "configuration.h"
#include "core.h"
#include "debug.h"
......
......@@ -74,11 +74,12 @@ wp_client_permissions_class_init (WpClientPermissionsClass * klass)
plugin_class->disable = wp_client_permissions_disable;
}
WP_PLUGIN_EXPORT void
wireplumber__module_init (WpModule * module, WpCore * core, GVariant * args)
WP_PLUGIN_EXPORT gboolean
wireplumber__module_init (WpCore * core, GVariant * args, GError ** error)
{
wp_plugin_register (g_object_new (wp_client_permissions_get_type (),
"name", "client-permissions",
"core", core,
NULL));
return TRUE;
}
......@@ -402,11 +402,12 @@ wp_default_metadata_class_init (WpDefaultMetadataClass * klass)
plugin_class->disable = wp_default_metadata_disable;
}
WP_PLUGIN_EXPORT void
wireplumber__module_init (WpModule * module, WpCore * core, GVariant * args)
WP_PLUGIN_EXPORT gboolean
wireplumber__module_init (WpCore * core, GVariant * args, GError ** error)
{
wp_plugin_register (g_object_new (wp_default_metadata_get_type (),
"name", "default-metadata",
"core", core,
NULL));
return TRUE;
}
......@@ -332,11 +332,12 @@ wp_default_profile_class_init (WpDefaultProfileClass * klass)
NULL, G_TYPE_NONE, 2, WP_TYPE_DEVICE, G_TYPE_POINTER);
}
WP_PLUGIN_EXPORT void
wireplumber__module_init (WpModule * module, WpCore * core, GVariant * args)
WP_PLUGIN_EXPORT gboolean
wireplumber__module_init (WpCore * core, GVariant * args, GError ** error)
{
wp_plugin_register (g_object_new (wp_default_profile_get_type (),
"name", STATE_NAME,
"core", core,
NULL));
return TRUE;
}
......@@ -182,12 +182,12 @@ wp_device_activation_class_init (WpDeviceActivationClass * klass)
plugin_class->disable = wp_device_activation_disable;
}
WP_PLUGIN_EXPORT void
wireplumber__module_init (WpModule * module, WpCore * core, GVariant * args)
WP_PLUGIN_EXPORT gboolean
wireplumber__module_init (WpCore * core, GVariant * args, GError ** error)
{
wp_plugin_register (g_object_new (wp_device_activation_get_type (),
"name", "device-activation",
"core", core,
NULL));
return TRUE;
}
......@@ -168,14 +168,15 @@ wp_lua_scripting_plugin_class_init (WpLuaScriptingPluginClass * klass)
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
}
WP_PLUGIN_EXPORT void
wireplumber__module_init (WpModule * module, WpCore * core, GVariant * args)
WP_PLUGIN_EXPORT gboolean
wireplumber__module_init (WpCore * core, GVariant * args, GError ** error)
{
const gchar *profile;
if (!g_variant_lookup (args, "profile", "&s", &profile)) {
wp_warning_object (module, "module-lua-scripting requires a 'profile'");
return;
g_set_error (error, WP_DOMAIN_LIBRARY, WP_LIBRARY_ERROR_INVALID_ARGUMENT,
"module-lua-scripting requires a 'profile'");
return FALSE;
}
wp_plugin_register (g_object_new (wp_lua_scripting_plugin_get_type (),
......@@ -183,4 +184,5 @@ wireplumber__module_init (WpModule * module, WpCore * core, GVariant * args)
"core", core,
"profile", profile,
NULL));
return TRUE;
}
......@@ -70,11 +70,12 @@ wp_metadata_plugin_class_init (WpMetadataPluginClass * klass)
plugin_class->disable = wp_metadata_plugin_disable;
}
WP_PLUGIN_EXPORT void
wireplumber__module_init (WpModule * module, WpCore * core, GVariant * args)
WP_PLUGIN_EXPORT gboolean
wireplumber__module_init (WpCore * core, GVariant * args, GError ** error)
{
wp_plugin_register (g_object_new (wp_metadata_plugin_get_type (),
"name", "metadata",
"core", core,
NULL));
return TRUE;
}
......@@ -130,11 +130,12 @@ wp_node_suspension_class_init (WpNodeSuspensionClass * klass)
plugin_class->disable = wp_node_suspension_disable;
}
WP_PLUGIN_EXPORT void
wireplumber__module_init (WpModule * module, WpCore * core, GVariant * args)
WP_PLUGIN_EXPORT gboolean
wireplumber__module_init (WpCore * core, GVariant * args, GError ** error)
{
wp_plugin_register (g_object_new (wp_node_suspension_get_type (),
"name", "node-suspension",
"core", core,
NULL));
return TRUE;
}
......@@ -271,11 +271,12 @@ wp_reserve_device_plugin_class_init (WpReserveDevicePluginClass * klass)
}
WP_PLUGIN_EXPORT void
wireplumber__module_init (WpModule * module, WpCore * core, GVariant * args)
WP_PLUGIN_EXPORT gboolean
wireplumber__module_init (WpCore * core, GVariant * args, GError ** error)
{
wp_plugin_register (g_object_new (wp_reserve_device_plugin_get_type (),
"name", "reserve-device",
"core", core,
NULL));
return TRUE;
}
......@@ -563,8 +563,8 @@ si_adapter_port_info_init (WpSiPortInfoInterface * iface)
iface->get_ports = si_adapter_get_ports;
}
WP_PLUGIN_EXPORT void
wireplumber__module_init (WpModule * module, WpCore * core, GVariant * args)
WP_PLUGIN_EXPORT gboolean
wireplumber__module_init (WpCore * core, GVariant * args, GError ** error)
{
GVariantBuilder b;
......@@ -590,4 +590,5 @@ wireplumber__module_init (WpModule * module, WpCore * core, GVariant * args)
wp_si_factory_register (core, wp_si_factory_new_simple (
"si-adapter", si_adapter_get_type (), g_variant_builder_end (&b)));
return TRUE;
}
......@@ -290,8 +290,8 @@ si_audio_softdsp_endpoint_class_init (WpSiAudioSoftdspEndpointClass * klass)
si_class->activate_rollback = si_audio_softdsp_endpoint_activate_rollback;
}
WP_PLUGIN_EXPORT void
wireplumber__module_init (WpModule * module, WpCore * core, GVariant * args)
WP_PLUGIN_EXPORT gboolean
wireplumber__module_init (WpCore * core, GVariant * args, GError ** error)
{
GVariantBuilder b;
......@@ -302,4 +302,5 @@ wireplumber__module_init (WpModule * module, WpCore * core, GVariant * args)
wp_si_factory_register (core, wp_si_factory_new_simple (
"si-audio-softdsp-endpoint", si_audio_softdsp_endpoint_get_type (),
g_variant_builder_end (&b)));
return TRUE;
}
......@@ -540,8 +540,8 @@ si_bluez5_endpoint_stream_acquisition_init (
iface->release = si_bluez5_endpoint_stream_acquisition_release;
}
WP_PLUGIN_EXPORT void
wireplumber__module_init (WpModule * module, WpCore * core, GVariant * args)
WP_PLUGIN_EXPORT gboolean
wireplumber__module_init (WpCore * core, GVariant * args, GError ** error)
{
GVariantBuilder b;
......@@ -568,4 +568,5 @@ wireplumber__module_init (WpModule * module, WpCore * core, GVariant * args)
wp_si_factory_register (core, wp_si_factory_new_simple (
"si-bluez5-endpoint", si_bluez5_endpoint_get_type (),
g_variant_builder_end (&b)));
return TRUE;
}
......@@ -495,8 +495,8 @@ si_convert_class_init (WpSiConvertClass * klass)
si_class->activate_rollback = si_convert_activate_rollback;
}
WP_PLUGIN_EXPORT void
wireplumber__module_init (WpModule * module, WpCore * core, GVariant * args)
WP_PLUGIN_EXPORT gboolean
wireplumber__module_init (WpCore * core, GVariant * args, GError ** error)
{
GVariantBuilder b;
......@@ -510,4 +510,5 @@ wireplumber__module_init (WpModule * module, WpCore * core, GVariant * args)
wp_si_factory_register (core, wp_si_factory_new_simple (
"si-convert", si_convert_get_type (), g_variant_builder_end (&b)));
return TRUE;
}
......@@ -174,8 +174,8 @@ si_fake_stream_port_info_init (WpSiPortInfoInterface * iface)
iface->get_ports = si_fake_stream_get_ports;
}
WP_PLUGIN_EXPORT void
wireplumber__module_init (WpModule * module, WpCore * core, GVariant * args)
WP_PLUGIN_EXPORT gboolean
wireplumber__module_init (WpCore * core, GVariant * args, GError ** error)
{
GVariantBuilder b;
......@@ -185,4 +185,5 @@ wireplumber__module_init (WpModule * module, WpCore * core, GVariant * args)
wp_si_factory_register (core, wp_si_factory_new_simple (
"si-fake-stream", si_fake_stream_get_type (), g_variant_builder_end (&b)));
return TRUE;
}
......@@ -287,8 +287,8 @@ si_monitor_endpoint_port_info_init (WpSiPortInfoInterface * iface)
iface->get_ports = si_monitor_endpoint_get_ports;
}
WP_PLUGIN_EXPORT void
wireplumber__module_init (WpModule * module, WpCore * core, GVariant * args)
WP_PLUGIN_EXPORT gboolean
wireplumber__module_init (WpCore * core, GVariant * args, GError ** error)
{
GVariantBuilder b;
......@@ -299,4 +299,5 @@ wireplumber__module_init (WpModule * module, WpCore * core, GVariant * args)
wp_si_factory_register (core, wp_si_factory_new_simple (
"si-monitor-endpoint", si_monitor_endpoint_get_type (),
g_variant_builder_end (&b)));
return TRUE;
}
......@@ -415,8 +415,8 @@ si_simple_node_endpoint_port_info_init (WpSiPortInfoInterface * iface)
iface->get_ports = si_simple_node_endpoint_get_ports;
}
WP_PLUGIN_EXPORT void
wireplumber__module_init (WpModule * module, WpCore * core, GVariant * args)
WP_PLUGIN_EXPORT gboolean
wireplumber__module_init (WpCore * core, GVariant * args, GError ** error)
{
GVariantBuilder b;
......@@ -436,4 +436,5 @@ wireplumber__module_init (WpModule * module, WpCore * core, GVariant * args)
wp_si_factory_register (core, wp_si_factory_new_simple (
"si-simple-node-endpoint", si_simple_node_endpoint_get_type (),
g_variant_builder_end (&b)));
return TRUE;
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment