component-loader: make wp_core_load_component() API asynchronous
This change completely refactors the way components are loaded in wireplumber: - The module_init() function must return a GObject now. This object is either a WpPlugin or a WpSiFactory in the current modules. - When the component loader initializes a module, it automatically registers the WpPlugin or WpSiFactory with their respective methods. There is no need to register the WpPlugin or WpSiFactory in the module now. - The wp_core_load_component() API has been refactored to be asynchronows. This allows the component loader to automatically activate WpPlugin objects, and therefore allows the application to directly get the WpPlugin without having to find it. This simplifies a lot of things. - The 'ifexists' and 'nofail' component flags now work even if the respective WpPlugin could not be activated. - The code that loads components in main.c has also been simplified a lot, and the option to load dangling components has also been removed.
This commit is contained in:
@@ -32,7 +32,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#define WP_MODULE_INIT_SYMBOL "wireplumber__module_init"
|
#define WP_MODULE_INIT_SYMBOL "wireplumber__module_init"
|
||||||
typedef gboolean (*WpModuleInitFunc) (WpCore *, GVariant *, GError **);
|
typedef GObject *(*WpModuleInitFunc) (WpCore *, GVariant *, GError **);
|
||||||
|
|
||||||
G_DEFINE_ABSTRACT_TYPE (WpComponentLoader, wp_component_loader, WP_TYPE_PLUGIN)
|
G_DEFINE_ABSTRACT_TYPE (WpComponentLoader, wp_component_loader, WP_TYPE_PLUGIN)
|
||||||
|
|
||||||
@@ -46,7 +46,7 @@ wp_component_loader_class_init (WpComponentLoaderClass * klass)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static GObject *
|
||||||
load_module (WpCore * core, const gchar * module_name,
|
load_module (WpCore * core, const gchar * module_name,
|
||||||
GVariant * args, GError ** error)
|
GVariant * args, GError ** error)
|
||||||
{
|
{
|
||||||
@@ -64,7 +64,7 @@ load_module (WpCore * core, const gchar * module_name,
|
|||||||
if (!gmodule) {
|
if (!gmodule) {
|
||||||
g_set_error (error, WP_DOMAIN_LIBRARY, WP_LIBRARY_ERROR_OPERATION_FAILED,
|
g_set_error (error, WP_DOMAIN_LIBRARY, WP_LIBRARY_ERROR_OPERATION_FAILED,
|
||||||
"Failed to open module %s: %s", module_path, g_module_error ());
|
"Failed to open module %s: %s", module_path, g_module_error ());
|
||||||
return FALSE;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!g_module_symbol (gmodule, WP_MODULE_INIT_SYMBOL, &module_init)) {
|
if (!g_module_symbol (gmodule, WP_MODULE_INIT_SYMBOL, &module_init)) {
|
||||||
@@ -72,7 +72,7 @@ load_module (WpCore * core, const gchar * module_name,
|
|||||||
"Failed to locate symbol " WP_MODULE_INIT_SYMBOL " in %s",
|
"Failed to locate symbol " WP_MODULE_INIT_SYMBOL " in %s",
|
||||||
module_path);
|
module_path);
|
||||||
g_module_close (gmodule);
|
g_module_close (gmodule);
|
||||||
return FALSE;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ((WpModuleInitFunc) module_init) (core, args, error);
|
return ((WpModuleInitFunc) module_init) (core, args, error);
|
||||||
@@ -98,13 +98,28 @@ wp_component_loader_find (WpCore * core, const gchar * type)
|
|||||||
return c ? WP_COMPONENT_LOADER (c) : NULL;
|
return c ? WP_COMPONENT_LOADER (c) : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static void
|
||||||
wp_component_loader_load (WpComponentLoader * self, const gchar * component,
|
wp_component_loader_load (WpComponentLoader * self, const gchar * component,
|
||||||
const gchar * type, GVariant * args, GError ** error)
|
const gchar * type, GVariant * args, GAsyncReadyCallback callback,
|
||||||
|
gpointer data)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (WP_IS_COMPONENT_LOADER (self), FALSE);
|
g_return_if_fail (WP_IS_COMPONENT_LOADER (self));
|
||||||
return WP_COMPONENT_LOADER_GET_CLASS (self)->load (self, component, type,
|
WP_COMPONENT_LOADER_GET_CLASS (self)->load (self, component, type,
|
||||||
args, error);
|
args, callback, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_object_loaded (WpObject *object, GAsyncResult *res, gpointer data)
|
||||||
|
{
|
||||||
|
g_autoptr (GTask) task = G_TASK (data);
|
||||||
|
g_autoptr (GError) error = NULL;
|
||||||
|
|
||||||
|
if (!wp_object_activate_finish (object, res, &error)) {
|
||||||
|
g_task_return_error (task, g_steal_pointer (&error));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_task_return_pointer (task, g_object_ref (object), g_object_unref);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -121,25 +136,80 @@ wp_component_loader_load (WpComponentLoader * self, const gchar * component,
|
|||||||
* \param type the type of the component
|
* \param type the type of the component
|
||||||
* \param args (transfer floating)(nullable): additional arguments for the component,
|
* \param args (transfer floating)(nullable): additional arguments for the component,
|
||||||
* usually a dict or a string
|
* usually a dict or a string
|
||||||
* \param error (out) (optional): return location for errors, or NULL to ignore
|
* \param callback (scope async): the callback to call when the operation is done
|
||||||
* \returns TRUE if loaded, FALSE if there was an error
|
* \param data (closure): data to pass to \a callback
|
||||||
*/
|
*/
|
||||||
gboolean
|
void
|
||||||
wp_core_load_component (WpCore * self, const gchar * component,
|
wp_core_load_component (WpCore * self, const gchar * component,
|
||||||
const gchar * type, GVariant * args, GError ** error)
|
const gchar * type, GVariant * args, GAsyncReadyCallback callback,
|
||||||
|
gpointer data)
|
||||||
{
|
{
|
||||||
g_autoptr (GVariant) args_ref = args ? g_variant_ref_sink (args) : NULL;
|
g_autoptr (GVariant) args_ref = args ? g_variant_ref_sink (args) : NULL;
|
||||||
|
g_autoptr (GTask) task = NULL;
|
||||||
|
g_autoptr (WpComponentLoader) c = NULL;
|
||||||
|
|
||||||
if (!g_strcmp0 (type, "module"))
|
/* Special case for "module" component type */
|
||||||
return load_module (self, component, args_ref, error);
|
if (g_str_equal (type, "module")) {
|
||||||
else {
|
task = g_task_new (self, NULL, callback, data);
|
||||||
g_autoptr (WpComponentLoader) c = wp_component_loader_find (self, type);
|
g_autoptr (GError) error = NULL;
|
||||||
if (c)
|
g_autoptr (GObject) o = NULL;
|
||||||
return wp_component_loader_load (c, component, type, args, error);
|
|
||||||
else {
|
/* load Module */
|
||||||
g_set_error (error, WP_DOMAIN_LIBRARY, WP_LIBRARY_ERROR_INVALID_ARGUMENT,
|
o = load_module (self, component, args_ref, &error);
|
||||||
"No component loader was found for components of type '%s'", type);
|
if (!o) {
|
||||||
return FALSE;
|
g_task_return_error (task, g_steal_pointer (&error));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (WP_IS_OBJECT (o)) {
|
||||||
|
/* WpObject needs to be activated */
|
||||||
|
if (WP_IS_PLUGIN (o))
|
||||||
|
wp_plugin_register (WP_PLUGIN (g_object_ref (o)));
|
||||||
|
wp_object_activate (WP_OBJECT (o), WP_OBJECT_FEATURES_ALL, NULL,
|
||||||
|
(GAsyncReadyCallback) on_object_loaded, g_object_ref (task));
|
||||||
|
return;
|
||||||
|
} else if (WP_IS_SI_FACTORY (o)) {
|
||||||
|
/* WpSiFactory doesn't need to be activated */
|
||||||
|
wp_si_factory_register (self, WP_SI_FACTORY (g_object_ref (o)));
|
||||||
|
g_task_return_pointer (task, g_object_ref (o), g_object_unref);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_task_return_new_error (task, WP_DOMAIN_LIBRARY,
|
||||||
|
WP_LIBRARY_ERROR_INVALID_ARGUMENT,
|
||||||
|
"Invalid module object for component %s", component);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Otherwise find a component loader for that type and load the component */
|
||||||
|
c = wp_component_loader_find (self, type);
|
||||||
|
if (!c) {
|
||||||
|
task = g_task_new (self, NULL, callback, data);
|
||||||
|
g_task_return_new_error (task, WP_DOMAIN_LIBRARY,
|
||||||
|
WP_LIBRARY_ERROR_INVALID_ARGUMENT,
|
||||||
|
"No component loader was found for components of type '%s'", type);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wp_component_loader_load (c, component, type, args, callback, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Finishes the operation started by wp_core_load_component().
|
||||||
|
* This is meant to be called in the callback that was passed to that method.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* \ingroup wpcomponentloader
|
||||||
|
* \param self the component loader object
|
||||||
|
* \param res the async result
|
||||||
|
* \param error (out) (optional): the operation's error, if it occurred
|
||||||
|
* \returns (transfer full): The loaded component object, or NULL if an
|
||||||
|
* error happened.
|
||||||
|
*/
|
||||||
|
GObject *
|
||||||
|
wp_core_load_component_finish (WpCore * self, GAsyncResult * res,
|
||||||
|
GError ** error)
|
||||||
|
{
|
||||||
|
gpointer o = g_task_propagate_pointer (G_TASK (res), error);
|
||||||
|
return o ? g_object_ref (G_OBJECT (o)) : NULL;
|
||||||
}
|
}
|
||||||
|
@@ -28,8 +28,9 @@ struct _WpComponentLoaderClass
|
|||||||
|
|
||||||
gboolean (*supports_type) (WpComponentLoader * self, const gchar * type);
|
gboolean (*supports_type) (WpComponentLoader * self, const gchar * type);
|
||||||
|
|
||||||
gboolean (*load) (WpComponentLoader * self, const gchar * component,
|
void (*load) (WpComponentLoader * self, const gchar * component,
|
||||||
const gchar * type, GVariant * args, GError ** error);
|
const gchar * type, GVariant * args, GAsyncReadyCallback callback,
|
||||||
|
gpointer data);
|
||||||
|
|
||||||
/*< private >*/
|
/*< private >*/
|
||||||
WP_PADDING(6)
|
WP_PADDING(6)
|
||||||
|
@@ -48,8 +48,13 @@ WP_API
|
|||||||
gchar *wp_core_get_vm_type (WpCore *self);
|
gchar *wp_core_get_vm_type (WpCore *self);
|
||||||
|
|
||||||
WP_API
|
WP_API
|
||||||
gboolean wp_core_load_component (WpCore * self, const gchar * component,
|
void wp_core_load_component (WpCore * self, const gchar * component,
|
||||||
const gchar * type, GVariant * args, GError ** error);
|
const gchar * type, GVariant * args, GAsyncReadyCallback callback,
|
||||||
|
gpointer data);
|
||||||
|
|
||||||
|
WP_API
|
||||||
|
GObject * wp_core_load_component_finish (WpCore * self, GAsyncResult * res,
|
||||||
|
GError ** error);
|
||||||
|
|
||||||
/* Connection */
|
/* Connection */
|
||||||
|
|
||||||
|
@@ -304,12 +304,11 @@ wp_default_nodes_api_class_init (WpDefaultNodesApiClass * klass)
|
|||||||
G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 0);
|
G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
WP_PLUGIN_EXPORT gboolean
|
WP_PLUGIN_EXPORT GObject *
|
||||||
wireplumber__module_init (WpCore * core, GVariant * args, GError ** error)
|
wireplumber__module_init (WpCore * core, GVariant * args, GError ** error)
|
||||||
{
|
{
|
||||||
wp_plugin_register (g_object_new (wp_default_nodes_api_get_type (),
|
return G_OBJECT (g_object_new (wp_default_nodes_api_get_type (),
|
||||||
"name", "default-nodes-api",
|
"name", "default-nodes-api",
|
||||||
"core", core,
|
"core", core,
|
||||||
NULL));
|
NULL));
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
@@ -201,12 +201,11 @@ wp_file_monitor_api_class_init (WpFileMonitorApiClass * klass)
|
|||||||
G_TYPE_NONE, 3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
|
G_TYPE_NONE, 3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
|
||||||
}
|
}
|
||||||
|
|
||||||
WP_PLUGIN_EXPORT gboolean
|
WP_PLUGIN_EXPORT GObject *
|
||||||
wireplumber__module_init (WpCore * core, GVariant * args, GError ** error)
|
wireplumber__module_init (WpCore * core, GVariant * args, GError ** error)
|
||||||
{
|
{
|
||||||
wp_plugin_register (g_object_new (wp_file_monitor_api_get_type (),
|
return G_OBJECT (g_object_new (wp_file_monitor_api_get_type (),
|
||||||
"name", "file-monitor-api",
|
"name", "file-monitor-api",
|
||||||
"core", core,
|
"core", core,
|
||||||
NULL));
|
NULL));
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
@@ -131,12 +131,11 @@ wp_logind_class_init (WpLogindClass * klass)
|
|||||||
G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_STRING);
|
G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_STRING);
|
||||||
}
|
}
|
||||||
|
|
||||||
WP_PLUGIN_EXPORT gboolean
|
WP_PLUGIN_EXPORT GObject *
|
||||||
wireplumber__module_init (WpCore * core, GVariant * args, GError ** error)
|
wireplumber__module_init (WpCore * core, GVariant * args, GError ** error)
|
||||||
{
|
{
|
||||||
wp_plugin_register (g_object_new (wp_logind_get_type (),
|
return G_OBJECT (g_object_new (wp_logind_get_type (),
|
||||||
"name", NAME,
|
"name", NAME,
|
||||||
"core", core,
|
"core", core,
|
||||||
NULL));
|
NULL));
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
@@ -17,8 +17,7 @@ struct _WpRequireApiTransition
|
|||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
STEP_LOAD_MODULES = WP_TRANSITION_STEP_CUSTOM_START,
|
STEP_LOAD_PLUGINS = WP_TRANSITION_STEP_CUSTOM_START,
|
||||||
STEP_ACTIVATE_PLUGINS,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
G_DECLARE_FINAL_TYPE (WpRequireApiTransition, wp_require_api_transition,
|
G_DECLARE_FINAL_TYPE (WpRequireApiTransition, wp_require_api_transition,
|
||||||
@@ -47,23 +46,24 @@ wp_require_api_transition_get_next_step (WpTransition * transition, guint step)
|
|||||||
WpRequireApiTransition *self = WP_REQUIRE_API_TRANSITION (transition);
|
WpRequireApiTransition *self = WP_REQUIRE_API_TRANSITION (transition);
|
||||||
|
|
||||||
switch (step) {
|
switch (step) {
|
||||||
case WP_TRANSITION_STEP_NONE: return STEP_LOAD_MODULES;
|
case WP_TRANSITION_STEP_NONE: return STEP_LOAD_PLUGINS;
|
||||||
case STEP_LOAD_MODULES: return STEP_ACTIVATE_PLUGINS;
|
case STEP_LOAD_PLUGINS:
|
||||||
case STEP_ACTIVATE_PLUGINS:
|
|
||||||
return (self->pending_plugins > 0) ?
|
return (self->pending_plugins > 0) ?
|
||||||
STEP_ACTIVATE_PLUGINS : WP_TRANSITION_STEP_NONE;
|
STEP_LOAD_PLUGINS : WP_TRANSITION_STEP_NONE;
|
||||||
default:
|
default:
|
||||||
g_return_val_if_reached (WP_TRANSITION_STEP_ERROR);
|
g_return_val_if_reached (WP_TRANSITION_STEP_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
on_plugin_activated (WpObject * p, GAsyncResult * res,
|
on_plugin_loaded (WpCore * core, GAsyncResult * res,
|
||||||
WpRequireApiTransition *self)
|
WpRequireApiTransition *self)
|
||||||
{
|
{
|
||||||
|
g_autoptr (GObject) o = NULL;
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
|
|
||||||
if (!wp_object_activate_finish (p, res, &error)) {
|
o = wp_core_load_component_finish (core, res, &error);
|
||||||
|
if (!o) {
|
||||||
wp_transition_return_error (WP_TRANSITION (self), error);
|
wp_transition_return_error (WP_TRANSITION (self), error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -79,49 +79,24 @@ wp_require_api_transition_execute_step (WpTransition * transition, guint step)
|
|||||||
WpCore *core = wp_transition_get_source_object (transition);
|
WpCore *core = wp_transition_get_source_object (transition);
|
||||||
|
|
||||||
switch (step) {
|
switch (step) {
|
||||||
case STEP_LOAD_MODULES:
|
case STEP_LOAD_PLUGINS:
|
||||||
{
|
wp_debug_object (self, "Loading plugins...");
|
||||||
|
|
||||||
for (guint i = 0; i < self->apis->len; i++) {
|
for (guint i = 0; i < self->apis->len; i++) {
|
||||||
const gchar *api_name = g_ptr_array_index (self->apis, i);
|
const gchar *api_name = g_ptr_array_index (self->apis, i);
|
||||||
g_autoptr (WpPlugin) plugin = wp_plugin_find (core, api_name);
|
g_autoptr (WpPlugin) plugin = wp_plugin_find (core, api_name);
|
||||||
if (!plugin) {
|
if (!plugin) {
|
||||||
GError *error = NULL;
|
|
||||||
gchar module_name[50];
|
gchar module_name[50];
|
||||||
|
|
||||||
g_snprintf (module_name, sizeof (module_name),
|
g_snprintf (module_name, sizeof (module_name),
|
||||||
"libwireplumber-module-%s", api_name);
|
"libwireplumber-module-%s", api_name);
|
||||||
|
|
||||||
if (!wp_core_load_component (core, module_name, "module", NULL, &error)) {
|
self->pending_plugins++;
|
||||||
wp_transition_return_error (transition, error);
|
wp_core_load_component (core, module_name, "module", NULL,
|
||||||
return;
|
(GAsyncReadyCallback) on_plugin_loaded, self);
|
||||||
}
|
|
||||||
|
|
||||||
plugin = wp_plugin_find (core, api_name);
|
|
||||||
if (!plugin) {
|
|
||||||
wp_transition_return_error (transition, g_error_new (
|
|
||||||
WP_DOMAIN_LIBRARY, WP_LIBRARY_ERROR_INVALID_ARGUMENT,
|
|
||||||
"API '%s' was not found in module '%s'", api_name, module_name));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
wp_transition_advance (transition);
|
wp_transition_advance (transition);
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
case STEP_ACTIVATE_PLUGINS:
|
|
||||||
wp_debug_object (self, "Activating plugins...");
|
|
||||||
|
|
||||||
for (guint i = 0; i < self->apis->len; i++) {
|
|
||||||
const gchar *api_name = g_ptr_array_index (self->apis, i);
|
|
||||||
g_autoptr (WpPlugin) plugin = wp_plugin_find (core, api_name);
|
|
||||||
|
|
||||||
self->pending_plugins++;
|
|
||||||
wp_object_activate (WP_OBJECT (plugin), WP_PLUGIN_FEATURE_ENABLED, NULL,
|
|
||||||
(GAsyncReadyCallback) on_plugin_activated, self);
|
|
||||||
}
|
|
||||||
wp_transition_advance (transition);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WP_TRANSITION_STEP_ERROR:
|
case WP_TRANSITION_STEP_ERROR:
|
||||||
break;
|
break;
|
||||||
|
@@ -18,7 +18,6 @@ struct _WpLuaScriptingPlugin
|
|||||||
{
|
{
|
||||||
WpComponentLoader parent;
|
WpComponentLoader parent;
|
||||||
|
|
||||||
GPtrArray *scripts; /* element-type: WpPlugin* */
|
|
||||||
lua_State *L;
|
lua_State *L;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -90,17 +89,6 @@ G_DEFINE_TYPE (WpLuaScriptingPlugin, wp_lua_scripting_plugin,
|
|||||||
static void
|
static void
|
||||||
wp_lua_scripting_plugin_init (WpLuaScriptingPlugin * self)
|
wp_lua_scripting_plugin_init (WpLuaScriptingPlugin * self)
|
||||||
{
|
{
|
||||||
self->scripts = g_ptr_array_new_with_free_func (g_object_unref);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
wp_lua_scripting_plugin_finalize (GObject * object)
|
|
||||||
{
|
|
||||||
WpLuaScriptingPlugin * self = WP_LUA_SCRIPTING_PLUGIN (object);
|
|
||||||
|
|
||||||
g_clear_pointer (&self->scripts, g_ptr_array_unref);
|
|
||||||
|
|
||||||
G_OBJECT_CLASS (wp_lua_scripting_plugin_parent_class)->finalize (object);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -129,14 +117,6 @@ wp_lua_scripting_plugin_enable (WpPlugin * plugin, WpTransition * transition)
|
|||||||
wp_lua_scripting_enable_package_searcher (self->L);
|
wp_lua_scripting_enable_package_searcher (self->L);
|
||||||
wplua_enable_sandbox (self->L, WP_LUA_SANDBOX_ISOLATE_ENV);
|
wplua_enable_sandbox (self->L, WP_LUA_SANDBOX_ISOLATE_ENV);
|
||||||
|
|
||||||
/* register scripts that were queued in for loading */
|
|
||||||
for (guint i = 0; i < self->scripts->len; i++) {
|
|
||||||
WpPlugin *script = g_ptr_array_index (self->scripts, i);
|
|
||||||
g_object_set (script, "lua-engine", self->L, NULL);
|
|
||||||
wp_plugin_register (g_object_ref (script));
|
|
||||||
}
|
|
||||||
g_ptr_array_set_size (self->scripts, 0);
|
|
||||||
|
|
||||||
wp_object_update_features (WP_OBJECT (self), WP_PLUGIN_FEATURE_ENABLED, 0);
|
wp_object_update_features (WP_OBJECT (self), WP_PLUGIN_FEATURE_ENABLED, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,6 +124,7 @@ static void
|
|||||||
wp_lua_scripting_plugin_disable (WpPlugin * plugin)
|
wp_lua_scripting_plugin_disable (WpPlugin * plugin)
|
||||||
{
|
{
|
||||||
WpLuaScriptingPlugin * self = WP_LUA_SCRIPTING_PLUGIN (plugin);
|
WpLuaScriptingPlugin * self = WP_LUA_SCRIPTING_PLUGIN (plugin);
|
||||||
|
|
||||||
g_clear_pointer (&self->L, wplua_unref);
|
g_clear_pointer (&self->L, wplua_unref);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,7 +146,6 @@ find_script (const gchar * script, WpCore *core)
|
|||||||
g_file_test (script, G_FILE_TEST_IS_REGULAR))
|
g_file_test (script, G_FILE_TEST_IS_REGULAR))
|
||||||
return g_strdup (script);
|
return g_strdup (script);
|
||||||
|
|
||||||
|
|
||||||
return wp_find_file (WP_LOOKUP_DIR_ENV_DATA |
|
return wp_find_file (WP_LOOKUP_DIR_ENV_DATA |
|
||||||
WP_LOOKUP_DIR_ENV_TEST_SRCDIR |
|
WP_LOOKUP_DIR_ENV_TEST_SRCDIR |
|
||||||
WP_LOOKUP_DIR_XDG_CONFIG_HOME |
|
WP_LOOKUP_DIR_XDG_CONFIG_HOME |
|
||||||
@@ -174,71 +154,79 @@ find_script (const gchar * script, WpCore *core)
|
|||||||
script, "scripts");
|
script, "scripts");
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static void
|
||||||
|
on_script_loaded (WpObject *object, GAsyncResult *res, gpointer data)
|
||||||
|
{
|
||||||
|
g_autoptr (GTask) task = G_TASK (data);
|
||||||
|
g_autoptr (GError) error = NULL;
|
||||||
|
|
||||||
|
if (!wp_object_activate_finish (object, res, &error)) {
|
||||||
|
g_task_return_error (task, g_steal_pointer (&error));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_task_return_pointer (task, g_object_ref (object), g_object_unref);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
wp_lua_scripting_plugin_load (WpComponentLoader * cl, const gchar * component,
|
wp_lua_scripting_plugin_load (WpComponentLoader * cl, const gchar * component,
|
||||||
const gchar * type, GVariant * args, GError ** error)
|
const gchar * type, GVariant * args, GAsyncReadyCallback callback,
|
||||||
|
gpointer data)
|
||||||
{
|
{
|
||||||
WpLuaScriptingPlugin * self = WP_LUA_SCRIPTING_PLUGIN (cl);
|
WpLuaScriptingPlugin * self = WP_LUA_SCRIPTING_PLUGIN (cl);
|
||||||
g_autoptr (WpCore) core = NULL;
|
g_autoptr (WpCore) core = wp_object_get_core (WP_OBJECT (cl));
|
||||||
|
g_autoptr (GTask) task = task = g_task_new (core, NULL, callback, data);
|
||||||
g_autofree gchar *filepath = NULL;
|
g_autofree gchar *filepath = NULL;
|
||||||
g_autofree gchar *pluginname = NULL;
|
g_autofree gchar *pluginname = NULL;
|
||||||
g_autoptr (WpPlugin) script = NULL;
|
g_autoptr (WpPlugin) script = NULL;
|
||||||
|
|
||||||
|
/* make sure the component loader is activated */
|
||||||
|
if (!self->L) {
|
||||||
|
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
|
||||||
|
"Lua script component loader cannot load Lua scripts if not enabled");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* make sure the type is supported */
|
||||||
if (!g_str_equal (type, "script/lua")) {
|
if (!g_str_equal (type, "script/lua")) {
|
||||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
|
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
|
||||||
"Could not load script '%s' as its type is not 'script/lua'",
|
"Could not load script '%s' as its type is not 'script/lua'",
|
||||||
component);
|
component);
|
||||||
return FALSE;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
core = wp_object_get_core (WP_OBJECT (cl));
|
|
||||||
|
|
||||||
if (g_file_test (component, G_FILE_TEST_EXISTS)) {
|
|
||||||
/* dangling components come with full path */
|
|
||||||
g_autofree gchar *filename = g_path_get_basename (component);
|
|
||||||
filepath = g_strdup (component);
|
|
||||||
pluginname = g_strdup_printf ("script:%s", filename);
|
|
||||||
} else {
|
|
||||||
filepath = find_script (component, core);
|
|
||||||
pluginname = g_strdup_printf ("script:%s", component);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* find the script */
|
||||||
|
filepath = find_script (component, core);
|
||||||
if (!filepath) {
|
if (!filepath) {
|
||||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
|
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
|
||||||
"Could not locate script '%s'", component);
|
"Could not locate script '%s'", component);
|
||||||
return FALSE;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pluginname = g_strdup_printf ("script:%s", component);
|
||||||
|
|
||||||
script = g_object_new (WP_TYPE_LUA_SCRIPT,
|
script = g_object_new (WP_TYPE_LUA_SCRIPT,
|
||||||
"core", core,
|
"core", core,
|
||||||
"name", pluginname,
|
"name", pluginname,
|
||||||
|
"lua-engine", self->L,
|
||||||
"filename", filepath,
|
"filename", filepath,
|
||||||
"arguments", args,
|
"arguments", args,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
if (self->L) {
|
/* register the script */
|
||||||
wp_debug_object (core, "loading script(%s) plugin name(%s)",
|
wp_plugin_register (g_object_ref (script));
|
||||||
filepath, pluginname);
|
|
||||||
g_object_set (script, "lua-engine", self->L, NULL);
|
|
||||||
wp_plugin_register (g_steal_pointer (&script));
|
|
||||||
} else {
|
|
||||||
/* keep in a list and delay registering until the plugin is enabled */
|
|
||||||
wp_debug ("queuing script %s", filepath);
|
|
||||||
g_ptr_array_add (self->scripts, g_steal_pointer (&script));
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
/* enable script */
|
||||||
|
wp_object_activate (WP_OBJECT (script), WP_OBJECT_FEATURES_ALL, NULL,
|
||||||
|
(GAsyncReadyCallback) on_script_loaded, g_object_ref (task));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
wp_lua_scripting_plugin_class_init (WpLuaScriptingPluginClass * klass)
|
wp_lua_scripting_plugin_class_init (WpLuaScriptingPluginClass * klass)
|
||||||
{
|
{
|
||||||
GObjectClass *object_class = (GObjectClass *) klass;
|
|
||||||
WpPluginClass *plugin_class = (WpPluginClass *) klass;
|
WpPluginClass *plugin_class = (WpPluginClass *) klass;
|
||||||
WpComponentLoaderClass *cl_class = (WpComponentLoaderClass *) klass;
|
WpComponentLoaderClass *cl_class = (WpComponentLoaderClass *) klass;
|
||||||
|
|
||||||
object_class->finalize = wp_lua_scripting_plugin_finalize;
|
|
||||||
|
|
||||||
plugin_class->enable = wp_lua_scripting_plugin_enable;
|
plugin_class->enable = wp_lua_scripting_plugin_enable;
|
||||||
plugin_class->disable = wp_lua_scripting_plugin_disable;
|
plugin_class->disable = wp_lua_scripting_plugin_disable;
|
||||||
|
|
||||||
@@ -246,12 +234,11 @@ wp_lua_scripting_plugin_class_init (WpLuaScriptingPluginClass * klass)
|
|||||||
cl_class->load = wp_lua_scripting_plugin_load;
|
cl_class->load = wp_lua_scripting_plugin_load;
|
||||||
}
|
}
|
||||||
|
|
||||||
WP_PLUGIN_EXPORT gboolean
|
WP_PLUGIN_EXPORT GObject *
|
||||||
wireplumber__module_init (WpCore * core, GVariant * args, GError ** error)
|
wireplumber__module_init (WpCore * core, GVariant * args, GError ** error)
|
||||||
{
|
{
|
||||||
wp_plugin_register (g_object_new (wp_lua_scripting_plugin_get_type (),
|
return G_OBJECT (g_object_new (wp_lua_scripting_plugin_get_type (),
|
||||||
"name", "lua-scripting",
|
"name", "lua-scripting",
|
||||||
"core", core,
|
"core", core,
|
||||||
NULL));
|
NULL));
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
@@ -272,7 +272,7 @@ wp_lua_script_class_init (WpLuaScriptClass * klass)
|
|||||||
|
|
||||||
g_object_class_install_property (object_class, PROP_LUA_ENGINE,
|
g_object_class_install_property (object_class, PROP_LUA_ENGINE,
|
||||||
g_param_spec_pointer ("lua-engine", "lua-engine", "lua-engine",
|
g_param_spec_pointer ("lua-engine", "lua-engine", "lua-engine",
|
||||||
G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS));
|
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
g_object_class_install_property (object_class, PROP_FILENAME,
|
g_object_class_install_property (object_class, PROP_FILENAME,
|
||||||
g_param_spec_string ("filename", "filename", "filename", NULL,
|
g_param_spec_string ("filename", "filename", "filename", NULL,
|
||||||
|
@@ -614,12 +614,11 @@ wp_mixer_api_class_init (WpMixerApiClass * klass)
|
|||||||
G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_UINT);
|
G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_UINT);
|
||||||
}
|
}
|
||||||
|
|
||||||
WP_PLUGIN_EXPORT gboolean
|
WP_PLUGIN_EXPORT GObject *
|
||||||
wireplumber__module_init (WpCore * core, GVariant * args, GError ** error)
|
wireplumber__module_init (WpCore * core, GVariant * args, GError ** error)
|
||||||
{
|
{
|
||||||
wp_plugin_register (g_object_new (wp_mixer_api_get_type (),
|
return G_OBJECT (g_object_new (wp_mixer_api_get_type (),
|
||||||
"name", "mixer-api",
|
"name", "mixer-api",
|
||||||
"core", core,
|
"core", core,
|
||||||
NULL));
|
NULL));
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
@@ -302,12 +302,12 @@ wp_portal_permissionstore_plugin_class_init (
|
|||||||
G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_VARIANT);
|
G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_VARIANT);
|
||||||
}
|
}
|
||||||
|
|
||||||
WP_PLUGIN_EXPORT gboolean
|
WP_PLUGIN_EXPORT GObject *
|
||||||
wireplumber__module_init (WpCore * core, GVariant * args, GError ** error)
|
wireplumber__module_init (WpCore * core, GVariant * args, GError ** error)
|
||||||
{
|
{
|
||||||
wp_plugin_register (g_object_new (wp_portal_permissionstore_plugin_get_type(),
|
return G_OBJECT (g_object_new (
|
||||||
|
wp_portal_permissionstore_plugin_get_type(),
|
||||||
"name", "portal-permissionstore",
|
"name", "portal-permissionstore",
|
||||||
"core", core,
|
"core", core,
|
||||||
NULL));
|
NULL));
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
@@ -264,12 +264,11 @@ wp_reserve_device_plugin_class_init (WpReserveDevicePluginClass * klass)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WP_PLUGIN_EXPORT gboolean
|
WP_PLUGIN_EXPORT GObject *
|
||||||
wireplumber__module_init (WpCore * core, GVariant * args, GError ** error)
|
wireplumber__module_init (WpCore * core, GVariant * args, GError ** error)
|
||||||
{
|
{
|
||||||
wp_plugin_register (g_object_new (wp_reserve_device_plugin_get_type (),
|
return G_OBJECT (g_object_new (wp_reserve_device_plugin_get_type (),
|
||||||
"name", "reserve-device",
|
"name", "reserve-device",
|
||||||
"core", core,
|
"core", core,
|
||||||
NULL));
|
NULL));
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
@@ -336,18 +336,16 @@ wp_settings_plugin_class_init (WpSettingsPluginClass * klass)
|
|||||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
|
||||||
}
|
}
|
||||||
|
|
||||||
WP_PLUGIN_EXPORT gboolean
|
WP_PLUGIN_EXPORT GObject *
|
||||||
wireplumber__module_init (WpCore * core, GVariant * args, GError ** error)
|
wireplumber__module_init (WpCore * core, GVariant * args, GError ** error)
|
||||||
{
|
{
|
||||||
const gchar *metadata_name = "sm-settings";
|
const gchar *metadata_name = "sm-settings";
|
||||||
|
|
||||||
if (args)
|
if (args)
|
||||||
metadata_name = g_variant_get_string(args, NULL);
|
metadata_name = g_variant_get_string (args, NULL);
|
||||||
|
|
||||||
wp_plugin_register (g_object_new (wp_settings_plugin_get_type (),
|
return G_OBJECT (g_object_new (wp_settings_plugin_get_type (),
|
||||||
"name", "settings",
|
"name", "settings",
|
||||||
"core", core,
|
"core", core,
|
||||||
"metadata-name", metadata_name,
|
"metadata-name", metadata_name,
|
||||||
NULL));
|
NULL));
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
@@ -777,10 +777,9 @@ si_audio_adapter_linkable_init (WpSiLinkableInterface * iface)
|
|||||||
iface->get_ports = si_audio_adapter_get_ports;
|
iface->get_ports = si_audio_adapter_get_ports;
|
||||||
}
|
}
|
||||||
|
|
||||||
WP_PLUGIN_EXPORT gboolean
|
WP_PLUGIN_EXPORT GObject *
|
||||||
wireplumber__module_init (WpCore * core, GVariant * args, GError ** error)
|
wireplumber__module_init (WpCore * core, GVariant * args, GError ** error)
|
||||||
{
|
{
|
||||||
wp_si_factory_register (core, wp_si_factory_new_simple (SI_FACTORY_NAME,
|
return G_OBJECT (wp_si_factory_new_simple (SI_FACTORY_NAME,
|
||||||
si_audio_adapter_get_type ()));
|
si_audio_adapter_get_type ()));
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
@@ -355,10 +355,9 @@ si_audio_virtual_adapter_init (WpSiAdapterInterface * iface)
|
|||||||
iface->set_ports_format_finish = si_audio_virtual_set_ports_format_finish;
|
iface->set_ports_format_finish = si_audio_virtual_set_ports_format_finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
WP_PLUGIN_EXPORT gboolean
|
WP_PLUGIN_EXPORT GObject *
|
||||||
wireplumber__module_init (WpCore * core, GVariant * args, GError ** error)
|
wireplumber__module_init (WpCore * core, GVariant * args, GError ** error)
|
||||||
{
|
{
|
||||||
wp_si_factory_register (core, wp_si_factory_new_simple (SI_FACTORY_NAME,
|
return G_OBJECT (wp_si_factory_new_simple (SI_FACTORY_NAME,
|
||||||
si_audio_virtual_get_type ()));
|
si_audio_virtual_get_type ()));
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
@@ -219,10 +219,9 @@ si_node_linkable_init (WpSiLinkableInterface * iface)
|
|||||||
iface->get_ports = si_node_get_ports;
|
iface->get_ports = si_node_get_ports;
|
||||||
}
|
}
|
||||||
|
|
||||||
WP_PLUGIN_EXPORT gboolean
|
WP_PLUGIN_EXPORT GObject *
|
||||||
wireplumber__module_init (WpCore * core, GVariant * args, GError ** error)
|
wireplumber__module_init (WpCore * core, GVariant * args, GError ** error)
|
||||||
{
|
{
|
||||||
wp_si_factory_register (core, wp_si_factory_new_simple (SI_FACTORY_NAME,
|
return G_OBJECT (wp_si_factory_new_simple (SI_FACTORY_NAME,
|
||||||
si_node_get_type ()));
|
si_node_get_type ()));
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
@@ -775,10 +775,9 @@ si_standard_link_link_init (WpSiLinkInterface * iface)
|
|||||||
iface->get_in_item = si_standard_link_get_in_item;
|
iface->get_in_item = si_standard_link_get_in_item;
|
||||||
}
|
}
|
||||||
|
|
||||||
WP_PLUGIN_EXPORT gboolean
|
WP_PLUGIN_EXPORT GObject *
|
||||||
wireplumber__module_init (WpCore * core, GVariant * args, GError ** error)
|
wireplumber__module_init (WpCore * core, GVariant * args, GError ** error)
|
||||||
{
|
{
|
||||||
wp_si_factory_register (core, wp_si_factory_new_simple (SI_FACTORY_NAME,
|
return G_OBJECT (wp_si_factory_new_simple (SI_FACTORY_NAME,
|
||||||
si_standard_link_get_type ()));
|
si_standard_link_get_type ()));
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
@@ -449,12 +449,11 @@ wp_standard_event_source_class_init (WpStandardEventSourceClass * klass)
|
|||||||
NULL, NULL, NULL, G_TYPE_NONE, 1, TYPE_RESCAN_CONTEXT);
|
NULL, NULL, NULL, G_TYPE_NONE, 1, TYPE_RESCAN_CONTEXT);
|
||||||
}
|
}
|
||||||
|
|
||||||
WP_PLUGIN_EXPORT gboolean
|
WP_PLUGIN_EXPORT GObject *
|
||||||
wireplumber__module_init (WpCore * core, GVariant * args, GError ** error)
|
wireplumber__module_init (WpCore * core, GVariant * args, GError ** error)
|
||||||
{
|
{
|
||||||
wp_plugin_register (g_object_new (wp_standard_event_source_get_type (),
|
return G_OBJECT (g_object_new (wp_standard_event_source_get_type (),
|
||||||
"name", "standard-event-source",
|
"name", "standard-event-source",
|
||||||
"core", core,
|
"core", core,
|
||||||
NULL));
|
NULL));
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
536
src/main.c
536
src/main.c
@@ -36,6 +36,49 @@ static GOptionEntry entries[] =
|
|||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct _ComponentData
|
||||||
|
{
|
||||||
|
gchar *name;
|
||||||
|
gchar *type;
|
||||||
|
gint priority;
|
||||||
|
gint flags;
|
||||||
|
WpSpaJson *deps;
|
||||||
|
};
|
||||||
|
typedef struct _ComponentData ComponentData;
|
||||||
|
|
||||||
|
static gint
|
||||||
|
component_cmp_func (const ComponentData *a, const ComponentData *b)
|
||||||
|
{
|
||||||
|
return b->priority - a->priority;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gint
|
||||||
|
component_equal_func (const ComponentData *a, ComponentData * b)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
g_str_equal (a->name, b->name) && g_str_equal (a->type, b->type) ? 0 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
component_data_free (ComponentData *self)
|
||||||
|
{
|
||||||
|
g_clear_pointer (&self->name, g_free);
|
||||||
|
g_clear_pointer (&self->type, g_free);
|
||||||
|
g_clear_pointer (&self->deps, wp_spa_json_unref);
|
||||||
|
g_slice_free (ComponentData, self);
|
||||||
|
}
|
||||||
|
|
||||||
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ComponentData, component_data_free)
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
NO_FAIL = 0x1,
|
||||||
|
IF_EXISTS = 0x2
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_plugin_loaded (WpCore *core, GAsyncResult *res, gpointer user_data);
|
||||||
|
|
||||||
/*** WpInitTransition ***/
|
/*** WpInitTransition ***/
|
||||||
|
|
||||||
struct _WpInitTransition
|
struct _WpInitTransition
|
||||||
@@ -43,6 +86,7 @@ struct _WpInitTransition
|
|||||||
WpTransition parent;
|
WpTransition parent;
|
||||||
WpObjectManager *om;
|
WpObjectManager *om;
|
||||||
GList *components;
|
GList *components;
|
||||||
|
ComponentData *curr_component;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@@ -78,203 +122,101 @@ wp_init_transition_get_next_step (WpTransition * transition, guint step)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct _component_data component_data;
|
static gboolean
|
||||||
|
component_meets_dependencies (WpCore *core, ComponentData *comp)
|
||||||
struct _component_data
|
|
||||||
{
|
{
|
||||||
gchar *name;
|
g_autoptr (WpConf) conf = NULL;
|
||||||
gchar *type;
|
g_autoptr (WpIterator) it = NULL;
|
||||||
gint priority;
|
g_auto (GValue) item = G_VALUE_INIT;
|
||||||
gint flags;
|
|
||||||
WpSpaJson *deps;
|
|
||||||
};
|
|
||||||
|
|
||||||
static gint
|
if (!comp->deps)
|
||||||
component_cmp_func (const component_data *a, const component_data *b)
|
return TRUE;
|
||||||
{
|
|
||||||
return b->priority - a->priority;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
/* Note that we consider the dependency valid by default if it is not
|
||||||
component_unref (component_data *self)
|
* found in the settings configuration section */
|
||||||
{
|
conf = wp_conf_get_instance (core);
|
||||||
g_free (self->name);
|
it = wp_spa_json_new_iterator (comp->deps);
|
||||||
g_free (self->type);
|
for (; wp_iterator_next (it, &item); g_value_unset (&item)) {
|
||||||
g_clear_pointer (&self->deps, wp_spa_json_unref);
|
WpSpaJson *dep = g_value_get_boxed (&item);
|
||||||
g_slice_free (component_data, self);
|
g_autofree gchar *dep_str = wp_spa_json_parse_string (dep);
|
||||||
}
|
gboolean value = wp_conf_get_value_boolean (conf,
|
||||||
|
"wireplumber.settings", dep_str, TRUE);
|
||||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (component_data, component_unref)
|
if (!value)
|
||||||
|
return FALSE;
|
||||||
static gint
|
|
||||||
is_component_present (const component_data *listed_cmpnt,
|
|
||||||
const gchar *new_cmpnt_name)
|
|
||||||
{
|
|
||||||
return !g_str_equal (listed_cmpnt->name, new_cmpnt_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
NO_FAIL = 0x1,
|
|
||||||
IF_EXISTS = 0x2
|
|
||||||
};
|
|
||||||
|
|
||||||
static gchar *
|
|
||||||
extract_base_name (const gchar *filepath)
|
|
||||||
{
|
|
||||||
gchar *basename = g_path_get_basename (filepath);
|
|
||||||
|
|
||||||
if (!basename)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (g_str_has_prefix (basename, "libwireplumber-module-")) {
|
|
||||||
/* strip the file extension for modules */
|
|
||||||
basename [strlen (basename) - strlen (".so")] = '\0';
|
|
||||||
return basename;
|
|
||||||
} else if (g_str_has_suffix (basename, ".lua"))
|
|
||||||
return basename;
|
|
||||||
else
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gchar *
|
|
||||||
extract_plugin_name (gchar *name)
|
|
||||||
{
|
|
||||||
if (g_file_test (name, G_FILE_TEST_EXISTS)) {
|
|
||||||
/* dangling components */
|
|
||||||
name = extract_base_name (name);
|
|
||||||
}
|
}
|
||||||
if (g_str_has_prefix (name, "libwireplumber-module-"))
|
|
||||||
return g_strdup (name + strlen ("libwireplumber-module-"));
|
return TRUE;
|
||||||
else
|
|
||||||
return g_strdup_printf ("script:%s", name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static gboolean
|
||||||
on_plugin_activated (WpObject *p, GAsyncResult *res, WpInitTransition *self);
|
load_enable_components (WpInitTransition *self)
|
||||||
|
|
||||||
static int
|
|
||||||
load_enable_component (WpInitTransition *self, GError **error)
|
|
||||||
{
|
{
|
||||||
WpCore *core = wp_transition_get_source_object (WP_TRANSITION (self));
|
WpCore *core = wp_transition_get_source_object (WP_TRANSITION (self));
|
||||||
GList *comps = self->components;
|
|
||||||
GList *lcomp = g_list_first (comps);
|
|
||||||
|
|
||||||
while (lcomp) {
|
while (self->components) {
|
||||||
component_data *comp = (component_data *) lcomp->data;
|
self->curr_component = (ComponentData *) self->components->data;
|
||||||
g_autofree gchar *plugin_name = NULL;
|
g_autoptr (GError) error = NULL;
|
||||||
g_autoptr (WpPlugin) plugin = NULL;
|
|
||||||
|
|
||||||
if (comp->deps) {
|
/* Advance */
|
||||||
g_autoptr (WpConf) conf = wp_conf_get_instance (core);
|
self->components = g_list_next (self->components);
|
||||||
g_autoptr (WpIterator) it = wp_spa_json_new_iterator (comp->deps);
|
|
||||||
g_auto (GValue) item = G_VALUE_INIT;
|
|
||||||
gboolean deps_met = TRUE;
|
|
||||||
|
|
||||||
/* Note that we consider the dependency valid by default if it is not
|
/* Skip component if its dependencies are not met */
|
||||||
* found in the settings */
|
if (!component_meets_dependencies (core, self->curr_component)) {
|
||||||
for (; wp_iterator_next (it, &item); g_value_unset (&item)) {
|
wp_info ("... skipping comp '%s' as its dependencies are not met",
|
||||||
WpSpaJson *dep = g_value_get_boxed (&item);
|
self->curr_component->name);
|
||||||
g_autofree gchar *dep_str = wp_spa_json_parse_string (dep);
|
continue;
|
||||||
gboolean value = wp_conf_get_value_boolean (conf,
|
|
||||||
"wireplumber.settings", dep_str, TRUE);
|
|
||||||
if (!value) {
|
|
||||||
deps_met = FALSE;
|
|
||||||
wp_info (".. deps(%s) not met for component(%s), skip loading it",
|
|
||||||
dep_str, comp->name);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!deps_met) {
|
|
||||||
comps = g_list_delete_link (comps, g_steal_pointer (&lcomp));
|
|
||||||
self->components = comps;
|
|
||||||
lcomp = g_list_first (comps);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
wp_debug (".. loading component(%s) type(%s) priority(%d) flags(%x)",
|
|
||||||
comp->name, comp->type, comp->priority, comp->flags);
|
|
||||||
|
|
||||||
g_autoptr (GError) load_error = NULL;
|
|
||||||
if (!wp_core_load_component (core, comp->name, comp->type, NULL,
|
|
||||||
&load_error)) {
|
|
||||||
wp_warning (".. error in loading component (%s)", load_error->message);
|
|
||||||
if ((load_error->code == G_FILE_ERROR_NOENT) ||
|
|
||||||
(load_error->code == G_FILE_ERROR_ACCES)) {
|
|
||||||
|
|
||||||
if (comp->flags & IF_EXISTS) {
|
|
||||||
wp_warning (".. \"ifexists\" flag set, ignore the failure");
|
|
||||||
comps = g_list_delete_link (comps, g_steal_pointer (&lcomp));
|
|
||||||
lcomp = g_list_first (comps);
|
|
||||||
self->components = comps;
|
|
||||||
continue;
|
|
||||||
} else if (comp->flags & NO_FAIL) {
|
|
||||||
wp_warning (".. \"nofail\" flag set, ignore the failure");
|
|
||||||
comps = g_list_delete_link (comps, g_steal_pointer (&lcomp));
|
|
||||||
lcomp = g_list_first (comps);
|
|
||||||
self->components = comps;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
g_propagate_error (error, g_steal_pointer (&load_error));
|
|
||||||
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
}
|
||||||
/* get handle to corresponding plugin & activate it */
|
|
||||||
plugin_name = extract_plugin_name (comp->name);
|
|
||||||
plugin = wp_plugin_find (core, plugin_name);
|
|
||||||
|
|
||||||
if (!plugin) {
|
/* Load the component */
|
||||||
g_autoptr (WpSiFactory) si = wp_si_factory_find (core, plugin_name);
|
wp_debug ("... loading comp '%s' ('%s') with priority '%d' and flags '%x'",
|
||||||
if (si) {
|
self->curr_component->name, self->curr_component->type,
|
||||||
/* si factory modules register factories they need not be activated */
|
self->curr_component->priority, self->curr_component->flags);
|
||||||
comps = g_list_delete_link (comps, g_steal_pointer (&lcomp));
|
wp_core_load_component (core, self->curr_component->name,
|
||||||
lcomp = g_list_first (comps);
|
self->curr_component->type, NULL,
|
||||||
self->components = comps;
|
(GAsyncReadyCallback) on_plugin_loaded, self);
|
||||||
wp_debug (".. enabled si module(%s)", comp->name);
|
return FALSE;
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
wp_warning (".. unable to find (%s) plugin", plugin_name);
|
|
||||||
g_set_error (error, WP_DOMAIN_LIBRARY, WP_LIBRARY_ERROR_OPERATION_FAILED,
|
|
||||||
"unable to find %s plugin", plugin_name);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
wp_debug (".. enabling component(%s) plugin name(%s)", comp->name,
|
|
||||||
plugin_name);
|
|
||||||
|
|
||||||
comps = g_list_delete_link (comps, g_steal_pointer (&lcomp));
|
|
||||||
self->components = comps;
|
|
||||||
wp_object_activate_closure (WP_OBJECT (plugin), WP_OBJECT_FEATURES_ALL,
|
|
||||||
NULL, g_cclosure_new_object (G_CALLBACK (on_plugin_activated),
|
|
||||||
G_OBJECT (self)));
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
|
self->curr_component = NULL;
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
on_plugin_activated (WpObject *p, GAsyncResult *res, WpInitTransition *self)
|
on_plugin_loaded (WpCore *core, GAsyncResult *res, gpointer data)
|
||||||
{
|
{
|
||||||
|
WpInitTransition *self = data;
|
||||||
|
g_autoptr (GObject) o = NULL;
|
||||||
g_autoptr (GError) error = NULL;
|
g_autoptr (GError) error = NULL;
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
if (!wp_object_activate_finish (p, res, &error)) {
|
g_return_if_fail (self->curr_component);
|
||||||
wp_transition_return_error (WP_TRANSITION (self), g_steal_pointer (&error));
|
|
||||||
|
o = wp_core_load_component_finish (core, res, &error);
|
||||||
|
if (!o) {
|
||||||
|
if (self->curr_component->flags & IF_EXISTS &&
|
||||||
|
error->code == G_FILE_ERROR_ISDIR) {
|
||||||
|
wp_info ("skipping component '%s' with 'ifexists' flag because its "
|
||||||
|
"file does not exist", self->curr_component->name);
|
||||||
|
goto next;
|
||||||
|
} else if (self->curr_component->flags & NO_FAIL) {
|
||||||
|
wp_info ("skipping component '%s' with 'nofail' flag because of "
|
||||||
|
"loading error: %s", self->curr_component->name, error->message);
|
||||||
|
goto next;
|
||||||
|
}
|
||||||
|
|
||||||
|
wp_transition_return_error (WP_TRANSITION (self), g_error_new (
|
||||||
|
WP_DOMAIN_DAEMON, WP_EXIT_SOFTWARE,
|
||||||
|
"failed to activate component '%s': %s", self->curr_component->name,
|
||||||
|
error->message));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
wp_debug (".. enabled plugin %s", wp_plugin_get_name (WP_PLUGIN (p)));
|
wp_debug ("successfully enabled plugin %s",
|
||||||
ret = load_enable_component (self, &error);
|
wp_plugin_get_name (WP_PLUGIN (o)));
|
||||||
if (ret < 0) {
|
|
||||||
wp_transition_return_error (WP_TRANSITION (self), g_steal_pointer (&error));
|
next:
|
||||||
}
|
/* load and enable the rest of components */
|
||||||
else if (ret == 0)
|
if (load_enable_components (self))
|
||||||
{
|
|
||||||
wp_debug (".. loading components successful");
|
|
||||||
wp_transition_advance (WP_TRANSITION (self));
|
wp_transition_advance (WP_TRANSITION (self));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -290,88 +232,66 @@ check_media_session (WpObjectManager * om, WpInitTransition *self)
|
|||||||
wp_transition_advance (WP_TRANSITION (self));
|
wp_transition_advance (WP_TRANSITION (self));
|
||||||
}
|
}
|
||||||
|
|
||||||
struct data {
|
|
||||||
WpTransition *transition;
|
|
||||||
int count;
|
|
||||||
GList *components;
|
|
||||||
};
|
|
||||||
|
|
||||||
static gint
|
static gint
|
||||||
pick_default_component_priority (const char *name)
|
pick_default_component_priority (const char *type)
|
||||||
{
|
{
|
||||||
if (g_str_has_suffix (name, ".so"))
|
if (g_str_equal (type, "module"))
|
||||||
/* regular module default priority */
|
/* regular module default priority */
|
||||||
return 110;
|
return 110;
|
||||||
else if (g_str_has_suffix (name, ".lua"))
|
else if (g_str_equal (type, "script/lua"))
|
||||||
/* Lua Script default priority */
|
/* Lua Script default priority */
|
||||||
return 100;
|
return 100;
|
||||||
|
|
||||||
return 100;
|
return 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *
|
static void
|
||||||
pick_component_type (const char *name)
|
append_json_components (GList **list, WpSpaJson *json)
|
||||||
{
|
{
|
||||||
if (g_str_has_suffix (name, ".so"))
|
|
||||||
return g_strdup ("module");
|
|
||||||
else if (g_str_has_suffix (name, ".lua"))
|
|
||||||
return g_strdup ("script/lua");
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
do_parse_json_components (void *data, const char *location, const char *section,
|
|
||||||
const char *str, size_t len)
|
|
||||||
{
|
|
||||||
struct data *d = data;
|
|
||||||
WpTransition *transition = d->transition;
|
|
||||||
g_autoptr (WpSpaJson) json = NULL;
|
|
||||||
g_autoptr (WpIterator) it = NULL;
|
g_autoptr (WpIterator) it = NULL;
|
||||||
g_auto (GValue) item = G_VALUE_INIT;
|
g_auto (GValue) item = G_VALUE_INIT;
|
||||||
|
|
||||||
json = wp_spa_json_new_from_stringn (str, len);
|
|
||||||
|
|
||||||
if (!wp_spa_json_is_array (json)) {
|
if (!wp_spa_json_is_array (json)) {
|
||||||
wp_transition_return_error (transition, g_error_new (
|
wp_warning ("components section is not a JSON array, skipping...");
|
||||||
WP_DOMAIN_DAEMON, WP_EXIT_CONFIG,
|
return;
|
||||||
"wireplumber.components is not a JSON array"));
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
it = wp_spa_json_new_iterator (json);
|
it = wp_spa_json_new_iterator (json);
|
||||||
for (; wp_iterator_next (it, &item); g_value_unset (&item)) {
|
for (; wp_iterator_next (it, &item); g_value_unset (&item)) {
|
||||||
WpSpaJson *cjson = g_value_get_boxed (&item);
|
WpSpaJson *cjson = g_value_get_boxed (&item);
|
||||||
g_autoptr (component_data) component = g_slice_new0 (component_data);
|
g_autoptr (ComponentData) comp = g_slice_new0 (ComponentData);
|
||||||
g_autoptr (WpSpaJson) deps = NULL;
|
g_autoptr (WpSpaJson) deps = NULL;
|
||||||
g_autoptr (WpSpaJson) flags = NULL;
|
g_autoptr (WpSpaJson) flags = NULL;
|
||||||
|
|
||||||
/* name and type are mandatory tags */
|
/* Parse name and type (mandatory) */
|
||||||
if (!wp_spa_json_is_object (cjson) ||
|
if (!wp_spa_json_is_object (cjson) ||
|
||||||
!wp_spa_json_object_get (cjson,
|
!wp_spa_json_object_get (cjson,
|
||||||
"name", "s", &component->name,
|
"name", "s", &comp->name,
|
||||||
"type", "s", &component->type,
|
"type", "s", &comp->type,
|
||||||
NULL)) {
|
NULL)) {
|
||||||
wp_transition_return_error (transition, g_error_new (
|
wp_warning ("component must have both a 'name' and a 'type'");
|
||||||
WP_DOMAIN_DAEMON, WP_EXIT_CONFIG,
|
component_data_free (comp);
|
||||||
"component must have both a 'name' and a 'type'"));
|
continue;
|
||||||
return -EINVAL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!wp_spa_json_object_get (cjson, "priority", "i", &component->priority,
|
/* Parse priority (optional) */
|
||||||
|
if (!wp_spa_json_object_get (cjson, "priority", "i", &comp->priority,
|
||||||
NULL))
|
NULL))
|
||||||
component->priority = pick_default_component_priority (component->name);
|
comp->priority = pick_default_component_priority (comp->type);
|
||||||
|
|
||||||
|
/* Parse deps (optional) */
|
||||||
if (wp_spa_json_object_get (cjson, "deps", "J", &deps, NULL)) {
|
if (wp_spa_json_object_get (cjson, "deps", "J", &deps, NULL)) {
|
||||||
if (deps && wp_spa_json_is_array (deps)) {
|
if (wp_spa_json_is_array (deps)) {
|
||||||
component->deps = g_steal_pointer (&deps);
|
comp->deps = g_steal_pointer (&deps);
|
||||||
} else {
|
} else {
|
||||||
wp_warning ("deps must be an array for component(%s), skip loading it",
|
wp_warning ("skipping component %s as its 'deps' is not a JSON array",
|
||||||
component->name);
|
comp->name);
|
||||||
|
component_data_free (comp);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Parse flags (optional) */
|
||||||
if (wp_spa_json_object_get (cjson, "flags", "J", &flags, NULL)) {
|
if (wp_spa_json_object_get (cjson, "flags", "J", &flags, NULL)) {
|
||||||
if (flags && wp_spa_json_is_array (flags)) {
|
if (flags && wp_spa_json_is_array (flags)) {
|
||||||
g_autoptr (WpIterator) it = wp_spa_json_new_iterator (flags);
|
g_autoptr (WpIterator) it = wp_spa_json_new_iterator (flags);
|
||||||
@@ -382,124 +302,34 @@ do_parse_json_components (void *data, const char *location, const char *section,
|
|||||||
g_autofree gchar *flag_str = wp_spa_json_parse_string (flag);
|
g_autofree gchar *flag_str = wp_spa_json_parse_string (flag);
|
||||||
|
|
||||||
if (g_str_equal (flag_str, "ifexists"))
|
if (g_str_equal (flag_str, "ifexists"))
|
||||||
component->flags |= IF_EXISTS;
|
comp->flags |= IF_EXISTS;
|
||||||
else if (g_str_equal (flag_str, "nofail"))
|
else if (g_str_equal (flag_str, "nofail"))
|
||||||
component->flags |= NO_FAIL;
|
comp->flags |= NO_FAIL;
|
||||||
else
|
else
|
||||||
wp_warning ("flag(%s) is not valid for component(%s)", flag_str,
|
wp_warning ("flag '%s' is not valid for component '%s'", flag_str,
|
||||||
component->name);
|
comp->name);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
wp_warning ("flags must be an array for component(%s), skip loading it",
|
wp_warning ("skipping component %s as its 'flags' is not a JSON array",
|
||||||
component->name);
|
comp->name);
|
||||||
|
component_data_free (comp);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!g_list_find_custom (d->components, component->name,
|
/* Insert component into the list if it does not exist */
|
||||||
(GCompareFunc) is_component_present)) {
|
if (!g_list_find_custom (*list, comp,
|
||||||
wp_trace (".. parsed component(%s) type(%s) priority(%d) flags(%x) "
|
(GCompareFunc) component_equal_func)) {
|
||||||
"deps defined(%s)", component->name, component->type,
|
wp_trace ("appended component '%s' of type '%s' with priority '%d'",
|
||||||
component->priority, component->flags,
|
comp->name, comp->type, comp->priority);
|
||||||
(component->deps) ? "true" : "false");
|
*list = g_list_insert_sorted (*list, g_steal_pointer (&comp),
|
||||||
|
(GCompareFunc) component_cmp_func);
|
||||||
d->components = g_list_insert_sorted (d->components,
|
} else {
|
||||||
g_steal_pointer (&component), (GCompareFunc) component_cmp_func);
|
wp_debug ("ignoring component '%s' as it is already defined previously",
|
||||||
} else
|
comp->name);
|
||||||
wp_info (".. component(%s) already present, ignore this entry",
|
component_data_free (comp);
|
||||||
component->name);
|
}
|
||||||
|
|
||||||
d->count++;
|
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
do_parse_dangling_component (const GValue *item, GValue *ret, gpointer data)
|
|
||||||
{
|
|
||||||
GList *comps = data;
|
|
||||||
const gchar *path = g_value_dup_string (item);
|
|
||||||
g_autofree gchar *basename = NULL;
|
|
||||||
g_autoptr (component_data) comp = g_slice_new0 (component_data);
|
|
||||||
|
|
||||||
comp->type = pick_component_type (path);
|
|
||||||
comp->name = (gchar *) path;
|
|
||||||
comp->priority = pick_default_component_priority (path);
|
|
||||||
|
|
||||||
if (!(basename = extract_base_name (path))) {
|
|
||||||
wp_warning (".. ignore dangling shared object(%s), it is not a wireplumber"
|
|
||||||
" module", path);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!g_list_find_custom (comps, basename,
|
|
||||||
(GCompareFunc) is_component_present)) {
|
|
||||||
wp_debug (".. parsed dangling component(%s) type(%s)", comp->name,
|
|
||||||
comp->type);
|
|
||||||
comps = g_list_insert_sorted (comps, g_steal_pointer (&comp),
|
|
||||||
(GCompareFunc) component_cmp_func);
|
|
||||||
} else
|
|
||||||
wp_warning (".. dangling component(%s) already present, ignore this one",
|
|
||||||
comp->name);
|
|
||||||
|
|
||||||
g_value_set_int (ret, g_value_get_int (ret) + 1);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define CONFIG_DIRS_LOOKUP_SET \
|
|
||||||
(WP_LOOKUP_DIR_ENV_CONFIG | \
|
|
||||||
WP_LOOKUP_DIR_XDG_CONFIG_HOME | \
|
|
||||||
WP_LOOKUP_DIR_ETC | \
|
|
||||||
WP_LOOKUP_DIR_PREFIX_SHARE)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* dangling components are those not present in the json config files but
|
|
||||||
* present in the wireplumber lookup folders.
|
|
||||||
*/
|
|
||||||
static gboolean
|
|
||||||
do_parse_dangling_components (GList *components, GError **error)
|
|
||||||
{
|
|
||||||
g_autoptr (WpIterator) it = NULL;
|
|
||||||
g_auto (GValue) fold_ret = G_VALUE_INIT;
|
|
||||||
gint nfiles = 0;
|
|
||||||
|
|
||||||
/* look for 'modules' folder in the look up folders*/
|
|
||||||
it = wp_new_files_iterator (CONFIG_DIRS_LOOKUP_SET, "modules", ".so");
|
|
||||||
|
|
||||||
g_value_init (&fold_ret, G_TYPE_INT);
|
|
||||||
g_value_set_int (&fold_ret, nfiles);
|
|
||||||
if (!wp_iterator_fold (it, do_parse_dangling_component, &fold_ret,
|
|
||||||
components)) {
|
|
||||||
if (error && G_VALUE_HOLDS (&fold_ret, G_TYPE_ERROR))
|
|
||||||
*error = g_value_dup_boxed (&fold_ret);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
nfiles = g_value_get_int (&fold_ret);
|
|
||||||
if (nfiles > 0) {
|
|
||||||
wp_info (".. parsed %d dangling modules", nfiles);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_clear_pointer (&it, wp_iterator_unref);
|
|
||||||
g_value_unset (&fold_ret);
|
|
||||||
nfiles = 0;
|
|
||||||
|
|
||||||
/* look for 'scripts' folder in the look up folders*/
|
|
||||||
it = wp_new_files_iterator (CONFIG_DIRS_LOOKUP_SET, "scripts", ".lua");
|
|
||||||
|
|
||||||
g_value_init (&fold_ret, G_TYPE_INT);
|
|
||||||
g_value_set_int (&fold_ret, nfiles);
|
|
||||||
if (!wp_iterator_fold (it, do_parse_dangling_component, &fold_ret,
|
|
||||||
components)) {
|
|
||||||
if (error && G_VALUE_HOLDS (&fold_ret, G_TYPE_ERROR))
|
|
||||||
*error = g_value_dup_boxed (&fold_ret);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
nfiles = g_value_get_int (&fold_ret);
|
|
||||||
if (nfiles > 0) {
|
|
||||||
wp_info (".. parsed %d dangling scripts", nfiles);
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -552,47 +382,25 @@ wp_init_transition_execute_step (WpTransition * transition, guint step)
|
|||||||
}
|
}
|
||||||
|
|
||||||
case STEP_PARSE_COMPONENTS: {
|
case STEP_PARSE_COMPONENTS: {
|
||||||
struct data data = { .transition = transition, .components = NULL };
|
g_autoptr (WpConf) conf = wp_conf_get_instance (core);
|
||||||
GError *error = NULL;
|
g_autoptr (WpSpaJson) json_comps = NULL;
|
||||||
wp_info_object (self, "parse wireplumber components...");
|
|
||||||
|
|
||||||
if (pw_context_conf_section_for_each (pw_ctx, "wireplumber.components",
|
wp_info_object (self, "parsing components...");
|
||||||
do_parse_json_components, &data) < 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (data.count == 0) {
|
/* Append components that are defined in the configuration section */
|
||||||
wp_transition_return_error (transition, g_error_new (
|
json_comps = wp_conf_get_section (conf, "wireplumber.components", NULL);
|
||||||
WP_DOMAIN_DAEMON, WP_EXIT_CONFIG,
|
if (json_comps)
|
||||||
"No components configured in the context conf file; nothing to do"));
|
append_json_components (&self->components, json_comps);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!do_parse_dangling_components (data.components, &error)) {
|
|
||||||
wp_warning ("..error in traversing dangling components (%s)",
|
|
||||||
error->message);
|
|
||||||
wp_transition_return_error (transition, error);
|
|
||||||
}
|
|
||||||
|
|
||||||
self->components = g_steal_pointer (&data.components);
|
|
||||||
wp_transition_advance (transition);
|
wp_transition_advance (transition);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case STEP_LOAD_ENABLE_COMPONENTS: {
|
case STEP_LOAD_ENABLE_COMPONENTS:
|
||||||
g_autoptr (GError) error = NULL;
|
wp_info ("loading and enabling components...");
|
||||||
int ret = 0;
|
if (load_enable_components (self))
|
||||||
wp_info ("load enable components..");
|
wp_transition_advance (WP_TRANSITION (self));
|
||||||
|
|
||||||
ret = load_enable_component (self, &error);
|
|
||||||
if (ret < 0) {
|
|
||||||
wp_transition_return_error (transition, g_steal_pointer (&error));
|
|
||||||
} else if (ret == 0) {
|
|
||||||
g_set_error (&error, WP_DOMAIN_LIBRARY, WP_LIBRARY_ERROR_OPERATION_FAILED,
|
|
||||||
"list of components not available to load");
|
|
||||||
wp_transition_return_error (transition, g_steal_pointer (&error));
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
case STEP_CHECK_MEDIA_SESSION: {
|
case STEP_CHECK_MEDIA_SESSION: {
|
||||||
wp_info_object (self, "Checking for session manager conflicts...");
|
wp_info_object (self, "Checking for session manager conflicts...");
|
||||||
@@ -610,12 +418,14 @@ wp_init_transition_execute_step (WpTransition * transition, guint step)
|
|||||||
case STEP_CLEANUP:
|
case STEP_CLEANUP:
|
||||||
wp_info ("wirePlumber initialized");
|
wp_info ("wirePlumber initialized");
|
||||||
g_clear_object (&self->om);
|
g_clear_object (&self->om);
|
||||||
g_list_free_full (self->components, (GDestroyNotify) component_unref);
|
g_list_free_full (self->components, (GDestroyNotify) component_data_free);
|
||||||
|
self->components = NULL;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WP_TRANSITION_STEP_ERROR:
|
case WP_TRANSITION_STEP_ERROR:
|
||||||
g_clear_object (&self->om);
|
g_clear_object (&self->om);
|
||||||
g_list_free_full (self->components, (GDestroyNotify) component_unref);
|
g_list_free_full (self->components, (GDestroyNotify) component_data_free);
|
||||||
|
self->components = NULL;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@@ -25,7 +25,6 @@ struct _WpCtl
|
|||||||
GOptionContext *context;
|
GOptionContext *context;
|
||||||
GMainLoop *loop;
|
GMainLoop *loop;
|
||||||
WpCore *core;
|
WpCore *core;
|
||||||
GPtrArray *apis;
|
|
||||||
WpObjectManager *om;
|
WpObjectManager *om;
|
||||||
guint pending_plugins;
|
guint pending_plugins;
|
||||||
gint exit_code;
|
gint exit_code;
|
||||||
@@ -75,7 +74,6 @@ G_DEFINE_QUARK (wpctl-error, wpctl_error_domain)
|
|||||||
static void
|
static void
|
||||||
wp_ctl_clear (WpCtl * self)
|
wp_ctl_clear (WpCtl * self)
|
||||||
{
|
{
|
||||||
g_clear_pointer (&self->apis, g_ptr_array_unref);
|
|
||||||
g_clear_object (&self->om);
|
g_clear_object (&self->om);
|
||||||
g_clear_object (&self->core);
|
g_clear_object (&self->core);
|
||||||
g_clear_pointer (&self->loop, g_main_loop_unref);
|
g_clear_pointer (&self->loop, g_main_loop_unref);
|
||||||
@@ -1305,17 +1303,25 @@ static const struct subcommand {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
on_plugin_activated (WpObject * p, GAsyncResult * res, WpCtl * ctl)
|
on_plugin_loaded (WpCore * core, GAsyncResult * res, WpCtl *ctl)
|
||||||
{
|
{
|
||||||
g_autoptr (GError) error = NULL;
|
g_autoptr (GObject) o = NULL;
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
if (!wp_object_activate_finish (p, res, &error)) {
|
o = wp_core_load_component_finish (core, res, &error);
|
||||||
fprintf (stderr, "%s", error->message);
|
if (!o) {
|
||||||
|
fprintf (stderr, "%s\n", error->message);
|
||||||
ctl->exit_code = 1;
|
ctl->exit_code = 1;
|
||||||
g_main_loop_quit (ctl->loop);
|
g_main_loop_quit (ctl->loop);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (WP_IS_PLUGIN (o)) {
|
||||||
|
const gchar *name = wp_plugin_get_name (WP_PLUGIN (o));
|
||||||
|
if (g_str_equal (name, "mixer-api"))
|
||||||
|
g_object_set (o, "scale", 1 /* cubic */, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
if (--ctl->pending_plugins == 0)
|
if (--ctl->pending_plugins == 0)
|
||||||
wp_core_install_object_manager (ctl->core, ctl->om);
|
wp_core_install_object_manager (ctl->core, ctl->om);
|
||||||
}
|
}
|
||||||
@@ -1336,7 +1342,6 @@ main (gint argc, gchar **argv)
|
|||||||
"COMMAND [COMMAND_OPTIONS] - WirePlumber Control CLI");
|
"COMMAND [COMMAND_OPTIONS] - WirePlumber Control CLI");
|
||||||
ctl.loop = g_main_loop_new (NULL, FALSE);
|
ctl.loop = g_main_loop_new (NULL, FALSE);
|
||||||
ctl.core = wp_core_new (NULL, NULL);
|
ctl.core = wp_core_new (NULL, NULL);
|
||||||
ctl.apis = g_ptr_array_new_with_free_func (g_object_unref);
|
|
||||||
ctl.om = wp_object_manager_new ();
|
ctl.om = wp_object_manager_new ();
|
||||||
|
|
||||||
/* find the subcommand */
|
/* find the subcommand */
|
||||||
@@ -1403,22 +1408,12 @@ main (gint argc, gchar **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* load required API modules */
|
/* load required API modules */
|
||||||
if (!wp_core_load_component (ctl.core,
|
ctl.pending_plugins++;
|
||||||
"libwireplumber-module-default-nodes-api", "module", NULL, &error)) {
|
wp_core_load_component (ctl.core, "libwireplumber-module-default-nodes-api",
|
||||||
fprintf (stderr, "%s\n", error->message);
|
"module", NULL, (GAsyncReadyCallback) on_plugin_loaded, &ctl);
|
||||||
return 1;
|
ctl.pending_plugins++;
|
||||||
}
|
wp_core_load_component (ctl.core, "libwireplumber-module-mixer-api",
|
||||||
if (!wp_core_load_component (ctl.core,
|
"module", NULL, (GAsyncReadyCallback) on_plugin_loaded, &ctl);
|
||||||
"libwireplumber-module-mixer-api", "module", NULL, &error)) {
|
|
||||||
fprintf (stderr, "%s\n", error->message);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
g_ptr_array_add (ctl.apis, wp_plugin_find (ctl.core, "default-nodes-api"));
|
|
||||||
g_ptr_array_add (ctl.apis, ({
|
|
||||||
WpPlugin *p = wp_plugin_find (ctl.core, "mixer-api");
|
|
||||||
g_object_set (G_OBJECT (p), "scale", 1 /* cubic */, NULL);
|
|
||||||
p;
|
|
||||||
}));
|
|
||||||
|
|
||||||
/* connect */
|
/* connect */
|
||||||
if (!wp_core_connect (ctl.core)) {
|
if (!wp_core_connect (ctl.core)) {
|
||||||
@@ -1432,13 +1427,6 @@ main (gint argc, gchar **argv)
|
|||||||
g_signal_connect_swapped (ctl.om, "installed",
|
g_signal_connect_swapped (ctl.om, "installed",
|
||||||
(GCallback) cmd->run, &ctl);
|
(GCallback) cmd->run, &ctl);
|
||||||
|
|
||||||
for (guint i = 0; i < ctl.apis->len; i++) {
|
|
||||||
WpPlugin *plugin = g_ptr_array_index (ctl.apis, i);
|
|
||||||
ctl.pending_plugins++;
|
|
||||||
wp_object_activate (WP_OBJECT (plugin), WP_PLUGIN_FEATURE_ENABLED, NULL,
|
|
||||||
(GAsyncReadyCallback) on_plugin_activated, &ctl);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_main_loop_run (ctl.loop);
|
g_main_loop_run (ctl.loop);
|
||||||
|
|
||||||
wp_ctl_clear (&ctl);
|
wp_ctl_clear (&ctl);
|
||||||
|
@@ -103,10 +103,13 @@ wp_init_transition_get_next_step (WpTransition * transition, guint step)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
on_plugin_activated (WpObject * p, GAsyncResult * res, WpInitTransition *self)
|
on_plugin_loaded (WpCore * core, GAsyncResult * res, WpInitTransition *self)
|
||||||
{
|
{
|
||||||
|
g_autoptr (GObject) o = NULL;
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
if (!wp_object_activate_finish (p, res, &error)) {
|
|
||||||
|
o = wp_core_load_component_finish (core, res, &error);
|
||||||
|
if (!o) {
|
||||||
wp_transition_return_error (WP_TRANSITION (self), error);
|
wp_transition_return_error (WP_TRANSITION (self), error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -119,7 +122,6 @@ wp_init_transition_execute_step (WpTransition * transition, guint step)
|
|||||||
{
|
{
|
||||||
WpInitTransition *self = WP_INIT_TRANSITION (transition);
|
WpInitTransition *self = WP_INIT_TRANSITION (transition);
|
||||||
WpCore *core = wp_transition_get_source_object (transition);
|
WpCore *core = wp_transition_get_source_object (transition);
|
||||||
GError *error = NULL;
|
|
||||||
|
|
||||||
switch (step) {
|
switch (step) {
|
||||||
case STEP_CONNECT:
|
case STEP_CONNECT:
|
||||||
@@ -134,42 +136,17 @@ wp_init_transition_execute_step (WpTransition * transition, guint step)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case STEP_ACTIVATE_PLUGINS: {
|
case STEP_ACTIVATE_PLUGINS: {
|
||||||
if (!wp_core_load_component (core, "libwireplumber-module-lua-scripting",
|
wp_core_load_component (core, "libwireplumber-module-lua-scripting",
|
||||||
"module", NULL, &error)) {
|
"module", NULL, (GAsyncReadyCallback) on_plugin_loaded, self);
|
||||||
wp_transition_return_error (transition, error);
|
wp_core_load_component (core, "libwireplumber-module-standard-event-source",
|
||||||
return;
|
"module", NULL, (GAsyncReadyCallback) on_plugin_loaded, self);
|
||||||
}
|
|
||||||
if (!wp_core_load_component (core,
|
|
||||||
"libwireplumber-module-standard-event-source", "module", NULL,
|
|
||||||
&error)) {
|
|
||||||
wp_transition_return_error (transition, error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
g_autoptr (WpPlugin) p = wp_plugin_find (core, "lua-scripting");
|
|
||||||
wp_object_activate (WP_OBJECT (p), WP_PLUGIN_FEATURE_ENABLED, NULL,
|
|
||||||
(GAsyncReadyCallback) on_plugin_activated, self);
|
|
||||||
|
|
||||||
g_clear_object (&p);
|
|
||||||
p = wp_plugin_find (core, "standard-event-source");
|
|
||||||
wp_object_activate (WP_OBJECT (p), WP_PLUGIN_FEATURE_ENABLED, NULL,
|
|
||||||
(GAsyncReadyCallback) on_plugin_activated, self);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case STEP_ACTIVATE_SCRIPT: {
|
case STEP_ACTIVATE_SCRIPT: {
|
||||||
|
|
||||||
GVariant *args = g_variant_builder_end (&exec_args_b);
|
GVariant *args = g_variant_builder_end (&exec_args_b);
|
||||||
if (!wp_core_load_component (core, exec_script, "script/lua", args,
|
wp_core_load_component (core, exec_script, "script/lua", args,
|
||||||
&error)) {
|
(GAsyncReadyCallback) on_plugin_loaded, self);
|
||||||
wp_transition_return_error (transition, error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_autofree gchar *name = g_strdup_printf ("script:%s", exec_script);
|
|
||||||
g_autoptr (WpPlugin) p = wp_plugin_find (core, name);
|
|
||||||
|
|
||||||
wp_object_activate (WP_OBJECT (p), WP_PLUGIN_FEATURE_ENABLED, NULL,
|
|
||||||
(GAsyncReadyCallback) on_plugin_activated, self);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -19,15 +19,28 @@ typedef struct {
|
|||||||
gchar *evtype;
|
gchar *evtype;
|
||||||
} TestFixture;
|
} TestFixture;
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_plugin_loaded (WpCore * core, GAsyncResult * res, TestFixture *f)
|
||||||
|
{
|
||||||
|
g_autoptr (GObject) o = NULL;
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
o = wp_core_load_component_finish (core, res, &error);
|
||||||
|
g_assert_nonnull (o);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
|
||||||
|
g_main_loop_quit (f->base.loop);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_file_monitor_setup (TestFixture * f, gconstpointer user_data)
|
test_file_monitor_setup (TestFixture * f, gconstpointer user_data)
|
||||||
{
|
{
|
||||||
wp_base_test_fixture_setup (&f->base, WP_BASE_TEST_FLAG_DONT_CONNECT);
|
wp_base_test_fixture_setup (&f->base, WP_BASE_TEST_FLAG_DONT_CONNECT);
|
||||||
g_autoptr (GError) error = NULL;
|
|
||||||
|
|
||||||
wp_core_load_component (f->base.core,
|
wp_core_load_component (f->base.core,
|
||||||
"libwireplumber-module-file-monitor-api", "module", NULL, &error);
|
"libwireplumber-module-file-monitor-api", "module", NULL,
|
||||||
g_assert_no_error (error);
|
(GAsyncReadyCallback) on_plugin_loaded, f);
|
||||||
|
g_main_loop_run (f->base.loop);
|
||||||
|
|
||||||
f->plugin = wp_plugin_find (f->base.core, "file-monitor-api");
|
f->plugin = wp_plugin_find (f->base.core, "file-monitor-api");
|
||||||
g_assert_nonnull (f->plugin);
|
g_assert_nonnull (f->plugin);
|
||||||
@@ -46,16 +59,6 @@ test_file_monitor_teardown (TestFixture * f, gconstpointer user_data)
|
|||||||
wp_base_test_fixture_teardown (&f->base);
|
wp_base_test_fixture_teardown (&f->base);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
on_plugin_activated (WpObject * plugin, GAsyncResult * res, TestFixture * f)
|
|
||||||
{
|
|
||||||
g_autoptr (GError) error = NULL;
|
|
||||||
if (!wp_object_activate_finish (plugin, res, &error)) {
|
|
||||||
wp_critical_object (plugin, "%s", error->message);
|
|
||||||
g_main_loop_quit (f->base.loop);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
on_changed (WpPlugin *plugin, const gchar *file, const gchar *old,
|
on_changed (WpPlugin *plugin, const gchar *file, const gchar *old,
|
||||||
const char *evtype, TestFixture * f)
|
const char *evtype, TestFixture * f)
|
||||||
@@ -72,11 +75,6 @@ test_file_monitor_basic (TestFixture * f, gconstpointer user_data)
|
|||||||
{
|
{
|
||||||
gboolean res = FALSE;
|
gboolean res = FALSE;
|
||||||
|
|
||||||
/* activate plugin */
|
|
||||||
g_assert_nonnull (f->plugin);
|
|
||||||
wp_object_activate (WP_OBJECT (f->plugin), WP_PLUGIN_FEATURE_ENABLED,
|
|
||||||
NULL, (GAsyncReadyCallback) on_plugin_activated, f);
|
|
||||||
|
|
||||||
/* delete the 'foo' file if it exists in path */
|
/* delete the 'foo' file if it exists in path */
|
||||||
g_autofree gchar *filename = g_build_filename (f->path, "foo", NULL);
|
g_autofree gchar *filename = g_build_filename (f->path, "foo", NULL);
|
||||||
(void) remove (filename);
|
(void) remove (filename);
|
||||||
|
@@ -21,6 +21,19 @@ typedef struct {
|
|||||||
gint expected_rd2_state;
|
gint expected_rd2_state;
|
||||||
} RdTestFixture;
|
} RdTestFixture;
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_plugin_loaded (WpCore * core, GAsyncResult * res, RdTestFixture *f)
|
||||||
|
{
|
||||||
|
g_autoptr (GObject) o = NULL;
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
o = wp_core_load_component_finish (core, res, &error);
|
||||||
|
g_assert_nonnull (o);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
|
||||||
|
g_main_loop_quit (f->base.loop);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_rd_setup (RdTestFixture *f, gconstpointer data)
|
test_rd_setup (RdTestFixture *f, gconstpointer data)
|
||||||
{
|
{
|
||||||
@@ -31,16 +44,16 @@ test_rd_setup (RdTestFixture *f, gconstpointer data)
|
|||||||
g_test_dbus_up (f->test_dbus);
|
g_test_dbus_up (f->test_dbus);
|
||||||
|
|
||||||
{
|
{
|
||||||
g_autoptr (GError) error = NULL;
|
|
||||||
wp_core_load_component (f->base.core,
|
wp_core_load_component (f->base.core,
|
||||||
"libwireplumber-module-reserve-device", "module", NULL, &error);
|
"libwireplumber-module-reserve-device", "module", NULL,
|
||||||
g_assert_no_error (error);
|
(GAsyncReadyCallback) on_plugin_loaded, f);
|
||||||
|
g_main_loop_run (f->base.loop);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
g_autoptr (GError) error = NULL;
|
|
||||||
wp_core_load_component (f->base.client_core,
|
wp_core_load_component (f->base.client_core,
|
||||||
"libwireplumber-module-reserve-device", "module", NULL, &error);
|
"libwireplumber-module-reserve-device", "module", NULL,
|
||||||
g_assert_no_error (error);
|
(GAsyncReadyCallback) on_plugin_loaded, f);
|
||||||
|
g_main_loop_run (f->base.loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
f->rd_plugin_1 = wp_plugin_find (f->base.core, "reserve-device");
|
f->rd_plugin_1 = wp_plugin_find (f->base.core, "reserve-device");
|
||||||
@@ -68,16 +81,6 @@ test_rd_teardown (RdTestFixture *f, gconstpointer data)
|
|||||||
wp_base_test_fixture_teardown (&f->base);
|
wp_base_test_fixture_teardown (&f->base);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
on_plugin_activated (WpObject * plugin, GAsyncResult * res, RdTestFixture * f)
|
|
||||||
{
|
|
||||||
g_autoptr (GError) error = NULL;
|
|
||||||
if (!wp_object_activate_finish (plugin, res, &error)) {
|
|
||||||
wp_critical_object (plugin, "%s", error->message);
|
|
||||||
g_main_loop_quit (f->base.loop);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ensure_plugins_stable_state (GObject * obj, GParamSpec * spec, RdTestFixture *f)
|
ensure_plugins_stable_state (GObject * obj, GParamSpec * spec, RdTestFixture *f)
|
||||||
{
|
{
|
||||||
@@ -92,24 +95,13 @@ static void
|
|||||||
test_rd_plugin (RdTestFixture *f, gconstpointer data)
|
test_rd_plugin (RdTestFixture *f, gconstpointer data)
|
||||||
{
|
{
|
||||||
GObject *rd1 = NULL, *rd2 = NULL, *rd_video = NULL, *tmp = NULL;
|
GObject *rd1 = NULL, *rd2 = NULL, *rd_video = NULL, *tmp = NULL;
|
||||||
gint state = 0xffff;
|
gint state = 0;
|
||||||
gchar *str;
|
gchar *str;
|
||||||
|
|
||||||
g_object_get (f->dbus_1, "state", &state, NULL);
|
|
||||||
g_assert_cmpint (state, ==, 0);
|
|
||||||
g_object_get (f->dbus_2, "state", &state, NULL);
|
|
||||||
g_assert_cmpint (state, ==, 0);
|
|
||||||
|
|
||||||
wp_object_activate (WP_OBJECT (f->rd_plugin_1), WP_PLUGIN_FEATURE_ENABLED,
|
|
||||||
NULL, (GAsyncReadyCallback) on_plugin_activated, f);
|
|
||||||
wp_object_activate (WP_OBJECT (f->rd_plugin_2), WP_PLUGIN_FEATURE_ENABLED,
|
|
||||||
NULL, (GAsyncReadyCallback) on_plugin_activated, f);
|
|
||||||
|
|
||||||
g_signal_connect (f->dbus_1, "notify::state",
|
g_signal_connect (f->dbus_1, "notify::state",
|
||||||
G_CALLBACK (ensure_plugins_stable_state), f);
|
G_CALLBACK (ensure_plugins_stable_state), f);
|
||||||
g_signal_connect (f->dbus_2, "notify::state",
|
g_signal_connect (f->dbus_2, "notify::state",
|
||||||
G_CALLBACK (ensure_plugins_stable_state), f);
|
G_CALLBACK (ensure_plugins_stable_state), f);
|
||||||
g_main_loop_run (f->base.loop);
|
|
||||||
|
|
||||||
g_object_get (f->dbus_1, "state", &state, NULL);
|
g_object_get (f->dbus_1, "state", &state, NULL);
|
||||||
g_assert_cmpint (state, ==, 2);
|
g_assert_cmpint (state, ==, 2);
|
||||||
@@ -183,23 +175,12 @@ static void
|
|||||||
test_rd_conn_closed (RdTestFixture *f, gconstpointer data)
|
test_rd_conn_closed (RdTestFixture *f, gconstpointer data)
|
||||||
{
|
{
|
||||||
GObject *rd1 = NULL;
|
GObject *rd1 = NULL;
|
||||||
gint state = 0xffff;
|
gint state = 0;
|
||||||
|
|
||||||
g_object_get (f->dbus_1, "state", &state, NULL);
|
|
||||||
g_assert_cmpint (state, ==, 0);
|
|
||||||
g_object_get (f->dbus_2, "state", &state, NULL);
|
|
||||||
g_assert_cmpint (state, ==, 0);
|
|
||||||
|
|
||||||
wp_object_activate (WP_OBJECT (f->rd_plugin_1), WP_PLUGIN_FEATURE_ENABLED,
|
|
||||||
NULL, (GAsyncReadyCallback) on_plugin_activated, f);
|
|
||||||
wp_object_activate (WP_OBJECT (f->rd_plugin_2), WP_PLUGIN_FEATURE_ENABLED,
|
|
||||||
NULL, (GAsyncReadyCallback) on_plugin_activated, f);
|
|
||||||
|
|
||||||
g_signal_connect (f->dbus_1, "notify::state",
|
g_signal_connect (f->dbus_1, "notify::state",
|
||||||
G_CALLBACK (ensure_plugins_stable_state), f);
|
G_CALLBACK (ensure_plugins_stable_state), f);
|
||||||
g_signal_connect (f->dbus_2, "notify::state",
|
g_signal_connect (f->dbus_2, "notify::state",
|
||||||
G_CALLBACK (ensure_plugins_stable_state), f);
|
G_CALLBACK (ensure_plugins_stable_state), f);
|
||||||
g_main_loop_run (f->base.loop);
|
|
||||||
|
|
||||||
g_object_get (f->dbus_1, "state", &state, NULL);
|
g_object_get (f->dbus_1, "state", &state, NULL);
|
||||||
g_assert_cmpint (state, ==, 2);
|
g_assert_cmpint (state, ==, 2);
|
||||||
@@ -260,24 +241,13 @@ static void
|
|||||||
test_rd_acquire_release (RdTestFixture *f, gconstpointer data)
|
test_rd_acquire_release (RdTestFixture *f, gconstpointer data)
|
||||||
{
|
{
|
||||||
GObject *rd1 = NULL, *rd2 = NULL;
|
GObject *rd1 = NULL, *rd2 = NULL;
|
||||||
gint state = 0xffff;
|
gint state = 0;
|
||||||
gchar *str = NULL;
|
gchar *str = NULL;
|
||||||
|
|
||||||
g_object_get (f->dbus_1, "state", &state, NULL);
|
|
||||||
g_assert_cmpint (state, ==, 0);
|
|
||||||
g_object_get (f->dbus_2, "state", &state, NULL);
|
|
||||||
g_assert_cmpint (state, ==, 0);
|
|
||||||
|
|
||||||
wp_object_activate (WP_OBJECT (f->rd_plugin_1), WP_PLUGIN_FEATURE_ENABLED,
|
|
||||||
NULL, (GAsyncReadyCallback) on_plugin_activated, f);
|
|
||||||
wp_object_activate (WP_OBJECT (f->rd_plugin_2), WP_PLUGIN_FEATURE_ENABLED,
|
|
||||||
NULL, (GAsyncReadyCallback) on_plugin_activated, f);
|
|
||||||
|
|
||||||
g_signal_connect (f->dbus_1, "notify::state",
|
g_signal_connect (f->dbus_1, "notify::state",
|
||||||
G_CALLBACK (ensure_plugins_stable_state), f);
|
G_CALLBACK (ensure_plugins_stable_state), f);
|
||||||
g_signal_connect (f->dbus_2, "notify::state",
|
g_signal_connect (f->dbus_2, "notify::state",
|
||||||
G_CALLBACK (ensure_plugins_stable_state), f);
|
G_CALLBACK (ensure_plugins_stable_state), f);
|
||||||
g_main_loop_run (f->base.loop);
|
|
||||||
|
|
||||||
g_object_get (f->dbus_1, "state", &state, NULL);
|
g_object_get (f->dbus_1, "state", &state, NULL);
|
||||||
g_assert_cmpint (state, ==, 2);
|
g_assert_cmpint (state, ==, 2);
|
||||||
|
@@ -12,6 +12,17 @@ typedef struct {
|
|||||||
WpBaseTestFixture base;
|
WpBaseTestFixture base;
|
||||||
} TestFixture;
|
} TestFixture;
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_plugin_loaded (WpCore * core, GAsyncResult * res, TestFixture *f)
|
||||||
|
{
|
||||||
|
g_autoptr (GObject) o = NULL;
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
o = wp_core_load_component_finish (core, res, &error);
|
||||||
|
g_assert_nonnull (o);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_si_audio_adapter_setup (TestFixture * f, gconstpointer user_data)
|
test_si_audio_adapter_setup (TestFixture * f, gconstpointer user_data)
|
||||||
{
|
{
|
||||||
@@ -30,10 +41,9 @@ test_si_audio_adapter_setup (TestFixture * f, gconstpointer user_data)
|
|||||||
"libpipewire-module-adapter", NULL, NULL));
|
"libpipewire-module-adapter", NULL, NULL));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
g_autoptr (GError) error = NULL;
|
|
||||||
wp_core_load_component (f->base.core,
|
wp_core_load_component (f->base.core,
|
||||||
"libwireplumber-module-si-audio-adapter", "module", NULL, &error);
|
"libwireplumber-module-si-audio-adapter", "module", NULL,
|
||||||
g_assert_no_error (error);
|
(GAsyncReadyCallback) on_plugin_loaded, f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -12,6 +12,17 @@ typedef struct {
|
|||||||
WpBaseTestFixture base;
|
WpBaseTestFixture base;
|
||||||
} TestFixture;
|
} TestFixture;
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_plugin_loaded (WpCore * core, GAsyncResult * res, TestFixture *f)
|
||||||
|
{
|
||||||
|
g_autoptr (GObject) o = NULL;
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
o = wp_core_load_component_finish (core, res, &error);
|
||||||
|
g_assert_nonnull (o);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_si_audio_virtual_setup (TestFixture * f, gconstpointer user_data)
|
test_si_audio_virtual_setup (TestFixture * f, gconstpointer user_data)
|
||||||
{
|
{
|
||||||
@@ -28,16 +39,14 @@ test_si_audio_virtual_setup (TestFixture * f, gconstpointer user_data)
|
|||||||
"libpipewire-module-adapter", NULL, NULL));
|
"libpipewire-module-adapter", NULL, NULL));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
g_autoptr (GError) error = NULL;
|
|
||||||
wp_core_load_component (f->base.core,
|
wp_core_load_component (f->base.core,
|
||||||
"libwireplumber-module-si-audio-adapter", "module", NULL, &error);
|
"libwireplumber-module-si-audio-adapter", "module", NULL,
|
||||||
g_assert_no_error (error);
|
(GAsyncReadyCallback) on_plugin_loaded, f);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
g_autoptr (GError) error = NULL;
|
|
||||||
wp_core_load_component (f->base.core,
|
wp_core_load_component (f->base.core,
|
||||||
"libwireplumber-module-si-audio-virtual", "module", NULL, &error);
|
"libwireplumber-module-si-audio-virtual", "module", NULL,
|
||||||
g_assert_no_error (error);
|
(GAsyncReadyCallback) on_plugin_loaded, f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -20,6 +20,17 @@ typedef struct {
|
|||||||
WpDirection expected_direction;
|
WpDirection expected_direction;
|
||||||
} TestData;
|
} TestData;
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_plugin_loaded (WpCore * core, GAsyncResult * res, TestFixture *f)
|
||||||
|
{
|
||||||
|
g_autoptr (GObject) o = NULL;
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
o = wp_core_load_component_finish (core, res, &error);
|
||||||
|
g_assert_nonnull (o);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_si_node_setup (TestFixture * f, gconstpointer user_data)
|
test_si_node_setup (TestFixture * f, gconstpointer user_data)
|
||||||
{
|
{
|
||||||
@@ -36,10 +47,9 @@ test_si_node_setup (TestFixture * f, gconstpointer user_data)
|
|||||||
"libpipewire-module-spa-node-factory", NULL, NULL));
|
"libpipewire-module-spa-node-factory", NULL, NULL));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
g_autoptr (GError) error = NULL;
|
|
||||||
wp_core_load_component (f->base.core,
|
wp_core_load_component (f->base.core,
|
||||||
"libwireplumber-module-si-node", "module", NULL, &error);
|
"libwireplumber-module-si-node", "module", NULL,
|
||||||
g_assert_no_error (error);
|
(GAsyncReadyCallback) on_plugin_loaded, f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -65,6 +65,17 @@ load_node (TestFixture * f, const gchar * factory, const gchar * media_class,
|
|||||||
return g_steal_pointer (&adapter);
|
return g_steal_pointer (&adapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_plugin_loaded (WpCore * core, GAsyncResult * res, TestFixture *f)
|
||||||
|
{
|
||||||
|
g_autoptr (GObject) o = NULL;
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
o = wp_core_load_component_finish (core, res, &error);
|
||||||
|
g_assert_nonnull (o);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_si_standard_link_setup (TestFixture * f, gconstpointer user_data)
|
test_si_standard_link_setup (TestFixture * f, gconstpointer user_data)
|
||||||
{
|
{
|
||||||
@@ -83,14 +94,13 @@ test_si_standard_link_setup (TestFixture * f, gconstpointer user_data)
|
|||||||
"libpipewire-module-link-factory", NULL, NULL));
|
"libpipewire-module-link-factory", NULL, NULL));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
g_autoptr (GError) error = NULL;
|
|
||||||
wp_core_load_component (f->base.core,
|
wp_core_load_component (f->base.core,
|
||||||
"libwireplumber-module-si-audio-adapter", "module", NULL, &error);
|
"libwireplumber-module-si-audio-adapter", "module", NULL,
|
||||||
g_assert_no_error (error);
|
(GAsyncReadyCallback) on_plugin_loaded, f);
|
||||||
|
|
||||||
wp_core_load_component (f->base.core,
|
wp_core_load_component (f->base.core,
|
||||||
"libwireplumber-module-si-standard-link", "module", NULL, &error);
|
"libwireplumber-module-si-standard-link", "module", NULL,
|
||||||
g_assert_no_error (error);
|
(GAsyncReadyCallback) on_plugin_loaded, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (test_is_spa_lib_installed (&f->base, "audiotestsrc"))
|
if (test_is_spa_lib_installed (&f->base, "audiotestsrc"))
|
||||||
|
@@ -169,6 +169,20 @@ wp_script_tester_class_init (WpScriptTesterClass *klass)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_plugin_loaded (WpCore * core, GAsyncResult * res, ScriptRunnerFixture *f)
|
||||||
|
{
|
||||||
|
g_autoptr (GObject) o = NULL;
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
o = wp_core_load_component_finish (core, res, &error);
|
||||||
|
g_assert_nonnull (o);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
|
||||||
|
if (WP_IS_PLUGIN (o))
|
||||||
|
g_main_loop_quit (f->base.loop);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
load_component (ScriptRunnerFixture *f, const gchar *name, const gchar *type)
|
load_component (ScriptRunnerFixture *f, const gchar *name, const gchar *type)
|
||||||
{
|
{
|
||||||
@@ -191,17 +205,11 @@ load_component (ScriptRunnerFixture *f, const gchar *name, const gchar *type)
|
|||||||
plugin_name = g_strdup (name);
|
plugin_name = g_strdup (name);
|
||||||
}
|
}
|
||||||
|
|
||||||
wp_core_load_component (f->base.core, component_name, type, NULL, &error);
|
wp_core_load_component (f->base.core, component_name, type, NULL,
|
||||||
g_assert_no_error (error);
|
(GAsyncReadyCallback) on_plugin_loaded, f);
|
||||||
|
|
||||||
if (!g_str_has_prefix (name, "si")) {
|
|
||||||
g_autoptr (WpPlugin) plugin = wp_plugin_find (f->base.core, plugin_name);
|
|
||||||
|
|
||||||
wp_object_activate (WP_OBJECT (plugin), WP_PLUGIN_FEATURE_ENABLED,
|
|
||||||
NULL, (GAsyncReadyCallback) test_object_activate_finish_cb, f);
|
|
||||||
|
|
||||||
|
if (!g_str_has_prefix (name, "si"))
|
||||||
g_main_loop_run (f->base.loop);
|
g_main_loop_run (f->base.loop);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
Reference in New Issue
Block a user