diff options
Diffstat (limited to 'src/plugins/pglist.c')
-rw-r--r-- | src/plugins/pglist.c | 355 |
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); |