diff options
author | ToolsDevler <info@toolsdevler.net> | 2020-08-24 23:01:16 +0300 |
---|---|---|
committer | ToolsDevler <info@toolsdevler.net> | 2020-12-31 03:03:24 +0300 |
commit | 7d014f98d246fab86212c0876176d9fc30a93765 (patch) | |
tree | d69b88142619724846f749f22dd8acd86f199abc | |
parent | 178758c8f95410936762f43867adea348fbd1dc7 (diff) |
WIP: Python Plugin Structure
-rw-r--r-- | plugins/common/remmina_plugin_python.h | 62 | ||||
-rw-r--r-- | src/remmina_plugin_python.c | 460 |
2 files changed, 237 insertions, 285 deletions
diff --git a/plugins/common/remmina_plugin_python.h b/plugins/common/remmina_plugin_python.h deleted file mode 100644 index 5915adb82..000000000 --- a/plugins/common/remmina_plugin_python.h +++ /dev/null @@ -1,62 +0,0 @@ -#pragma once - -#include <Python.h> -#include "common/remmina_plugin.h" - -static PyTypeObject remmina_remmina_protocol_widget = { - PyVarObject_HEAD_INIT(NULL, 0) - "remmina.remmina_protocol_widget", /* tp_name */ - sizeof(remmina_remmina_protocol_widget), /* tp_basicsize */ - 0, /* tp_itemsize */ - 0, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - "remmina_protocol_widget", /* tp_doc */ -}; - -static PyTypeObject remmina_remmina_plugin = { - PyVarObject_HEAD_INIT(NULL, 0) - "remmina.remmina_plugin", /* tp_name */ - sizeof(remmina_remmina_plugin), /* tp_basicsize */ - 0, /* tp_itemsize */ - 0, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - "remmina_plugin", /* tp_doc */ -}; - -static PyModuleDef remminamodule = { - PyModuleDef_HEAD_INIT, - "remmina", - "Example module that creates an extension type.", - -1, - NULL, NULL, NULL, NULL, NULL -}; - -PyMODINIT_FUNC PyInit_remmina(void); diff --git a/src/remmina_plugin_python.c b/src/remmina_plugin_python.c index 33ca30b9d..b713391ec 100644 --- a/src/remmina_plugin_python.c +++ b/src/remmina_plugin_python.c @@ -5,282 +5,296 @@ #include <gio/gio.h> #include <string.h> -#define PY_SSIZE_T_CLEAN -#include <Python.h> - #include <gdk/gdkx.h> #include "remmina_public.h" #include "remmina_file_manager.h" #include "remmina_pref.h" -#include "common/remmina_plugin_python.h" #include "remmina_log.h" #include "remmina_widget_pool.h" #include "rcw.h" #include "remmina_public.h" #include "remmina_plugin_python.h" +#include "remmina_plugin_manager.h" #include "remmina_masterthread_exec.h" #include "remmina/remmina_trace_calls.h" -PyMODINIT_FUNC PyInit_remmina(void) { - // TODO: Initialize remmina Python module -} +#define PY_SSIZE_T_CLEAN +#include <Python.h> +#include "structmember.h" -static void -remmina_protocol_widget_dealloc(Noddy* self) -{ - // TODO: Free memory if necessary -} +// Level 0 - Remmina as a python module static PyObject * -remmina_protocol_widget_init(PyTypeObject *type, PyObject *args, PyObject *kwds) { - // TODO: In case python creates a new widget, implement. Otherwise raise error. -} +remmina_plugin_python_print(PyObject *self, PyObject *args) { + const char* format; + if (!PyArg_ParseTuple(args, "s", &format)) + return NULL; -static PyObject * -remmina_protocol_widget_new(PyTypeObject *self, PyObject *args, PyObject *kwds) { - // TODO: In case python creates a new widget, implement. Otherwise raise error. + printf("%s\n", format); + return self; } -static PyObject* remmina_plugin_manager_python_register_plugin() { - remmina_plugin_manager_python_register_plugin(); -} +static PyMethodDef remminaMethods[] = { + {"printf", remmina_plugin_python_print, METH_VARARGS, "Print to shell"}, + {NULL, NULL, 0, NULL} +}; -static PyObject* remmina_protocol_python_widget_get_width() { - RemminaProtocolWidget *gp; - remmina_protocol_widget_get_width(); -} -static PyObject* remmina_protocol_python_widget_set_width() { - remmina_protocol_widget_set_width(); -} -static PyObject* remmina_protocol_python_widget_get_height() { - remmina_protocol_widget_get_height(); -} -static PyObject* remmina_protocol_python_widget_set_height() { - remmina_protocol_widget_set_height(); -} -static PyObject* remmina_protocol_python_widget_get_current_scale_mode() { - remmina_protocol_widget_get_current_scale_mode(); -} -static PyObject* remmina_protocol_python_widget_get_expand() { - remmina_protocol_widget_get_expand(); -} -static PyObject* remmina_protocol_python_widget_set_expand() { - remmina_protocol_widget_set_expand(); -} -static PyObject* remmina_protocol_python_widget_has_error() { - remmina_protocol_widget_has_error(); -} -static PyObject* remmina_protocol_python_widget_set_error() { - remmina_protocol_widget_set_error(); -} -static PyObject* remmina_protocol_python_widget_is_closed() { - remmina_protocol_widget_is_closed(); -} -static PyObject* remmina_protocol_python_widget_get_file() { - remmina_protocol_widget_get_file(); -} -static PyObject* remmina_protocol_python_widget_emit_signal() { - remmina_protocol_widget_emit_signal(); -} -static PyObject* remmina_protocol_python_widget_register_hostkey() { - remmina_protocol_widget_register_hostkey(); -} -static PyObject* remmina_protocol_python_widget_start_direct_tunnel() { - remmina_protocol_widget_start_direct_tunnel(); -} -static PyObject* remmina_protocol_python_widget_start_reverse_tunnel() { - remmina_protocol_widget_start_reverse_tunnel(); -} -static PyObject* remmina_protocol_python_widget_start_xport_tunnel() { - remmina_protocol_widget_start_xport_tunnel(); -} -static PyObject* remmina_protocol_python_widget_set_display() { - remmina_protocol_widget_set_display(); -} -static PyObject* remmina_protocol_python_widget_signal_connection_closed() { - remmina_protocol_widget_signal_connection_closed(); -} -static PyObject* remmina_protocol_python_widget_signal_connection_opened() { - remmina_protocol_widget_signal_connection_opened(); -} -static PyObject* remmina_protocol_python_widget_update_align() { - remmina_protocol_widget_update_align(); -} -static PyObject* remmina_protocol_python_widget_unlock_dynres() { - remmina_protocol_widget_unlock_dynres(); -} -static PyObject* remmina_protocol_python_widget_desktop_resize() { - remmina_protocol_widget_desktop_resize(); -} -static PyObject* remmina_protocol_python_widget_panel_auth() { - remmina_protocol_widget_panel_auth(); -} -static PyObject* remmina_protocol_python_widget_panel_new_certificate() { - remmina_protocol_widget_panel_new_certificate(); -} -static PyObject* remmina_protocol_python_widget_panel_changed_certificate() { - remmina_protocol_widget_panel_changed_certificate(); -} -static PyObject* remmina_protocol_python_widget_get_username() { - remmina_protocol_widget_get_username(); -} -static PyObject* remmina_protocol_python_widget_get_password() { - remmina_protocol_widget_get_password(); -} -static PyObject* remmina_protocol_python_widget_get_domain() { - remmina_protocol_widget_get_domain(); -} -static PyObject* remmina_protocol_python_widget_get_savepassword() { - remmina_protocol_widget_get_savepassword(); -} -static PyObject* remmina_protocol_python_widget_panel_authx509() { - remmina_protocol_widget_panel_authx509(); -} -static PyObject* remmina_protocol_python_widget_get_cacert() { - remmina_protocol_widget_get_cacert(); -} -static PyObject* remmina_protocol_python_widget_get_cacrl() { - remmina_protocol_widget_get_cacrl(); -} -static PyObject* remmina_protocol_python_widget_get_clientcert() { - remmina_protocol_widget_get_clientcert(); -} -static PyObject* remmina_protocol_python_widget_get_clientkey() { - remmina_protocol_widget_get_clientkey(); -} -static PyObject* remmina_protocol_python_widget_save_cred() { - remmina_protocol_widget_save_cred(); -} -static PyObject* remmina_protocol_python_widget_panel_show_listen() { - remmina_protocol_widget_panel_show_listen(); -} -static PyObject* remmina_protocol_python_widget_panel_show_retry() { - remmina_protocol_widget_panel_show_retry(); -} -static PyObject* remmina_protocol_python_widget_panel_show() { - remmina_protocol_widget_panel_show(); -} -static PyObject* remmina_protocol_python_widget_panel_hide() { - remmina_protocol_widget_panel_hide(); -} -static PyObject* remmina_protocol_python_widget_ssh_exec() { - remmina_protocol_widget_ssh_exec(); -} -static PyObject* remmina_protocol_python_widget_chat_open() { - remmina_protocol_widget_chat_open(); -} -static PyObject* remmina_protocol_python_widget_chat_close() { - remmina_protocol_widget_chat_close(); -} -static PyObject* remmina_protocol_python_widget_chat_receive() { - remmina_protocol_widget_chat_receive(); -} -static PyObject* remmina_protocol_python_widget_send_keys_signals() { - remmina_protocol_widget_send_keys_signals(); +static PyModuleDef remminamodule = { + PyModuleDef_HEAD_INIT, + "remmina", + "Remmina API.", + -1, + remminaMethods +}; + +// Level 1 - Remmina Plugin + + + +typedef struct { + PyObject_HEAD + PyObject *name; + PyObject *description; + PyObject *version; + PyObject *appicon; +} RemminaPluginPython; + +static void +RemminaPluginPython_dealloc(RemminaPluginPython *self) +{ + Py_XDECREF(self->name); + Py_XDECREF(self->description); + Py_XDECREF(self->version); + Py_XDECREF(self->appicon); + Py_TYPE(self)->tp_free((PyObject *) self); } +static PyObject * +remmina_remmina_plugin_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + RemminaPluginPython *self; - static PyObject* remmina_file_python_get_datadir() { - remmina_file_get_datadir(); - } + self = (RemminaPluginPython *)type->tp_alloc(type, 0); + if (!self) + return NULL; - static PyObject* remmina_file_python_new() { - remmina_file_new(); + + self->name = PyUnicode_FromString(""); + if (!self->name) { + Py_DECREF(self); + return NULL; } - - static PyObject* remmina_file_python_get_filename() { - remmina_file_get_filename(); + + self->description = PyUnicode_FromString(""); + if (!self->description) { + Py_DECREF(self); + return NULL; } - - static PyObject* remmina_file_python_set_string() { - remmina_file_set_string(); + + self->version = PyUnicode_FromString(""); + if (!self->version) { + Py_DECREF(self); + return NULL; } - - static PyObject* remmina_file_python_get_string() { - remmina_file_get_string(); + + self->appicon = PyUnicode_FromString(""); + if (!self->appicon) { + Py_DECREF(self); + return NULL; } - static PyObject* remmina_file_python_get_secret() { - remmina_file_get_secret(); - } + return (PyObject *)self; +} - static PyObject* remmina_file_python_set_int() { - remmina_file_set_int(); - } - static PyObject* remmina_file_python_get_int() { - remmina_file_get_int(); - } +static RemminaPluginService *remmina_plugin_service = NULL; - static PyObject* remmina_file_python_unsave_passwords() { - remmina_file_unsave_passwords(); - } +static void remmina_plugin_hello_init(RemminaProtocolWidget *gp) +{ + TRACE_CALL(__func__); + remmina_plugin_service->log_printf("[Hello] Plugin init\n"); +} +static gboolean remmina_plugin_hello_open_connection(RemminaProtocolWidget *gp) +{ + TRACE_CALL(__func__); + remmina_plugin_service->log_printf("[Hello] Plugin open connection\n"); - static PyObject* remmina_pref_pyton_set_value() { - remmina_pref_set_value(); - } - static PyObject* remmina_pref_pyton_get_value() { - remmina_pref_get_value(); - } - static PyObject* remmina_pref_pyton_get_scale_quality() { - remmina_pref_get_scale_quality(); - } - static PyObject* remmina_pref_pyton_get_sshtunnel_port() { - remmina_pref_get_sshtunnel_port(); + GtkDialog *dialog; + dialog = GTK_DIALOG(gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL | GTK_DIALOG_USE_HEADER_BAR, + GTK_MESSAGE_INFO, GTK_BUTTONS_OK, "")); + gtk_dialog_run(dialog); + gtk_widget_destroy(GTK_WIDGET(dialog)); + return FALSE; +} + +static gboolean remmina_plugin_hello_close_connection(RemminaProtocolWidget *gp) +{ + TRACE_CALL(__func__); + remmina_plugin_service->log_printf("[Hello] Plugin close connection\n"); + remmina_plugin_service->protocol_plugin_emit_signal(gp, "disconnect"); + return FALSE; +} + +#define PLUGIN_NAME "SET BY PYTHON" +#define PLUGIN_DESCRIPTION N_("SET BY PYTHON") +#define PLUGIN_VERSION "SET BY PYTHON" +#define PLUGIN_APPICON "SET BY PYTHON" + +/* Array of RemminaProtocolSetting for basic settings. +* Each item is composed by: +* a) RemminaProtocolSettingType for setting type +* b) Setting name +* c) Setting description +* d) Compact disposition +* e) Values for REMMINA_PROTOCOL_SETTING_TYPE_SELECT or REMMINA_PROTOCOL_SETTING_TYPE_COMBO +* f) Setting Tooltip +*/ +static const RemminaProtocolSetting remmina_plugin_hello_basic_settings[] = +{ + { REMMINA_PROTOCOL_SETTING_TYPE_END, NULL, NULL, FALSE, NULL, NULL } +}; + +RemminaProtocolPlugin remmina_hello_plugin = { + REMMINA_PLUGIN_TYPE_PROTOCOL, // Type + PLUGIN_NAME, // Name + PLUGIN_DESCRIPTION, // Description + GETTEXT_PACKAGE, // Translation domain + PLUGIN_VERSION, // Version number + PLUGIN_APPICON, // Icon for normal connection + PLUGIN_APPICON, // Icon for SSH connection + remmina_plugin_hello_basic_settings, // Array for basic settings + NULL, // Array for advanced settings + REMMINA_PROTOCOL_SSH_SETTING_NONE, // SSH settings type + NULL, // Array for available features + remmina_plugin_hello_init, // Plugin initialization + remmina_plugin_hello_open_connection, // Plugin open connection + remmina_plugin_hello_close_connection, // Plugin close connection + NULL, // Query for available features + NULL, // Call a feature + NULL, // Send a keystroke + NULL // No screenshot support available +}; + +static int +remmina_remmina_plugin_init(RemminaPluginPython *self, PyObject *args, PyObject *kwds) +{ + static char* kwlist[] = { "name", "description", "version", "appicon", NULL }; + PyObject *name = NULL; + PyObject *description = NULL; + PyObject *version = NULL; + PyObject *appicon = NULL; + PyObject *tmp; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO", kwlist, &name, &description, &version, &appicon)) + return -1; + + if (name) { + tmp = self->name; + Py_INCREF(name); + self->name = name; + Py_XDECREF(tmp); } - static PyObject* remmina_pref_pyton_get_ssh_loglevel() { - remmina_pref_get_ssh_loglevel(); + if (description) { + tmp = self->description; + Py_INCREF(description); + self->description = description; + Py_XDECREF(tmp); } - static PyObject* remmina_pref_pyton_get_ssh_parseconfig() { - remmina_pref_get_ssh_parseconfig(); + if (version) { + tmp = self->version; + Py_INCREF(version); + self->version = version; + Py_XDECREF(tmp); } - static PyObject* remmina_pref_pyton_keymap_get_keyval() { - remmina_pref_keymap_get_keyval(); + if (appicon) { + tmp = self->appicon; + Py_INCREF(appicon); + self->appicon = appicon; + Py_XDECREF(tmp); } - static PyObject* remmina_log_python_print() { - remmina_log_print(); - } - static PyObject* remmina_log_python_printf() { - remmina_log_printf(); - } + const char *name_str; + const char *description_str; + const char *version_str; + const char *appicon_str; - static PyObject* remmina_widget_python_pool_register() { - remmina_widget_pool_register(); - } - static PyObject* rcw_open_python_from_file_full() { - rcw_open_from_file_full(); - } + if (PyArg_ParseTuple(args, "ssss", &name_str, &version_str, &appicon_str, &description_str)) + printf("Initialied plugin: %s\nVersion: %s\nApp-Icon: %s\nDescription: %s\n", name_str, version_str, appicon_str, description_str); + - static PyObject* remmina_public_python_get_server_port() { - remmina_public_get_server_port(); - } + remmina_hello_plugin.name = name_str; + remmina_hello_plugin.description = description_str; + remmina_hello_plugin.version = version_str; + remmina_hello_plugin.icon_name = appicon_str; + remmina_hello_plugin.icon_name_ssh = appicon_str; - static PyObject* remmina_masterthread_exec_python_is_main_thread() { - return remmina_masterthread_exec_is_main_thread(); - } + return 0; +} - static PyObject* remmina_gtksocket_available() { - remmina_gtksocket_available(); - } +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"}, + {NULL} /* Sentinel */ +}; + +static PyTypeObject RemminaPluginPythonType = { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = "remmina.Plugin", + .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 +}; - static PyObject* remmina_protocol_python_widget_get_profile_remote_width() { - remmina_protocol_widget_get_profile_remote_width(); - } - static PyObject* remmina_protocol_python_widget_get_profile_remote_height() { - remmina_protocol_widget_get_profile_remote_height(); +PyMODINIT_FUNC PyInit_remmina(void) { + // TODO: Initialize remmina Python module + printf("Initializing remmina Python module"); + PyObject* module; + + if (PyType_Ready(&RemminaPluginPythonType) < 0) + return NULL; + + module = PyModule_Create(&remminamodule); + + if (module) + { + Py_INCREF(&RemminaPluginPythonType); + if (PyModule_AddObject(module, "Plugin", (PyObject*) &RemminaPluginPythonType) < 0) + { + Py_DECREF(&RemminaPluginPythonType); + Py_DECREF(module); + return NULL; + } } -}; + + + return module; +} + gboolean remmina_plugin_python_load(RemminaPluginService* service, const char* name) { PyObject *pName, *pModule, *pFunc; PyObject *pArgs, *pValue; int i; + + if (PyImport_AppendInittab("remmina", PyInit_remmina) == -1) { + fprintf(stderr, "Error: could not extend in-built modules table\n"); + return FALSE; + } Py_Initialize(); |