X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Fplugin.c;h=a5055de9a1088a27dd2a227219b277d605d6000f;hb=2b2beddc7447197d12fcbcae96772e1f38eef138;hp=d4c19b12081d529059b8aa390418cb7a0fdca95b;hpb=4ed3fb89150d05e6fa134798315269c62de1bed9;p=chaz%2Fopenbox diff --git a/openbox/plugin.c b/openbox/plugin.c index d4c19b12..a5055de9 100644 --- a/openbox/plugin.c +++ b/openbox/plugin.c @@ -1,22 +1,33 @@ #include #include +typedef void (*PluginSetupConfig)(); typedef void (*PluginStartup)(); typedef void (*PluginShutdown)(); +typedef void *(*PluginCreate)(/* TODO */); +typedef void (*PluginDestroy)(void *); typedef struct { GModule *module; char *name; + PluginSetupConfig config; PluginStartup startup; PluginShutdown shutdown; + PluginCreate create; + PluginDestroy destroy; } Plugin; -static gpointer load_sym(GModule *module, char *name, char *symbol) +static gpointer load_sym(GModule *module, char *name, char *symbol, + gboolean allow_fail) { - gpointer var = NULL; - if (!g_module_symbol(module, symbol, &var)) - g_warning("Failed to load symbol '%s' from plugin '%s'", symbol, name); + gpointer var; + if (!g_module_symbol(module, symbol, &var)) { + if (!allow_fail) + g_warning("Failed to load symbol '%s' from plugin '%s'", + symbol, name); + var = NULL; + } return var; } @@ -27,26 +38,34 @@ static Plugin *plugin_new(char *name) p = g_new(Plugin, 1); - path = g_build_filename(PLUGINDIR, name, NULL); - p->module = g_module_open(path, G_MODULE_BIND_LAZY); + path = g_build_filename(g_get_home_dir(), ".openbox", "plugins", name, + NULL); + p->module = g_module_open(path, 0); g_free(path); if (p->module == NULL) { - path = g_build_filename(g_get_home_dir(), ".openbox", "plugins", name, - NULL); - p->module = g_module_open(path, G_MODULE_BIND_LAZY); - g_free(path); + path = g_build_filename(PLUGINDIR, name, NULL); + p->module = g_module_open(path, 0); + g_free(path); } if (p->module == NULL) { + g_warning(g_module_error()); g_free(p); return NULL; } - p->startup = load_sym(p->module, name, "startup"); - p->shutdown = load_sym(p->module, name, "shutdown"); - - if (p->startup == NULL || p->shutdown == NULL) { + p->config = (PluginSetupConfig)load_sym(p->module, name, + "plugin_setup_config", FALSE); + p->startup = (PluginStartup)load_sym(p->module, name, "plugin_startup", + FALSE); + p->shutdown = (PluginShutdown)load_sym(p->module, name, "plugin_shutdown", + FALSE); + p->create = (PluginCreate)load_sym(p->module, name, "plugin_create", TRUE); + p->destroy = (PluginDestroy)load_sym(p->module, name, "plugin_destroy", + TRUE); + + if (p->config == NULL || p->startup == NULL || p->shutdown == NULL) { g_module_close(p->module); g_free(p); return NULL; @@ -77,12 +96,13 @@ void plugin_shutdown() g_datalist_clear(&plugins); } -gboolean plugin_open(char *name) +gboolean plugin_open_full(char *name, gboolean reopen) { Plugin *p; if (g_datalist_get_data(&plugins, name) != NULL) { - g_warning("plugin '%s' already loaded, can't load again", name); + if (!reopen) + g_warning("plugin '%s' already loaded, can't load again", name); return TRUE; } @@ -91,13 +111,106 @@ gboolean plugin_open(char *name) g_warning("failed to load plugin '%s'", name); return FALSE; } + p->config(); - g_datalist_set_data_full(&plugins, name, p, (GDestroyNotify) plugin_free); - p->startup(); + g_datalist_set_data_full(&plugins, name, p, (GDestroyNotify) plugin_free); return TRUE; } +gboolean plugin_open(char *name) { + return plugin_open_full(name, FALSE); +} + +gboolean plugin_open_reopen(char *name) { + return plugin_open_full(name, TRUE); +} + void plugin_close(char *name) { g_datalist_remove_data(&plugins, name); } + +static void foreach_start(GQuark key, Plugin *p, gpointer *foo) +{ + p->startup(); +} + +void plugin_startall() +{ + g_datalist_foreach(&plugins, (GDataForeachFunc)foreach_start, NULL); +} + +void plugin_loadall() +{ + GIOChannel *io; + GError *err; + char *path, *name; + + path = g_build_filename(g_get_home_dir(), ".openbox", "pluginrc", NULL); + err = NULL; + io = g_io_channel_new_file(path, "r", &err); + g_free(path); + + if (io == NULL) { + path = g_build_filename(RCDIR, "pluginrc", NULL); + err = NULL; + io = g_io_channel_new_file(path, "r", &err); + g_free(path); + } + + if (io == NULL) { + /* load the default plugins */ + plugin_open("keyboard"); + plugin_open("mouse"); + plugin_open("placement"); + plugin_open("resistance"); + } else { + /* load the plugins in the rc file */ + while (g_io_channel_read_line(io, &name, NULL, NULL, &err) == + G_IO_STATUS_NORMAL) { + g_strstrip(name); + if (name[0] != '\0' && name[0] != '#') + plugin_open(name); + g_free(name); + } + g_io_channel_unref(io); + } +} + +void *plugin_create(char *name /* TODO */) +{ + Plugin *p = (Plugin *)g_datalist_get_data(&plugins, name); + + if (p == NULL) { + g_warning("Unable to find plugin for create: %s", name); + return NULL; + } + + if (p->create == NULL || p->destroy == NULL) { + g_critical("Unsupported create/destroy: %s", name); + return NULL; + } + + return p->create(); +} + +void plugin_destroy(char *name, void *data) +{ + Plugin *p = (Plugin *)g_datalist_get_data(&plugins, name); + + if (p == NULL) { + g_critical("Unable to find plugin for destroy: %s", name); + /* really shouldn't happen, but attempt to free something anyway? */ + g_free(data); + return; + } + + if (p->destroy == NULL || p->create == NULL) { + g_critical("Unsupported create/destroy: %s", name); + /* really, really shouldn't happen, but attempt to free anyway? */ + g_free(data); + return; + } + + p->destroy(data); +}