/* vi:set et ai sw=2 sts=2 ts=2: */ /*- * Copyright (c) 2009 Jannis Pohlmann * * 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., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include "tumbler/tumbler-provider-plugin.h" #include /* Property identifiers */ enum { PROP_0, }; static void tumbler_provider_plugin_finalize (GObject *object); static gboolean tumbler_provider_plugin_load (GTypeModule *type_module); static void tumbler_provider_plugin_unload (GTypeModule *type_module); struct _TumblerProviderPluginClass { GTypeModuleClass __parent__; }; struct _TumblerProviderPlugin { GTypeModule __parent__; GModule *library; void (*initialize) (TumblerProviderPlugin *plugin); void (*shutdown) (void); void (*get_types) (const GType **types, gint *n_types); }; G_DEFINE_TYPE (TumblerProviderPlugin, tumbler_provider_plugin, G_TYPE_TYPE_MODULE) static void tumbler_provider_plugin_class_init (TumblerProviderPluginClass *klass) { GTypeModuleClass *gtype_module_class; GObjectClass *gobject_class; gobject_class = G_OBJECT_CLASS (klass); gobject_class->finalize = tumbler_provider_plugin_finalize; gtype_module_class = G_TYPE_MODULE_CLASS (klass); gtype_module_class->load = tumbler_provider_plugin_load; gtype_module_class->unload = tumbler_provider_plugin_unload; } static void tumbler_provider_plugin_init (TumblerProviderPlugin *plugin) { } static void tumbler_provider_plugin_finalize (GObject *object) { TumblerProviderPlugin *plugin = TUMBLER_PROVIDER_PLUGIN (object); if (plugin->library != NULL) g_module_close (plugin->library); (*G_OBJECT_CLASS (tumbler_provider_plugin_parent_class)->finalize) (object); } static gboolean tumbler_provider_plugin_load (GTypeModule *type_module) { TumblerProviderPlugin *plugin = TUMBLER_PROVIDER_PLUGIN (type_module); gchar *path; /* load the module using the runtime link editor */ path = g_build_filename (TUMBLER_PLUGIN_DIRECTORY, type_module->name, NULL); plugin->library = g_module_open (path, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL); g_free (path); /* check if the load operation was successful */ if (G_LIKELY (plugin->library != NULL)) { /* verify that all required public symbols are present in the plugin */ if (g_module_symbol (plugin->library, "tumbler_plugin_initialize", (gpointer) &plugin->initialize) && g_module_symbol (plugin->library, "tumbler_plugin_shutdown", (gpointer) &plugin->shutdown) && g_module_symbol (plugin->library, "tumbler_plugin_get_types", (gpointer) &plugin->get_types)) { /* initialize the plugin */ (*plugin->initialize) (plugin); return TRUE; } else { g_warning (TUMBLER_WARNING_PLUGIN_LACKS_SYMBOLS, type_module->name); g_module_close (plugin->library); plugin->library = NULL; return FALSE; } } else { g_warning (TUMBLER_WARNING_LOAD_PLUGIN_FAILED, type_module->name, g_module_error ()); return FALSE; } } static void tumbler_provider_plugin_unload (GTypeModule *type_module) { TumblerProviderPlugin *plugin = TUMBLER_PROVIDER_PLUGIN (type_module); /* shutdown the plugin */ (*plugin->shutdown) (); /* unload the plugin from memory */ g_module_close (plugin->library); plugin->library = NULL; /* reset plugin state */ plugin->initialize = NULL; plugin->shutdown = NULL; plugin->get_types = NULL; } TumblerProviderPlugin * tumbler_provider_plugin_new (const gchar *filename) { TumblerProviderPlugin *plugin; g_return_val_if_fail (filename != NULL && *filename != '\0', NULL); plugin = g_object_new (TUMBLER_TYPE_PROVIDER_PLUGIN, NULL); g_type_module_set_name (G_TYPE_MODULE (plugin), filename); return plugin; } void tumbler_provider_plugin_get_types (const TumblerProviderPlugin *plugin, const GType **types, gint *n_types) { g_return_if_fail (TUMBLER_IS_PROVIDER_PLUGIN (plugin)); g_return_if_fail (plugin->get_types != NULL); g_return_if_fail (types != NULL); g_return_if_fail (n_types != NULL); (*plugin->get_types) (types, n_types); }