diff options
author | Perberos <[email protected]> | 2011-12-01 22:24:23 -0300 |
---|---|---|
committer | Perberos <[email protected]> | 2011-12-01 22:24:23 -0300 |
commit | 0e004c696b0e68b2cff37a4c3315b022a35eaf43 (patch) | |
tree | 43261e815529cb9518ed7be37af13b846af8b26b /libcaja-private/caja-module.c | |
download | caja-0e004c696b0e68b2cff37a4c3315b022a35eaf43.tar.bz2 caja-0e004c696b0e68b2cff37a4c3315b022a35eaf43.tar.xz |
moving from https://github.com/perberos/mate-desktop-environment
Diffstat (limited to 'libcaja-private/caja-module.c')
-rw-r--r-- | libcaja-private/caja-module.c | 293 |
1 files changed, 293 insertions, 0 deletions
diff --git a/libcaja-private/caja-module.c b/libcaja-private/caja-module.c new file mode 100644 index 00000000..3cadd59e --- /dev/null +++ b/libcaja-private/caja-module.c @@ -0,0 +1,293 @@ +/* + * caja-module.h - Interface to caja extensions + * + * Copyright (C) 2003 Novell, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Author: Dave Camp <[email protected]> + * + */ + +#include <config.h> +#include "caja-module.h" + +#include <eel/eel-gtk-macros.h> +#include <eel/eel-debug.h> +#include <gmodule.h> + +#define CAJA_TYPE_MODULE (caja_module_get_type ()) +#define CAJA_MODULE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CAJA_TYPE_MODULE, CajaModule)) +#define CAJA_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CAJA_TYPE_MODULE, CajaModule)) +#define CAJA_IS_MODULE(obj) (G_TYPE_INSTANCE_CHECK_TYPE ((obj), CAJA_TYPE_MODULE)) +#define CAJA_IS_MODULE_CLASS(klass) (G_TYPE_CLASS_CHECK_CLASS_TYPE ((klass), CAJA_TYPE_MODULE)) + +typedef struct _CajaModule CajaModule; +typedef struct _CajaModuleClass CajaModuleClass; + +struct _CajaModule +{ + GTypeModule parent; + + GModule *library; + + char *path; + + void (*initialize) (GTypeModule *module); + void (*shutdown) (void); + + void (*list_types) (const GType **types, + int *num_types); + +}; + +struct _CajaModuleClass +{ + GTypeModuleClass parent; +}; + +static GList *module_objects = NULL; + +static GType caja_module_get_type (void); + +G_DEFINE_TYPE (CajaModule, caja_module, G_TYPE_TYPE_MODULE); +#define parent_class caja_module_parent_class + +static gboolean +caja_module_load (GTypeModule *gmodule) +{ + CajaModule *module; + + module = CAJA_MODULE (gmodule); + + module->library = g_module_open (module->path, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL); + + if (!module->library) + { + g_warning ("%s", g_module_error ()); + return FALSE; + } + + if (!g_module_symbol (module->library, + "caja_module_initialize", + (gpointer *)&module->initialize) || + !g_module_symbol (module->library, + "caja_module_shutdown", + (gpointer *)&module->shutdown) || + !g_module_symbol (module->library, + "caja_module_list_types", + (gpointer *)&module->list_types)) + { + + g_warning ("%s", g_module_error ()); + g_module_close (module->library); + + return FALSE; + } + + module->initialize (gmodule); + + return TRUE; +} + +static void +caja_module_unload (GTypeModule *gmodule) +{ + CajaModule *module; + + module = CAJA_MODULE (gmodule); + + module->shutdown (); + + g_module_close (module->library); + + module->initialize = NULL; + module->shutdown = NULL; + module->list_types = NULL; +} + +static void +caja_module_finalize (GObject *object) +{ + CajaModule *module; + + module = CAJA_MODULE (object); + + g_free (module->path); + + EEL_CALL_PARENT (G_OBJECT_CLASS, finalize, (object)); +} + +static void +caja_module_init (CajaModule *module) +{ +} + +static void +caja_module_class_init (CajaModuleClass *class) +{ + G_OBJECT_CLASS (class)->finalize = caja_module_finalize; + G_TYPE_MODULE_CLASS (class)->load = caja_module_load; + G_TYPE_MODULE_CLASS (class)->unload = caja_module_unload; +} + +static void +module_object_weak_notify (gpointer user_data, GObject *object) +{ + module_objects = g_list_remove (module_objects, object); +} + +static void +add_module_objects (CajaModule *module) +{ + const GType *types; + int num_types; + int i; + + module->list_types (&types, &num_types); + + for (i = 0; i < num_types; i++) + { + if (types[i] == 0) /* Work around broken extensions */ + { + break; + } + caja_module_add_type (types[i]); + } +} + +static CajaModule * +caja_module_load_file (const char *filename) +{ + CajaModule *module; + + module = g_object_new (CAJA_TYPE_MODULE, NULL); + module->path = g_strdup (filename); + + if (g_type_module_use (G_TYPE_MODULE (module))) + { + add_module_objects (module); + g_type_module_unuse (G_TYPE_MODULE (module)); + return module; + } + else + { + g_object_unref (module); + return NULL; + } +} + +static void +load_module_dir (const char *dirname) +{ + GDir *dir; + + dir = g_dir_open (dirname, 0, NULL); + + if (dir) + { + const char *name; + + while ((name = g_dir_read_name (dir))) + { + if (g_str_has_suffix (name, "." G_MODULE_SUFFIX)) + { + char *filename; + + filename = g_build_filename (dirname, + name, + NULL); + caja_module_load_file (filename); + g_free (filename); + } + } + + g_dir_close (dir); + } +} + +static void +free_module_objects (void) +{ + GList *l, *next; + + for (l = module_objects; l != NULL; l = next) + { + next = l->next; + g_object_unref (l->data); + } + + g_list_free (module_objects); +} + +void +caja_module_setup (void) +{ + static gboolean initialized = FALSE; + + if (!initialized) + { + initialized = TRUE; + + load_module_dir (CAJA_EXTENSIONDIR); + + eel_debug_call_at_shutdown (free_module_objects); + } +} + +GList * +caja_module_get_extensions_for_type (GType type) +{ + GList *l; + GList *ret = NULL; + + for (l = module_objects; l != NULL; l = l->next) + { + if (G_TYPE_CHECK_INSTANCE_TYPE (G_OBJECT (l->data), + type)) + { + g_object_ref (l->data); + ret = g_list_prepend (ret, l->data); + } + } + + return ret; +} + +void +caja_module_extension_list_free (GList *extensions) +{ + GList *l, *next; + + for (l = extensions; l != NULL; l = next) + { + next = l->next; + g_object_unref (l->data); + } + g_list_free (extensions); +} + +void +caja_module_add_type (GType type) +{ + GObject *object; + + object = g_object_new (type, NULL); + g_object_weak_ref (object, + (GWeakNotify)module_object_weak_notify, + NULL); + + module_objects = g_list_prepend (module_objects, object); +} |