00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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 }