grim/gplugin-purple2-loader

beddfd4f9bf9
Parents
Children fd4ebce81b79
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 @@
+syntax: regexp
+^build.*\/
+
--- /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.h>
+#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[] = {
+ "get rekt",
+ NULL,
+ };
+
+ return gplugin_plugin_info_new(
+ "gplugin-purple2/purple2",
+ GPLUGIN_NATIVE_PLUGIN_ABI_VERSION,
+ "internal", TRUE,
+ "load-on-query", TRUE,
+ "name", "Purple2 Plugin Loader",
+ "version", "0.0.1",
+ "license-id", "GPL2",
+ "summary", "A plugin that can load purple2 plugins",
+ "description", "This plugin mocks the purple2 api and calls the "
+ "appropriate purple3 api",
+ "authors", authors,
+ NULL
+ );
+}
+
+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);
+
+ return TRUE;
+}
+
+G_MODULE_EXPORT gboolean
+gplugin_unload(G_GNUC_UNUSED GPluginNativePlugin *plugin,
+ G_GNUC_UNUSED GError **error)
+{
+ return FALSE;
+}
+
--- /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
+
+#include <glib.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);
+
+/******************************************************************************
+ * GPluginLoader Stuff
+ *****************************************************************************/
+static GSList *
+gplugin_purple2_loader_class_supported_extensions(G_GNUC_UNUSED const GPluginLoaderClass *klass) {
+ return g_slist_append(NULL, G_MODULE_SUFFIX);
+}
+
+static GPluginPlugin *
+gplugin_purple2_loader_query(G_GNUC_UNUSED GPluginLoader *loader,
+ const gchar *filename,
+ GError **error)
+{
+ GPluginPluginInfo *info = NULL;
+ GModule *module = NULL;
+ PurplePlugin *purple_plugin = NULL;
+ gboolean (*init_func)(PurplePlugin *);
+
+ module = g_module_open(filename, 0);
+ if(module == NULL) {
+ const gchar *msg = g_module_error();
+
+ g_set_error(
+ error,
+ GPLUGIN_PURPLE2_DOMAIN,
+ 0,
+ "failed to open plugin %s: %s",
+ filename,
+ msg
+ );
+
+ return NULL;
+ }
+
+ /* look for the purple_init_plugin symbol */
+ if(!g_module_symbol(module, "purple_init_plugin", (gpointer)(&init_func))) {
+ g_module_close(module);
+
+ g_set_error(
+ error,
+ GPLUGIN_PURPLE2_DOMAIN,
+ 0,
+ "failed to query plugin %s: purple_init_plugin function not found",
+ filename
+ );
+
+ return NULL;
+ }
+
+ /* 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);
+
+ g_set_error(
+ error,
+ GPLUGIN_PURPLE2_DOMAIN,
+ 0,
+ "purple_init_plugin failed for %s",
+ filename
+ );
+
+ return NULL;
+ }
+
+ /* 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);
+
+ g_set_error(
+ error,
+ GPLUGIN_PURPLE2_DOMAIN,
+ 0,
+ "plugin %s does not have an id set",
+ filename
+ );
+
+ return NULL;
+ }
+
+ /* 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,
+ NULL
+ );
+
+ /* finally return the plugin */
+ return g_object_new(
+ GPLUGIN_PURPLE2_TYPE_PLUGIN,
+ "module", module,
+ "purple-plugin", purple_plugin,
+ "filename", filename,
+ "loader", loader,
+ "info", info,
+ NULL
+ );
+}
+
+static gboolean
+gplugin_purple2_loader_load(G_GNUC_UNUSED GPluginLoader *loader,
+ GPluginPlugin *plugin,
+ GError **error)
+{
+ return FALSE;
+}
+
+static gboolean
+gplugin_purple2_loader_unload(G_GNUC_UNUSED GPluginLoader *loader,
+ GPluginPlugin *plugin,
+ GError **error)
+{
+ return FALSE;
+}
+
+
+/******************************************************************************
+ * GObject Stuff
+ *****************************************************************************/
+static void
+gplugin_purple2_loader_init(G_GNUC_UNUSED GPluginPurple2Loader *loader) {
+}
+
+static void
+gplugin_purple2_loader_class_finalize(G_GNUC_UNUSED GPluginPurple2LoaderClass *klass) {
+}
+
+static void
+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;
+}
+
+/******************************************************************************
+ * API
+ *****************************************************************************/
+void
+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.h>
+#include <gplugin-native.h>
+
+struct _GPluginPurple2Loader {
+ /*< private >*/
+ GPluginLoader parent;
+
+ gpointer reserved[4];
+};
+
+struct _GPluginPurple2LoaderClass {
+ /*< private >*/
+ GPluginLoaderClass parent;
+
+ gpointer reserved[4];
+};
+
+G_BEGIN_DECLS
+
+void gplugin_purple2_loader_register(GPluginNativePlugin *native);
+GType gplugin_purple2_loader_get_type(void);
+
+G_END_DECLS
+
+#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"
+
+/******************************************************************************
+ * Structs
+ *****************************************************************************/
+typedef struct {
+ GModule *module;
+ PurplePlugin *purple_plugin;
+
+ /* overrides */
+ gchar *filename;
+ GPluginLoader *loader;
+ GPluginPluginInfo *info;
+ GPluginPluginState state;
+} GPluginPurple2PluginPrivate;
+
+/******************************************************************************
+ * Enums
+ *****************************************************************************/
+enum {
+ PROP_ZERO,
+ PROP_MODULE,
+ PROP_PURPLE_PLUGIN,
+ N_PROPERTIES,
+
+ /* overrides */
+ PROP_FILENAME = N_PROPERTIES,
+ PROP_LOADER,
+ PROP_INFO,
+ PROP_STATE,
+};
+static GParamSpec *properties[N_PROPERTIES] = {NULL,};
+
+/* I hate forward declarations... */
+static void gplugin_purple2_plugin_iface_init(GPluginPluginInterface *iface);
+
+G_DEFINE_DYNAMIC_TYPE_EXTENDED(
+ GPluginPurple2Plugin,
+ gplugin_purple2_plugin,
+ G_TYPE_OBJECT,
+ 0,
+ G_ADD_PRIVATE_DYNAMIC(GPluginPurple2Plugin)
+ G_IMPLEMENT_INTERFACE(GPLUGIN_TYPE_PLUGIN, gplugin_purple2_plugin_iface_init)
+);
+
+/******************************************************************************
+ * GPluginPlugin Interface
+ *****************************************************************************/
+static void
+gplugin_purple2_plugin_iface_init(GPluginPluginInterface *iface) {
+}
+
+/******************************************************************************
+ * GObject Stuff
+ *****************************************************************************/
+static void
+gplugin_purple2_plugin_get_property(GObject *obj, guint param_id, GValue *value,
+ GParamSpec *pspec)
+{
+ GPluginPurple2Plugin *plugin = GPLUGIN_PURPLE2_PLUGIN(obj);
+ GPluginPurple2PluginPrivate *priv = gplugin_purple2_plugin_get_instance_private(plugin);
+
+ switch(param_id) {
+ case PROP_MODULE:
+ g_value_set_pointer(value, priv->module);
+ break;
+ case PROP_PURPLE_PLUGIN:
+ g_value_set_pointer(value, priv->purple_plugin);
+ break;
+
+ /* overrides */
+ case PROP_FILENAME:
+ g_value_set_string(value, priv->filename);
+ break;
+ case PROP_LOADER:
+ g_value_set_object(value, priv->loader);
+ break;
+ case PROP_INFO:
+ g_value_set_object(value, priv->info);
+ break;
+ case PROP_STATE:
+ g_value_set_enum(value, priv->state);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
+ break;
+ }
+}
+
+static void
+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);
+
+ switch(param_id) {
+ case PROP_MODULE:
+ priv->module = g_value_get_pointer(value);
+ break;
+ case PROP_PURPLE_PLUGIN:
+ priv->purple_plugin = g_value_get_pointer(value);
+ break;
+
+ /* overrides */
+ case PROP_FILENAME:
+ priv->filename = g_value_dup_string(value);
+ break;
+ case PROP_LOADER:
+ priv->loader = g_value_dup_object(value);
+ break;
+ case PROP_INFO:
+ priv->info = g_value_dup_object(value);
+ break;
+ case PROP_STATE:
+ priv->state = g_value_get_enum(value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
+ break;
+ }
+}
+
+static void
+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);
+}
+
+static void
+gplugin_purple2_plugin_init(G_GNUC_UNUSED GPluginPurple2Plugin *plugin) {
+}
+
+static void
+gplugin_purple2_plugin_class_finalize(G_GNUC_UNUSED GPluginPurple2PluginClass *klass)
+{
+}
+
+static void
+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");
+}
+
+/******************************************************************************
+ * API
+ *****************************************************************************/
+void
+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.h>
+#include <gplugin-native.h>
+
+#include "purple2/gplugin-purple2-stubs-purple.h"
+
+struct _GPluginPurple2Plugin {
+ /*< private >*/
+ GObject parent;
+
+ gpointer reserved[4];
+};
+
+struct _GPluginPurple2PluginClass {
+ /*< private >*/
+ GObjectClass parent;
+
+ gpointer reserved[4];
+};
+
+typedef gboolean (*GPluginPurple2PluginInitFunc)(PurplePlugin *plugin);
+
+G_BEGIN_DECLS
+
+void gplugin_purple2_plugin_register(GPluginNativePlugin *native);
+GType gplugin_purple2_plugin_get_type(void);
+
+G_BEGIN_DECLS
+
+#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 @@
+###############################################################################
+# Library
+###############################################################################
+
+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',
+]
+
+###############################################################################
+# Library target
+###############################################################################
+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,
+ install : true
+)
+
--- /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"
+
+#include <glib.h>
+
+const guint purple_major_version = 2;
+const guint purple_minor_version = 99;
+const guint purple_micro_version = 99;
+
+/******************************************************************************
+ * eventloop.h
+ *****************************************************************************/
+gboolean
+purple_timeout_remove(guint sourceid) {
+ return g_source_remove(sourceid);
+}
+
+/******************************************************************************
+ * plugin.h
+ *****************************************************************************/
+gboolean
+purple_plugin_register(PurplePlugin *plugin) {
+ g_message("purple_plugin_register stub");
+
+ return TRUE;
+}
+
+const gchar *
+purple_plugin_get_id(const PurplePlugin *plugin) {
+ g_message("purple_plugin_get_id stub");
+
+ return NULL;
+}
+
+void
+purple_plugin_destroy(PurplePlugin *plugin) {
+ g_message("purple_plugin_destroy stub");
+}
+
+/******************************************************************************
+ * prpl.h
+ *****************************************************************************/
+PurplePlugin *
+purple_find_prpl(const gchar *name) {
+ g_message("purple_prpl_find stub");
+
+ return NULL;
+}
--- /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
+
+#include <glib.h>
+
+typedef gint PurplePluginPriority;
+
+typedef enum {
+ PURPLE_PLUGIN_UNKNOWN = -1,
+ PURPLE_PLUGIN_STANDARD = 0,
+ PURPLE_PLUGIN_LOADER,
+ PURPLE_PLUGIN_PROTOCOL
+} PurplePluginType;
+
+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{
+ guint magic;
+ guint major_version;
+ guint minor_version;
+ PurplePluginType type;
+ gchar *ui_requirement;
+ gulong flags;
+ GList *dependencies;
+ PurplePluginPriority priority;
+
+ gchar *id;
+ gchar *name;
+ gchar *version;
+ gchar *summary;
+ gchar *description;
+ gchar *author;
+ gchar *homepage;
+
+ gboolean (*load)(PurplePlugin *plugin);
+ gboolean (*unload)(PurplePlugin *plugin);
+ void (*destroy)(PurplePlugin *plugin);
+
+ gpointer ui_info;
+ gpointer extra_info;
+ PurplePluginUiInfo *prefs_info;
+
+ GList *(*actions)(PurplePlugin *plugin, gpointer context);
+};
+
+struct _PurplePluginLoaderInfo {
+ GList *exts;
+
+ gboolean (*probe)(PurplePlugin *plugin);
+ gboolean (*load)(PurplePlugin *plugin);
+ gboolean (*unload)(PurplePlugin *plugin);
+ void (*destroy)(PurplePlugin *plugin);
+};
+
+struct _PurplePlugin {
+ gboolean native_plugin;
+ gboolean loaded;
+ gpointer handle;
+ gchar *path;
+ PurplePluginInfo *info;
+ gchar *error;
+ gpointer ipc_data;
+ gpointer extra;
+ gboolean unloadable;
+ GList *dependent_plugins;
+
+ /* this is using a reserved slot */
+ gpointer _gplugin_plugin;
+};
+
+struct _PurplePluginUiInfo {
+ PurplePluginPrefFrame *(*get_plugin_pref_frame)(PurplePlugin *plugin);
+
+ gint page_num;
+ PurplePluginPrefFrame *frame;
+};
+
+struct _PurplePluginAction {
+ gchar *label;
+ void (*callback)(PurplePluginAction *);
+
+ PurplePlugin *plugin;
+
+ gpointer context;
+
+ gpointer user_data;
+};
+
+G_BEGIN_DECLS
+
+extern const guint purple_major_version;
+extern const guint purple_minor_version;
+extern const guint purple_micro_version;
+
+G_BEGIN_DECLS
+
+#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 Info
+###############################################################################
+project('gplugin-purple2', 'c', version : '0.0.1-dev',
+ meson_version : '>=0.37.0',
+ default_options : ['c_std=c99'])
+
+parts = meson.project_version().split('-')
+if parts.length() > 1
+ extra = parts[1]
+else
+ extra = ''
+endif
+
+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())
+
+###############################################################################
+# Dependencies
+###############################################################################
+gnome = import('gnome')
+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')
+
+###############################################################################
+# Build Info
+###############################################################################
+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')
+ endif
+endif
+
+toplevel_inc = include_directories('.')
+
+###############################################################################
+# Subdirectories
+###############################################################################
+subdir('gplugin-purple2')
+