Main Page | Data Structures | File List | Data Fields | Globals

timer-loader.c

Go to the documentation of this file.
00001 /**
00002  * This file is part of alarmd
00003  *
00004  * Contact Person: David Weinehall <david.weinehall@nokia.com>
00005  *
00006  * Copyright (C) 2006 Nokia Corporation
00007  * alarmd and libalarm are free software; you can redistribute them
00008  * and/or modify them under the terms of the GNU Lesser General Public
00009  * License version 2.1 as published by the Free Software Foundation.
00010  *
00011  * alarmd and libalarm are distributed in the hope that they will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this software; if not, write to the Free
00018  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
00019  * 02110-1301 USA
00020  */
00021 
00022 #include <glib.h>
00023 #ifdef G_MODULE
00024 #include <gmodule.h>
00025 #else
00026 #include <dlfcn.h>
00027 #endif
00028 #include <stdio.h>
00029 #include "timer-loader.h"
00030 #include "include/timer-interface.h"
00031 
00032 typedef struct _TimerModule TimerModule;
00033 struct _TimerModule {
00034         TimerPlugin plugin;
00035         gchar *module_path;
00036 #ifdef G_MODULE
00037         GModule *loaded;
00038 #else
00039         void *loaded;
00040 #endif
00041 };
00042 
00043 static gboolean _module_load(TimerModule *mod);
00044 static gint _timer_plugin_compare(gconstpointer lval, gconstpointer rval);
00045 static void _module_free(TimerModule *mod);
00046 static void _module_foreach_free(gpointer mod, gpointer user_data);
00047 
00048 static gint _timer_plugin_compare(gconstpointer lval, gconstpointer rval)
00049 {
00050         const TimerModule *lpl = (const TimerModule *)lval;
00051         const TimerModule *rpl = (const TimerModule *)rval;
00052 
00053         return rpl->plugin.priority - lpl->plugin.priority;
00054 }
00055 
00056 GSList *load_timer_plugins(const gchar *path)
00057 {
00058         GDir *dir = NULL;
00059         GSList *retval = NULL;
00060         gboolean have_power_up = FALSE;
00061         const gchar *module_name = NULL;
00062 
00063         if (!path) {
00064                 path = PLUGINDIR;
00065         }
00066         dir = g_dir_open(path, 0, NULL);
00067 
00068         if (dir == NULL) {
00069                 g_warning("Opening dir %s failed", path);
00070                 return NULL;
00071         }
00072         while ((module_name = g_dir_read_name(dir))) {
00073                 TimerModule *module = NULL;
00074 
00075                 if (!g_str_has_suffix(module_name, ".so")) {
00076                         continue;
00077                 }
00078                 
00079                 module = g_new0(TimerModule, 1);
00080                 module->module_path = g_build_filename(path, module_name, NULL);
00081                 module->plugin.is_startup = TRUE;
00082                 if (!_module_load(module)) {
00083                         _module_free(module);
00084                         continue;
00085                 }
00086                 retval = g_slist_insert_sorted(retval, (gpointer)module, _timer_plugin_compare);
00087         }
00088         g_dir_close(dir);
00089         
00090         if (retval) {
00091                 if (((TimerModule *)retval->data)->plugin.can_power_up) {
00092                         have_power_up = TRUE;
00093                 }
00094                 GSList *iter;
00095                 for (iter = retval->next; iter != NULL; iter = iter->next)
00096                 {
00097                         TimerModule *mod = (TimerModule *)iter->data;
00098                         if (!have_power_up && mod->plugin.can_power_up) {
00099                                 have_power_up = TRUE;
00100                                 continue;
00101                         }
00102                         if (mod->plugin.plugin_deinit != NULL) {
00103                                 mod->plugin.plugin_deinit(&mod->plugin);
00104                         }
00105 #ifdef G_MODULE
00106                         g_module_close(mod->loaded);
00107 #else
00108                         dlclose(mod->loaded);
00109 #endif
00110                         mod->loaded = NULL;
00111                         mod->plugin.set_event = NULL;
00112                         mod->plugin.remove_event = NULL;
00113                         mod->plugin.get_time = NULL;
00114                         mod->plugin.plugin_deinit = NULL;
00115                         mod->plugin.plugin_data = NULL;
00116                 }
00117         }
00118 
00119         return retval;
00120 }
00121 
00122 TimerPlugin *timers_get_plugin(GSList *plugins, gboolean need_power_up)
00123 {
00124         TimerPlugin *retval = NULL;
00125 
00126         if (!plugins) {
00127                 return NULL;
00128         }
00129 
00130         if (!need_power_up || (need_power_up && ((TimerModule *)plugins->data)->plugin.can_power_up)) {
00131                 _module_load((TimerModule *)plugins->data);
00132                 retval = &((TimerModule *)plugins->data)->plugin;
00133         } else {
00134                 GSList *iter;
00135                 for (iter = plugins->next; iter != NULL; iter = iter->next) {
00136                         TimerModule *mod = (TimerModule *)iter->data;
00137 
00138                         if (mod->plugin.can_power_up) {
00139                                 _module_load(mod);
00140                                 retval = &mod->plugin;
00141                                 break;
00142                         }
00143                 }
00144         }
00145         return retval;
00146 }
00147 
00148 static void _module_foreach_free(gpointer mod, gpointer user_data)
00149 {
00150         (void)user_data;
00151         _module_free((TimerModule *)mod);
00152 }
00153 
00154 void close_timer_plugins(GSList *plugins) {
00155         g_slist_foreach(plugins, _module_foreach_free, NULL);
00156         g_slist_free(plugins);
00157 }
00158 
00159 static void _set_startup(gpointer mod, gpointer user_data)
00160 {
00161         gboolean is_startup = GPOINTER_TO_INT(user_data);
00162         TimerModule *plug = mod;
00163         plug->plugin.is_startup = is_startup;
00164 }
00165 
00166 void timer_plugins_set_startup(GSList *plugins, gboolean is_startup)
00167 {
00168         g_slist_foreach(plugins, _set_startup, GINT_TO_POINTER(is_startup));
00169 }
00170 
00171 static void _module_free(TimerModule *mod)
00172 {
00173         if (mod->plugin.plugin_deinit != NULL) {
00174                 mod->plugin.plugin_deinit(&mod->plugin);
00175         }
00176         if (mod->loaded) {
00177 #ifdef G_MODULE
00178                 g_module_close(mod->loaded);
00179 #else
00180                 dlclose(mod->loaded);
00181 #endif
00182         }
00183         g_free(mod->module_path);
00184         g_free(mod);
00185 }
00186 
00187 static gboolean _module_load(TimerModule *mod) {
00188         union {
00189                 gboolean (*init_mod)(TimerPlugin *plugin);
00190                 gpointer pointer;
00191         } no_warnings;
00192         if (mod->loaded) {
00193                 return TRUE;
00194         }
00195 #ifdef G_MODULE
00196         mod->loaded = g_module_open(mod->module_path, G_MODULE_BIND_LAZY);
00197 #else
00198         mod->loaded = dlopen(mod->module_path, RTLD_LAZY);
00199 #endif
00200         if (mod->loaded == NULL) {
00201 #ifdef G_MODULE
00202                 g_warning("Failed to load %s", mod->module_path);
00203 #else
00204                 g_warning("Failed to load %s: %s", mod->module_path, dlerror());
00205 #endif
00206                 return FALSE;
00207         }
00208 #ifdef G_MODULE
00209         if (!g_module_symbol(mod->loaded, "plugin_initialize", &no_warnings.pointer)) {
00210 #else
00211         if (!(no_warnings.pointer = (gboolean (*)(TimerPlugin *plugin))dlsym(mod->loaded, "plugin_initialize"))) {
00212 #endif
00213                 g_warning("Could not find init func on %s", mod->module_path);
00214                 return FALSE;
00215         }
00216         if (!no_warnings.init_mod(&mod->plugin))
00217         {
00218                 g_warning("Module %s initialization failed", mod->module_path);
00219                 return FALSE;
00220         }
00221 
00222         return TRUE;
00223 }

Generated on Thu Dec 21 18:23:30 2006 for Alarmd by  doxygen 1.4.2