summaryrefslogtreecommitdiff
path: root/src/plugins/pglist.c
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2025-01-12 14:23:01 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2025-01-12 14:23:01 (GMT)
commitbaa854bfcc969022a00617b58a661e37f345cab5 (patch)
tree093d3ace4c2e1ad8fa37ce5e08723f768fffbada /src/plugins/pglist.c
parent0fdba5bd3e2c9ed913619990dbda7925867e46c5 (diff)
Rewrite the plugin system.
Diffstat (limited to 'src/plugins/pglist.c')
-rw-r--r--src/plugins/pglist.c355
1 files changed, 213 insertions, 142 deletions
diff --git a/src/plugins/pglist.c b/src/plugins/pglist.c
index e4cb825..083f11f 100644
--- a/src/plugins/pglist.c
+++ b/src/plugins/pglist.c
@@ -30,20 +30,29 @@
#include <malloc.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#include <i18n.h>
#include "dt.h"
+#include "manager.h"
#include "plugin-int.h"
-#include "../common/extstr.h"
+#include "../common/cpp.h"
+#include "../common/extstr.h" // REMME ?
#include "../core/logs.h"
#include "../core/nox.h"
#include "../core/paths.h"
+/**
+ * Prototype de la fonction de création, à garder synchronisé avec
+ * NATIVE_PLUGIN_ENTRYPOINT() (cf. native-int.h).
+ */
+typedef GPluginModule * (* get_plugin_instance_cb) (GModule *);
+
/* Liste de l'ensemble des greffons */
static GPluginModule **_pg_list = NULL;
static size_t _pg_count = 0;
@@ -129,6 +138,10 @@ bool init_all_plugins(bool load)
void exit_all_plugins(void)
{
+
+#if 0 //////
+
+
size_t i; /* Boucle de parcours */
const plugin_interface *pg_iface; /* Définition du greffon */
@@ -188,6 +201,10 @@ void exit_all_plugins(void)
exit_chrysalide_dynamic_types();
+
+
+#endif
+
}
@@ -244,83 +261,95 @@ static int filter_dirs_or_mods(const struct dirent *entry)
* *
* Paramètres : dir = répertoire à parcourir en quête de greffons (sans /). *
* *
-* Description : Part à la recherche de greffons sous forme de modules. *
+* Description : Indique la version (NOX/UI) associée à un nom de fichier. *
* *
-* Retour : - *
+* Retour : true si la version complémentaire existe ou false. *
* *
* Remarques : - *
* *
******************************************************************************/
-static void browse_directory_for_plugins(const char *dir)
+static bool check_for_plugin_versions(const char *dir, const char *filename, bool *is_nox, bool *is_ui)
{
- struct dirent **namelist; /* Eléments trouvés */
- int ret; /* Bilan du parcours */
- bool nox; /* Absence de support graphique*/
- char *filename; /* Elément à ausculter */
- GPluginModule *plugin; /* Greffon à intégrer ou pas */
-
- ret = scandir(dir, &namelist, filter_dirs_or_mods, alphasort);
- if (ret < 0)
- {
- LOG_ERROR_N("scandir");
- return;
- }
-
- nox = run_in_nox_mode();
+ bool result; /* Bilan à renvoyer */
+ size_t length; /* Taille du nom de fichier */
+ char *alt_path; /* Autre chemin complet testé */
+ int ret; /* Bilan d'une impression */
- while (ret--)
- {
-
- if (nox)
- {
#ifdef _WIN32
-# define UI_SHARED_SUFFIX "-ui.dll"
+# define SHARED_SUFFIX ".dll"
#else
-# define UI_SHARED_SUFFIX "-ui.so"
+# define SHARED_SUFFIX ".so"
#endif
+#define UI_SHARED_SUFFIX "ui" SHARED_SUFFIX
- if (strstr(namelist[ret]->d_name, UI_SHARED_SUFFIX) != NULL)
- {
- log_variadic_message(LMT_ERROR, _("Skipping unsuitable file: %s"), namelist[ret]->d_name);
- continue;
- }
+ result = false;
- }
+ /* Propriétés du fichier courant */
- filename = (char *)calloc(strlen(dir) + 1 + strlen(namelist[ret]->d_name) + 1, sizeof(char));
+ length = strlen(filename);
- strcpy(filename, dir);
- strcat(filename, G_DIR_SEPARATOR_S);
- strcat(filename, namelist[ret]->d_name);
+ if (length < STATIC_STR_SIZE(UI_SHARED_SUFFIX))
+ *is_ui = false;
- if (namelist[ret]->d_type == DT_DIR)
- browse_directory_for_plugins(filename);
+ else
+ *is_ui = (strcmp(filename + length - STATIC_STR_SIZE(UI_SHARED_SUFFIX), UI_SHARED_SUFFIX) == 0);
+
+ if (*is_ui)
+ *is_nox = false;
+
+ else
+ {
+ if (length < STATIC_STR_SIZE(SHARED_SUFFIX))
+ *is_nox = false;
else
- {
- plugin = g_plugin_module_new(filename);
+ *is_nox = (strcmp(filename + length - STATIC_STR_SIZE(SHARED_SUFFIX), SHARED_SUFFIX) == 0);
- if (plugin != NULL)
- register_plugin(plugin);
+ }
+
+ /* Recherche d'une version alternative */
+ if (*is_nox || *is_ui)
+ {
+
+ if (*is_nox)
+ ret = asprintf(&alt_path, "%s%s%.*s%s",
+ dir, G_DIR_SEPARATOR_S,
+ (int)(length - STATIC_STR_SIZE(SHARED_SUFFIX)), filename,
+ UI_SHARED_SUFFIX);
+ else
+ ret = asprintf(&alt_path, "%s%s%.*s%s",
+ dir, G_DIR_SEPARATOR_S,
+ (int)(length - STATIC_STR_SIZE(SHARED_SUFFIX)), filename,
+ SHARED_SUFFIX);
+
+ if (ret <= 0)
+ {
+ LOG_ERROR_N("asprintf");
+ goto exit;
}
- free(filename);
- free(namelist[ret]);
+ ret = access(alt_path, R_OK | X_OK);
+
+ result = (ret == 0);
+
+ free(alt_path);
}
- free(namelist);
+ exit:
+
+ return result;
}
/******************************************************************************
* *
-* Paramètres : plugin = greffon à ajouter aux autres disponibles. *
+* Paramètres : dir = répertoire à parcourir en quête de greffons (sans /). *
* *
-* Description : Ajoute un greffon à la liste principale de greffons. *
+* Description : Part à la recherche de greffons sous forme de modules. *
* *
* Retour : - *
* *
@@ -328,52 +357,117 @@ static void browse_directory_for_plugins(const char *dir)
* *
******************************************************************************/
-void _register_plugin(GPluginModule *plugin)
+static void browse_directory_for_plugins(const char *dir)
{
- size_t i; /* Boucle de parcours */
- const plugin_interface *pg_iface; /* Informations à consulter */
- const char *name; /* Désignation du greffon */
-
- /**
- * L'appel sans verrou n'est fourni que pour les greffons
- * mettant en place des greffons en interne !
- */
-
- /* Recherche d'un éventuel doublon */
+ struct dirent **namelist; /* Eléments trouvés */
+ int ret; /* Bilan d'un appel */
+ int k; /* Boucle de parcours */
+ bool nox_mode; /* Absence de support graphique*/
+ char *filename; /* Elément à ausculter */
+ bool is_nox; /* Chemin de version basique ? */
+ bool is_ui; /* Chemin de version graphique */
+ bool has_alt; /* Existence d'une alternative */
+ GModule *module; /* Abstration de manipulation */
+ get_plugin_instance_cb get_instance; /* Point d'entrée exporté */
+ GPluginModule *plugin; /* Greffon à intégrer ou pas */
- pg_iface = g_plugin_module_get_interface(plugin);
+ ret = scandir(dir, &namelist, filter_dirs_or_mods, alphasort);
+ if (ret < 0)
+ {
+ LOG_ERROR_N("scandir");
+ return;
+ }
- name = pg_iface->name;
+ nox_mode = run_in_nox_mode();
- for (i = 0; i < _pg_count; i++)
+ for (k = ret; k--; )
{
- pg_iface = g_plugin_module_get_interface(_pg_list[i]);
+ ret = asprintf(&filename, "%s%s%s", dir, G_DIR_SEPARATOR_S, namelist[k]->d_name);
+ if (ret <= 0)
+ {
+ LOG_ERROR_N("asprintf");
+ continue;
+ }
+
+ if (namelist[k]->d_type == DT_DIR)
+ browse_directory_for_plugins(filename);
- if (strcmp(name, pg_iface->name) == 0)
+ else
{
- log_variadic_message(LMT_ERROR,
- _("Plugin '%s' already registered!"), name);
- break;
+ printf("// Candidate // %s\n", filename);
- }
+ has_alt = check_for_plugin_versions(dir, namelist[k]->d_name, &is_nox, &is_ui);
- }
+ printf(" -> nox=%d ui=%d -> alt? %d\n", is_nox, is_ui, has_alt);
- /* Ajout du greffon à la liste */
- if (i == _pg_count)
- {
- _pg_list = (GPluginModule **)realloc(_pg_list, ++_pg_count * sizeof(GPluginModule));
+ if ((nox_mode && is_nox) || (!nox_mode && ((is_nox && !has_alt) || is_ui)))
+ {
+
+
+ printf(" ---> load!\n");
- _pg_list[_pg_count - 1] = plugin;
- g_object_add_toggle_ref(G_OBJECT(plugin), (GToggleNotify)on_plugin_ref_toggle, NULL);
+
+ module = g_module_open(filename, G_MODULE_BIND_LAZY);
+ if (module == NULL)
+ {
+ log_variadic_message(LMT_ERROR,
+ _("Error while loading the plugin candidate '%s' : %s"),
+ filename, g_module_error());
+ goto next_file;
+ }
+
+
+ printf(" (main) module=%p '%s'\n", module, g_module_name(module));
+
+
+ if (!g_module_symbol(module, "get_chrysalide_plugin_instance", (gpointer *)&get_instance))
+ {
+ log_variadic_message(LMT_ERROR,
+ _("No '%s' entry in plugin candidate '%s'"),
+ "<sym>", filename);
+
+
+
+ }
+
+
+ if (get_instance == NULL)
+ plugin = NULL;
+ else
+ plugin = get_instance(module);
+
+
+
+ printf(" ===> plugin: %p\n", plugin);
+
+
+
+ if (plugin != NULL)
+ {
+ register_plugin(plugin);
+ unref_object(plugin);
+ }
+
+ else
+ g_module_close(module);
+
+ }
+ else
+ log_variadic_message(LMT_INFO, _("Skipping unsuitable file for plugin: %s"), filename);
+
+ }
+
+ next_file:
+
+ free(filename);
+ free(namelist[k]);
}
- else
- /* FIXME : leak(plugin); */;
+ free(namelist);
}
@@ -394,7 +488,7 @@ void _register_plugin(GPluginModule *plugin)
static void on_plugin_ref_toggle(gpointer unused, GPluginModule *plugin, gboolean last)
{
- const plugin_interface *pg_iface; /* Vitrine d'un greffon */
+ const char *name; /* Désignation du greffon */
size_t index; /* Indice du greffon */
GPluginModule *same; /* Juste pour la récupération */
@@ -402,16 +496,17 @@ static void on_plugin_ref_toggle(gpointer unused, GPluginModule *plugin, gboolea
{
assert(g_rw_lock_writer_trylock(&_pg_lock) == FALSE);
- pg_iface = g_plugin_module_get_interface(plugin);
+ name = g_plugin_module_get_name(plugin);
- same = get_plugin_by_name(pg_iface->name, &index);
+ same = get_plugin_by_name(name, &index);
assert(same != NULL);
+ assert(same == plugin);
- _pg_list[index] = NULL;
+ g_clear_object(&_pg_list[index]);
- g_object_remove_toggle_ref(G_OBJECT(plugin), (GToggleNotify)on_plugin_ref_toggle, NULL);
+ g_object_remove_toggle_ref(G_OBJECT(same), (GToggleNotify)on_plugin_ref_toggle, NULL);
- g_object_unref(G_OBJECT(same));
+ unref_object(same);
}
@@ -432,9 +527,40 @@ static void on_plugin_ref_toggle(gpointer unused, GPluginModule *plugin, gboolea
void register_plugin(GPluginModule *plugin)
{
+ size_t i; /* Boucle de parcours */
+ const char *name; /* Désignation du greffon */
+ const char *existing; /* Nom d'un greffon en place */
+
g_rw_lock_writer_lock(&_pg_lock);
- _register_plugin(plugin);
+ /* Recherche d'un éventuel doublon */
+
+ name = g_plugin_module_get_name(plugin);
+
+ for (i = 0; i < _pg_count; i++)
+ {
+ existing = g_plugin_module_get_name(_pg_list[i]);
+
+ if (strcmp(name, existing) == 0)
+ {
+ log_variadic_message(LMT_ERROR, _("Plugin '%s' already registered!"), name);
+ break;
+ }
+
+ }
+
+ /* Ajout du greffon à la liste */
+
+ if (i == _pg_count)
+ {
+ _pg_list = realloc(_pg_list, ++_pg_count * sizeof(GPluginModule));
+
+ _pg_list[_pg_count - 1] = plugin;
+ ref_object(plugin);
+
+ g_object_add_toggle_ref(G_OBJECT(plugin), (GToggleNotify)on_plugin_ref_toggle, NULL);
+
+ }
g_rw_lock_writer_unlock(&_pg_lock);
@@ -543,7 +669,7 @@ GPluginModule *get_plugin_by_name(const char *name, size_t *index)
{
GPluginModule *result; /* Greffon trouvé à renvoyer */
size_t i; /* Boucle de parcours */
- const plugin_interface *pg_iface; /* Vitrine d'un greffon */
+ const char *current; /* Nom du greffon courant */
result = NULL;
@@ -557,11 +683,12 @@ GPluginModule *get_plugin_by_name(const char *name, size_t *index)
/* Si on est en train de procéder à un nettoyage... */
if (_pg_list[i] == NULL) continue;
- pg_iface = g_plugin_module_get_interface(_pg_list[i]);
+ current = g_plugin_module_get_name(_pg_list[i]);
- if (strcmp(pg_iface->name, name) == 0)
+ if (strcmp(current, name) == 0)
{
result = _pg_list[i];
+ ref_object(result);
if (index != NULL)
*index = i;
@@ -570,9 +697,6 @@ GPluginModule *get_plugin_by_name(const char *name, size_t *index)
}
- if (result != NULL)
- g_object_ref(G_OBJECT(result));
-
return result;
}
@@ -603,60 +727,7 @@ GPluginModule **get_all_plugins(size_t *count)
for (i = 0; i < _pg_count; i++)
{
result[i] = _pg_list[i];
- g_object_ref(G_OBJECT(_pg_list[i]));
- }
-
- g_rw_lock_reader_unlock(&_pg_lock);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : action = fonctionnalité recherchée. *
-* count = nombre de greffons trouvés. [OUT] *
-* *
-* Description : Fournit les greffons offrant le service demandé. *
-* *
-* Retour : Liste de greffons correspondants issue d'un tri interne. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GPluginModule **get_all_plugins_for_action(PluginAction action, size_t *count)
-{
- GPluginModule **result; /* Liste à retourner */
- size_t i; /* Boucle de parcours #1 */
- const plugin_interface *pg_iface; /* Informations à consulter */
- size_t j; /* Boucle de parcours #2 */
-
- result = NULL;
- *count = 0;
-
- g_rw_lock_reader_lock(&_pg_lock);
-
- for (i = 0; i < _pg_count; i++)
- {
- pg_iface = g_plugin_module_get_interface(_pg_list[i]);
-
- for (j = 0; j < pg_iface->actions_count; j++)
- {
- if (pg_iface->actions[j] == action)
- {
- result = realloc(result, ++(*count) * sizeof(GPluginModule *));
-
- result[*count - 1] = _pg_list[i];
- g_object_ref(G_OBJECT(_pg_list[i]));
-
- break;
-
- }
-
- }
-
+ ref_object(result[i]);
}
g_rw_lock_reader_unlock(&_pg_lock);