grim/gplugin-purple2-loader
Initial revision, we can query the no-irc-who plugin now
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/.hgignore Sat Feb 02 03:18:30 2019 -0600
@@ -0,0 +1,3 @@
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/gplugin-purple2/gplugin-purple2-core.c Sat Feb 02 03:18:30 2019 -0600
@@ -0,0 +1,52 @@
+#include <gplugin-native.h> +#include "gplugin-purple2-loader.h" +#include "gplugin-purple2-plugin.h" +#include <libpurple/core.h> +G_MODULE_EXPORT GPluginPluginInfo * +gplugin_query(G_GNUC_UNUSED GError **error) { + g_warning("hack to make sure we stay linked to libpurple3 for dev: %p", purple_core_init); + const gchar * const authors[] = { + return gplugin_plugin_info_new( + "gplugin-purple2/purple2", + GPLUGIN_NATIVE_PLUGIN_ABI_VERSION, + "name", "Purple2 Plugin Loader", + "summary", "A plugin that can load purple2 plugins", + "description", "This plugin mocks the purple2 api and calls the " + "appropriate purple3 api", +G_MODULE_EXPORT gboolean +gplugin_load(GPluginNativePlugin *plugin, + G_GNUC_UNUSED GError **error) + gplugin_purple2_loader_register(plugin); + gplugin_purple2_plugin_register(plugin); + gplugin_manager_register_loader(GPLUGIN_PURPLE2_TYPE_LOADER); +G_MODULE_EXPORT gboolean +gplugin_unload(G_GNUC_UNUSED GPluginNativePlugin *plugin, + G_GNUC_UNUSED GError **error) --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/gplugin-purple2/gplugin-purple2-core.h Sat Feb 02 03:18:30 2019 -0600
@@ -0,0 +1,9 @@
+#ifndef GPLUGIN_PURPLE2_CORE_H +#define GPLUGIN_PURPLE2_CORE_H +#define GPLUGIN_PURPLE2_DOMAIN (g_quark_from_static_string("gplugin-purple2")) +#endif /* GPLUGIN_PURPLE2_CORE_H */ --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/gplugin-purple2/gplugin-purple2-loader.c Sat Feb 02 03:18:30 2019 -0600
@@ -0,0 +1,167 @@
+#include "gplugin-purple2-loader.h" +#include "gplugin-purple2-core.h" +#include "gplugin-purple2-plugin.h" +#include "purple2/gplugin-purple2-stubs-purple.h" +G_DEFINE_DYNAMIC_TYPE(GPluginPurple2Loader, gplugin_purple2_loader, GPLUGIN_TYPE_LOADER); +/****************************************************************************** + *****************************************************************************/ +gplugin_purple2_loader_class_supported_extensions(G_GNUC_UNUSED const GPluginLoaderClass *klass) { + return g_slist_append(NULL, G_MODULE_SUFFIX); +gplugin_purple2_loader_query(G_GNUC_UNUSED GPluginLoader *loader, + GPluginPluginInfo *info = NULL; + GModule *module = NULL; + PurplePlugin *purple_plugin = NULL; + gboolean (*init_func)(PurplePlugin *); + module = g_module_open(filename, 0); + const gchar *msg = g_module_error(); + GPLUGIN_PURPLE2_DOMAIN, + "failed to open plugin %s: %s", + /* look for the purple_init_plugin symbol */ + if(!g_module_symbol(module, "purple_init_plugin", (gpointer)(&init_func))) { + g_module_close(module); + GPLUGIN_PURPLE2_DOMAIN, + "failed to query plugin %s: purple_init_plugin function not found", + /* now create the PurplePlugin instance so we can call the + * purple_init_plugin function. + purple_plugin = g_new0(PurplePlugin, 1); + purple_plugin->native_plugin = TRUE; + purple_plugin->path = g_strdup(filename); + purple_plugin->handle = module; + /* now call the init function */ + if(!init_func(purple_plugin)) { + g_module_close(module); + GPLUGIN_PURPLE2_DOMAIN, + "purple_init_plugin failed for %s", + /* do some validation */ + if(purple_plugin->info->id == NULL || *purple_plugin->info->id == '\0') { + g_module_close(module); + g_clear_pointer(&purple_plugin, g_free); + GPLUGIN_PURPLE2_DOMAIN, + "plugin %s does not have an id set", + /* now create the GPluginPluginInfo */ + info = gplugin_plugin_info_new( + purple_plugin->info->id, + GPLUGIN_NATIVE_PLUGIN_ABI_VERSION, + "name", purple_plugin->info->name, + "version", purple_plugin->info->version, + "summary", purple_plugin->info->summary, + "description", purple_plugin->info->description, + "website", purple_plugin->info->homepage, + /* finally return the plugin */ + GPLUGIN_PURPLE2_TYPE_PLUGIN, + "purple-plugin", purple_plugin, +gplugin_purple2_loader_load(G_GNUC_UNUSED GPluginLoader *loader, +gplugin_purple2_loader_unload(G_GNUC_UNUSED GPluginLoader *loader, +/****************************************************************************** + *****************************************************************************/ +gplugin_purple2_loader_init(G_GNUC_UNUSED GPluginPurple2Loader *loader) { +gplugin_purple2_loader_class_finalize(G_GNUC_UNUSED GPluginPurple2LoaderClass *klass) { +gplugin_purple2_loader_class_init(GPluginPurple2LoaderClass *klass) { + GPluginLoaderClass *loader_class = GPLUGIN_LOADER_CLASS(klass); + loader_class->supported_extensions = + gplugin_purple2_loader_class_supported_extensions; + loader_class->query = gplugin_purple2_loader_query; + loader_class->load = gplugin_purple2_loader_load; + loader_class->unload = gplugin_purple2_loader_unload; +/****************************************************************************** + *****************************************************************************/ +gplugin_purple2_loader_register(GPluginNativePlugin *native) { + gplugin_purple2_loader_register_type(G_TYPE_MODULE(native)); --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/gplugin-purple2/gplugin-purple2-loader.h Sat Feb 02 03:18:30 2019 -0600
@@ -0,0 +1,39 @@
+#ifndef GPLUGIN_PURPLE2_LOADER_H +#define GPLUGIN_PURPLE2_LOADER_H +#define GPLUGIN_PURPLE2_TYPE_LOADER (gplugin_purple2_loader_get_type()) +#define GPLUGIN_PURPLE2_LOADER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GPLUGIN_PURPLE2_TYPE_LOADER, GPluginPurple2Loader)) +#define GPLUGIN_PURPLE2_LOADER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GPLUGIN_PURPLE2_TYPE_LOADER, GPluginPurple2LoaderClass)) +#define GPLUGIN_PURPLE2_IS_LOADER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GPLUGIN_PURPLE2_TYPE_LOADER)); +#define GPLUGIN_PURPLE2_IS_LOADER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GPLUGIN_PURPLE2_TYPE_LOADER)); +#define GPLUGIN_PURPLE2_LOADER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GPLUGIN_PURPLE2_TYPE_LOADER, GPluginPurple2LoaderClass)) +typedef struct _GPluginPurple2Loader GPluginPurple2Loader; +typedef struct _GPluginPurple2LoaderClass GPluginPurple2LoaderClass; +#include <gplugin-native.h> +struct _GPluginPurple2Loader { +struct _GPluginPurple2LoaderClass { + GPluginLoaderClass parent; +void gplugin_purple2_loader_register(GPluginNativePlugin *native); +GType gplugin_purple2_loader_get_type(void); +#endif /* GPLUGIN_PURPLE2_LOADER_H */ --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/gplugin-purple2/gplugin-purple2-plugin.c Sat Feb 02 03:18:30 2019 -0600
@@ -0,0 +1,191 @@
+#include "gplugin-purple2-plugin.h" +/****************************************************************************** + *****************************************************************************/ + PurplePlugin *purple_plugin; + GPluginPluginInfo *info; + GPluginPluginState state; +} GPluginPurple2PluginPrivate; +/****************************************************************************** + *****************************************************************************/ + PROP_FILENAME = N_PROPERTIES, +static GParamSpec *properties[N_PROPERTIES] = {NULL,}; +/* I hate forward declarations... */ +static void gplugin_purple2_plugin_iface_init(GPluginPluginInterface *iface); +G_DEFINE_DYNAMIC_TYPE_EXTENDED( + gplugin_purple2_plugin, + G_ADD_PRIVATE_DYNAMIC(GPluginPurple2Plugin) + G_IMPLEMENT_INTERFACE(GPLUGIN_TYPE_PLUGIN, gplugin_purple2_plugin_iface_init) +/****************************************************************************** + * GPluginPlugin Interface + *****************************************************************************/ +gplugin_purple2_plugin_iface_init(GPluginPluginInterface *iface) { +/****************************************************************************** + *****************************************************************************/ +gplugin_purple2_plugin_get_property(GObject *obj, guint param_id, GValue *value, + GPluginPurple2Plugin *plugin = GPLUGIN_PURPLE2_PLUGIN(obj); + GPluginPurple2PluginPrivate *priv = gplugin_purple2_plugin_get_instance_private(plugin); + g_value_set_pointer(value, priv->module); + case PROP_PURPLE_PLUGIN: + g_value_set_pointer(value, priv->purple_plugin); + g_value_set_string(value, priv->filename); + g_value_set_object(value, priv->loader); + g_value_set_object(value, priv->info); + g_value_set_enum(value, priv->state); + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); +gplugin_purple2_plugin_set_property(GObject *obj, guint param_id, + const GValue *value, GParamSpec *pspec) + GPluginPurple2Plugin *plugin = GPLUGIN_PURPLE2_PLUGIN(obj); + GPluginPurple2PluginPrivate *priv = gplugin_purple2_plugin_get_instance_private(plugin); + priv->module = g_value_get_pointer(value); + case PROP_PURPLE_PLUGIN: + priv->purple_plugin = g_value_get_pointer(value); + priv->filename = g_value_dup_string(value); + priv->loader = g_value_dup_object(value); + priv->info = g_value_dup_object(value); + priv->state = g_value_get_enum(value); + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); +gplugin_purple2_plugin_finalize(GObject *obj) { + GPluginPurple2Plugin *plugin = GPLUGIN_PURPLE2_PLUGIN(obj); + GPluginPurple2PluginPrivate *priv = gplugin_purple2_plugin_get_instance_private(plugin); + g_clear_pointer(&priv->filename, g_free); + g_clear_object(&priv->loader); + g_clear_object(&priv->info); + G_OBJECT_CLASS(gplugin_purple2_plugin_parent_class)->finalize(obj); +gplugin_purple2_plugin_init(G_GNUC_UNUSED GPluginPurple2Plugin *plugin) { +gplugin_purple2_plugin_class_finalize(G_GNUC_UNUSED GPluginPurple2PluginClass *klass) +gplugin_purple2_plugin_class_init(GPluginPurple2PluginClass *klass) { + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + obj_class->get_property = gplugin_purple2_plugin_get_property; + obj_class->set_property = gplugin_purple2_plugin_set_property; + obj_class->finalize = gplugin_purple2_plugin_finalize; + * GPluginPurple2Plugin:module: + * The GModule instance for this plugin. + properties[PROP_MODULE] = g_param_spec_pointer( + "module", "module handle", + "The GModule instance of the plugin", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY + * GPluginPurple2Plugin:purple_plugin: + * The PurplePlugin that this plugin is wrapping. + properties[PROP_PURPLE_PLUGIN] = g_param_spec_pointer( + "purple-plugin", "purple plugin", + "The PurplePlugin that is wrapped", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY + g_object_class_install_properties(obj_class, N_PROPERTIES, properties); + /* add our overrides */ + g_object_class_override_property(obj_class, PROP_FILENAME, "filename"); + g_object_class_override_property(obj_class, PROP_LOADER, "loader"); + g_object_class_override_property(obj_class, PROP_INFO, "info"); + g_object_class_override_property(obj_class, PROP_STATE, "state"); +/****************************************************************************** + *****************************************************************************/ +gplugin_purple2_plugin_register(GPluginNativePlugin *native) { + gplugin_purple2_plugin_register_type(G_TYPE_MODULE(native)); --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/gplugin-purple2/gplugin-purple2-plugin.h Sat Feb 02 03:18:30 2019 -0600
@@ -0,0 +1,42 @@
+#ifndef GPLUGIN_PURPLE2_PLUGIN_H +#define GPLUGIN_PURPLE2_PLUGIN_H +#define GPLUGIN_PURPLE2_TYPE_PLUGIN (gplugin_purple2_plugin_get_type()) +#define GPLUGIN_PURPLE2_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GPLUGIN_PURPLE2_TYPE_PLUGIN, GPluginPurple2Plugin)) +#define GPLUGIN_PURPLE2_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GPLUGIN_PURPLE2_TYPE_PLUGIN, GPluginPurple2PluginClass)) +#define GPLUGIN_PURPLE2_IS_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GPLUGIN_PURPLE2_TYPE_PLUGIN)); +#define GPLUGIN_PURPLE2_IS_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GPLUGIN_PURPLE2_TYPE_PLUGIN)); +#define GPLUGIN_PURPLE2_PLUGIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GPLUGIN_PURPLE2_TYPE_PLUGIN, GPluginPurple2PluginClass)) +typedef struct _GPluginPurple2Plugin GPluginPurple2Plugin; +typedef struct _GPluginPurple2PluginClass GPluginPurple2PluginClass; +#include <gplugin-native.h> +#include "purple2/gplugin-purple2-stubs-purple.h" +struct _GPluginPurple2Plugin { +struct _GPluginPurple2PluginClass { +typedef gboolean (*GPluginPurple2PluginInitFunc)(PurplePlugin *plugin); +void gplugin_purple2_plugin_register(GPluginNativePlugin *native); +GType gplugin_purple2_plugin_get_type(void); +#endif /* GPLUGIN_PURPLE2_PLUGIN_H */ --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/gplugin-purple2/meson.build Sat Feb 02 03:18:30 2019 -0600
@@ -0,0 +1,32 @@
+############################################################################### +############################################################################### +GPLUGIN_PURPLE2_LIBRARY_VERSION = '0.0.1' +GPLUGIN_PURPLE2_HEADERS = [ + 'gplugin-purple2-core.h', + 'gplugin-purple2-loader.h', + 'gplugin-purple2-plugin.h', + 'purple2/gplugin-purple2-stubs-purple.h', +GPLUGIN_PURPLE2_SOURCES = [ + 'gplugin-purple2-core.c', + 'gplugin-purple2-loader.c', + 'gplugin-purple2-plugin.c', + 'purple2/gplugin-purple2-stubs-purple.c', +############################################################################### +############################################################################### +shared_library('gplugin-purple2', + GPLUGIN_PURPLE2_SOURCES, + GPLUGIN_PURPLE2_HEADERS, + c_args : ['-DGPLUGIN_PURPLE2_COMPILATION', '-DG_LOG_DOMAIN="GPluginPurple2"'], + include_directories : toplevel_inc, + dependencies : [GLIB, GOBJECT, GMODULE, GPLUGIN, PURPLE3], + version : GPLUGIN_PURPLE2_LIBRARY_VERSION, --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/gplugin-purple2/purple2/gplugin-purple2-stubs-purple.c Sat Feb 02 03:18:30 2019 -0600
@@ -0,0 +1,47 @@
+#include "gplugin-purple2-stubs-purple.h" +const guint purple_major_version = 2; +const guint purple_minor_version = 99; +const guint purple_micro_version = 99; +/****************************************************************************** + *****************************************************************************/ +purple_timeout_remove(guint sourceid) { + return g_source_remove(sourceid); +/****************************************************************************** + *****************************************************************************/ +purple_plugin_register(PurplePlugin *plugin) { + g_message("purple_plugin_register stub"); +purple_plugin_get_id(const PurplePlugin *plugin) { + g_message("purple_plugin_get_id stub"); +purple_plugin_destroy(PurplePlugin *plugin) { + g_message("purple_plugin_destroy stub"); +/****************************************************************************** + *****************************************************************************/ +purple_find_prpl(const gchar *name) { + g_message("purple_prpl_find stub"); --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/gplugin-purple2/purple2/gplugin-purple2-stubs-purple.h Sat Feb 02 03:18:30 2019 -0600
@@ -0,0 +1,104 @@
+#ifndef GPLUGIN_PURPLE2_STUBS_PURPLE +#define GPLUGIN_PURPLE2_STUBS_PURPLE +typedef gint PurplePluginPriority; + PURPLE_PLUGIN_UNKNOWN = -1, + PURPLE_PLUGIN_STANDARD = 0, +typedef struct _PurplePluginAction PurplePluginAction; +typedef struct _PurplePluginInfo PurplePluginInfo; +typedef struct _PurplePluginLoaderInfo PurplePluginLoaderInfo; +typedef struct _PurplePlugin PurplePlugin; +typedef struct _PurplePluginUiInfo PurplePluginUiInfo; +/* these should be implemented as necessary */ +typedef void PurplePluginPrefFrame; +struct _PurplePluginInfo{ + PurplePluginPriority priority; + gboolean (*load)(PurplePlugin *plugin); + gboolean (*unload)(PurplePlugin *plugin); + void (*destroy)(PurplePlugin *plugin); + PurplePluginUiInfo *prefs_info; + GList *(*actions)(PurplePlugin *plugin, gpointer context); +struct _PurplePluginLoaderInfo { + gboolean (*probe)(PurplePlugin *plugin); + gboolean (*load)(PurplePlugin *plugin); + gboolean (*unload)(PurplePlugin *plugin); + void (*destroy)(PurplePlugin *plugin); + gboolean native_plugin; + PurplePluginInfo *info; + GList *dependent_plugins; + /* this is using a reserved slot */ + gpointer _gplugin_plugin; +struct _PurplePluginUiInfo { + PurplePluginPrefFrame *(*get_plugin_pref_frame)(PurplePlugin *plugin); + PurplePluginPrefFrame *frame; +struct _PurplePluginAction { + void (*callback)(PurplePluginAction *); +extern const guint purple_major_version; +extern const guint purple_minor_version; +extern const guint purple_micro_version; +#endif /* GPLUGIN_PURPLE2_STUBS_PURPLE */ --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/meson.build Sat Feb 02 03:18:30 2019 -0600
@@ -0,0 +1,57 @@
+############################################################################### +############################################################################### +project('gplugin-purple2', 'c', version : '0.0.1-dev', + meson_version : '>=0.37.0', + default_options : ['c_std=c99']) +parts = meson.project_version().split('-') +parts = parts[0].split('.') +GPLUGIN_PURPLE2_MAJOR_VERSION = parts[0] +version_conf = configuration_data() +version_conf.set('GPLUGIN_PURPLE2_MAJOR_VERSION', GPLUGIN_PURPLE2_MAJOR_VERSION) +version_conf.set('GPLUGIN_PURPLE2_MINOR_VERSION', parts[1]) +version_conf.set('GPLUGIN_PURPLE2_MICRO_VERSION', parts[2]) +version_conf.set('GPLUGIN_PURPLE2_EXTRA_VERSION', extra) +version_conf.set('GPLUGIN_PURPLE2_VERSION', meson.project_version()) +############################################################################### +############################################################################### +pkgconfig = import('pkgconfig') +GLIB = dependency('glib-2.0', version : '>=2.40.0') +GOBJECT = dependency('gobject-2.0') +GMODULE = dependency('gmodule-2.0') +GPLUGIN = dependency('gplugin') +PURPLE3 = dependency('purple-3') +############################################################################### +############################################################################### +compiler = meson.get_compiler('c') +if compiler.has_argument('-Wformat') + add_project_arguments('-Wformat', language : 'c') + if compiler.has_multi_arguments(['-Wformat', '-Werror=format-security']) + add_project_arguments('-Werror=format-security', language : 'c') +toplevel_inc = include_directories('.') +############################################################################### +############################################################################### +subdir('gplugin-purple2')