summaryrefslogtreecommitdiff
path: root/libcaja-private/caja-module.c
diff options
context:
space:
mode:
authorPerberos <[email protected]>2011-12-01 22:24:23 -0300
committerPerberos <[email protected]>2011-12-01 22:24:23 -0300
commit0e004c696b0e68b2cff37a4c3315b022a35eaf43 (patch)
tree43261e815529cb9518ed7be37af13b846af8b26b /libcaja-private/caja-module.c
downloadcaja-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.c293
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);
+}