
There is no reason to return the component object... all components are supposed to be long-lived objects that are referenced by the registry and there is API to find them. The caller is only interested in the success or failure of the operation.
178 lines
5.0 KiB
C
178 lines
5.0 KiB
C
/* WirePlumber
|
|
*
|
|
* Copyright © 2021 Collabora Ltd.
|
|
* @author George Kiagiadakis <george.kiagiadakis@collabora.com>
|
|
*
|
|
* SPDX-License-Identifier: MIT
|
|
*/
|
|
|
|
#include <wp/wp.h>
|
|
#include <wplua/wplua.h>
|
|
|
|
#define WP_LOCAL_LOG_TOPIC log_topic_lua_scripting
|
|
WP_LOG_TOPIC_EXTERN (log_topic_lua_scripting)
|
|
|
|
struct _WpRequireApiTransition
|
|
{
|
|
WpTransition parent;
|
|
GPtrArray *apis;
|
|
guint pending_plugins;
|
|
};
|
|
|
|
enum {
|
|
STEP_LOAD_PLUGINS = WP_TRANSITION_STEP_CUSTOM_START,
|
|
};
|
|
|
|
G_DECLARE_FINAL_TYPE (WpRequireApiTransition, wp_require_api_transition,
|
|
WP, REQUIRE_API_TRANSITION, WpTransition)
|
|
G_DEFINE_TYPE (WpRequireApiTransition, wp_require_api_transition, WP_TYPE_TRANSITION)
|
|
|
|
static void
|
|
wp_require_api_transition_init (WpRequireApiTransition * self)
|
|
{
|
|
self->apis = g_ptr_array_new_with_free_func (g_free);
|
|
}
|
|
|
|
static void
|
|
wp_require_api_transition_finalize (GObject * object)
|
|
{
|
|
WpRequireApiTransition *self = WP_REQUIRE_API_TRANSITION (object);
|
|
|
|
g_clear_pointer (&self->apis, g_ptr_array_unref);
|
|
|
|
G_OBJECT_CLASS (wp_require_api_transition_parent_class)->finalize (object);
|
|
}
|
|
|
|
static guint
|
|
wp_require_api_transition_get_next_step (WpTransition * transition, guint step)
|
|
{
|
|
WpRequireApiTransition *self = WP_REQUIRE_API_TRANSITION (transition);
|
|
|
|
switch (step) {
|
|
case WP_TRANSITION_STEP_NONE: return STEP_LOAD_PLUGINS;
|
|
case STEP_LOAD_PLUGINS:
|
|
return (self->pending_plugins > 0) ?
|
|
STEP_LOAD_PLUGINS : WP_TRANSITION_STEP_NONE;
|
|
default:
|
|
g_return_val_if_reached (WP_TRANSITION_STEP_ERROR);
|
|
}
|
|
}
|
|
|
|
static void
|
|
on_plugin_loaded (WpCore * core, GAsyncResult * res,
|
|
WpRequireApiTransition *self)
|
|
{
|
|
GError *error = NULL;
|
|
|
|
if (!wp_core_load_component_finish (core, res, &error)) {
|
|
wp_transition_return_error (WP_TRANSITION (self), error);
|
|
return;
|
|
}
|
|
|
|
--self->pending_plugins;
|
|
wp_transition_advance (WP_TRANSITION (self));
|
|
}
|
|
|
|
static void
|
|
wp_require_api_transition_execute_step (WpTransition * transition, guint step)
|
|
{
|
|
WpRequireApiTransition *self = WP_REQUIRE_API_TRANSITION (transition);
|
|
WpCore *core = wp_transition_get_source_object (transition);
|
|
|
|
switch (step) {
|
|
case STEP_LOAD_PLUGINS:
|
|
wp_debug_object (self, "Loading 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);
|
|
if (!plugin) {
|
|
gchar module_name[50];
|
|
g_snprintf (module_name, sizeof (module_name),
|
|
"libwireplumber-module-%s", api_name);
|
|
|
|
self->pending_plugins++;
|
|
wp_core_load_component (core, module_name, "module", NULL, NULL,
|
|
(GAsyncReadyCallback) on_plugin_loaded, self);
|
|
}
|
|
}
|
|
wp_transition_advance (transition);
|
|
break;
|
|
|
|
case WP_TRANSITION_STEP_ERROR:
|
|
break;
|
|
|
|
default:
|
|
g_assert_not_reached ();
|
|
}
|
|
}
|
|
|
|
static void
|
|
wp_require_api_transition_class_init (WpRequireApiTransitionClass * klass)
|
|
{
|
|
GObjectClass * object_class = (GObjectClass *) klass;
|
|
WpTransitionClass * transition_class = (WpTransitionClass *) klass;
|
|
|
|
object_class->finalize = wp_require_api_transition_finalize;
|
|
|
|
transition_class->get_next_step = wp_require_api_transition_get_next_step;
|
|
transition_class->execute_step = wp_require_api_transition_execute_step;
|
|
}
|
|
|
|
static void
|
|
on_require_api_transition_done (WpCore * core, GAsyncResult * res, gpointer data)
|
|
{
|
|
g_autoptr (GClosure) closure = data;
|
|
g_autoptr (GError) error = NULL;
|
|
|
|
if (!wp_transition_finish (res, &error)) {
|
|
wp_warning ("Core.require_api failed: %s", error->message);
|
|
wp_core_idle_add (core, NULL, G_SOURCE_FUNC (core_disconnect), core, NULL);
|
|
return;
|
|
}
|
|
|
|
WpRequireApiTransition *t = WP_REQUIRE_API_TRANSITION (res);
|
|
g_autoptr (GArray) params = g_array_new (FALSE, TRUE, sizeof (GValue));
|
|
|
|
g_array_set_clear_func (params, (GDestroyNotify) g_value_unset);
|
|
g_array_set_size (params, t->apis->len);
|
|
|
|
for (guint i = 0; i < t->apis->len; i++) {
|
|
const gchar *api_name = g_ptr_array_index (t->apis, i);
|
|
g_autoptr (WpPlugin) plugin = wp_plugin_find (core, api_name);
|
|
g_value_init_from_instance (&g_array_index (params, GValue, i), plugin);
|
|
}
|
|
|
|
g_closure_invoke (closure, NULL,
|
|
params->len, (const GValue *) params->data, NULL);
|
|
g_closure_invalidate (closure);
|
|
}
|
|
|
|
static int
|
|
wp_require_api_transition_new_from_lua (lua_State *L, WpCore * core)
|
|
{
|
|
int n_args = lua_gettop (L);
|
|
|
|
wp_info("n_args = %d", n_args);
|
|
|
|
for (int i = 1; i < n_args; i++)
|
|
luaL_checktype (L, i, LUA_TSTRING);
|
|
luaL_checktype (L, n_args, LUA_TFUNCTION);
|
|
|
|
GClosure *closure = wplua_function_to_closure (L, n_args);
|
|
g_closure_ref (closure);
|
|
g_closure_sink (closure);
|
|
|
|
WpRequireApiTransition *t = (WpRequireApiTransition *)
|
|
wp_transition_new (wp_require_api_transition_get_type (), core, NULL,
|
|
(GAsyncReadyCallback) on_require_api_transition_done, closure);
|
|
|
|
for (int i = 1; i < n_args; i++) {
|
|
const char * api_name = lua_tostring (L, i);
|
|
g_ptr_array_add (t->apis, g_strdup_printf ("%s-api", api_name));
|
|
}
|
|
|
|
wp_transition_advance (WP_TRANSITION (t));
|
|
return 0;
|
|
}
|