Commit 102e1b13 authored by Arun Raghavan's avatar Arun Raghavan 🐾
Browse files

wp: Add a WpImplModule for loading modules in WirePlumber context

parent 9ebea297
Pipeline #376886 failed with stages
in 43 seconds
......@@ -10,6 +10,7 @@ wp_lib_sources = files(
'link.c',
'log.c',
'metadata.c',
'module.c',
'node.c',
'object.c',
'object-interest.c',
......@@ -46,6 +47,7 @@ wp_lib_headers = files(
'link.h',
'log.h',
'metadata.h',
'module.h',
'node.h',
'object.h',
'object-interest.h',
......
/* WirePlumber
*
* Copyright © 2021 Asymptotic
* @author Arun Raghavan <arun@asymptotic.io>
*
* SPDX-License-Identifier: MIT
*/
#define G_LOG_DOMAIN "wp-module"
#include <pipewire/impl.h>
#include "module.h"
/*! \defgroup wpimplmodule WpImplModule */
/*!
* \struct WpImplModule
*
* Used to load PipeWire modules within the WirePlumber process. This is
* slightly different from other objects in that the module is not exported to
* PipeWire, but it may create an export objects itself.
*/
struct _WpImplModule
{
GObject parent;
GWeakRef core;
gchar *name;
gchar *args;
WpProperties *props; /* only used during module load */
struct pw_impl_module *pw_impl_module;
};
G_DEFINE_TYPE (WpImplModule, wp_impl_module, G_TYPE_OBJECT);
enum {
PROP_0,
PROP_CORE,
PROP_NAME,
PROP_ARGUMENTS,
PROP_PROPERTIES,
PROP_PW_IMPL_MODULE,
};
static void
wp_impl_module_init (WpImplModule * self)
{
g_weak_ref_init (&self->core, NULL);
self->name = NULL;
self->args = NULL;
self->props = NULL;
self->pw_impl_module = NULL;
}
static void
wp_impl_module_constructed (GObject * object)
{
WpImplModule *self = WP_IMPL_MODULE (object);
WpCore *core = g_weak_ref_get (&self->core);
struct pw_context *context = core ? wp_core_get_pw_context (core) : NULL;
struct pw_properties *props = NULL;
if (!core || !context) {
g_warning ("Tried to load module on unconnected core");
return;
}
if (!self->name) {
g_warning ("Invalid name while loading warnings");
return;
}
if (self->props)
props = wp_properties_to_pw_properties (self->props);
self->pw_impl_module =
pw_context_load_module (context, self->name, self->args, props);
if (self->pw_impl_module) {
/* With the module loaded, properties are just passthrough now */
wp_properties_unref (self->props);
self->props = NULL;
}
G_OBJECT_CLASS (wp_impl_module_parent_class)->constructed (object);
}
static void
wp_impl_module_finalize (GObject * object)
{
WpImplModule *self = WP_IMPL_MODULE (object);
g_weak_ref_clear (&self->core);
if (self->pw_impl_module)
pw_impl_module_destroy (self->pw_impl_module);
g_free (self->name);
g_free (self->args);
if (self->props)
wp_properties_unref (self->props);
}
static void
wp_impl_module_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec)
{
WpImplModule *self = WP_IMPL_MODULE (object);
switch (prop_id) {
case PROP_CORE:
g_value_set_pointer (value, g_weak_ref_get (&self->core));
break;
case PROP_NAME:
g_value_set_string (value, self->name);
break;
case PROP_ARGUMENTS:
g_value_set_string (value, self->args);
break;
case PROP_PROPERTIES:
if (self->pw_impl_module) {
const struct pw_properties *props =
pw_impl_module_get_properties (self->pw_impl_module);
/* Should we just wrap instead of copying? */
if (props)
g_value_set_boxed (value, wp_properties_new_copy (props));
else
g_value_set_boxed (value, NULL);
} else {
g_value_set_boxed (value, self->props);
}
break;
case PROP_PW_IMPL_MODULE:
g_value_set_pointer (value, self->pw_impl_module);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
wp_impl_module_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
{
WpImplModule *self = WP_IMPL_MODULE (object);
WpProperties *props;
switch (prop_id) {
case PROP_CORE:
g_weak_ref_set (&self->core, g_value_get_pointer (value));
break;
case PROP_NAME:
g_free (self->name);
self->name = g_value_dup_string (value);
break;
case PROP_ARGUMENTS:
g_free (self->args);
self->args = g_value_dup_string (value);
break;
case PROP_PROPERTIES:
props = g_value_get_boxed (value);
if (props && self->pw_impl_module) {
pw_impl_module_update_properties (self->pw_impl_module,
wp_properties_peek_dict (props));
} else {
if (props)
self->props = wp_properties_ref (props);
else
self->props = NULL;
}
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
wp_impl_module_class_init (WpImplModuleClass * klass)
{
GObjectClass *gobject_class = (GObjectClass *) klass;
gobject_class->constructed = wp_impl_module_constructed;
gobject_class->finalize = wp_impl_module_finalize;
gobject_class->get_property = wp_impl_module_get_property;
gobject_class->set_property = wp_impl_module_set_property;
g_object_class_install_property (gobject_class, PROP_CORE,
g_param_spec_pointer ("core", "Core", "The WirePlumber core",
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_NAME,
g_param_spec_string ("name", "Name", "The name of the PipeWire module",
NULL,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_ARGUMENTS,
g_param_spec_string ("arguments", "Arguments",
"The arguments to provide to the module while loading", NULL,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_PROPERTIES,
g_param_spec_boxed ("properties", "Properties",
"Properties of the module", WP_TYPE_PROPERTIES,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_PW_IMPL_MODULE,
g_param_spec_pointer ("pw-impl-module", "Underlying pw_impl_module",
"Pointer to the underlying pw_impl_module structure for the module",
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
}
/*!
* \brief Loads a PipeWire module into the WirePlumber process
*
* \ingroup wpmodule
* \param core (transfer none): The WirePlumber core
* \param name (transfer none): the name of the module to load
* \param arguments (nullable) (transfer none): arguments to be passed to the module
* \param properties (nullable) (transfer none): additional properties to be
* provided to the module
* \returns (nullable) (transfer full): the WpImplModule for the module that
* was loaded on success, %NULL on failure.
*/
WpImplModule *
wp_impl_module_load (WpCore * core, const gchar * name,
const gchar * arguments, WpProperties * properties)
{
WpImplModule *module = WP_IMPL_MODULE (
g_object_new (WP_TYPE_IMPL_MODULE,
"core", core,
"name", name,
"arguments", arguments,
"properties", properties,
NULL)
);
if (!module->pw_impl_module) {
/* Module loading failed, free and return */
g_object_unref (module);
return NULL;
}
return module;
}
/* WirePlumber
*
* Copyright © 2021 Asymptotic
* @author Arun Raghavan <arun@asymptotic.io>
*
* SPDX-License-Identifier: MIT
*/
#ifndef __WIREPLUMBER_MODULE_H__
#define __WIREPLUMBER_MODULE_H__
#include <glib-object.h>
#include "core.h"
#include "defs.h"
#include "properties.h"
G_BEGIN_DECLS
/*!
* \brief The WpImplModule GType
* \ingroup wpimplmodule
*/
#define WP_TYPE_IMPL_MODULE (wp_impl_module_get_type())
WP_API
G_DECLARE_FINAL_TYPE (WpImplModule, wp_impl_module, WP, IMPL_MODULE, GObject);
WP_API
WpImplModule * wp_impl_module_load (WpCore * core, const gchar * name,
const gchar * args, WpProperties * properties);
G_END_DECLS
#endif /* __WIREPLUMBER_MODULE_H__ */
......@@ -20,6 +20,7 @@
#include "link.h"
#include "log.h"
#include "metadata.h"
#include "module.h"
#include "node.h"
#include "object-interest.h"
#include "object-manager.h"
......
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