Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/Remmina/Remmina.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorToolsDevler <info@toolsdevler.net>2020-10-10 20:48:21 +0300
committerToolsDevler <info@toolsdevler.net>2020-12-31 03:03:24 +0300
commitc2d7c99c61d7b5f8879f14b073dc51d1603facdc (patch)
tree040df0f2face7c33bfa28a4135b28ff86887a968
parent3b9043d6ed81d3afb451f2c07377e5741a6c0340 (diff)
WIP: Fixed plugin loading
-rw-r--r--plugins/tool_hello_world_python/toolsdevler.py48
-rw-r--r--src/remmina_plugin_manager.c18
-rw-r--r--src/remmina_plugin_manager.h1
-rw-r--r--src/remmina_plugin_python.c33
-rw-r--r--src/remmina_plugin_python.h1
-rw-r--r--src/remmina_plugin_python_module.c2
-rw-r--r--src/remmina_plugin_python_plugin.c284
7 files changed, 282 insertions, 105 deletions
diff --git a/plugins/tool_hello_world_python/toolsdevler.py b/plugins/tool_hello_world_python/toolsdevler.py
index d1f3c1041..7c79d7233 100644
--- a/plugins/tool_hello_world_python/toolsdevler.py
+++ b/plugins/tool_hello_world_python/toolsdevler.py
@@ -4,27 +4,27 @@ if not hasattr(sys, 'argv'):
sys.argv = ['']
import remmina
+import gi
+gi.require_version("Gtk", "3.0")
+from gi.repository import Gtk, GLib
+import psutil
-class HelloPlugin(remmina.Plugin):
+class HelloPlugin(remmina.ProtocolPlugin):
def __init__(self):
- self.type = remmina.PLUGIN_TYPE_PROTOCOL
- self.name = "Hello"
- self.description = "Just a Plugin saying hello :)"
- self.version = "1.0"
- self.appicon = ""
- self.service = None
- self.protocol_setting = None
+ super().__init__("Hello", "Just a Plugin saying hello :)", "1.0", "")
def init(self, service):
self.service = service
- service.log_printf("[%s]: Plugin init\n" % self.name)
+ print("Init!")
+ self.show_gui()
+ super.init()
def open_connection(self):
- service.log_printf("[%s]: Plugin open connection\n" % self.name)
-
+ self.service.log_printf("[%s]: Plugin open connection\n" % self.name)
+ super.open_connection()
def close_connection(self):
- service.log_printf("[%s]: Plugin close connection\n" % self.name)
+ self.service.log_printf("[%s]: Plugin close connection\n" % self.name)
def query_feature(self):
pass
@@ -38,12 +38,18 @@ class HelloPlugin(remmina.Plugin):
def get_plugin_screenshot(self):
pass
-print("import gi")
-import gi
-gi.require_version("Gtk", "3.0")
-from gi.repository import Gtk
-
-window = Gtk.Window(title="Hello World")
-window.show()
-window.connect("destroy", Gtk.main_quit)
-Gtk.main()
+ def show_gui(self):
+ self.window = Gtk.Window(title="Hello World")
+ self.lblMemUsage = Gtk.Label(label="CPU Usage: ")
+ self.window.add(self.lblMemUsage)
+ self.window.show_all()
+ self.window.connect("destroy", Gtk.main_quit)
+ GLib.timeout_add_seconds(1, self.threaded_mem_usage)
+ Gtk.main()
+
+ def threaded_mem_usage(self):
+ self.lblMemUsage.set_text("CPU Usage: %s" % psutil.cpu_percent())
+ return True
+
+myPlugin = HelloPlugin()
+#myPlugin.show_gui()
diff --git a/src/remmina_plugin_manager.c b/src/remmina_plugin_manager.c
index 1f3731ec9..3f51beb85 100644
--- a/src/remmina_plugin_manager.c
+++ b/src/remmina_plugin_manager.c
@@ -320,7 +320,8 @@ void remmina_plugin_manager_init()
if ((ptr = strrchr(name, '.')) == NULL)
continue;
ptr++;
- if (g_strcmp0(ptr, G_MODULE_SUFFIX) != 0 && g_strcmp0(ptr, "py"))
+ // TODO: Iterate plugin loaders to find out at runtime if we support it
+ if (g_strcmp0(ptr, G_MODULE_SUFFIX) != 0 && !remmina_plugin_manager_supported(ptr))
continue;
fullpath = g_strdup_printf(REMMINA_RUNTIME_PLUGINDIR "/%s", name);
remmina_plugin_manager_load_plugin(fullpath);
@@ -358,6 +359,21 @@ void remmina_plugin_manager_init()
g_slist_free(secret_plugins);
}
+gboolean remmina_plugin_manager_supported(const char *filetype) {
+ TRACE_CALL(__func__);
+ RemminaPluginLoader *loader;
+ gint i;
+
+ for (i = 0; i < remmina_plugin_loaders->len; i++) {
+ loader = (RemminaPluginLoader*)g_ptr_array_index(remmina_plugin_loaders, i);
+ if (g_strcmp0(loader->filetype, filetype) == 0) {
+ g_print("Plugin type %s for %s is supported!\n", filetype, loader->filetype);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
void remmina_plugin_manager_add_loader(char *filetype, RemminaPluginLoaderFunc func) {
if (!remmina_plugin_loaders)
remmina_plugin_loaders = g_ptr_array_new();
diff --git a/src/remmina_plugin_manager.h b/src/remmina_plugin_manager.h
index 578d95d5b..731f48e0c 100644
--- a/src/remmina_plugin_manager.h
+++ b/src/remmina_plugin_manager.h
@@ -65,6 +65,7 @@ typedef struct {
RemminaPluginLoaderFunc func;
} RemminaPluginLoader;
+gboolean remmina_plugin_manager_supported(const char *filetype);
void remmina_plugin_manager_add_loader(char *filetype, RemminaPluginLoaderFunc func);
G_END_DECLS
diff --git a/src/remmina_plugin_python.c b/src/remmina_plugin_python.c
index d2db79696..43257175b 100644
--- a/src/remmina_plugin_python.c
+++ b/src/remmina_plugin_python.c
@@ -13,6 +13,7 @@
#include "remmina_plugin_python_module.h"
#include "remmina_plugin_python_plugin.h"
+
void remmina_plugin_python_init(void) {
TRACE_CALL(__FUNC__);
// Initialize Python environment
@@ -20,14 +21,33 @@ void remmina_plugin_python_init(void) {
remmina_plugin_python_module_register_object(plugin_object);
remmina_plugin_python_module_init();
-
Py_Initialize();
PyRun_SimpleString("import sys");
PyRun_SimpleString("sys.path.append('" REMMINA_RUNTIME_PLUGINDIR "')");
}
-static char* basename(const char* path) {
- return "toolsdevler";
+int basename_no_ext(const char* in, char** out) {
+ // Find last segment of path...
+ const char* end = in + strlen(in);
+ const char* from = in;
+ const char* to = end;
+ for (const char* ptr = in; ptr != end; ++ptr) {
+ if (*ptr == '/') {
+ while (*ptr == '/' && ptr != end)
+ ++ptr;
+ if (ptr == end)
+ return NULL;
+ from = ptr;
+ } else if (*ptr == '.') {
+ to = ptr;
+ }
+ }
+
+ int length = to - from;
+ *out = (char*)malloc(sizeof(char*) * ((length) + 1));
+ strncpy(*out, from, to-from);
+ (*out)[length] = '\0';
+ return length;
}
gboolean
@@ -36,14 +56,15 @@ remmina_plugin_python_load(RemminaPluginService* service, const char* name) {
PyObject *plugin_name, *plugin_file;
PyObject *pArgs, *pValue;
int i;
-
- plugin_name = PyUnicode_DecodeFSDefault(basename(name));
+ char* filename = NULL;
+ basename_no_ext(name, &filename);
+ plugin_name = PyUnicode_DecodeFSDefault(filename);
plugin_file = PyImport_Import(plugin_name);
if (plugin_file != NULL) {
return TRUE;
} else {
- PyErr_Print();
g_print("Failed to load \"%s\"\n", name);
+ PyErr_Print();
return FALSE;
}
return TRUE;
diff --git a/src/remmina_plugin_python.h b/src/remmina_plugin_python.h
index 307588904..fbf921669 100644
--- a/src/remmina_plugin_python.h
+++ b/src/remmina_plugin_python.h
@@ -41,5 +41,6 @@
G_BEGIN_DECLS
gboolean remmina_plugin_python_load(RemminaPluginService* service, const char* name);
+void remmina_plugin_python_init(void);
G_END_DECLS
diff --git a/src/remmina_plugin_python_module.c b/src/remmina_plugin_python_module.c
index 17d896d91..fc1e25f53 100644
--- a/src/remmina_plugin_python_module.c
+++ b/src/remmina_plugin_python_module.c
@@ -75,7 +75,7 @@ PyMODINIT_FUNC remmina_plugin_python_module_initialize(void) {
builtin = (PyTypeObject*)g_ptr_array_index(remmina_python_module_object_table, i);
if (builtin) {
Py_INCREF(builtin);
- if (PyModule_AddObject(module_instance, "Plugin", (PyObject*)builtin)) {
+ if (PyModule_AddObject(module_instance, "ProtocolPlugin", (PyObject*)builtin)) {
printf("%s: Error initializing\n", builtin->tp_name);
Py_INCREF(builtin);
}
diff --git a/src/remmina_plugin_python_plugin.c b/src/remmina_plugin_python_plugin.c
index edf833e87..a25df8026 100644
--- a/src/remmina_plugin_python_plugin.c
+++ b/src/remmina_plugin_python_plugin.c
@@ -6,6 +6,7 @@
#include <glib.h>
#include <gtk/gtk.h>
+#include "remmina_plugin_manager.h"
#include "remmina/plugin.h"
#include "remmina_plugin_python_plugin.h"
@@ -16,73 +17,96 @@ static const gchar* STR_REMMINA_PLUGIN_TYPE_TOOL = "remmina.plugin_type.tool";
static const gchar* STR_REMMINA_PLUGIN_TYPE_PREF = "remmina.plugin_type.pref";
static const gchar* STR_REMMINA_PLUGIN_TYPE_SECRET = "remmina.plugin_type.secret";
+GPtrArray* remmina_plugin_registry = NULL;
-static int
-remmina_remmina_plugin_init(RemminaPluginPython *self, PyObject *args, PyObject *kwds);
+typedef struct {
+ PyObject * name;
+ PyObject * description;
+ PyObject * version;
+ PyObject * appicon;
+ PyObject * icon_name;
+ PyObject * icon_name_ssh;
+ PyObject * basic_settings;
+ PyObject * advanced_settings;
+ PyObject * ssh_setting;
+ PyObject * features;
+ RemminaProtocolWidget* widget;
+} RemminaPluginPythonProtocolPlugin;
-static PyObject *
-remmina_remmina_plugin_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
-
-static PyMemberDef RemminaPluginPython_members[] = {
- {"name", T_OBJECT_EX, offsetof(RemminaPluginPython, name), 0,
- "plugin name"},
- {"description", T_OBJECT_EX, offsetof(RemminaPluginPython, description), 0,
- "plugin description"},
- {"version", T_OBJECT_EX, offsetof(RemminaPluginPython, version), 0,
- "plugin version"},
- {"appicon", T_OBJECT_EX, offsetof(RemminaPluginPython, appicon), 0,
- "plugin app-icon name"},
+
+static PyMemberDef remmina_plugin_python_protocol_plugin_members[] = {
+ {"name", T_OBJECT_EX, offsetof(RemminaPluginPythonProtocolPlugin, name), 0, "plugin name"},
+ {"description", T_OBJECT_EX, offsetof(RemminaPluginPythonProtocolPlugin, description), 0, "plugin description"},
+ {"version", T_OBJECT_EX, offsetof(RemminaPluginPythonProtocolPlugin, version), 0, "plugin version"},
+ {"appicon", T_OBJECT_EX, offsetof(RemminaPluginPythonProtocolPlugin, appicon), 0, "plugin app-icon name"},
+ {"icon_name", T_OBJECT_EX, offsetof(RemminaPluginPythonProtocolPlugin, icon_name), 0, "icon_name"},
+ {"icon_name_ssh", T_OBJECT_EX, offsetof(RemminaPluginPythonProtocolPlugin, icon_name_ssh), 0, "icon_name_ssh"},
+ {"basic_settings", T_OBJECT_EX, offsetof(RemminaPluginPythonProtocolPlugin, basic_settings), 0, "basic_settings"},
+ {"advanced_settings", T_INT, offsetof(RemminaPluginPythonProtocolPlugin, advanced_settings), 0, "advanced_settings"},
+ {"ssh_setting", T_INT, offsetof(RemminaPluginPythonProtocolPlugin, ssh_setting), 0, "ssh_setting"},
+ {"features", T_OBJECT_EX, offsetof(RemminaPluginPythonProtocolPlugin, features), 0, "features"},
{NULL} /* Sentinel */
};
+/* Array for available features.
+ * The last element of the array must be REMMINA_PROTOCOL_FEATURE_TYPE_END. */
+static const RemminaProtocolFeature remmina_protocol_python_plugin_features[] =
+{
+ { REMMINA_PROTOCOL_FEATURE_TYPE_END, 0, NULL, NULL, NULL }
+};
-typedef struct {
- PyObject_HEAD
- PyObject *name;
- PyObject *description;
- PyObject *version;
- PyObject *appicon;
- RemminaPlugin* remmina_plugin;
-} RemminaPluginPython;
-typedef struct {
- PyObject * type;
- PyObject * name;
- PyObject * description;
- PyObject * domain;
- PyObject * version;
-
- PyObject * icon_name;
- PyObject * icon_name_ssh;
- PyObject * basic_settings;
- PyObject * advanced_settings;
- PyObject * ssh_setting;
- PyObject * features;
-
- PyMethodDef m_mehods[] = {
+PyMethodDef remmina_plugin_python_protocol_plugin_methods[] = {
{"init", METH_VARARGS, NULL },
{"open_connection", METH_VARARGS, NULL },
{"close_connection", METH_VARARGS, NULL },
{"query_feature", METH_VARARGS, NULL },
{"call_feature", METH_VARARGS, NULL },
{"send_keystrokes", METH_VARARGS, NULL },
- {"get_plugin_screenshot", METH_VARARGS, NULL }};
-} RemminaProtocolPluginPython;
+ {"get_plugin_screenshot", METH_VARARGS, NULL }
+};
+
+/*
+ void (*init)(RemminaProtocolWidget *gp);
+ gboolean (*open_connection)(RemminaProtocolWidget *gp);
+ gboolean (*close_connection)(RemminaProtocolWidget *gp);
+ gboolean (*query_feature)(RemminaProtocolWidget *gp, const RemminaProtocolFeature *feature);
+ void (*call_feature)(RemminaProtocolWidget *gp, const RemminaProtocolFeature *feature);
+ void (*send_keystrokes)(RemminaProtocolWidget *gp, const guint keystrokes[], const gint keylen);
+ gboolean (*get_plugin_screenshot)(RemminaProtocolWidget *gp, RemminaPluginScreenshotData *rpsd);*/
-static PyTypeObject RemminaPluginPythonType = {
+static void remmina_protocol_plugin_wrapper_init(RemminaProtocolWidget *gp);
+static gboolean remmina_protocol_plugin_wrapper_open_connection(RemminaProtocolWidget *gp);
+static gboolean remmina_protocol_plugin_wrapper_close_connection(RemminaProtocolWidget *gp);
+static gboolean remmina_protocol_plugin_wrapper_query_feature(RemminaProtocolWidget *gp, const RemminaProtocolFeature *feature);
+static void remmina_protocol_plugin_wrapper_call_feature(RemminaProtocolWidget *gp, const RemminaProtocolFeature *feature);
+static void remmina_protocol_plugin_wrapper_send_keystrokes(RemminaProtocolWidget *gp, const guint keystrokes[], const gint keylen);
+static gboolean remmina_protocol_plugin_wrapper_get_plugin_screenshot(RemminaProtocolWidget *gp, RemminaPluginScreenshotData *rpsd);
+
+static void
+remmina_plugin_python_init_protocol_plugin(RemminaProtocolPlugin* plugin, RemminaPluginPythonProtocolPlugin* pythonObject);
+
+static int
+remmina_protocol_plugin_init(RemminaPluginPythonProtocolPlugin *self, PyObject *args, PyObject *kwds);
+
+static PyObject *
+remmina_protocol_plugin_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
+
+static PyTypeObject RemminaProtocolPluginPythonType = {
PyVarObject_HEAD_INIT(NULL, 0)
- .tp_name = "remmina.Plugin",
+ .tp_name = "remmina.ProtocolPlugin",
.tp_doc = "Custom objects",
- .tp_basicsize = sizeof(RemminaPluginPython),
- .tp_itemsize = 0,
- .tp_flags = Py_TPFLAGS_DEFAULT,
- .tp_members = RemminaPluginPython_members,
- .tp_new = remmina_remmina_plugin_new,
- .tp_init = remmina_remmina_plugin_init
+ .tp_basicsize = sizeof(RemminaPluginPythonProtocolPlugin),
+ .tp_itemsize = sizeof(RemminaPluginPythonProtocolPlugin),
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+ .tp_members = remmina_plugin_python_protocol_plugin_members,
+ .tp_methods = remmina_plugin_python_protocol_plugin_methods,
+ .tp_new = remmina_protocol_plugin_new,
+ .tp_init = remmina_protocol_plugin_init
};
static void
-RemminaPluginPython_dealloc(RemminaPluginPython *self){
+RemminaPluginPython_dealloc(RemminaPluginPythonProtocolPlugin *self){
Py_XDECREF(self->name);
Py_XDECREF(self->description);
Py_XDECREF(self->version);
@@ -90,46 +114,107 @@ RemminaPluginPython_dealloc(RemminaPluginPython *self){
Py_TYPE(self)->tp_free((PyObject *) self);
}
-PyTypeObject* remmina_plugin_python_plugin_create(void) { return &RemminaPluginPythonType; }
+static void
+remmina_plugin_python_init_protocol_plugin(RemminaProtocolPlugin* plugin, RemminaPluginPythonProtocolPlugin* pythonObject) {
+
+}
+
+struct PyPlugin {
+ PyObject_HEAD
+ RemminaPluginPythonProtocolPlugin* internal;
+};
+
+PyTypeObject* remmina_plugin_python_plugin_create(void) { return &RemminaProtocolPluginPythonType; }
static PyObject *
-remmina_remmina_plugin_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+remmina_protocol_plugin_new(PyTypeObject *type, PyObject *parent, PyObject *args)
{
- RemminaPluginPython *self;
+ struct PyPlugin *state;
+ PyObject *self;
+ self = PyType_GenericNew(type, parent, args);
+ if (self == NULL)
+ return NULL;
+ // Cast the object to the appropriate type
+ state = (struct PyPlugin *) self;
+ // Initialize your internal structure
+ state->internal = malloc(sizeof(*state->internal));
+ if (state->internal == NULL)
+ return NULL;
+ memset(state->internal, 0, sizeof(*state->internal));
+ // This means no error occurred
- self = (RemminaPluginPython *)type->tp_alloc(type, 0);
- if (!self)
+ state->internal->name = PyUnicode_FromString("");
+ if (!state->internal->name) {
+ Py_DECREF(self);
return NULL;
-
- self->name = PyUnicode_FromString("");
- if (!self->name) {
+ }
+
+ state->internal->name = PyUnicode_FromString("");
+ if (!state->internal->name) {
Py_DECREF(self);
return NULL;
}
-
- self->description = PyUnicode_FromString("");
- if (!self->description) {
+
+ state->internal->description = PyUnicode_FromString("");
+ if (!state->internal->description) {
Py_DECREF(self);
return NULL;
}
-
- self->version = PyUnicode_FromString("");
- if (!self->version) {
+
+ state->internal->version = PyUnicode_FromString("");
+ if (!state->internal->version) {
Py_DECREF(self);
return NULL;
}
-
- self->appicon = PyUnicode_FromString("");
- if (!self->appicon) {
+
+ state->internal->appicon = PyUnicode_FromString("");
+ if (!state->internal->appicon) {
+ Py_DECREF(self);
+ return NULL;
+ }
+
+ state->internal->icon_name = PyUnicode_FromString("");
+ if (!state->internal->icon_name) {
Py_DECREF(self);
return NULL;
}
- return (PyObject *)self;
+ state->internal->icon_name_ssh = PyUnicode_FromString("");
+ if (!state->internal->icon_name_ssh) {
+ Py_DECREF(self);
+ return NULL;
+ }
+
+ state->internal->basic_settings = PyUnicode_FromString("");
+ if (!state->internal->basic_settings) {
+ Py_DECREF(self);
+ return NULL;
+ }
+
+ state->internal->advanced_settings = PyUnicode_FromString("");
+ if (!state->internal->advanced_settings) {
+ Py_DECREF(self);
+ return NULL;
+ }
+
+ state->internal->ssh_setting = PyUnicode_FromString("");
+ if (!state->internal->ssh_setting) {
+ Py_DECREF(self);
+ return NULL;
+ }
+
+ state->internal->features = PyUnicode_FromString("");
+ if (!state->internal->features) {
+ Py_DECREF(self);
+ return NULL;
+ }
+
+ return self;
}
+
static int
-remmina_remmina_plugin_init(RemminaPluginPython *self, PyObject *args, PyObject *kwds)
+remmina_protocol_plugin_init(RemminaPluginPythonProtocolPlugin *self, PyObject *args, PyObject *kwds)
{
static char* kwlist[] = { "name", "description", "version", "appicon", NULL };
PyObject *name = NULL;
@@ -145,25 +230,21 @@ remmina_remmina_plugin_init(RemminaPluginPython *self, PyObject *args, PyObject
tmp = self->name;
Py_INCREF(name);
self->name = name;
- Py_XDECREF(tmp);
}
if (description) {
tmp = self->description;
Py_INCREF(description);
self->description = description;
- Py_XDECREF(tmp);
}
if (version) {
tmp = self->version;
Py_INCREF(version);
self->version = version;
- Py_XDECREF(tmp);
}
if (appicon) {
tmp = self->appicon;
Py_INCREF(appicon);
self->appicon = appicon;
- Py_XDECREF(tmp);
}
const char *name_str;
@@ -171,12 +252,63 @@ remmina_remmina_plugin_init(RemminaPluginPython *self, PyObject *args, PyObject
const char *version_str;
const char *appicon_str;
- if (PyArg_ParseTuple(args, "ssss", &name_str, &version_str, &appicon_str, &description_str))
+ if (PyArg_ParseTuple(args, "ssss", &name_str, &description_str, &version_str, &appicon_str))
printf("Initialied plugin: %s\nVersion: %s\nApp-Icon: %s\nDescription: %s\n", name_str, version_str, appicon_str, description_str);
- self->remmina_plugin = (RemminaPlugin*)malloc(sizeof(*self->remmina_plugin));
- self->remmina_plugin->name = name_str;
- self->remmina_plugin->type = REMMINA_PLUGIN_TYPE_PROTOCOL;
+
+ /* Protocol plugin definition and features */
+ RemminaProtocolPlugin* remmina_plugin = (RemminaProtocolPlugin*)malloc(sizeof(RemminaProtocolPlugin));
+ remmina_plugin->type = REMMINA_PLUGIN_TYPE_PROTOCOL;
+ remmina_plugin->name = name_str; // Name
+ remmina_plugin->description = description_str; // Description
+ remmina_plugin->domain = GETTEXT_PACKAGE; // Translation domain
+ remmina_plugin->version = version_str; // Version number
+ remmina_plugin->icon_name = appicon_str; // Icon for normal connection
+ remmina_plugin->icon_name_ssh = appicon_str; // Icon for SSH connection
+ remmina_plugin->basic_settings = remmina_protocol_python_plugin_features; // Array for basic settings
+ remmina_plugin->advanced_settings = NULL; // Array for advanced settings
+ remmina_plugin->ssh_setting = REMMINA_PROTOCOL_SSH_SETTING_TUNNEL; // SSH settings type
+ remmina_plugin->features = remmina_protocol_python_plugin_features; // Array for available features
+ remmina_plugin->init = remmina_protocol_plugin_wrapper_init; // Plugin initialization
+ remmina_plugin->open_connection = remmina_protocol_plugin_wrapper_open_connection; // Plugin open connection
+ remmina_plugin->close_connection = remmina_protocol_plugin_wrapper_close_connection; // Plugin close connection
+ remmina_plugin->query_feature = remmina_protocol_plugin_wrapper_query_feature; // Query for available features
+ remmina_plugin->call_feature = remmina_protocol_plugin_wrapper_call_feature; // Call a feature
+ remmina_plugin->send_keystrokes = NULL; // Send a keystroke
+ remmina_plugin->get_plugin_screenshot = NULL; // Screenshot support unavailable
+
+ remmina_plugin_manager_service.register_plugin((RemminaPlugin *)remmina_plugin);
+
return 0;
-} \ No newline at end of file
+}
+
+
+static void remmina_protocol_plugin_wrapper_init(RemminaProtocolWidget *gp) {
+
+}
+
+static gboolean remmina_protocol_plugin_wrapper_open_connection(RemminaProtocolWidget *gp) {
+ return TRUE;
+}
+
+static gboolean remmina_protocol_plugin_wrapper_close_connection(RemminaProtocolWidget *gp) {
+ return TRUE;
+}
+
+static gboolean remmina_protocol_plugin_wrapper_query_feature(RemminaProtocolWidget *gp, const RemminaProtocolFeature *feature) {
+ return TRUE;
+}
+
+static void remmina_protocol_plugin_wrapper_call_feature(RemminaProtocolWidget *gp, const RemminaProtocolFeature *feature) {
+
+}
+
+static void remmina_protocol_plugin_wrapper_send_keystrokes(RemminaProtocolWidget *gp, const guint keystrokes[], const gint keylen) {
+
+}
+
+static gboolean remmina_protocol_plugin_wrapper_get_plugin_screenshot(RemminaProtocolWidget *gp, RemminaPluginScreenshotData *rpsd) {
+ return TRUE;
+}
+