diff options
author | Mathias Winterhalter <2370037-ToolsDevler@users.noreply.gitlab.com> | 2022-04-30 01:21:52 +0300 |
---|---|---|
committer | Antenore Gatta (tmow) <antenore@simbiosi.org> | 2022-04-30 01:21:52 +0300 |
commit | faead9ed83c97c5260910f14b232dcb3f9c89d7b (patch) | |
tree | 5a1ef0d7fa6fcf258510361d63a7c4a89f47d620 | |
parent | 90f483b1afb43db0bc7f5e68f844931953bb185d (diff) |
Extract python plugin
-rw-r--r-- | CMakeLists.txt | 2 | ||||
-rw-r--r-- | flatpak/org.remmina.Remmina-local.json | 13 | ||||
-rw-r--r-- | flatpak/org.remmina.Remmina.json | 13 | ||||
-rw-r--r-- | plugins/CMakeLists.txt | 12 | ||||
-rw-r--r-- | plugins/python_wrapper/CMakeLists.txt | 69 | ||||
-rw-r--r-- | plugins/python_wrapper/pygobject.h | 669 | ||||
-rw-r--r-- | plugins/python_wrapper/python_wrapper_common.c (renamed from src/remmina_plugin_python_common.c) | 61 | ||||
-rw-r--r-- | plugins/python_wrapper/python_wrapper_common.h (renamed from src/remmina_plugin_python_common.h) | 54 | ||||
-rw-r--r-- | plugins/python_wrapper/python_wrapper_entry.c (renamed from src/remmina_plugin_python_entry.c) | 26 | ||||
-rw-r--r-- | plugins/python_wrapper/python_wrapper_entry.h (renamed from src/remmina_plugin_python_entry.h) | 6 | ||||
-rw-r--r-- | plugins/python_wrapper/python_wrapper_file.c (renamed from src/remmina_plugin_python_file.c) | 43 | ||||
-rw-r--r-- | plugins/python_wrapper/python_wrapper_file.h (renamed from src/remmina_plugin_python_file.h) | 6 | ||||
-rw-r--r-- | plugins/python_wrapper/python_wrapper_plugin.c (renamed from src/remmina_plugin_python.c) | 73 | ||||
-rw-r--r-- | plugins/python_wrapper/python_wrapper_plugin.h (renamed from src/remmina_plugin_python.h) | 8 | ||||
-rw-r--r-- | plugins/python_wrapper/python_wrapper_pref.c (renamed from src/remmina_plugin_python_pref.c) | 26 | ||||
-rw-r--r-- | plugins/python_wrapper/python_wrapper_pref.h (renamed from src/remmina_plugin_python_pref.h) | 6 | ||||
-rw-r--r-- | plugins/python_wrapper/python_wrapper_protocol.c (renamed from src/remmina_plugin_python_protocol.c) | 82 | ||||
-rw-r--r-- | plugins/python_wrapper/python_wrapper_protocol.h (renamed from src/remmina_plugin_python_protocol.h) | 10 | ||||
-rw-r--r-- | plugins/python_wrapper/python_wrapper_protocol_widget.c (renamed from src/remmina_plugin_python_protocol_widget.c) | 113 | ||||
-rw-r--r-- | plugins/python_wrapper/python_wrapper_protocol_widget.h (renamed from src/remmina_plugin_python_protocol_widget.h) | 8 | ||||
-rw-r--r-- | plugins/python_wrapper/python_wrapper_remmina.c (renamed from src/remmina_plugin_python_remmina.c) | 241 | ||||
-rw-r--r-- | plugins/python_wrapper/python_wrapper_remmina.h (renamed from src/remmina_plugin_python_remmina.h) | 14 | ||||
-rw-r--r-- | plugins/python_wrapper/python_wrapper_remmina_file.c (renamed from src/remmina_plugin_python_remmina_file.c) | 26 | ||||
-rw-r--r-- | plugins/python_wrapper/python_wrapper_remmina_file.h (renamed from src/remmina_plugin_python_remmina_file.h) | 6 | ||||
-rw-r--r-- | plugins/python_wrapper/python_wrapper_secret.c (renamed from src/remmina_plugin_python_secret.c) | 54 | ||||
-rw-r--r-- | plugins/python_wrapper/python_wrapper_secret.h (renamed from src/remmina_plugin_python_secret.h) | 6 | ||||
-rw-r--r-- | plugins/python_wrapper/python_wrapper_tool.c (renamed from src/remmina_plugin_python_tool.c) | 20 | ||||
-rw-r--r-- | plugins/python_wrapper/python_wrapper_tool.h (renamed from src/remmina_plugin_python_tool.h) | 6 | ||||
-rw-r--r-- | plugins/rdp/rdp_file.c | 9 | ||||
-rw-r--r-- | plugins/rdp/rdp_file.h | 8 | ||||
-rw-r--r-- | plugins/rdp/rdp_plugin.c | 1 | ||||
-rw-r--r-- | plugins/rdp/rdp_settings.c | 2 | ||||
-rw-r--r-- | plugins/rdp/rdp_settings.h | 2 | ||||
-rw-r--r-- | snap/snapcraft.yaml | 2 | ||||
-rw-r--r-- | src/CMakeLists.txt | 44 | ||||
-rw-r--r-- | src/include/remmina/plugin.h | 66 | ||||
-rw-r--r-- | src/remmina_plugin_manager.c | 120 | ||||
-rw-r--r-- | src/remmina_protocol_widget.c | 5 | ||||
-rw-r--r-- | src/remmina_protocol_widget.h | 1 |
39 files changed, 1418 insertions, 515 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index ec06950da..575a37e56 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -145,7 +145,7 @@ if(CMAKE_COMPILER_IS_GNUCC) endif() endif() - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wno-macro-redefined") if(WITH_SSE2) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -msse2") diff --git a/flatpak/org.remmina.Remmina-local.json b/flatpak/org.remmina.Remmina-local.json index 55aec3bca..81d0704b5 100644 --- a/flatpak/org.remmina.Remmina-local.json +++ b/flatpak/org.remmina.Remmina-local.json @@ -412,10 +412,14 @@ "name": "libsodium", "sources": [ { - "type": "git", - "url": "https://github.com/jedisct1/libsodium.git", - "branch": "stable", - "commit": "7389bf7f2968be75520e932704f18f038c29e581" + "type": "archive", + "url": "https://github.com/jedisct1/libsodium/archive/1.0.18-RELEASE.tar.gz", + "sha256": "b7292dd1da67a049c8e78415cd498ec138d194cfdb302e716b08d26b80fecc10", + "x-checker-data": { + "type": "anitya", + "project-id": 1728, + "url-template": "https://github.com/jedisct1/libsodium/archive/$version.tar.gz" + } } ], "post-install": [ @@ -521,6 +525,7 @@ "-DWITH_FREERDP3:BOOL=OFF", "-DWITH_GVNC:BOOL=ON", "-DWITH_CUPS:BOOL=ON", + "-DWITH_PYTHON:BOOL=ON", "-DWITH_MANPAGES:BOOL=OFF" ], "sources": [ diff --git a/flatpak/org.remmina.Remmina.json b/flatpak/org.remmina.Remmina.json index d3a563848..f94c4421d 100644 --- a/flatpak/org.remmina.Remmina.json +++ b/flatpak/org.remmina.Remmina.json @@ -412,10 +412,14 @@ "name": "libsodium", "sources": [ { - "type": "git", - "url": "https://github.com/jedisct1/libsodium.git", - "branch": "stable", - "commit": "7389bf7f2968be75520e932704f18f038c29e581" + "type": "archive", + "url": "https://github.com/jedisct1/libsodium/archive/1.0.18-RELEASE.tar.gz", + "sha256": "b7292dd1da67a049c8e78415cd498ec138d194cfdb302e716b08d26b80fecc10", + "x-checker-data": { + "type": "anitya", + "project-id": 1728, + "url-template": "https://github.com/jedisct1/libsodium/archive/$version.tar.gz" + } } ], "post-install": [ @@ -521,6 +525,7 @@ "-DWITH_FREERDP3:BOOL=OFF", "-DWITH_GVNC:BOOL=ON", "-DWITH_CUPS:BOOL=ON", + "-DWITH_PYTHON:BOOL=ON", "-DWITH_MANPAGES:BOOL=OFF" ], "sources": [ diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 1075bd7fd..264c7af94 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -169,6 +169,18 @@ if(WITH_NX) endif() endif() +option(WITH_PYTHONLIBS "Build Python Wrapper Plugin" ON) +if(WITH_PYTHONLIBS) + message(STATUS "Enabling Python Wrapper Plugin.") + add_definitions(-DWITH_PYTHONLIBS) + find_suggested_package(PythonLibs) + if(PythonLibs_FOUND) + add_subdirectory(python_wrapper) + endif() +else() + message(STATUS "Disabling Python Wrapper plugin.") +endif() + #find_suggested_package(TELEPATHY) #if(TELEPATHY_FOUND) #add_subdirectory(telepathy) diff --git a/plugins/python_wrapper/CMakeLists.txt b/plugins/python_wrapper/CMakeLists.txt new file mode 100644 index 000000000..54c6cf3db --- /dev/null +++ b/plugins/python_wrapper/CMakeLists.txt @@ -0,0 +1,69 @@ +# Remmina - The GTK+ Remote Desktop Client +# +# Copyright (C) 2016-2018 Denis Ollier +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# In addition, as a special exception, the copyright holders give +# permission to link the code of portions of this program with the +# OpenSSL library under certain conditions as described in each +# individual source file, and distribute linked combinations +# including the two. +# You must obey the GNU General Public License in all respects +# for all of the code used other than OpenSSL. * If you modify +# file(s) with this exception, you may extend this exception to your +# version of the file(s), but you are not obligated to do so. * If you +# do not wish to do so, delete this exception statement from your +# version. * If you delete this exception statement from all source +# files in the program, then also delete it here. + +set(REMMINA_PLUGIN_PYTHON_WRAPPER_SRCS + python_wrapper_common.c + python_wrapper_common.h + python_wrapper_entry.c + python_wrapper_entry.h + python_wrapper_file.c + python_wrapper_file.h + python_wrapper_plugin.c + python_wrapper_plugin.h + python_wrapper_pref.c + python_wrapper_pref.h + python_wrapper_protocol.c + python_wrapper_protocol.h + python_wrapper_protocol_widget.c + python_wrapper_protocol_widget.h + python_wrapper_remmina.c + python_wrapper_remmina.h + python_wrapper_remmina_file.c + python_wrapper_remmina_file.h + python_wrapper_secret.c + python_wrapper_secret.h + python_wrapper_tool.c + python_wrapper_tool.h + ) + +add_library(remmina-plugin-python_wrapper ${REMMINA_PLUGIN_PYTHON_WRAPPER_SRCS}) +set_target_properties(remmina-plugin-python_wrapper PROPERTIES PREFIX "") +set_target_properties(remmina-plugin-python_wrapper PROPERTIES NO_SONAME 1) + +message(${REMMINA_COMMON_INCLUDE_DIRS}) +include_directories(${REMMINA_COMMON_INCLUDE_DIRS} ${PYTHON_WRAPPER_INCLUDE_DIRS}) +target_link_libraries(remmina-plugin-python_wrapper ${REMMINA_COMMON_LIBRARIES} ${PYTHON_WRAPPER_LIBRARIES}) + +install(TARGETS remmina-plugin-python_wrapper DESTINATION ${REMMINA_PLUGINDIR}) + +target_include_directories(remmina-plugin-python_wrapper PRIVATE ${PYTHON_INCLUDE_DIRS}) +target_link_libraries(remmina-plugin-python_wrapper ${PYTHON_LIBRARIES}) diff --git a/plugins/python_wrapper/pygobject.h b/plugins/python_wrapper/pygobject.h new file mode 100644 index 000000000..627a030be --- /dev/null +++ b/plugins/python_wrapper/pygobject.h @@ -0,0 +1,669 @@ +/* -*- Mode: C; c-basic-offset: 4 -*- */ +/* + * Remmina - The GTK+ Remote Desktop Client + * Copyright (C) 2016-2022 Antenore Gatta, Giovanni Panozzo + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. * If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. * If you + * do not wish to do so, delete this exception statement from your + * version. * If you delete this exception statement from all source + * files in the program, then also delete it here. + * + */ + +#ifndef _PYGOBJECT_H_ +#define _PYGOBJECT_H_ + +#include <Python.h> + +#include <glib.h> +#include <glib-object.h> + +G_BEGIN_DECLS + +/* PyGClosure is a _private_ structure */ +typedef void (* PyClosureExceptionHandler) (GValue *ret, guint n_param_values, const GValue *params); +typedef struct _PyGClosure PyGClosure; +typedef struct _PyGObjectData PyGObjectData; + +struct _PyGClosure { + GClosure closure; + PyObject *callback; + PyObject *extra_args; /* tuple of extra args to pass to callback */ + PyObject *swap_data; /* other object for gtk_signal_connect__object */ + PyClosureExceptionHandler exception_handler; +}; + +typedef enum { + PYGOBJECT_USING_TOGGLE_REF = 1 << 0, + PYGOBJECT_IS_FLOATING_REF = 1 << 1 +} PyGObjectFlags; + + /* closures is just an alias for what is found in the + * PyGObjectData */ +typedef struct { + PyObject_HEAD + GObject *obj; + PyObject *inst_dict; /* the instance dictionary -- must be last */ + PyObject *weakreflist; /* list of weak references */ + + /*< private >*/ + /* using union to preserve ABI compatibility (structure size + * must not change) */ + union { + GSList *closures; /* stale field; no longer updated DO-NOT-USE! */ + PyGObjectFlags flags; + } private_flags; + +} PyGObject; + +#define pygobject_get(v) (((PyGObject *)(v))->obj) +#define pygobject_check(v,base) (PyObject_TypeCheck(v,base)) + +typedef struct { + PyObject_HEAD + gpointer boxed; + GType gtype; + gboolean free_on_dealloc; +} PyGBoxed; + +#define pyg_boxed_get(v,t) ((t *)((PyGBoxed *)(v))->boxed) +#define pyg_boxed_check(v,typecode) (PyObject_TypeCheck(v, &PyGBoxed_Type) && ((PyGBoxed *)(v))->gtype == typecode) + +typedef struct { + PyObject_HEAD + gpointer pointer; + GType gtype; +} PyGPointer; + +#define pyg_pointer_get(v,t) ((t *)((PyGPointer *)(v))->pointer) +#define pyg_pointer_check(v,typecode) (PyObject_TypeCheck(v, &PyGPointer_Type) && ((PyGPointer *)(v))->gtype == typecode) + +typedef void (*PyGFatalExceptionFunc) (void); +typedef void (*PyGThreadBlockFunc) (void); + +typedef struct { + PyObject_HEAD + GParamSpec *pspec; +} PyGParamSpec; + +#define PyGParamSpec_Get(v) (((PyGParamSpec *)v)->pspec) +#define PyGParamSpec_Check(v) (PyObject_TypeCheck(v, &PyGParamSpec_Type)) + +typedef int (*PyGClassInitFunc) (gpointer gclass, PyTypeObject *pyclass); +typedef PyTypeObject * (*PyGTypeRegistrationFunction) (const gchar *name, + gpointer data); + +struct _PyGObject_Functions { + /* + * All field names in here are considered private, + * use the macros below instead, which provides stability + */ + void (* register_class)(PyObject *dict, const gchar *class_name, + GType gtype, PyTypeObject *type, PyObject *bases); + void (* register_wrapper)(PyObject *self); + PyTypeObject *(* lookup_class)(GType type); + PyObject *(* newgobj)(GObject *obj); + + GClosure *(* closure_new)(PyObject *callback, PyObject *extra_args, + PyObject *swap_data); + void (* object_watch_closure)(PyObject *self, GClosure *closure); + GDestroyNotify destroy_notify; + + GType (* type_from_object)(PyObject *obj); + PyObject *(* type_wrapper_new)(GType type); + + gint (* enum_get_value)(GType enum_type, PyObject *obj, gint *val); + gint (* flags_get_value)(GType flag_type, PyObject *obj, gint *val); + void (* register_gtype_custom)(GType gtype, + PyObject *(* from_func)(const GValue *value), + int (* to_func)(GValue *value, PyObject *obj)); + int (* value_from_pyobject)(GValue *value, PyObject *obj); + PyObject *(* value_as_pyobject)(const GValue *value, gboolean copy_boxed); + + void (* register_interface)(PyObject *dict, const gchar *class_name, + GType gtype, PyTypeObject *type); + + PyTypeObject *boxed_type; + void (* register_boxed)(PyObject *dict, const gchar *class_name, + GType boxed_type, PyTypeObject *type); + PyObject *(* boxed_new)(GType boxed_type, gpointer boxed, + gboolean copy_boxed, gboolean own_ref); + + PyTypeObject *pointer_type; + void (* register_pointer)(PyObject *dict, const gchar *class_name, + GType pointer_type, PyTypeObject *type); + PyObject *(* pointer_new)(GType boxed_type, gpointer pointer); + + void (* enum_add_constants)(PyObject *module, GType enum_type, + const gchar *strip_prefix); + void (* flags_add_constants)(PyObject *module, GType flags_type, + const gchar *strip_prefix); + + const gchar *(* constant_strip_prefix)(const gchar *name, + const gchar *strip_prefix); + + gboolean (* error_check)(GError **error); + + /* hooks to register handlers for getting GDK threads to cooperate + * with python threading */ + void (* set_thread_block_funcs) (PyGThreadBlockFunc block_threads_func, + PyGThreadBlockFunc unblock_threads_func); + PyGThreadBlockFunc block_threads; + PyGThreadBlockFunc unblock_threads; + PyTypeObject *paramspec_type; + PyObject *(* paramspec_new)(GParamSpec *spec); + GParamSpec *(*paramspec_get)(PyObject *tuple); + int (*pyobj_to_unichar_conv)(PyObject *pyobj, void* ptr); + gboolean (*parse_constructor_args)(GType obj_type, + char **arg_names, + char **prop_names, + GParameter *params, + guint *nparams, + PyObject **py_args); + PyObject *(* param_gvalue_as_pyobject) (const GValue* gvalue, + gboolean copy_boxed, + const GParamSpec* pspec); + int (* gvalue_from_param_pyobject) (GValue* value, + PyObject* py_obj, + const GParamSpec* pspec); + PyTypeObject *enum_type; + PyObject *(*enum_add)(PyObject *module, + const char *type_name_, + const char *strip_prefix, + GType gtype); + PyObject* (*enum_from_gtype)(GType gtype, int value); + + PyTypeObject *flags_type; + PyObject *(*flags_add)(PyObject *module, + const char *type_name_, + const char *strip_prefix, + GType gtype); + PyObject* (*flags_from_gtype)(GType gtype, int value); + + gboolean threads_enabled; + int (*enable_threads) (void); + + int (*gil_state_ensure) (void); + void (*gil_state_release) (int flag); + + void (*register_class_init) (GType gtype, PyGClassInitFunc class_init); + void (*register_interface_info) (GType gtype, const GInterfaceInfo *info); + void (*closure_set_exception_handler) (GClosure *closure, PyClosureExceptionHandler handler); + + void (*add_warning_redirection) (const char *domain, + PyObject *warning); + void (*disable_warning_redirections) (void); + void (*type_register_custom)(const gchar *type_name, + PyGTypeRegistrationFunction callback, + gpointer data); + gboolean (*gerror_exception_check) (GError **error); + PyObject* (*option_group_new) (GOptionGroup *group); + GType (* type_from_object_strict) (PyObject *obj, gboolean strict); +}; + +#ifndef _INSIDE_PYGOBJECT_ + +#if defined(NO_IMPORT) || defined(NO_IMPORT_PYGOBJECT) +extern struct _PyGObject_Functions *_PyGObject_API; +#else +struct _PyGObject_Functions *_PyGObject_API; +#endif + +#define pygobject_register_class (_PyGObject_API->register_class) +#define pygobject_register_wrapper (_PyGObject_API->register_wrapper) +#define pygobject_lookup_class (_PyGObject_API->lookup_class) +#define pygobject_new (_PyGObject_API->newgobj) +#define pyg_closure_new (_PyGObject_API->closure_new) +#define pygobject_watch_closure (_PyGObject_API->object_watch_closure) +#define pyg_closure_set_exception_handler (_PyGObject_API->closure_set_exception_handler) +#define pyg_destroy_notify (_PyGObject_API->destroy_notify) +#define pyg_type_from_object_strict (_PyGObject_API->type_from_object_strict) +#define pyg_type_from_object (_PyGObject_API->type_from_object) +#define pyg_type_wrapper_new (_PyGObject_API->type_wrapper_new) +#define pyg_enum_get_value (_PyGObject_API->enum_get_value) +#define pyg_flags_get_value (_PyGObject_API->flags_get_value) +#define pyg_register_gtype_custom (_PyGObject_API->register_gtype_custom) +#define pyg_value_from_pyobject (_PyGObject_API->value_from_pyobject) +#define pyg_value_as_pyobject (_PyGObject_API->value_as_pyobject) +#define pyg_register_interface (_PyGObject_API->register_interface) +#define PyGBoxed_Type (*_PyGObject_API->boxed_type) +#define pyg_register_boxed (_PyGObject_API->register_boxed) +#define pyg_boxed_new (_PyGObject_API->boxed_new) +#define PyGPointer_Type (*_PyGObject_API->pointer_type) +#define pyg_register_pointer (_PyGObject_API->register_pointer) +#define pyg_pointer_new (_PyGObject_API->pointer_new) +#define pyg_enum_add_constants (_PyGObject_API->enum_add_constants) +#define pyg_flags_add_constants (_PyGObject_API->flags_add_constants) +#define pyg_constant_strip_prefix (_PyGObject_API->constant_strip_prefix) +#define pyg_error_check (_PyGObject_API->error_check) +#define pyg_set_thread_block_funcs (_PyGObject_API->set_thread_block_funcs) +#define PyGParamSpec_Type (*_PyGObject_API->paramspec_type) +#define pyg_param_spec_new (_PyGObject_API->paramspec_new) +#define pyg_param_spec_from_object (_PyGObject_API->paramspec_get) +#define pyg_pyobj_to_unichar_conv (_PyGObject_API->pyobj_to_unichar_conv) +#define pyg_parse_constructor_args (_PyGObject_API->parse_constructor_args) +#define pyg_param_gvalue_as_pyobject (_PyGObject_API->value_as_pyobject) +#define pyg_param_gvalue_from_pyobject (_PyGObject_API->gvalue_from_param_pyobject) +#define PyGEnum_Type (*_PyGObject_API->enum_type) +#define pyg_enum_add (_PyGObject_API->enum_add) +#define pyg_enum_from_gtype (_PyGObject_API->enum_from_gtype) +#define PyGFlags_Type (*_PyGObject_API->flags_type) +#define pyg_flags_add (_PyGObject_API->flags_add) +#define pyg_flags_from_gtype (_PyGObject_API->flags_from_gtype) +#define pyg_enable_threads (_PyGObject_API->enable_threads) +#define pyg_gil_state_ensure (_PyGObject_API->gil_state_ensure) +#define pyg_gil_state_release (_PyGObject_API->gil_state_release) +#define pyg_register_class_init (_PyGObject_API->register_class_init) +#define pyg_register_interface_info (_PyGObject_API->register_interface_info) +#define pyg_add_warning_redirection (_PyGObject_API->add_warning_redirection) +#define pyg_disable_warning_redirections (_PyGObject_API->disable_warning_redirections) +#define pyg_type_register_custom_callback (_PyGObject_API->type_register_custom) +#define pyg_gerror_exception_check (_PyGObject_API->gerror_exception_check) +#define pyg_option_group_new (_PyGObject_API->option_group_new) + +#define pyg_block_threads() G_STMT_START { \ + if (_PyGObject_API->block_threads != NULL) \ + (* _PyGObject_API->block_threads)(); \ + } G_STMT_END +#define pyg_unblock_threads() G_STMT_START { \ + if (_PyGObject_API->unblock_threads != NULL) \ + (* _PyGObject_API->unblock_threads)(); \ + } G_STMT_END + +#define pyg_threads_enabled (_PyGObject_API->threads_enabled) + +#define pyg_begin_allow_threads \ + G_STMT_START { \ + PyThreadState *_save = NULL; \ + if (_PyGObject_API->threads_enabled) \ + _save = PyEval_SaveThread(); +#define pyg_end_allow_threads \ + if (_PyGObject_API->threads_enabled) \ + PyEval_RestoreThread(_save); \ + } G_STMT_END + + +/** + * pygobject_init: + * @req_major: minimum version major number, or -1 + * @req_minor: minimum version minor number, or -1 + * @req_micro: minimum version micro number, or -1 + * + * Imports and initializes the 'gobject' python module. Can + * optionally check for a required minimum version if @req_major, + * @req_minor, and @req_micro are all different from -1. + * + * Returns: a new reference to the gobject module on success, NULL in + * case of failure (and raises ImportError). + **/ +static inline PyObject * +pygobject_init(int req_major, int req_minor, int req_micro) +{ + PyObject *gobject, *cobject; + + gobject = PyImport_ImportModule("gi._gobject"); + if (!gobject) { + if (PyErr_Occurred()) + { + PyObject *type, *value, *traceback; + PyObject *py_orig_exc; + PyErr_Fetch(&type, &value, &traceback); + py_orig_exc = PyObject_Repr(value); + Py_XDECREF(type); + Py_XDECREF(value); + Py_XDECREF(traceback); + + +#if PY_VERSION_HEX < 0x03000000 + PyErr_Format(PyExc_ImportError, + "could not import gobject (error was: %s)", + PyString_AsString(py_orig_exc)); +#else + { + /* Can not use PyErr_Format because it doesn't have + * a format string for dealing with PyUnicode objects + * like PyUnicode_FromFormat has + */ + PyObject *errmsg = PyUnicode_FromFormat("could not import gobject (error was: %U)", + py_orig_exc); + + if (errmsg) { + PyErr_SetObject(PyExc_ImportError, + errmsg); + Py_DECREF(errmsg); + } + /* if errmsg is NULL then we might have OOM + * PyErr should already be set and trying to + * return our own error would be futile + */ + } +#endif + Py_DECREF(py_orig_exc); + } else { + PyErr_SetString(PyExc_ImportError, + "could not import gobject (no error given)"); + } + return NULL; + } + + cobject = PyObject_GetAttrString(gobject, "_PyGObject_API"); +#if PY_VERSION_HEX >= 0x03000000 + if (cobject && PyCapsule_CheckExact(cobject)) + _PyGObject_API = (struct _PyGObject_Functions *) PyCapsule_GetPointer(cobject, "gobject._PyGObject_API"); + +#else + if (cobject && PyCObject_Check(cobject)) + _PyGObject_API = (struct _PyGObject_Functions *) PyCObject_AsVoidPtr(cobject); +#endif + else { + PyErr_SetString(PyExc_ImportError, + "could not import gobject (could not find _PyGObject_API object)"); + Py_DECREF(gobject); + return NULL; + } + + if (req_major != -1) + { + int found_major, found_minor, found_micro; + PyObject *version; + + version = PyObject_GetAttrString(gobject, "pygobject_version"); + if (!version) { + PyErr_SetString(PyExc_ImportError, + "could not import gobject (version too old)"); + Py_DECREF(gobject); + return NULL; + } + if (!PyArg_ParseTuple(version, "iii", + &found_major, &found_minor, &found_micro)) { + PyErr_SetString(PyExc_ImportError, + "could not import gobject (version has invalid format)"); + Py_DECREF(version); + Py_DECREF(gobject); + return NULL; + } + Py_DECREF(version); + if (req_major != found_major || + req_minor > found_minor || + (req_minor == found_minor && req_micro > found_micro)) { + PyErr_Format(PyExc_ImportError, + "could not import gobject (version mismatch, %d.%d.%d is required, " + "found %d.%d.%d)", req_major, req_minor, req_micro, + found_major, found_minor, found_micro); + Py_DECREF(gobject); + return NULL; + } + } + return gobject; +} + +/** + * PYLIST_FROMGLIBLIST: + * @type: the type of the GLib list e.g. #GList or #GSList + * @prefix: the prefix of functions that manipulate a list of the type + * given by type. + * + * A macro that creates a type specific code block which converts a GLib + * list (#GSList or #GList) to a Python list. The first two args of the macro + * are used to specify the type and list function prefix so that the type + * specific macros can be generated. + * + * The rest of the args are for the standard args for the type specific + * macro(s) created from this macro. + */ + #define PYLIST_FROMGLIBLIST(type,prefix,py_list,list,item_convert_func,\ + list_free,list_item_free) \ +G_STMT_START \ +{ \ + gint i, len; \ + PyObject *item; \ + void (*glib_list_free)(type*) = list_free; \ + GFunc glib_list_item_free = (GFunc)list_item_free; \ + \ + len = prefix##_length(list); \ + py_list = PyList_New(len); \ + for (i = 0; i < len; i++) { \ + gpointer list_item = prefix##_nth_data(list, i); \ + \ + item = item_convert_func; \ + PyList_SetItem(py_list, i, item); \ + } \ + if (glib_list_item_free != NULL) \ + prefix##_foreach(list, glib_list_item_free, NULL); \ + if (glib_list_free != NULL) \ + glib_list_free(list); \ +} G_STMT_END + +/** + * PYLIST_FROMGLIST: + * @py_list: the name of the Python list + * + * @list: the #GList to be converted to a Python list + * + * @item_convert_func: the function that converts a list item to a Python + * object. The function must refer to the list item using "@list_item" and + * must return a #PyObject* object. An example conversion function is: + * [[ + * PyString_FromString(list_item) + * ]] + * A more elaborate function is: + * [[ + * pyg_boxed_new(GTK_TYPE_RECENT_INFO, list_item, TRUE, TRUE) + * ]] + * @list_free: the name of a function that takes a single arg (the list) and + * frees its memory. Can be NULL if the list should not be freed. An example + * is: + * [[ + * g_list_free + * ]] + * @list_item_free: the name of a #GFunc function that frees the memory used + * by the items in the list or %NULL if the list items do not have to be + * freed. A simple example is: + * [[ + * g_free + * ]] + * + * A macro that adds code that converts a #GList to a Python list. + * + */ +#define PYLIST_FROMGLIST(py_list,list,item_convert_func,list_free,\ + list_item_free) \ + PYLIST_FROMGLIBLIST(GList,g_list,py_list,list,item_convert_func,\ + list_free,list_item_free) + +/** + * PYLIST_FROMGSLIST: + * @py_list: the name of the Python list + * + * @list: the #GSList to be converted to a Python list + * + * @item_convert_func: the function that converts a list item to a Python + * object. The function must refer to the list item using "@list_item" and + * must return a #PyObject* object. An example conversion function is: + * [[ + * PyString_FromString(list_item) + * ]] + * A more elaborate function is: + * [[ + * pyg_boxed_new(GTK_TYPE_RECENT_INFO, list_item, TRUE, TRUE) + * ]] + * @list_free: the name of a function that takes a single arg (the list) and + * frees its memory. Can be %NULL if the list should not be freed. An example + * is: + * [[ + * g_list_free + * ]] + * @list_item_free: the name of a #GFunc function that frees the memory used + * by the items in the list or %NULL if the list items do not have to be + * freed. A simple example is: + * [[ + * g_free + * ]] + * + * A macro that adds code that converts a #GSList to a Python list. + * + */ +#define PYLIST_FROMGSLIST(py_list,list,item_convert_func,list_free,\ + list_item_free) \ + PYLIST_FROMGLIBLIST(GSList,g_slist,py_list,list,item_convert_func,\ + list_free,list_item_free) + +/** + * PYLIST_ASGLIBLIST + * @type: the type of the GLib list e.g. GList or GSList + * @prefix: the prefix of functions that manipulate a list of the type + * given by type e.g. g_list or g_slist + * + * A macro that creates a type specific code block to be used to convert a + * Python list to a GLib list (GList or GSList). The first two args of the + * macro are used to specify the type and list function prefix so that the + * type specific macros can be generated. + * + * The rest of the args are for the standard args for the type specific + * macro(s) created from this macro. + */ +#define PYLIST_ASGLIBLIST(type,prefix,py_list,list,check_func,\ + convert_func,child_free_func,errormsg,errorreturn) \ +G_STMT_START \ +{ \ + Py_ssize_t i, n_list; \ + GFunc glib_child_free_func = (GFunc)child_free_func; \ + \ + if (!(py_list = PySequence_Fast(py_list, ""))) { \ + errormsg; \ + return errorreturn; \ + } \ + n_list = PySequence_Fast_GET_SIZE(py_list); \ + for (i = 0; i < n_list; i++) { \ + PyObject *py_item = PySequence_Fast_GET_ITEM(py_list, i); \ + \ + if (!check_func) { \ + if (glib_child_free_func) \ + prefix##_foreach(list, glib_child_free_func, NULL); \ + prefix##_free(list); \ + Py_DECREF(py_list); \ + errormsg; \ + return errorreturn; \ + } \ + list = prefix##_prepend(list, convert_func); \ + }; \ + Py_DECREF(py_list); \ + list = prefix##_reverse(list); \ +} \ +G_STMT_END +/** + * PYLIST_ASGLIST + * @py_list: the Python list to be converted + * @list: the #GList list to be converted + * @check_func: the expression that takes a #PyObject* arg (must be named + * @py_item) and returns an int value indicating if the Python object matches + * the required list item type (0 - %False or 1 - %True). An example is: + * [[ + * (PyString_Check(py_item)||PyUnicode_Check(py_item)) + * ]] + * @convert_func: the function that takes a #PyObject* arg (must be named + * py_item) and returns a pointer to the converted list object. An example + * is: + * [[ + * pygobject_get(py_item) + * ]] + * @child_free_func: the name of a #GFunc function that frees a GLib list + * item or %NULL if the list item does not have to be freed. This function is + * used to help free the items in a partially created list if there is an + * error. An example is: + * [[ + * g_free + * ]] + * @errormsg: a function that sets up a Python error message. An example is: + * [[ + * PyErr_SetString(PyExc_TypeError, "strings must be a sequence of" "strings + * or unicode objects") + * ]] + * @errorreturn: the value to return if an error occurs, e.g.: + * [[ + * %NULL + * ]] + * + * A macro that creates code that converts a Python list to a #GList. The + * returned list must be freed using the appropriate list free function when + * it's no longer needed. If an error occurs the child_free_func is used to + * release the memory used by the list items and then the list memory is + * freed. + */ +#define PYLIST_ASGLIST(py_list,list,check_func,convert_func,child_free_func,\ + errormsg,errorreturn) \ + PYLIST_ASGLIBLIST(GList,g_list,py_list,list,check_func,convert_func,\ + child_free_func,errormsg,errorreturn) + +/** + * PYLIST_ASGSLIST + * @py_list: the Python list to be converted + * @list: the #GSList list to be converted + * @check_func: the expression that takes a #PyObject* arg (must be named + * @py_item) and returns an int value indicating if the Python object matches + * the required list item type (0 - %False or 1 - %True). An example is: + * [[ + * (PyString_Check(py_item)||PyUnicode_Check(py_item)) + * ]] + * @convert_func: the function that takes a #PyObject* arg (must be named + * py_item) and returns a pointer to the converted list object. An example + * is: + * [[ + * pygobject_get(py_item) + * ]] + * @child_free_func: the name of a #GFunc function that frees a GLib list + * item or %NULL if the list item does not have to be freed. This function is + * used to help free the items in a partially created list if there is an + * error. An example is: + * [[ + * g_free + * ]] + * @errormsg: a function that sets up a Python error message. An example is: + * [[ + * PyErr_SetString(PyExc_TypeError, "strings must be a sequence of" "strings + * or unicode objects") + * ]] + * @errorreturn: the value to return if an error occurs, e.g.: + * [[ + * %NULL + * ]] + * + * A macro that creates code that converts a Python list to a #GSList. The + * returned list must be freed using the appropriate list free function when + * it's no longer needed. If an error occurs the child_free_func is used to + * release the memory used by the list items and then the list memory is + * freed. + */ +#define PYLIST_ASGSLIST(py_list,list,check_func,convert_func,child_free_func,\ + errormsg,errorreturn) \ + PYLIST_ASGLIBLIST(GSList,g_slist,py_list,list,check_func,convert_func,\ + child_free_func,errormsg,errorreturn) + +#endif /* !_INSIDE_PYGOBJECT_ */ + +G_END_DECLS + +#endif /* !_PYGOBJECT_H_ */ diff --git a/src/remmina_plugin_python_common.c b/plugins/python_wrapper/python_wrapper_common.c index 527d96d6a..1b1c77d51 100644 --- a/src/remmina_plugin_python_common.c +++ b/plugins/python_wrapper/python_wrapper_common.c @@ -35,7 +35,7 @@ // I N C L U D E S //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#include "remmina_plugin_python_common.h" +#include "python_wrapper_common.h" #include <assert.h> #include <stdio.h> @@ -51,7 +51,7 @@ /** * A cache to store the last result that has been returned by the Python code using CallPythonMethod - * (@see remmina_plugin_python_common.h) + * (@see python_wrapper_common.h) */ static PyObject* __last_result; static GPtrArray* plugin_map = NULL; @@ -81,21 +81,21 @@ static const int REASONABLE_LIMIT_FOR_MALLOC = 1024 * 1024; // A P I //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -PyObject* remmina_plugin_python_last_result(void) +PyObject* python_wrapper_last_result(void) { TRACE_CALL(__func__); return __last_result; } -PyObject* remmina_plugin_python_last_result_set(PyObject* last_result) +PyObject* python_wrapper_last_result_set(PyObject* last_result) { TRACE_CALL(__func__); return __last_result = last_result; } -gboolean remmina_plugin_python_check_error(void) +gboolean python_wrapper_check_error(void) { TRACE_CALL(__func__); @@ -108,7 +108,7 @@ gboolean remmina_plugin_python_check_error(void) return FALSE; } -void remmina_plugin_python_log_method_call(PyObject* instance, const char* method) +void python_wrapper_log_method_call(PyObject* instance, const char* method) { TRACE_CALL(__func__); @@ -118,10 +118,10 @@ void remmina_plugin_python_log_method_call(PyObject* instance, const char* metho PyObject_Hash(instance), instance->ob_type->tp_name, method, - PyUnicode_AsUTF8(PyObject_Str(remmina_plugin_python_last_result()))); + PyUnicode_AsUTF8(PyObject_Str(python_wrapper_last_result()))); } -long remmina_plugin_python_get_attribute_long(PyObject* instance, const char* attr_name, long def) +long python_wrapper_get_attribute_long(PyObject* instance, const char* attr_name, long def) { TRACE_CALL(__func__); @@ -136,7 +136,7 @@ long remmina_plugin_python_get_attribute_long(PyObject* instance, const char* at return def; } -gboolean remmina_plugin_python_check_attribute(PyObject* instance, const char* attr_name) +gboolean python_wrapper_check_attribute(PyObject* instance, const char* attr_name) { TRACE_CALL(__func__); @@ -151,7 +151,7 @@ gboolean remmina_plugin_python_check_attribute(PyObject* instance, const char* a return FALSE; } -void* remmina_plugin_python_malloc(int bytes) +void* python_wrapper_malloc(int bytes) { TRACE_CALL(__func__); @@ -169,7 +169,7 @@ void* remmina_plugin_python_malloc(int bytes) return result; } -char* remmina_plugin_python_copy_string_from_python(PyObject* string, Py_ssize_t len) +char* python_wrapper_copy_string_from_python(PyObject* string, Py_ssize_t len) { TRACE_CALL(__func__); @@ -183,7 +183,7 @@ char* remmina_plugin_python_copy_string_from_python(PyObject* string, Py_ssize_t if (py_str) { const int label_size = sizeof(char) * (len + 1); - result = (char*)remmina_plugin_python_malloc(label_size); + result = (char*)python_wrapper_malloc(label_size); result[len] = '\0'; memcpy(result, py_str, len); } @@ -191,17 +191,17 @@ char* remmina_plugin_python_copy_string_from_python(PyObject* string, Py_ssize_t return result; } -void remmina_plugin_python_set_service(RemminaPluginService* service) +void python_wrapper_set_service(RemminaPluginService* service) { remmina_plugin_service = service; } -RemminaPluginService* remmina_plugin_python_get_service(void) +RemminaPluginService* python_wrapper_get_service(void) { return remmina_plugin_service; } -void remmina_plugin_python_add_plugin(PyPlugin* plugin) +void python_wrapper_add_plugin(PyPlugin* plugin) { TRACE_CALL(__func__); @@ -210,7 +210,7 @@ void remmina_plugin_python_add_plugin(PyPlugin* plugin) plugin_map = g_ptr_array_new(); } - PyPlugin* test = remmina_plugin_python_get_plugin(plugin->generic_plugin->name); + PyPlugin* test = python_wrapper_get_plugin(plugin->generic_plugin->name); if (test) { g_printerr("A plugin named '%s' has already been registered! Skipping...", plugin->generic_plugin->name); @@ -221,7 +221,7 @@ void remmina_plugin_python_add_plugin(PyPlugin* plugin) } } -RemminaTypeHint remmina_plugin_python_to_generic(PyObject* field, gpointer* target) +RemminaTypeHint python_wrapper_to_generic(PyObject* field, gpointer* target) { TRACE_CALL(__func__); @@ -231,7 +231,7 @@ RemminaTypeHint remmina_plugin_python_to_generic(PyObject* field, gpointer* targ if (len > 0) { - *target = remmina_plugin_python_copy_string_from_python(field, len); + *target = python_wrapper_copy_string_from_python(field, len); } else { @@ -242,14 +242,14 @@ RemminaTypeHint remmina_plugin_python_to_generic(PyObject* field, gpointer* targ } else if (PyBool_Check(field)) { - *target = remmina_plugin_python_malloc(sizeof(long)); + *target = python_wrapper_malloc(sizeof(long)); long* long_target = (long*)target; *long_target = PyLong_AsLong(field); return REMMINA_TYPEHINT_BOOLEAN; } else if (PyLong_Check(field)) { - *target = remmina_plugin_python_malloc(sizeof(long)); + *target = python_wrapper_malloc(sizeof(long)); long* long_target = (long*)target; *long_target = PyLong_AsLong(field); return REMMINA_TYPEHINT_SIGNED; @@ -259,13 +259,13 @@ RemminaTypeHint remmina_plugin_python_to_generic(PyObject* field, gpointer* targ Py_ssize_t len = PyTuple_Size(field); if (len) { - gpointer* dest = (gpointer*)remmina_plugin_python_malloc(sizeof(gpointer) * (len + 1)); + gpointer* dest = (gpointer*)python_wrapper_malloc(sizeof(gpointer) * (len + 1)); memset(dest, 0, sizeof(gpointer) * (len + 1)); for (Py_ssize_t i = 0; i < len; ++i) { PyObject* item = PyTuple_GetItem(field, i); - remmina_plugin_python_to_generic(item, dest + i); + python_wrapper_to_generic(item, dest + i); } *target = dest; @@ -277,7 +277,7 @@ RemminaTypeHint remmina_plugin_python_to_generic(PyObject* field, gpointer* targ return REMMINA_TYPEHINT_UNDEFINED; } -PyPlugin* remmina_plugin_python_get_plugin(const char* name) +PyPlugin* python_wrapper_get_plugin(const gchar* name) { TRACE_CALL(__func__); @@ -296,6 +296,21 @@ PyPlugin* remmina_plugin_python_get_plugin(const char* name) return NULL; } +PyPlugin* python_wrapper_get_plugin_by_protocol_widget(RemminaProtocolWidget* gp) +{ + TRACE_CALL(__func__); + + assert(plugin_map); + assert(gp); + + const gchar* name = python_wrapper_get_service()->protocol_widget_get_name(gp); + if (!name) { + return NULL; + } + + return python_wrapper_get_plugin(name); +} + void init_pygobject() { pygobject_init(-1, -1, -1); diff --git a/src/remmina_plugin_python_common.h b/plugins/python_wrapper/python_wrapper_common.h index 21557bb65..e7d7f16a2 100644 --- a/src/remmina_plugin_python_common.h +++ b/plugins/python_wrapper/python_wrapper_common.h @@ -32,7 +32,7 @@ */ /** - * @file remmina_plugin_python_common.h + * @file python_wrapper_common.h * * @brief Contains functions and constants that are commonly used throughout the Python plugin implementation. * @@ -46,7 +46,8 @@ // I N C L U D E S //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#include <glib.h> +#include "common/remmina_plugin.h" + #include <gtk/gtk.h> #include <Python.h> @@ -87,16 +88,16 @@ extern const char* ATTR_INIT_ORDER; */ #ifdef WITH_PYTHON_TRACE_CALLS #define CallPythonMethod(instance, name, params, ...) \ - remmina_plugin_python_last_result_set(PyObject_CallMethod(instance, name, params, ##__VA_ARGS__)); \ - remmina_plugin_python_log_method_call(instance, name); \ - remmina_plugin_python_check_error() + python_wrapper_last_result_set(PyObject_CallMethod(instance, name, params, ##__VA_ARGS__)); \ + python_wrapper_log_method_call(instance, name); \ + python_wrapper_check_error() #else /** * If WITH_TRACE_CALL is not defined, it still logs errors but doesn't print the call anymore. */ #define CallPythonMethod(instance, name, params, ...) \ PyObject_CallMethod(instance, name, params, ##__VA_ARGS__); \ - remmina_plugin_python_check_error() + python_wrapper_check_error() #endif // WITH_PYTHON_TRACE_CALLS @@ -161,34 +162,39 @@ typedef struct /** * Creates a new instance of PyGeneric. */ -PyGeneric* remmina_plugin_python_generic_new(void); +PyGeneric* python_wrapper_generic_new(void); /** * Registers the given plugin if no other plugin with the same name has been already registered. */ -void remmina_plugin_python_add_plugin(PyPlugin* plugin); +void python_wrapper_add_plugin(PyPlugin* plugin); /** * Sets the pointer to the plugin service of Remmina. */ -void remmina_plugin_python_set_service(RemminaPluginService* service); +void python_wrapper_set_service(RemminaPluginService* service); + +/** + * Gets the pointer to the plugin service of Remmina. + */ +RemminaPluginService* python_wrapper_get_service(void); /** * Extracts data from a PyObject instance to a generic pointer and returns a type hint if it could be determined. */ -RemminaTypeHint remmina_plugin_python_to_generic(PyObject* field, gpointer* target); +RemminaTypeHint python_wrapper_to_generic(PyObject* field, gpointer* target); /** * Gets the result of the last python method call. */ -PyObject* remmina_plugin_python_last_result(void); +PyObject* python_wrapper_last_result(void); /** * @brief Sets the result of the last python method call. * * @return Returns the passed result (it's done to be compatible with the CallPythonMethod macro). */ -PyObject* remmina_plugin_python_last_result_set(PyObject* result); +PyObject* python_wrapper_last_result_set(PyObject* result); /** * @brief Prints a log message to inform the user a python message has been called. @@ -198,14 +204,14 @@ PyObject* remmina_plugin_python_last_result_set(PyObject* result); * @param instance The instance that contains the called method. * @param method The name of the method called. */ -void remmina_plugin_python_log_method_call(PyObject* instance, const char* method); +void python_wrapper_log_method_call(PyObject* instance, const char* method); /** * @brief Checks if an error has occurred and prints it. * * @return Returns TRUE if an error has occurred. */ -gboolean remmina_plugin_python_check_error(void); +gboolean python_wrapper_check_error(void); /** * @brief Gets the attribute as long value. @@ -216,7 +222,7 @@ gboolean remmina_plugin_python_check_error(void); * * @return The value attribute as long. */ -long remmina_plugin_python_get_attribute_long(PyObject* instance, const char* attr_name, long def); +long python_wrapper_get_attribute_long(PyObject* instance, const char* attr_name, long def); /** * @brief Checks if a given attribute exists. @@ -226,7 +232,7 @@ long remmina_plugin_python_get_attribute_long(PyObject* instance, const char* at * * @return Returns TRUE if the attribute exists. */ -gboolean remmina_plugin_python_check_attribute(PyObject* instance, const char* attr_name); +gboolean python_wrapper_check_attribute(PyObject* instance, const char* attr_name); /** * @brief Allocates memory and checks for errors before returning. @@ -235,7 +241,7 @@ gboolean remmina_plugin_python_check_attribute(PyObject* instance, const char* a * * @return Address to the allocated memory. */ -void* remmina_plugin_python_malloc(int bytes); +void* python_wrapper_malloc(int bytes); /** * @biref Copies a string from a Python object to a new point in memory. @@ -245,7 +251,17 @@ void* remmina_plugin_python_malloc(int bytes); * * @return A char pointer to the new copy of the string. */ -char* remmina_plugin_python_copy_string_from_python(PyObject* string, Py_ssize_t len); +char* python_wrapper_copy_string_from_python(PyObject* string, Py_ssize_t len); + +/** + * @brief Tries to find the Python plugin matching to the given instance of RemminaPlugin. + * + * @param plugin_map An array of PyPlugin pointers to search. + * @param instance The RemminaPlugin instance to find the correct PyPlugin instance for. + * + * @return A pointer to a PyPlugin instance if successful. Otherwise NULL is returned. + */ +PyPlugin* python_wrapper_get_plugin(const gchar* name); /** * @brief Tries to find the Python plugin matching to the given instance of RemminaPlugin. @@ -255,7 +271,7 @@ char* remmina_plugin_python_copy_string_from_python(PyObject* string, Py_ssize_t * * @return A pointer to a PyPlugin instance if successful. Otherwise NULL is returned. */ -PyPlugin* remmina_plugin_python_get_plugin(const char* name); +PyPlugin* python_wrapper_get_plugin_by_protocol_widget(RemminaProtocolWidget* gp); /** * Creates a new GtkWidget diff --git a/src/remmina_plugin_python_entry.c b/plugins/python_wrapper/python_wrapper_entry.c index 54a478b18..53b9a6755 100644 --- a/src/remmina_plugin_python_entry.c +++ b/plugins/python_wrapper/python_wrapper_entry.c @@ -32,7 +32,7 @@ */ /** - * @file remmina_plugin_python_entry.c + * @file python_wrapper_entry.c * @brief Contains the wiring of a Python pluing based on RemminaPluginProtocol. * @author Mathias Winterhalter * @date 07.04.2021 @@ -42,8 +42,8 @@ // I N C L U D E S //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#include "remmina_plugin_python_common.h" -#include "remmina_plugin_python_entry.h" +#include "python_wrapper_common.h" +#include "python_wrapper_entry.h" //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // D E C L A R A T I O N S @@ -53,49 +53,49 @@ // A P I //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void remmina_plugin_python_entry_init(void) +void python_wrapper_entry_init(void) { TRACE_CALL(__func__); } -void remmina_plugin_python_entry_entry_func_wrapper(RemminaEntryPlugin* instance) +void python_wrapper_entry_entry_func_wrapper(RemminaEntryPlugin* instance) { TRACE_CALL(__func__); - PyPlugin* plugin = remmina_plugin_python_get_plugin(instance->name); + PyPlugin* plugin = python_wrapper_get_plugin(instance->name); if (plugin) { CallPythonMethod(plugin->instance, "entry_func", NULL); } } -RemminaPlugin* remmina_plugin_python_create_entry_plugin(PyPlugin* plugin) +RemminaPlugin* python_wrapper_create_entry_plugin(PyPlugin* plugin) { TRACE_CALL(__func__); PyObject* instance = plugin->instance; - if (!remmina_plugin_python_check_attribute(instance, ATTR_NAME) - || !remmina_plugin_python_check_attribute(instance, ATTR_VERSION) - || !remmina_plugin_python_check_attribute(instance, ATTR_DESCRIPTION)) + if (!python_wrapper_check_attribute(instance, ATTR_NAME) + || !python_wrapper_check_attribute(instance, ATTR_VERSION) + || !python_wrapper_check_attribute(instance, ATTR_DESCRIPTION)) { g_printerr("Unable to create entry plugin. Aborting!\n"); return NULL; } - RemminaEntryPlugin* remmina_plugin = (RemminaEntryPlugin*)remmina_plugin_python_malloc(sizeof(RemminaEntryPlugin)); + RemminaEntryPlugin* remmina_plugin = (RemminaEntryPlugin*)python_wrapper_malloc(sizeof(RemminaEntryPlugin)); remmina_plugin->type = REMMINA_PLUGIN_TYPE_ENTRY; remmina_plugin->domain = GETTEXT_PACKAGE; remmina_plugin->name = PyUnicode_AsUTF8(PyObject_GetAttrString(instance, ATTR_NAME)); remmina_plugin->version = PyUnicode_AsUTF8(PyObject_GetAttrString(instance, ATTR_VERSION)); remmina_plugin->description = PyUnicode_AsUTF8(PyObject_GetAttrString(instance, ATTR_DESCRIPTION)); - remmina_plugin->entry_func = remmina_plugin_python_entry_entry_func_wrapper; + remmina_plugin->entry_func = python_wrapper_entry_entry_func_wrapper; plugin->entry_plugin = remmina_plugin; plugin->generic_plugin = (RemminaPlugin*)remmina_plugin; - remmina_plugin_python_add_plugin(plugin); + python_wrapper_add_plugin(plugin); return (RemminaPlugin*)remmina_plugin; } diff --git a/src/remmina_plugin_python_entry.h b/plugins/python_wrapper/python_wrapper_entry.h index 3b4c3ee38..5dc356184 100644 --- a/src/remmina_plugin_python_entry.h +++ b/plugins/python_wrapper/python_wrapper_entry.h @@ -32,7 +32,7 @@ */ /** - * @file remmina_plugin_python_entry.h + * @file python_wrapper_entry.h * * @brief Contains the specialisation of RemminaPluginEntry plugins in Python. */ @@ -48,7 +48,7 @@ G_BEGIN_DECLS /** * Initializes the Python plugin specialisation for entry plugins. */ -void remmina_plugin_python_entry_init(void); +void python_wrapper_entry_init(void); /** * @brief Creates a new instance of the RemminaPluginEntry, initializes its members and references the wrapper @@ -56,6 +56,6 @@ void remmina_plugin_python_entry_init(void); * @param instance The instance of the Python plugin. * @return Returns a new instance of the RemminaPlugin (must be freed!). */ -RemminaPlugin* remmina_plugin_python_create_entry_plugin(PyPlugin* instance); +RemminaPlugin* python_wrapper_create_entry_plugin(PyPlugin* instance); G_END_DECLS diff --git a/src/remmina_plugin_python_file.c b/plugins/python_wrapper/python_wrapper_file.c index 71a4dcd75..4f318a1d7 100644 --- a/src/remmina_plugin_python_file.c +++ b/plugins/python_wrapper/python_wrapper_file.c @@ -35,10 +35,9 @@ // I N C L U D E S //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#include "remmina_plugin_python_common.h" -#include "remmina_plugin_python_file.h" -#include "remmina_plugin_python_remmina_file.h" -#include "remmina_file.h" +#include "python_wrapper_common.h" +#include "python_wrapper_file.h" +#include "python_wrapper_remmina_file.h" //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // D E C L A R A T I O N S @@ -48,18 +47,18 @@ // A P I //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void remmina_plugin_python_file_init(void) +void python_wrapper_file_init(void) { TRACE_CALL(__func__); } -gboolean remmina_plugin_python_file_import_test_func_wrapper(RemminaFilePlugin* instance, const gchar* from_file) +gboolean python_wrapper_file_import_test_func_wrapper(RemminaFilePlugin* instance, const gchar* from_file) { TRACE_CALL(__func__); PyObject* result = NULL; - PyPlugin* plugin = remmina_plugin_python_get_plugin(instance->name); + PyPlugin* plugin = python_wrapper_get_plugin(instance->name); if (plugin) { @@ -69,13 +68,13 @@ gboolean remmina_plugin_python_file_import_test_func_wrapper(RemminaFilePlugin* return result == Py_None || result != Py_False; } -RemminaFile* remmina_plugin_python_file_import_func_wrapper(RemminaFilePlugin* instance, const gchar* from_file) +RemminaFile* python_wrapper_file_import_func_wrapper(RemminaFilePlugin* instance, const gchar* from_file) { TRACE_CALL(__func__); PyObject* result = NULL; - PyPlugin* plugin = remmina_plugin_python_get_plugin(instance->name); + PyPlugin* plugin = python_wrapper_get_plugin(instance->name); if (!plugin) { return NULL; @@ -91,32 +90,32 @@ RemminaFile* remmina_plugin_python_file_import_func_wrapper(RemminaFilePlugin* i return ((PyRemminaFile*)result)->file; } -gboolean remmina_plugin_python_file_export_test_func_wrapper(RemminaFilePlugin* instance, RemminaFile* file) +gboolean python_wrapper_file_export_test_func_wrapper(RemminaFilePlugin* instance, RemminaFile* file) { TRACE_CALL(__func__); PyObject* result = NULL; - PyPlugin* plugin = remmina_plugin_python_get_plugin(instance->name); + PyPlugin* plugin = python_wrapper_get_plugin(instance->name); if (plugin) { result = CallPythonMethod(plugin->instance, "export_test_func", "O", - remmina_plugin_python_remmina_file_to_python(file)); + python_wrapper_remmina_file_to_python(file)); } return result == Py_None || result != Py_False; } gboolean -remmina_plugin_python_file_export_func_wrapper(RemminaFilePlugin* instance, RemminaFile* file, const gchar* to_file) +python_wrapper_file_export_func_wrapper(RemminaFilePlugin* instance, RemminaFile* file, const gchar* to_file) { TRACE_CALL(__func__); PyObject* result = NULL; - PyPlugin* plugin = remmina_plugin_python_get_plugin(instance->name); + PyPlugin* plugin = python_wrapper_get_plugin(instance->name); if (plugin) { result = CallPythonMethod(plugin->instance, "export_func", "s", to_file); @@ -125,20 +124,20 @@ remmina_plugin_python_file_export_func_wrapper(RemminaFilePlugin* instance, Remm return result == Py_None || result != Py_False; } -RemminaPlugin* remmina_plugin_python_create_file_plugin(PyPlugin* plugin) +RemminaPlugin* python_wrapper_create_file_plugin(PyPlugin* plugin) { TRACE_CALL(__func__); PyObject* instance = plugin->instance; Py_IncRef(instance); - if (!remmina_plugin_python_check_attribute(instance, ATTR_NAME)) + if (!python_wrapper_check_attribute(instance, ATTR_NAME)) { g_printerr("Unable to create file plugin. Aborting!\n"); return NULL; } - RemminaFilePlugin* remmina_plugin = (RemminaFilePlugin*)remmina_plugin_python_malloc(sizeof(RemminaFilePlugin)); + RemminaFilePlugin* remmina_plugin = (RemminaFilePlugin*)python_wrapper_malloc(sizeof(RemminaFilePlugin)); remmina_plugin->type = REMMINA_PLUGIN_TYPE_FILE; remmina_plugin->domain = GETTEXT_PACKAGE; @@ -147,15 +146,15 @@ RemminaPlugin* remmina_plugin_python_create_file_plugin(PyPlugin* plugin) remmina_plugin->description = PyUnicode_AsUTF8(PyObject_GetAttrString(instance, ATTR_DESCRIPTION)); remmina_plugin->export_hints = PyUnicode_AsUTF8(PyObject_GetAttrString(instance, ATTR_EXPORT_HINTS)); - remmina_plugin->import_test_func = remmina_plugin_python_file_import_test_func_wrapper; - remmina_plugin->import_func = remmina_plugin_python_file_import_func_wrapper; - remmina_plugin->export_test_func = remmina_plugin_python_file_export_test_func_wrapper; - remmina_plugin->export_func = remmina_plugin_python_file_export_func_wrapper; + remmina_plugin->import_test_func = python_wrapper_file_import_test_func_wrapper; + remmina_plugin->import_func = python_wrapper_file_import_func_wrapper; + remmina_plugin->export_test_func = python_wrapper_file_export_test_func_wrapper; + remmina_plugin->export_func = python_wrapper_file_export_func_wrapper; plugin->file_plugin = remmina_plugin; plugin->generic_plugin = (RemminaPlugin*)remmina_plugin; - remmina_plugin_python_add_plugin(plugin); + python_wrapper_add_plugin(plugin); return (RemminaPlugin*)remmina_plugin; } diff --git a/src/remmina_plugin_python_file.h b/plugins/python_wrapper/python_wrapper_file.h index b45326f7f..c8d25fa34 100644 --- a/src/remmina_plugin_python_file.h +++ b/plugins/python_wrapper/python_wrapper_file.h @@ -32,7 +32,7 @@ */ /** - * @file remmina_plugin_python_file.h + * @file python_wrapper_file.h * * @brief Contains the specialisation of RemminaPluginFile plugins in Python. */ @@ -48,7 +48,7 @@ G_BEGIN_DECLS /** * Initializes the Python plugin specialisation for file plugins. */ -void remmina_plugin_python_file_init(void); +void python_wrapper_file_init(void); /** * @brief Creates a new instance of the RemminaPluginFile, initializes its members and references the wrapper @@ -56,6 +56,6 @@ void remmina_plugin_python_file_init(void); * @param instance The instance of the Python plugin. * @return Returns a new instance of the RemminaPlugin (must be freed!). */ -RemminaPlugin* remmina_plugin_python_create_file_plugin(PyPlugin* instance); +RemminaPlugin* python_wrapper_create_file_plugin(PyPlugin* instance); G_END_DECLS diff --git a/src/remmina_plugin_python.c b/plugins/python_wrapper/python_wrapper_plugin.c index be83a4635..3f9885227 100644 --- a/src/remmina_plugin_python.c +++ b/plugins/python_wrapper/python_wrapper_plugin.c @@ -35,12 +35,15 @@ // I N C L U D E S //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#include <gtk/gtk.h> +#include <gdk/gdkx.h> #include "config.h" +#include "remmina/plugin.h" #include "remmina/remmina_trace_calls.h" -#include "remmina_plugin_python_common.h" -#include "remmina_plugin_python.h" -#include "remmina_plugin_python_remmina.h" -#include "remmina_plugin_python_protocol_widget.h" +#include "python_wrapper_common.h" +#include "python_wrapper_plugin.h" +#include "python_wrapper_remmina.h" +#include "python_wrapper_protocol_widget.h" /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // D E C L A R A T I O N S @@ -54,6 +57,21 @@ static const char * python_init_commands[] = { "import sys", "sys.path.append('" REMMINA_RUNTIME_PLUGINDIR "')", NULL // Sentinel }; + +static const gchar* python_wrapper_supported_extensions[] = {"py", NULL}; + +static RemminaLanguageWrapperPlugin remmina_python_wrapper = +{ + REMMINA_PLUGIN_TYPE_LANGUAGE_WRAPPER, // Type + "Python Wrapper", // Name + "Enables Python plugins for Remmina", // Description + GETTEXT_PACKAGE, // Translation domain + "Python Wrapper for Remmina v0.1", // Version number + python_wrapper_supported_extensions, // Supported extentions + python_wrapper_init, // Plugin initialization + python_wrapper_load, // Plugin load Python file +}; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // U T I L S //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -77,6 +95,8 @@ static int basename_no_ext(const char* in, char** out) if (base) { base++; + } else { + return 0; } const char* base_end = strrchr(base, '.'); @@ -88,7 +108,7 @@ static int basename_no_ext(const char* in, char** out) const int length = base_end - base; const int memsize = sizeof(char*) * ((length) + 1); - *out = (char*)remmina_plugin_python_malloc(memsize); + *out = (char*)python_wrapper_malloc(memsize); memset(*out, 0, memsize); strncpy(*out, base, length); @@ -101,29 +121,21 @@ static int basename_no_ext(const char* in, char** out) // A P I //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void remmina_plugin_python_init(void) + +gboolean python_wrapper_init(RemminaLanguageWrapperPlugin* plugin) { TRACE_CALL(__func__); - - remmina_plugin_python_module_init(); - Py_Initialize(); - - for (const char** ptr = python_init_commands; *ptr; ++ptr) - { - PyRun_SimpleString(*ptr); - } - - remmina_plugin_python_protocol_widget_init(); + assert(plugin); + return TRUE; } -gboolean remmina_plugin_python_load(RemminaPluginService* service, const char* name) +gboolean python_wrapper_load(RemminaLanguageWrapperPlugin* plugin, const char* name) { TRACE_CALL(__func__); - assert(service); + assert(plugin); assert(name); - remmina_plugin_python_set_service(service); char* filename = NULL; if (basename_no_ext(name, &filename) == 0) @@ -150,7 +162,7 @@ gboolean remmina_plugin_python_load(RemminaPluginService* service, const char* n return FALSE; } - program_name = (wchar_t*)remmina_plugin_python_malloc(sizeof(wchar_t) * len); + program_name = (wchar_t*)python_wrapper_malloc(sizeof(wchar_t) * len); if (!program_name) { free(filename); @@ -174,3 +186,24 @@ gboolean remmina_plugin_python_load(RemminaPluginService* service, const char* n return FALSE; } + + +G_MODULE_EXPORT gboolean remmina_plugin_entry(RemminaPluginService *service) +{ + TRACE_CALL(__func__); + python_wrapper_set_service(service); + + python_wrapper_module_init(); + Py_Initialize(); + + for (const char** ptr = python_init_commands; *ptr; ++ptr) + { + PyRun_SimpleString(*ptr); + } + + python_wrapper_protocol_widget_init(); + + service->register_plugin((RemminaPlugin*)&remmina_python_wrapper); + + return TRUE; +} diff --git a/src/remmina_plugin_python.h b/plugins/python_wrapper/python_wrapper_plugin.h index 97f53768d..c6caba09a 100644 --- a/src/remmina_plugin_python.h +++ b/plugins/python_wrapper/python_wrapper_plugin.h @@ -32,7 +32,7 @@ */ /** - * @file remmina_plugin_python.h + * @file python_wrapper.h * * @brief Declares the interface between the Python plugin implementation and Remmina covering the initialization of * the implementation and the load function, that allows Remmina to load plugins into the application. @@ -42,7 +42,7 @@ * instances. * * For the communication between Remmina and Python the python module called 'remmina' is initialized and - * loaded into the environment of the plugin script (@see remmina_plugin_python_module.c). + * loaded into the environment of the plugin script (@see python_wrapper_module.c). * * @see http://www.remmina.org/wp for more information. */ @@ -65,7 +65,7 @@ G_BEGIN_DECLS * @brief Initializes the Python plugin loaders. * @details This does not load any plugins but initializes the implementation (e.g. globals and the Python engine). */ -void remmina_plugin_python_init(void); +gboolean python_wrapper_init(RemminaLanguageWrapperPlugin* plugin); /** * @brief Loads a plugin from the Remmina plugin folder with the given name. @@ -75,6 +75,6 @@ void remmina_plugin_python_init(void); * * @return TRUE on success, FALSE otherwise. */ -gboolean remmina_plugin_python_load(RemminaPluginService* service, const gchar* filename); +gboolean python_wrapper_load(RemminaLanguageWrapperPlugin* plugin, const gchar* filename); G_END_DECLS diff --git a/src/remmina_plugin_python_pref.c b/plugins/python_wrapper/python_wrapper_pref.c index b799d105a..7c1849249 100644 --- a/src/remmina_plugin_python_pref.c +++ b/plugins/python_wrapper/python_wrapper_pref.c @@ -35,8 +35,8 @@ // I N C L U D E S //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#include "remmina_plugin_python_common.h" -#include "remmina_plugin_python_pref.h" +#include "python_wrapper_common.h" +#include "python_wrapper_pref.h" //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // D E C L A R A T I O N S @@ -46,7 +46,7 @@ // A P I //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void remmina_plugin_python_pref_init(void) +void python_wrapper_pref_init(void) { TRACE_CALL(__func__); @@ -55,11 +55,11 @@ void remmina_plugin_python_pref_init(void) /** * @brief */ -GtkWidget* remmina_plugin_python_pref_get_pref_body_wrapper(RemminaPrefPlugin* instance) +GtkWidget* python_wrapper_pref_get_pref_body_wrapper(RemminaPrefPlugin* instance) { TRACE_CALL(__func__); - PyPlugin* plugin = remmina_plugin_python_get_plugin(instance->name); + PyPlugin* plugin = python_wrapper_get_plugin(instance->name); PyObject* result = CallPythonMethod(plugin->instance, "get_pref_body", NULL, NULL); if (result == Py_None || result == NULL) @@ -70,22 +70,22 @@ GtkWidget* remmina_plugin_python_pref_get_pref_body_wrapper(RemminaPrefPlugin* i return get_pywidget(result); } -RemminaPlugin* remmina_plugin_python_create_pref_plugin(PyPlugin* plugin) +RemminaPlugin* python_wrapper_create_pref_plugin(PyPlugin* plugin) { TRACE_CALL(__func__); PyObject* instance = plugin->instance; - if (!remmina_plugin_python_check_attribute(instance, ATTR_NAME) - || !remmina_plugin_python_check_attribute(instance, ATTR_VERSION) - || !remmina_plugin_python_check_attribute(instance, ATTR_DESCRIPTION) - || !remmina_plugin_python_check_attribute(instance, ATTR_PREF_LABEL)) + if (!python_wrapper_check_attribute(instance, ATTR_NAME) + || !python_wrapper_check_attribute(instance, ATTR_VERSION) + || !python_wrapper_check_attribute(instance, ATTR_DESCRIPTION) + || !python_wrapper_check_attribute(instance, ATTR_PREF_LABEL)) { g_printerr("Unable to create pref plugin. Aborting!\n"); return NULL; } - RemminaPrefPlugin* remmina_plugin = (RemminaPrefPlugin*)remmina_plugin_python_malloc(sizeof(RemminaPrefPlugin)); + RemminaPrefPlugin* remmina_plugin = (RemminaPrefPlugin*)python_wrapper_malloc(sizeof(RemminaPrefPlugin)); remmina_plugin->type = REMMINA_PLUGIN_TYPE_PREF; remmina_plugin->domain = GETTEXT_PACKAGE; @@ -93,12 +93,12 @@ RemminaPlugin* remmina_plugin_python_create_pref_plugin(PyPlugin* plugin) remmina_plugin->version = PyUnicode_AsUTF8(PyObject_GetAttrString(instance, ATTR_VERSION)); remmina_plugin->description = PyUnicode_AsUTF8(PyObject_GetAttrString(instance, ATTR_DESCRIPTION)); remmina_plugin->pref_label = PyUnicode_AsUTF8(PyObject_GetAttrString(instance, ATTR_PREF_LABEL)); - remmina_plugin->get_pref_body = remmina_plugin_python_pref_get_pref_body_wrapper; + remmina_plugin->get_pref_body = python_wrapper_pref_get_pref_body_wrapper; plugin->pref_plugin = remmina_plugin; plugin->generic_plugin = (RemminaPlugin*)remmina_plugin; - remmina_plugin_python_add_plugin(plugin); + python_wrapper_add_plugin(plugin); return (RemminaPlugin*)remmina_plugin; } diff --git a/src/remmina_plugin_python_pref.h b/plugins/python_wrapper/python_wrapper_pref.h index ede1357ab..40855367e 100644 --- a/src/remmina_plugin_python_pref.h +++ b/plugins/python_wrapper/python_wrapper_pref.h @@ -32,7 +32,7 @@ */ /** - * @file remmina_plugin_python_pref.h + * @file python_wrapper_pref.h * * @brief Contains the specialisation of RemminaPluginFile plugins in Python. */ @@ -48,7 +48,7 @@ G_BEGIN_DECLS /** * Initializes the Python plugin specialisation for preferences plugins. */ -void remmina_plugin_python_pref_init(void); +void python_wrapper_pref_init(void); /** * @brief Creates a new instance of the RemminaPluginPref, initializes its members and references the wrapper @@ -56,6 +56,6 @@ void remmina_plugin_python_pref_init(void); * @param instance The instance of the Python plugin. * @return Returns a new instance of the RemminaPlugin (must be freed!). */ -RemminaPlugin* remmina_plugin_python_create_pref_plugin(PyPlugin* instance); +RemminaPlugin* python_wrapper_create_pref_plugin(PyPlugin* instance); G_END_DECLS diff --git a/src/remmina_plugin_python_protocol.c b/plugins/python_wrapper/python_wrapper_protocol.c index d01b2a657..19c90f9a1 100644 --- a/src/remmina_plugin_python_protocol.c +++ b/plugins/python_wrapper/python_wrapper_protocol.c @@ -32,7 +32,7 @@ */ /** - * @file remmina_plugin_python_common.c + * @file python_wrapper_common.c * @brief * @author Mathias Winterhalter * @date 07.04.2021 @@ -42,11 +42,9 @@ // I N C L U D E S //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#include "remmina_plugin_python_common.h" -#include "remmina_plugin_python_protocol.h" -#include "remmina_plugin_python_remmina.h" - -#include "remmina_protocol_widget.h" +#include "python_wrapper_common.h" +#include "python_wrapper_protocol.h" +#include "python_wrapper_remmina.h" //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // D E C L A R A T I O N S @@ -56,7 +54,7 @@ // A P I //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void remmina_plugin_python_protocol_init(void) +void python_wrapper_protocol_init(void) { TRACE_CALL(__func__); } @@ -64,7 +62,7 @@ void remmina_plugin_python_protocol_init(void) void remmina_protocol_init_wrapper(RemminaProtocolWidget* gp) { TRACE_CALL(__func__); - PyPlugin* py_plugin = remmina_plugin_python_get_plugin(gp->plugin->name); + PyPlugin* py_plugin = python_wrapper_get_plugin_by_protocol_widget(gp); py_plugin->gp->gp = gp; CallPythonMethod(py_plugin->instance, "init", "O", py_plugin->gp); } @@ -72,7 +70,7 @@ void remmina_protocol_init_wrapper(RemminaProtocolWidget* gp) gboolean remmina_protocol_open_connection_wrapper(RemminaProtocolWidget* gp) { TRACE_CALL(__func__); - PyPlugin* py_plugin = remmina_plugin_python_get_plugin(gp->plugin->name); + PyPlugin* py_plugin = python_wrapper_get_plugin_by_protocol_widget(gp); if (py_plugin) { PyObject* result = CallPythonMethod(py_plugin->instance, "open_connection", "O", py_plugin->gp); @@ -87,7 +85,7 @@ gboolean remmina_protocol_open_connection_wrapper(RemminaProtocolWidget* gp) gboolean remmina_protocol_close_connection_wrapper(RemminaProtocolWidget* gp) { TRACE_CALL(__func__); - PyPlugin* py_plugin = remmina_plugin_python_get_plugin(gp->plugin->name); + PyPlugin* py_plugin = python_wrapper_get_plugin_by_protocol_widget(gp); PyObject* result = CallPythonMethod(py_plugin->instance, "close_connection", "O", py_plugin->gp); return result == Py_True; } @@ -96,15 +94,15 @@ gboolean remmina_protocol_query_feature_wrapper(RemminaProtocolWidget* gp, const RemminaProtocolFeature* feature) { TRACE_CALL(__func__); - PyPlugin* py_plugin = remmina_plugin_python_get_plugin(gp->plugin->name); - PyRemminaProtocolFeature* pyFeature = remmina_plugin_python_protocol_feature_new(); + PyPlugin* py_plugin = python_wrapper_get_plugin_by_protocol_widget(gp); + PyRemminaProtocolFeature* pyFeature = python_wrapper_protocol_feature_new(); pyFeature->type = (gint)feature->type; pyFeature->id = feature->id; - pyFeature->opt1 = remmina_plugin_python_generic_new(); + pyFeature->opt1 = python_wrapper_generic_new(); pyFeature->opt1->raw = feature->opt1; - pyFeature->opt2 = remmina_plugin_python_generic_new(); + pyFeature->opt2 = python_wrapper_generic_new(); pyFeature->opt2->raw = feature->opt2; - pyFeature->opt3 = remmina_plugin_python_generic_new(); + pyFeature->opt3 = python_wrapper_generic_new(); pyFeature->opt3->raw = feature->opt3; PyObject* result = CallPythonMethod(py_plugin->instance, "query_feature", "OO", py_plugin->gp, pyFeature); @@ -118,17 +116,17 @@ gboolean remmina_protocol_query_feature_wrapper(RemminaProtocolWidget* gp, void remmina_protocol_call_feature_wrapper(RemminaProtocolWidget* gp, const RemminaProtocolFeature* feature) { TRACE_CALL(__func__); - PyPlugin* py_plugin = remmina_plugin_python_get_plugin(gp->plugin->name); - PyRemminaProtocolFeature* pyFeature = remmina_plugin_python_protocol_feature_new(); + PyPlugin* py_plugin = python_wrapper_get_plugin_by_protocol_widget(gp); + PyRemminaProtocolFeature* pyFeature = python_wrapper_protocol_feature_new(); pyFeature->type = (gint)feature->type; pyFeature->id = feature->id; - pyFeature->opt1 = remmina_plugin_python_generic_new(); + pyFeature->opt1 = python_wrapper_generic_new(); pyFeature->opt1->raw = feature->opt1; pyFeature->opt1->type_hint = feature->opt1_type_hint; - pyFeature->opt2 = remmina_plugin_python_generic_new(); + pyFeature->opt2 = python_wrapper_generic_new(); pyFeature->opt2->raw = feature->opt2; pyFeature->opt2->type_hint = feature->opt2_type_hint; - pyFeature->opt3 = remmina_plugin_python_generic_new(); + pyFeature->opt3 = python_wrapper_generic_new(); pyFeature->opt3->raw = feature->opt3; pyFeature->opt3->type_hint = feature->opt3_type_hint; @@ -144,7 +142,7 @@ void remmina_protocol_send_keytrokes_wrapper(RemminaProtocolWidget* gp, const gint keylen) { TRACE_CALL(__func__); - PyPlugin* py_plugin = remmina_plugin_python_get_plugin(gp->plugin->name); + PyPlugin* py_plugin = python_wrapper_get_plugin_by_protocol_widget(gp); PyObject* obj = PyList_New(keylen); Py_IncRef(obj); for (int i = 0; i < keylen; ++i) @@ -160,8 +158,8 @@ gboolean remmina_protocol_get_plugin_screenshot_wrapper(RemminaProtocolWidget* g { TRACE_CALL(__func__); - PyPlugin* py_plugin = remmina_plugin_python_get_plugin(gp->plugin->name); - PyRemminaPluginScreenshotData* data = remmina_plugin_python_screenshot_data_new(); + PyPlugin* py_plugin = python_wrapper_get_plugin_by_protocol_widget(gp); + PyRemminaPluginScreenshotData* data = python_wrapper_screenshot_data_new(); Py_IncRef((PyObject*)data); PyObject* result = CallPythonMethod(py_plugin->instance, "get_plugin_screenshot", "OO", py_plugin->gp, data); if (result == Py_True) @@ -174,7 +172,7 @@ gboolean remmina_protocol_get_plugin_screenshot_wrapper(RemminaProtocolWidget* g Py_ssize_t buffer_len = PyByteArray_Size((PyObject*)data->buffer); // Is being freed by Remmina! - rpsd->buffer = (unsigned char*)remmina_plugin_python_malloc(sizeof(unsigned char) * buffer_len); + rpsd->buffer = (unsigned char*)python_wrapper_malloc(sizeof(unsigned char) * buffer_len); if (!rpsd->buffer) { return 0; @@ -192,34 +190,34 @@ gboolean remmina_protocol_get_plugin_screenshot_wrapper(RemminaProtocolWidget* g gboolean remmina_protocol_map_event_wrapper(RemminaProtocolWidget* gp) { - PyPlugin* plugin = remmina_plugin_python_get_plugin(gp->plugin->name); + PyPlugin* plugin = python_wrapper_get_plugin_by_protocol_widget(gp); PyObject* result = CallPythonMethod(plugin->instance, "map_event", "O", plugin->gp); return PyBool_Check(result) && result == Py_True; } gboolean remmina_protocol_unmap_event_wrapper(RemminaProtocolWidget* gp) { - PyPlugin* plugin = remmina_plugin_python_get_plugin(gp->plugin->name); + PyPlugin* plugin = python_wrapper_get_plugin_by_protocol_widget(gp); PyObject* result = CallPythonMethod(plugin->instance, "unmap_event", "O", plugin->gp); return PyBool_Check(result) && result == Py_True; } -RemminaPlugin* remmina_plugin_python_create_protocol_plugin(PyPlugin* plugin) +RemminaPlugin* python_wrapper_create_protocol_plugin(PyPlugin* plugin) { PyObject* instance = plugin->instance; - if (!remmina_plugin_python_check_attribute(instance, ATTR_ICON_NAME_SSH) - || !remmina_plugin_python_check_attribute(instance, ATTR_ICON_NAME) - || !remmina_plugin_python_check_attribute(instance, ATTR_FEATURES) - || !remmina_plugin_python_check_attribute(instance, ATTR_BASIC_SETTINGS) - || !remmina_plugin_python_check_attribute(instance, ATTR_ADVANCED_SETTINGS) - || !remmina_plugin_python_check_attribute(instance, ATTR_SSH_SETTING)) + if (!python_wrapper_check_attribute(instance, ATTR_ICON_NAME_SSH) + || !python_wrapper_check_attribute(instance, ATTR_ICON_NAME) + || !python_wrapper_check_attribute(instance, ATTR_FEATURES) + || !python_wrapper_check_attribute(instance, ATTR_BASIC_SETTINGS) + || !python_wrapper_check_attribute(instance, ATTR_ADVANCED_SETTINGS) + || !python_wrapper_check_attribute(instance, ATTR_SSH_SETTING)) { g_printerr("Unable to create protocol plugin. Aborting!\n"); return NULL; } - RemminaProtocolPlugin* remmina_plugin = (RemminaProtocolPlugin*)remmina_plugin_python_malloc(sizeof(RemminaProtocolPlugin)); + RemminaProtocolPlugin* remmina_plugin = (RemminaProtocolPlugin*)python_wrapper_malloc(sizeof(RemminaProtocolPlugin)); remmina_plugin->type = REMMINA_PLUGIN_TYPE_PROTOCOL; remmina_plugin->domain = GETTEXT_PACKAGE; @@ -237,14 +235,14 @@ RemminaPlugin* remmina_plugin_python_create_protocol_plugin(PyPlugin* plugin) Py_ssize_t len = PyList_Size(list); if (len) { - RemminaProtocolSetting* basic_settings = (RemminaProtocolSetting*)remmina_plugin_python_malloc( + RemminaProtocolSetting* basic_settings = (RemminaProtocolSetting*)python_wrapper_malloc( sizeof(RemminaProtocolSetting) * (len + 1)); memset(basic_settings, 0, sizeof(RemminaProtocolSetting) * (len + 1)); for (Py_ssize_t i = 0; i < len; ++i) { RemminaProtocolSetting* dest = basic_settings + i; - remmina_plugin_python_to_protocol_setting(dest, PyList_GetItem(list, i)); + python_wrapper_to_protocol_setting(dest, PyList_GetItem(list, i)); } RemminaProtocolSetting* dest = basic_settings + len; dest->type = REMMINA_PROTOCOL_SETTING_TYPE_END; @@ -255,14 +253,14 @@ RemminaPlugin* remmina_plugin_python_create_protocol_plugin(PyPlugin* plugin) len = PyList_Size(list); if (len) { - RemminaProtocolSetting* advanced_settings = (RemminaProtocolSetting*)remmina_plugin_python_malloc( + RemminaProtocolSetting* advanced_settings = (RemminaProtocolSetting*)python_wrapper_malloc( sizeof(RemminaProtocolSetting) * (len + 1)); memset(advanced_settings, 0, sizeof(RemminaProtocolSetting) * (len + 1)); for (Py_ssize_t i = 0; i < len; ++i) { RemminaProtocolSetting* dest = advanced_settings + i; - remmina_plugin_python_to_protocol_setting(dest, PyList_GetItem(list, i)); + python_wrapper_to_protocol_setting(dest, PyList_GetItem(list, i)); } RemminaProtocolSetting* dest = advanced_settings + len; @@ -275,14 +273,14 @@ RemminaPlugin* remmina_plugin_python_create_protocol_plugin(PyPlugin* plugin) len = PyList_Size(list); if (len) { - RemminaProtocolFeature* features = (RemminaProtocolFeature*)remmina_plugin_python_malloc( + RemminaProtocolFeature* features = (RemminaProtocolFeature*)python_wrapper_malloc( sizeof(RemminaProtocolFeature) * (len + 1)); memset(features, 0, sizeof(RemminaProtocolFeature) * (len + 1)); for (Py_ssize_t i = 0; i < len; ++i) { RemminaProtocolFeature* dest = features + i; - remmina_plugin_python_to_protocol_feature(dest, PyList_GetItem(list, i)); + python_wrapper_to_protocol_feature(dest, PyList_GetItem(list, i)); } RemminaProtocolFeature* dest = features + len; @@ -291,7 +289,7 @@ RemminaPlugin* remmina_plugin_python_create_protocol_plugin(PyPlugin* plugin) remmina_plugin->features = features; } - remmina_plugin->ssh_setting = (RemminaProtocolSSHSetting)remmina_plugin_python_get_attribute_long(instance, + remmina_plugin->ssh_setting = (RemminaProtocolSSHSetting)python_wrapper_get_attribute_long(instance, ATTR_SSH_SETTING, REMMINA_PROTOCOL_SSH_SETTING_NONE); @@ -311,7 +309,7 @@ RemminaPlugin* remmina_plugin_python_create_protocol_plugin(PyPlugin* plugin) plugin->protocol_plugin = remmina_plugin; plugin->generic_plugin = (RemminaPlugin*)remmina_plugin; - remmina_plugin_python_add_plugin(plugin); + python_wrapper_add_plugin(plugin); return (RemminaPlugin*)remmina_plugin; }
\ No newline at end of file diff --git a/src/remmina_plugin_python_protocol.h b/plugins/python_wrapper/python_wrapper_protocol.h index 42724dcc6..0e0db676c 100644 --- a/src/remmina_plugin_python_protocol.h +++ b/plugins/python_wrapper/python_wrapper_protocol.h @@ -32,7 +32,7 @@ */ /** - * @file remmina_plugin_python_protocol.h + * @file python_wrapper_protocol.h * * @brief Contains the specialisation of RemminaPluginFile plugins in Python. */ @@ -80,7 +80,7 @@ typedef struct /** * Initializes the Python plugin specialisation for protocol plugins. */ -void remmina_plugin_python_protocol_init(void); +void python_wrapper_protocol_init(void); /** * @brief Creates a new instance of the RemminaPluginProtocol, initializes its members and references the wrapper @@ -90,18 +90,18 @@ void remmina_plugin_python_protocol_init(void); * * @return Returns a new instance of the RemminaPlugin (must be freed!). */ -RemminaPlugin* remmina_plugin_python_create_protocol_plugin(PyPlugin* plugin); +RemminaPlugin* python_wrapper_create_protocol_plugin(PyPlugin* plugin); /** * * @return */ -PyRemminaProtocolFeature* remmina_plugin_python_protocol_feature_new(void); +PyRemminaProtocolFeature* python_wrapper_protocol_feature_new(void); /** * * @return */ -PyRemminaPluginScreenshotData* remmina_plugin_python_screenshot_data_new(void); +PyRemminaPluginScreenshotData* python_wrapper_screenshot_data_new(void); G_END_DECLS diff --git a/src/remmina_plugin_python_protocol_widget.c b/plugins/python_wrapper/python_wrapper_protocol_widget.c index eceb22422..cd46dcc88 100644 --- a/src/remmina_plugin_python_protocol_widget.c +++ b/plugins/python_wrapper/python_wrapper_protocol_widget.c @@ -32,7 +32,7 @@ */ /** - * @file remmina_plugin_python_protocol_widget.c + * @file python_wrapper_protocol_widget.c * @brief Implementation of the Protocol Widget API. * @author Mathias Winterhalter * @date 19.11.2020 @@ -86,13 +86,12 @@ // I N L U C E S //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#include "remmina_plugin_python_common.h" +#include "python_wrapper_common.h" #include "remmina/plugin.h" -#include "remmina_protocol_widget.h" #include "remmina/types.h" -#include "remmina_plugin_python_remmina_file.h" -#include "remmina_plugin_python_protocol_widget.h" -#include "remmina_plugin_python_protocol.h" +#include "python_wrapper_remmina_file.h" +#include "python_wrapper_protocol_widget.h" +#include "python_wrapper_protocol.h" // -- Python Type -> RemminaWidget @@ -227,7 +226,7 @@ static PyTypeObject python_protocol_widget_type = { .tp_methods = python_protocol_widget_type_methods }; -PyRemminaProtocolWidget* remmina_plugin_python_protocol_widget_create(void) +PyRemminaProtocolWidget* python_wrapper_protocol_widget_create(void) { TRACE_CALL(__func__); @@ -240,12 +239,12 @@ PyRemminaProtocolWidget* remmina_plugin_python_protocol_widget_create(void) return result; } -void remmina_plugin_python_protocol_widget_init(void) +void python_wrapper_protocol_widget_init(void) { init_pygobject(); } -void remmina_plugin_python_protocol_widget_type_ready(void) +void python_wrapper_protocol_widget_type_ready(void) { TRACE_CALL(__func__); if (PyType_Ready(&python_protocol_widget_type) < 0) @@ -259,7 +258,7 @@ static PyObject* protocol_widget_get_viewport(PyRemminaProtocolWidget* self, PyO { TRACE_CALL(__func__); SELF_CHECK(); - return (PyObject*)new_pywidget(G_OBJECT(remmina_protocol_widget_gtkviewport(self->gp))); + return (PyObject*)new_pywidget(G_OBJECT(python_wrapper_get_service()->protocol_widget_gtkviewport(self->gp))); } static PyObject* protocol_widget_get_width(PyRemminaProtocolWidget* self, PyObject* args) @@ -267,7 +266,7 @@ static PyObject* protocol_widget_get_width(PyRemminaProtocolWidget* self, PyObje TRACE_CALL(__func__); SELF_CHECK(); - return Py_BuildValue("i", remmina_protocol_widget_get_width(self->gp)); + return Py_BuildValue("i", python_wrapper_get_service()->protocol_widget_get_width(self->gp)); } static PyObject* protocol_widget_set_width(PyRemminaProtocolWidget* self, PyObject* var_width) @@ -288,7 +287,7 @@ static PyObject* protocol_widget_set_width(PyRemminaProtocolWidget* self, PyObje } gint width = (gint)PyLong_AsLong(var_width); - remmina_protocol_widget_set_height(self->gp, width); + python_wrapper_get_service()->protocol_widget_set_height(self->gp, width); return Py_None; } @@ -298,7 +297,7 @@ static PyObject* protocol_widget_get_height(PyRemminaProtocolWidget* self, PyObj TRACE_CALL(__func__); SELF_CHECK(); - return Py_BuildValue("i", remmina_protocol_widget_get_height(self->gp)); + return Py_BuildValue("i", python_wrapper_get_service()->protocol_widget_get_height(self->gp)); } static PyObject* protocol_widget_set_height(PyRemminaProtocolWidget* self, PyObject* var_height) @@ -319,7 +318,7 @@ static PyObject* protocol_widget_set_height(PyRemminaProtocolWidget* self, PyObj } gint height = (gint)PyLong_AsLong(var_height); - remmina_protocol_widget_set_height(self->gp, height); + python_wrapper_get_service()->protocol_widget_set_height(self->gp, height); return Py_None; } @@ -329,7 +328,7 @@ static PyObject* protocol_widget_get_current_scale_mode(PyRemminaProtocolWidget* TRACE_CALL(__func__); SELF_CHECK(); - return Py_BuildValue("i", remmina_protocol_widget_get_current_scale_mode(self->gp)); + return Py_BuildValue("i", python_wrapper_get_service()->protocol_widget_get_current_scale_mode(self->gp)); } static PyObject* protocol_widget_get_expand(PyRemminaProtocolWidget* self, PyObject* args) @@ -337,7 +336,7 @@ static PyObject* protocol_widget_get_expand(PyRemminaProtocolWidget* self, PyObj TRACE_CALL(__func__); SELF_CHECK(); - return Py_BuildValue("p", remmina_protocol_widget_get_expand(self->gp)); + return Py_BuildValue("p", python_wrapper_get_service()->protocol_widget_get_expand(self->gp)); } static PyObject* protocol_widget_set_expand(PyRemminaProtocolWidget* self, PyObject* var_expand) @@ -357,7 +356,7 @@ static PyObject* protocol_widget_set_expand(PyRemminaProtocolWidget* self, PyObj return NULL; } - remmina_protocol_widget_set_expand(self->gp, PyObject_IsTrue(var_expand)); + python_wrapper_get_service()->protocol_widget_set_expand(self->gp, PyObject_IsTrue(var_expand)); return Py_None; } @@ -367,7 +366,7 @@ static PyObject* protocol_widget_has_error(PyRemminaProtocolWidget* self, PyObje TRACE_CALL(__func__); SELF_CHECK(); - return Py_BuildValue("p", remmina_protocol_widget_has_error(self->gp)); + return Py_BuildValue("p", python_wrapper_get_service()->protocol_widget_has_error(self->gp)); } static PyObject* protocol_widget_set_error(PyRemminaProtocolWidget* self, PyObject* var_msg) @@ -388,7 +387,7 @@ static PyObject* protocol_widget_set_error(PyRemminaProtocolWidget* self, PyObje } const gchar* msg = PyUnicode_AsUTF8(var_msg); - remmina_protocol_widget_set_error(self->gp, msg); + python_wrapper_get_service()->protocol_widget_set_error(self->gp, msg); return Py_None; } @@ -398,7 +397,7 @@ static PyObject* protocol_widget_is_closed(PyRemminaProtocolWidget* self, PyObje TRACE_CALL(__func__); SELF_CHECK(); - return Py_BuildValue("p", remmina_protocol_widget_is_closed(self->gp)); + return Py_BuildValue("p", python_wrapper_get_service()->protocol_widget_is_closed(self->gp)); } static PyObject* protocol_widget_get_file(PyRemminaProtocolWidget* self, PyObject* args) @@ -406,8 +405,8 @@ static PyObject* protocol_widget_get_file(PyRemminaProtocolWidget* self, PyObjec TRACE_CALL(__func__); SELF_CHECK(); - RemminaFile* file = remmina_protocol_widget_get_file(self->gp); - return (PyObject*)remmina_plugin_python_remmina_file_to_python(file); + RemminaFile* file = python_wrapper_get_service()->protocol_widget_get_file(self->gp); + return (PyObject*)python_wrapper_remmina_file_to_python(file); } static PyObject* protocol_widget_emit_signal(PyRemminaProtocolWidget* self, PyObject* var_signal) @@ -427,7 +426,7 @@ static PyObject* protocol_widget_emit_signal(PyRemminaProtocolWidget* self, PyOb return NULL; } - remmina_protocol_widget_set_error(self->gp, PyUnicode_AsUTF8(var_signal)); + python_wrapper_get_service()->protocol_widget_set_error(self->gp, PyUnicode_AsUTF8(var_signal)); return Py_None; } @@ -443,7 +442,7 @@ static PyObject* protocol_widget_register_hostkey(PyRemminaProtocolWidget* self, return NULL; } - remmina_protocol_widget_register_hostkey(self->gp, get_pywidget(var_widget)); + python_wrapper_get_service()->protocol_widget_register_hostkey(self->gp, get_pywidget(var_widget)); return Py_None; } @@ -463,7 +462,7 @@ static PyObject* protocol_widget_start_direct_tunnel(PyRemminaProtocolWidget* se if (PyArg_ParseTuple(args, "ii", &default_port, &port_plus)) { - return Py_BuildValue("s", remmina_protocol_widget_start_direct_tunnel(self->gp, default_port, port_plus)); + return Py_BuildValue("s", python_wrapper_get_service()->protocol_widget_start_direct_tunnel(self->gp, default_port, port_plus)); } else { @@ -490,13 +489,13 @@ static PyObject* protocol_widget_start_reverse_tunnel(PyRemminaProtocolWidget* s return NULL; } - return Py_BuildValue("p", remmina_protocol_widget_start_reverse_tunnel(self->gp, (gint)PyLong_AsLong(var_local_port))); + return Py_BuildValue("p", python_wrapper_get_service()->protocol_widget_start_reverse_tunnel(self->gp, (gint)PyLong_AsLong(var_local_port))); } static gboolean xport_tunnel_init(RemminaProtocolWidget* gp, gint remotedisplay, const gchar* server, gint port) { TRACE_CALL(__func__); - PyPlugin* plugin = remmina_plugin_python_get_plugin(gp->plugin->name); + PyPlugin* plugin = python_wrapper_get_plugin_by_protocol_widget(gp); PyObject* result = PyObject_CallMethod(plugin->instance, "xport_tunnel_init", "Oisi", gp, remotedisplay, server, port); return PyObject_IsTrue(result); } @@ -506,7 +505,7 @@ static PyObject* protocol_widget_start_xport_tunnel(PyRemminaProtocolWidget* sel TRACE_CALL(__func__); SELF_CHECK(); - return Py_BuildValue("p", remmina_protocol_widget_start_xport_tunnel(self->gp, xport_tunnel_init)); + return Py_BuildValue("p", python_wrapper_get_service()->protocol_widget_start_xport_tunnel(self->gp, xport_tunnel_init)); } static PyObject* protocol_widget_set_display(PyRemminaProtocolWidget* self, PyObject* var_display) @@ -526,7 +525,7 @@ static PyObject* protocol_widget_set_display(PyRemminaProtocolWidget* self, PyOb return NULL; } - remmina_protocol_widget_set_display(self->gp, (gint)PyLong_AsLong(var_display)); + python_wrapper_get_service()->protocol_widget_set_display(self->gp, (gint)PyLong_AsLong(var_display)); return Py_None; } @@ -536,7 +535,7 @@ static PyObject* protocol_widget_signal_connection_closed(PyRemminaProtocolWidge TRACE_CALL(__func__); SELF_CHECK(); - remmina_protocol_widget_signal_connection_closed(self->gp); + python_wrapper_get_service()->protocol_widget_signal_connection_closed(self->gp); return Py_None; } @@ -545,7 +544,7 @@ static PyObject* protocol_widget_signal_connection_opened(PyRemminaProtocolWidge TRACE_CALL(__func__); SELF_CHECK(); - remmina_protocol_widget_signal_connection_opened(self->gp); + python_wrapper_get_service()->protocol_widget_signal_connection_opened(self->gp); return Py_None; } @@ -554,7 +553,7 @@ static PyObject* protocol_widget_update_align(PyRemminaProtocolWidget* self, PyO TRACE_CALL(__func__); SELF_CHECK(); - remmina_protocol_widget_update_align(self->gp); + python_wrapper_get_service()->protocol_widget_update_align(self->gp); return Py_None; } @@ -563,7 +562,7 @@ static PyObject* protocol_widget_unlock_dynres(PyRemminaProtocolWidget* self, Py TRACE_CALL(__func__); SELF_CHECK(); - remmina_protocol_widget_unlock_dynres(self->gp); + python_wrapper_get_service()->protocol_widget_unlock_dynres(self->gp); return Py_None; } @@ -572,7 +571,7 @@ static PyObject* protocol_widget_desktop_resize(PyRemminaProtocolWidget* self, P TRACE_CALL(__func__); SELF_CHECK(); - remmina_protocol_widget_desktop_resize(self->gp); + python_wrapper_get_service()->protocol_widget_desktop_resize(self->gp); return Py_None; } @@ -584,7 +583,7 @@ static PyObject* protocol_widget_panel_new_certificate(PyRemminaProtocolWidget* if (PyArg_ParseTuple(args, "sss", &subject, &issuer, &fingerprint)) { - remmina_protocol_widget_panel_new_certificate(self->gp, subject, issuer, fingerprint); + python_wrapper_get_service()->protocol_widget_panel_new_certificate(self->gp, subject, issuer, fingerprint); } else { @@ -602,7 +601,7 @@ static PyObject* protocol_widget_panel_changed_certificate(PyRemminaProtocolWidg if (PyArg_ParseTuple(args, "sss", &subject, &issuer, &new_fingerprint, &old_fingerprint)) { - remmina_protocol_widget_panel_changed_certificate(self->gp, subject, issuer, new_fingerprint, old_fingerprint); + python_wrapper_get_service()->protocol_widget_panel_changed_certificate(self->gp, subject, issuer, new_fingerprint, old_fingerprint); } else { @@ -617,7 +616,7 @@ static PyObject* protocol_widget_get_username(PyRemminaProtocolWidget* self, PyO TRACE_CALL(__func__); SELF_CHECK(); - return Py_BuildValue("s", remmina_protocol_widget_get_username(self->gp)); + return Py_BuildValue("s", python_wrapper_get_service()->protocol_widget_get_username(self->gp)); } static PyObject* protocol_widget_get_password(PyRemminaProtocolWidget* self, PyObject* args) @@ -625,7 +624,7 @@ static PyObject* protocol_widget_get_password(PyRemminaProtocolWidget* self, PyO TRACE_CALL(__func__); SELF_CHECK(); - return Py_BuildValue("s", remmina_protocol_widget_get_password(self->gp)); + return Py_BuildValue("s", python_wrapper_get_service()->protocol_widget_get_password(self->gp)); } static PyObject* protocol_widget_get_domain(PyRemminaProtocolWidget* self, PyObject* args) @@ -633,7 +632,7 @@ static PyObject* protocol_widget_get_domain(PyRemminaProtocolWidget* self, PyObj TRACE_CALL(__func__); SELF_CHECK(); - return Py_BuildValue("s", remmina_protocol_widget_get_domain(self->gp)); + return Py_BuildValue("s", python_wrapper_get_service()->protocol_widget_get_domain(self->gp)); } static PyObject* protocol_widget_get_savepassword(PyRemminaProtocolWidget* self, PyObject* args) @@ -641,7 +640,7 @@ static PyObject* protocol_widget_get_savepassword(PyRemminaProtocolWidget* self, TRACE_CALL(__func__); SELF_CHECK(); - return Py_BuildValue("p", remmina_protocol_widget_get_savepassword(self->gp)); + return Py_BuildValue("p", python_wrapper_get_service()->protocol_widget_get_savepassword(self->gp)); } static PyObject* protocol_widget_panel_authx509(PyRemminaProtocolWidget* self, PyObject* args) @@ -649,7 +648,7 @@ static PyObject* protocol_widget_panel_authx509(PyRemminaProtocolWidget* self, P TRACE_CALL(__func__); SELF_CHECK(); - return Py_BuildValue("i", remmina_protocol_widget_panel_authx509(self->gp)); + return Py_BuildValue("i", python_wrapper_get_service()->protocol_widget_panel_authx509(self->gp)); } static PyObject* protocol_widget_get_cacert(PyRemminaProtocolWidget* self, PyObject* args) @@ -657,7 +656,7 @@ static PyObject* protocol_widget_get_cacert(PyRemminaProtocolWidget* self, PyObj TRACE_CALL(__func__); SELF_CHECK(); - return Py_BuildValue("s", remmina_protocol_widget_get_cacert(self->gp)); + return Py_BuildValue("s", python_wrapper_get_service()->protocol_widget_get_cacert(self->gp)); } static PyObject* protocol_widget_get_cacrl(PyRemminaProtocolWidget* self, PyObject* args) @@ -665,7 +664,7 @@ static PyObject* protocol_widget_get_cacrl(PyRemminaProtocolWidget* self, PyObje TRACE_CALL(__func__); SELF_CHECK(); - return Py_BuildValue("s", remmina_protocol_widget_get_cacrl(self->gp)); + return Py_BuildValue("s", python_wrapper_get_service()->protocol_widget_get_cacrl(self->gp)); } static PyObject* protocol_widget_get_clientcert(PyRemminaProtocolWidget* self, PyObject* args) @@ -673,7 +672,7 @@ static PyObject* protocol_widget_get_clientcert(PyRemminaProtocolWidget* self, P TRACE_CALL(__func__); SELF_CHECK(); - return Py_BuildValue("s", remmina_protocol_widget_get_clientcert(self->gp)); + return Py_BuildValue("s", python_wrapper_get_service()->protocol_widget_get_clientcert(self->gp)); } static PyObject* protocol_widget_get_clientkey(PyRemminaProtocolWidget* self, PyObject* args) @@ -681,7 +680,7 @@ static PyObject* protocol_widget_get_clientkey(PyRemminaProtocolWidget* self, Py TRACE_CALL(__func__); SELF_CHECK(); - return Py_BuildValue("s", remmina_protocol_widget_get_clientkey(self->gp)); + return Py_BuildValue("s", python_wrapper_get_service()->protocol_widget_get_clientkey(self->gp)); } static PyObject* protocol_widget_save_cred(PyRemminaProtocolWidget* self, PyObject* args) @@ -689,7 +688,7 @@ static PyObject* protocol_widget_save_cred(PyRemminaProtocolWidget* self, PyObje TRACE_CALL(__func__); SELF_CHECK(); - remmina_protocol_widget_save_cred(self->gp); + python_wrapper_get_service()->protocol_widget_save_cred(self->gp); return Py_None; } @@ -701,7 +700,7 @@ static PyObject* protocol_widget_panel_show_listen(PyRemminaProtocolWidget* self if (PyArg_ParseTuple(args, "i", &port)) { - remmina_protocol_widget_panel_show_listen(self->gp, port); + python_wrapper_get_service()->protocol_widget_panel_show_listen(self->gp, port); } else { @@ -716,7 +715,7 @@ static PyObject* protocol_widget_panel_show_retry(PyRemminaProtocolWidget* self, TRACE_CALL(__func__); SELF_CHECK(); - remmina_protocol_widget_panel_show_retry(self->gp); + python_wrapper_get_service()->protocol_widget_panel_show_retry(self->gp); return Py_None; } @@ -725,7 +724,7 @@ static PyObject* protocol_widget_panel_show(PyRemminaProtocolWidget* self, PyObj TRACE_CALL(__func__); SELF_CHECK(); - remmina_protocol_widget_panel_show(self->gp); + python_wrapper_get_service()->protocol_widget_panel_show(self->gp); return Py_None; } @@ -734,7 +733,7 @@ static PyObject* protocol_widget_panel_hide(PyRemminaProtocolWidget* self, PyObj TRACE_CALL(__func__); SELF_CHECK(); - remmina_protocol_widget_panel_hide(self->gp); + python_wrapper_get_service()->protocol_widget_panel_hide(self->gp); return Py_None; } @@ -747,7 +746,7 @@ static PyObject* protocol_widget_ssh_exec(PyRemminaProtocolWidget* self, PyObjec if (PyArg_ParseTuple(args, "ps", &wait, &cmd)) { - remmina_protocol_widget_ssh_exec(self->gp, wait, cmd); + python_wrapper_get_service()->protocol_widget_ssh_exec(self->gp, wait, cmd); } else { @@ -759,13 +758,13 @@ static PyObject* protocol_widget_ssh_exec(PyRemminaProtocolWidget* self, PyObjec static void _on_send_callback_wrapper(RemminaProtocolWidget* gp, const gchar* text) { - PyPlugin* plugin = remmina_plugin_python_get_plugin(gp->plugin->name); + PyPlugin* plugin = python_wrapper_get_plugin_by_protocol_widget(gp); PyObject_CallMethod(plugin->instance, "on_send", "Os", gp, text); } static void _on_destroy_callback_wrapper(RemminaProtocolWidget* gp) { - PyPlugin* plugin = remmina_plugin_python_get_plugin(gp->plugin->name); + PyPlugin* plugin = python_wrapper_get_plugin_by_protocol_widget(gp); PyObject_CallMethod(plugin->instance, "on_destroy", "O", gp); } @@ -779,7 +778,7 @@ static PyObject* protocol_widget_chat_open(PyRemminaProtocolWidget* self, PyObje g_printerr("[%s:%d@%s]: Argument is not of type String!\n", __FILE__, __LINE__, __func__); } - remmina_protocol_widget_chat_open(self->gp, + python_wrapper_get_service()->protocol_widget_chat_open(self->gp, PyUnicode_AsUTF8(var_name), _on_send_callback_wrapper, _on_destroy_callback_wrapper); @@ -792,7 +791,7 @@ static PyObject* protocol_widget_chat_close(PyRemminaProtocolWidget* self, PyObj TRACE_CALL(__func__); SELF_CHECK(); - remmina_protocol_widget_panel_hide(self->gp); + python_wrapper_get_service()->protocol_widget_panel_hide(self->gp); return Py_None; } @@ -804,7 +803,7 @@ static PyObject* protocol_widget_chat_receive(PyRemminaProtocolWidget* self, PyO if (PyArg_ParseTuple(args, "s", &text)) { - remmina_protocol_widget_chat_receive(self->gp, text); + python_wrapper_get_service()->protocol_widget_chat_receive(self->gp, text); } else { @@ -833,7 +832,7 @@ static PyObject* protocol_widget_send_keys_signals(PyRemminaProtocolWidget* self } else { - remmina_protocol_widget_send_keys_signals((GtkWidget*)widget, keyvals, length, event_type); + python_wrapper_get_service()->protocol_widget_send_keys_signals((GtkWidget*)widget, keyvals, length, event_type); } } else diff --git a/src/remmina_plugin_python_protocol_widget.h b/plugins/python_wrapper/python_wrapper_protocol_widget.h index dcbbc8093..b6a9c8ed1 100644 --- a/src/remmina_plugin_python_protocol_widget.h +++ b/plugins/python_wrapper/python_wrapper_protocol_widget.h @@ -32,7 +32,7 @@ */ /** - * @file remmina_plugin_python_protocol_widget.h + * @file python_wrapper_protocol_widget.h * * @brief Contains the implementation of the widget handling used from the protocol plugin. */ @@ -48,16 +48,16 @@ G_BEGIN_DECLS /** * Initializes the widget backend of the protocol plugin implementation. */ -void remmina_plugin_python_protocol_widget_init(void); +void python_wrapper_protocol_widget_init(void); /** * Initializes Python types used for protocol widgets. */ -void remmina_plugin_python_protocol_widget_type_ready(void); +void python_wrapper_protocol_widget_type_ready(void); /** * Creates a new instance of PyRemminaProtocolWidget and initializes its fields. */ -PyRemminaProtocolWidget* remmina_plugin_python_protocol_widget_create(); +PyRemminaProtocolWidget* python_wrapper_protocol_widget_create(); G_END_DECLS diff --git a/src/remmina_plugin_python_remmina.c b/plugins/python_wrapper/python_wrapper_remmina.c index ad0ebc7a4..eeda8d2f1 100644 --- a/src/remmina_plugin_python_remmina.c +++ b/plugins/python_wrapper/python_wrapper_remmina.c @@ -35,33 +35,21 @@ // I N C L U D E S //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#include "remmina_plugin_python_common.h" -#include "remmina_main.h" -#include "remmina_plugin_manager.h" +#include "python_wrapper_common.h" #include "remmina/plugin.h" #include "remmina/types.h" -#include "remmina_protocol_widget.h" -#include "remmina_log.h" -#include "remmina_plugin_python_remmina.h" -#include "remmina_plugin_python_protocol_widget.h" +#include "python_wrapper_remmina.h" +#include "python_wrapper_protocol_widget.h" -#include "remmina_plugin_python_entry.h" -#include "remmina_plugin_python_file.h" -#include "remmina_plugin_python_protocol.h" -#include "remmina_plugin_python_tool.h" -#include "remmina_plugin_python_secret.h" -#include "remmina_plugin_python_pref.h" +#include "python_wrapper_entry.h" +#include "python_wrapper_file.h" +#include "python_wrapper_protocol.h" +#include "python_wrapper_tool.h" +#include "python_wrapper_secret.h" +#include "python_wrapper_pref.h" -#include "remmina_pref.h" -#include "remmina_ssh.h" -#include "remmina_file_manager.h" -#include "remmina_widget_pool.h" -#include "remmina_public.h" -#include "remmina_masterthread_exec.h" - -#include "rcw.h" -#include "remmina_plugin_python_remmina_file.h" +#include "python_wrapper_remmina_file.h" #include <string.h> @@ -73,9 +61,9 @@ /** * Util function to check if a specific member is define in a Python object. */ -gboolean remmina_plugin_python_check_mandatory_member(PyObject* instance, const gchar* member); +gboolean python_wrapper_check_mandatory_member(PyObject* instance, const gchar* member); -static PyObject* remmina_plugin_python_debug_wrapper(PyObject* self, PyObject* msg); +static PyObject* python_wrapper_debug_wrapper(PyObject* self, PyObject* msg); static PyObject* remmina_register_plugin_wrapper(PyObject* self, PyObject* plugin); static PyObject* remmina_file_get_datadir_wrapper(PyObject* self, PyObject* plugin); static PyObject* remmina_file_new_wrapper(PyObject* self, PyObject* args, PyObject* kwargs); @@ -86,7 +74,7 @@ static PyObject* remmina_pref_get_sshtunnel_port_wrapper(PyObject* self, PyObjec static PyObject* remmina_pref_get_ssh_loglevel_wrapper(PyObject* self, PyObject* plugin); static PyObject* remmina_pref_get_ssh_parseconfig_wrapper(PyObject* self, PyObject* plugin); static PyObject* remmina_pref_keymap_get_keyval_wrapper(PyObject* self, PyObject* args, PyObject* kwargs); -static PyObject* remmina_plugin_python_log_print_wrapper(PyObject* self, PyObject* arg); +static PyObject* python_wrapper_log_print_wrapper(PyObject* self, PyObject* arg); static PyObject* remmina_widget_pool_register_wrapper(PyObject* self, PyObject* args, PyObject* kwargs); static PyObject* rcw_open_from_file_full_wrapper(PyObject* self, PyObject* args, PyObject* kwargs); static PyObject* remmina_public_get_server_port_wrapper(PyObject* self, PyObject* args, PyObject* kwargs); @@ -96,8 +84,8 @@ static PyObject* remmina_protocol_widget_get_profile_remote_height_wrapper(PyObject* self, PyObject* args, PyObject* kwargs); static PyObject* remmina_protocol_widget_get_profile_remote_width_wrapper(PyObject* self, PyObject* args, PyObject* kwargs); -static PyObject* remmina_plugin_python_show_dialog_wrapper(PyObject* self, PyObject* args, PyObject* kwargs); -static PyObject* remmina_plugin_python_get_mainwindow_wrapper(PyObject* self, PyObject* args); +static PyObject* python_wrapper_show_dialog_wrapper(PyObject* self, PyObject* args, PyObject* kwargs); +static PyObject* python_wrapper_get_mainwindow_wrapper(PyObject* self, PyObject* args); static PyObject* remmina_protocol_plugin_signal_connection_opened_wrapper(PyObject* self, PyObject* args); static PyObject* remmina_protocol_plugin_signal_connection_closed_wrapper(PyObject* self, PyObject* args); static PyObject* remmina_protocol_plugin_init_auth_wrapper(PyObject* self, PyObject* args, PyObject* kwargs); @@ -116,23 +104,23 @@ static PyMethodDef remmina_python_module_type_methods[] = { /** * Prints a string into the Remmina log infrastructure. */ - { "log_print", remmina_plugin_python_log_print_wrapper, METH_VARARGS, NULL }, + { "log_print", python_wrapper_log_print_wrapper, METH_VARARGS, NULL }, /** * Prints a debug message if enabled. */ - { "debug", remmina_plugin_python_debug_wrapper, METH_VARARGS, NULL }, + { "debug", python_wrapper_debug_wrapper, METH_VARARGS, NULL }, /** * Shows a GTK+ dialog. */ - { "show_dialog", (PyCFunction)remmina_plugin_python_show_dialog_wrapper, METH_VARARGS | METH_KEYWORDS, + { "show_dialog", (PyCFunction)python_wrapper_show_dialog_wrapper, METH_VARARGS | METH_KEYWORDS, NULL }, /** * Returns the GTK+ object of the main window of Remmina. */ - { "get_main_window", remmina_plugin_python_get_mainwindow_wrapper, METH_NOARGS, NULL }, + { "get_main_window", python_wrapper_get_mainwindow_wrapper, METH_NOARGS, NULL }, /** * Calls remmina_file_get_datadir and returns its result. @@ -307,11 +295,11 @@ static int python_protocol_setting_init(PyRemminaProtocolSetting* self, PyObject } else { - self->label = remmina_plugin_python_copy_string_from_python(label, len); + self->label = python_wrapper_copy_string_from_python(label, len); if (!self->label) { g_printerr("Unable to extract label during initialization of Python settings module!\n"); - remmina_plugin_python_check_error(); + python_wrapper_check_error(); } } @@ -322,11 +310,11 @@ static int python_protocol_setting_init(PyRemminaProtocolSetting* self, PyObject } else { - self->name = remmina_plugin_python_copy_string_from_python(label, len); + self->name = python_wrapper_copy_string_from_python(label, len); if (!self->name) { g_printerr("Unable to extract name during initialization of Python settings module!\n"); - remmina_plugin_python_check_error(); + python_wrapper_check_error(); } } @@ -416,17 +404,17 @@ static PyTypeObject python_protocol_feature_type = { .tp_members = python_protocol_feature_members }; -PyRemminaProtocolFeature* remmina_plugin_python_protocol_feature_new(void) +PyRemminaProtocolFeature* python_wrapper_protocol_feature_new(void) { PyRemminaProtocolFeature* feature = (PyRemminaProtocolFeature*)PyObject_New(PyRemminaProtocolFeature, &python_protocol_feature_type); feature->id = 0; - feature->opt1 = remmina_plugin_python_generic_new(); + feature->opt1 = python_wrapper_generic_new(); feature->opt1->raw = NULL; feature->opt1->type_hint = REMMINA_TYPEHINT_UNDEFINED; - feature->opt2 = remmina_plugin_python_generic_new(); + feature->opt2 = python_wrapper_generic_new(); feature->opt2->raw = NULL; feature->opt2->type_hint = REMMINA_TYPEHINT_UNDEFINED; - feature->opt3 = remmina_plugin_python_generic_new(); + feature->opt3 = python_wrapper_generic_new(); feature->opt3->raw = NULL; feature->opt3->type_hint = REMMINA_TYPEHINT_UNDEFINED; feature->type = 0; @@ -483,7 +471,7 @@ static PyTypeObject python_screenshot_data_type = { .tp_init = (initproc)python_screenshot_data_init, .tp_members = python_screenshot_data_members }; -PyRemminaPluginScreenshotData* remmina_plugin_python_screenshot_data_new(void) +PyRemminaPluginScreenshotData* python_wrapper_screenshot_data_new(void) { PyRemminaPluginScreenshotData* data = (PyRemminaPluginScreenshotData*)PyObject_New(PyRemminaPluginScreenshotData, &python_screenshot_data_type); data->buffer = PyObject_New(PyByteArrayObject, &PyByteArray_Type); @@ -495,28 +483,28 @@ PyRemminaPluginScreenshotData* remmina_plugin_python_screenshot_data_new(void) return data; } -static PyObject* remmina_plugin_python_generic_to_int(PyGeneric* self, PyObject* args); -static PyObject* remmina_plugin_python_generic_to_bool(PyGeneric* self, PyObject* args); -static PyObject* remmina_plugin_python_generic_to_string(PyGeneric* self, PyObject* args); +static PyObject* python_wrapper_generic_to_int(PyGeneric* self, PyObject* args); +static PyObject* python_wrapper_generic_to_bool(PyGeneric* self, PyObject* args); +static PyObject* python_wrapper_generic_to_string(PyGeneric* self, PyObject* args); -static void remmina_plugin_python_generic_dealloc(PyObject* self) +static void python_wrapper_generic_dealloc(PyObject* self) { PyObject_Del(self); } -static PyMethodDef remmina_plugin_python_generic_methods[] = { - { "to_int", (PyCFunction)remmina_plugin_python_generic_to_int, METH_NOARGS, "" }, - { "to_bool", (PyCFunction)remmina_plugin_python_generic_to_bool, METH_NOARGS, "" }, - { "to_string", (PyCFunction)remmina_plugin_python_generic_to_string, METH_NOARGS, "" }, +static PyMethodDef python_wrapper_generic_methods[] = { + { "to_int", (PyCFunction)python_wrapper_generic_to_int, METH_NOARGS, "" }, + { "to_bool", (PyCFunction)python_wrapper_generic_to_bool, METH_NOARGS, "" }, + { "to_string", (PyCFunction)python_wrapper_generic_to_string, METH_NOARGS, "" }, { NULL } }; -static PyMemberDef remmina_plugin_python_generic_members[] = { +static PyMemberDef python_wrapper_generic_members[] = { { "raw", T_OBJECT, offsetof(PyGeneric, raw), 0, "" }, { NULL } }; -PyObject* remmina_plugin_python_generic_type_new(PyTypeObject* type, PyObject* kws, PyObject* args) +PyObject* python_wrapper_generic_type_new(PyTypeObject* type, PyObject* kws, PyObject* args) { TRACE_CALL(__func__); @@ -530,7 +518,7 @@ PyObject* remmina_plugin_python_generic_type_new(PyTypeObject* type, PyObject* k return (PyObject*)self; } -static int remmina_plugin_python_generic_init(PyGeneric* self, PyObject* args, PyObject* kwargs) +static int python_wrapper_generic_init(PyGeneric* self, PyObject* args, PyObject* kwargs) { TRACE_CALL(__func__); @@ -548,15 +536,15 @@ static PyTypeObject python_generic_type = { .tp_doc = "", .tp_basicsize = sizeof(PyGeneric), .tp_itemsize = 0, - .tp_dealloc = remmina_plugin_python_generic_dealloc, + .tp_dealloc = python_wrapper_generic_dealloc, .tp_flags = Py_TPFLAGS_DEFAULT, - .tp_new = remmina_plugin_python_generic_type_new, - .tp_init = (initproc)remmina_plugin_python_generic_init, - .tp_members = remmina_plugin_python_generic_members, - .tp_methods = remmina_plugin_python_generic_methods, + .tp_new = python_wrapper_generic_type_new, + .tp_init = (initproc)python_wrapper_generic_init, + .tp_members = python_wrapper_generic_members, + .tp_methods = python_wrapper_generic_methods, }; -PyGeneric* remmina_plugin_python_generic_new(void) +PyGeneric* python_wrapper_generic_new(void) { PyGeneric* generic = (PyGeneric*)PyObject_New(PyGeneric, &python_generic_type); generic->raw = PyLong_FromLongLong(0LL); @@ -564,7 +552,7 @@ PyGeneric* remmina_plugin_python_generic_new(void) return generic; } -static PyObject* remmina_plugin_python_generic_to_int(PyGeneric* self, PyObject* args) +static PyObject* python_wrapper_generic_to_int(PyGeneric* self, PyObject* args) { SELF_CHECK(); @@ -583,7 +571,7 @@ static PyObject* remmina_plugin_python_generic_to_int(PyGeneric* self, PyObject* return Py_None; } -static PyObject* remmina_plugin_python_generic_to_bool(PyGeneric* self, PyObject* args) +static PyObject* python_wrapper_generic_to_bool(PyGeneric* self, PyObject* args) { SELF_CHECK(); @@ -598,7 +586,7 @@ static PyObject* remmina_plugin_python_generic_to_bool(PyGeneric* self, PyObject return Py_None; } -static PyObject* remmina_plugin_python_generic_to_string(PyGeneric* self, PyObject* args) +static PyObject* python_wrapper_generic_to_string(PyGeneric* self, PyObject* args) { SELF_CHECK(); @@ -618,7 +606,7 @@ static PyObject* remmina_plugin_python_generic_to_string(PyGeneric* self, PyObje * Is called from the Python engine when it initializes the 'remmina' module. * @details This function is only called by the Python engine! */ -PyMODINIT_FUNC remmina_plugin_python_module_initialize(void) +PyMODINIT_FUNC python_wrapper_module_initialize(void) { TRACE_CALL(__func__); @@ -646,8 +634,8 @@ PyMODINIT_FUNC remmina_plugin_python_module_initialize(void) return NULL; } - remmina_plugin_python_protocol_widget_type_ready(); - remmina_plugin_python_remmina_init_types(); + python_wrapper_protocol_widget_type_ready(); + python_wrapper_remmina_init_types(); PyObject* module = PyModule_Create(&remmina_python_module_type); if (!module) @@ -728,25 +716,25 @@ PyMODINIT_FUNC remmina_plugin_python_module_initialize(void) * Initializes all globals and registers the 'remmina' module in the Python engine. * @details This */ -void remmina_plugin_python_module_init(void) +void python_wrapper_module_init(void) { TRACE_CALL(__func__); - if (PyImport_AppendInittab("remmina", remmina_plugin_python_module_initialize)) + if (PyImport_AppendInittab("remmina", python_wrapper_module_initialize)) { PyErr_Print(); exit(1); } - remmina_plugin_python_entry_init(); - remmina_plugin_python_protocol_init(); - remmina_plugin_python_tool_init(); - remmina_plugin_python_pref_init(); - remmina_plugin_python_secret_init(); - remmina_plugin_python_file_init(); + python_wrapper_entry_init(); + python_wrapper_protocol_init(); + python_wrapper_tool_init(); + python_wrapper_pref_init(); + python_wrapper_secret_init(); + python_wrapper_file_init(); } -gboolean remmina_plugin_python_check_mandatory_member(PyObject* instance, const gchar* member) +gboolean python_wrapper_check_mandatory_member(PyObject* instance, const gchar* member) { TRACE_CALL(__func__); @@ -765,8 +753,8 @@ static PyObject* remmina_register_plugin_wrapper(PyObject* self, PyObject* plugi if (plugin_instance) { - if (!remmina_plugin_python_check_mandatory_member(plugin_instance, "name") - || !remmina_plugin_python_check_mandatory_member(plugin_instance, "version")) + if (!python_wrapper_check_mandatory_member(plugin_instance, "name") + || !python_wrapper_check_mandatory_member(plugin_instance, "version")) { return NULL; } @@ -776,7 +764,7 @@ static PyObject* remmina_register_plugin_wrapper(PyObject* self, PyObject* plugi RemminaPlugin* remmina_plugin = NULL; - PyPlugin* plugin = (PyPlugin*)remmina_plugin_python_malloc(sizeof(PyPlugin)); + PyPlugin* plugin = (PyPlugin*)python_wrapper_malloc(sizeof(PyPlugin)); plugin->instance = plugin_instance; Py_INCREF(plugin_instance); plugin->protocol_plugin = NULL; @@ -789,27 +777,27 @@ static PyObject* remmina_register_plugin_wrapper(PyObject* self, PyObject* plugi if (g_str_equal(pluginType, "protocol")) { - remmina_plugin = remmina_plugin_python_create_protocol_plugin(plugin); + remmina_plugin = python_wrapper_create_protocol_plugin(plugin); } else if (g_str_equal(pluginType, "entry")) { - remmina_plugin = remmina_plugin_python_create_entry_plugin(plugin); + remmina_plugin = python_wrapper_create_entry_plugin(plugin); } else if (g_str_equal(pluginType, "file")) { - remmina_plugin = remmina_plugin_python_create_file_plugin(plugin); + remmina_plugin = python_wrapper_create_file_plugin(plugin); } else if (g_str_equal(pluginType, "tool")) { - remmina_plugin = remmina_plugin_python_create_tool_plugin(plugin); + remmina_plugin = python_wrapper_create_tool_plugin(plugin); } else if (g_str_equal(pluginType, "pref")) { - remmina_plugin = remmina_plugin_python_create_pref_plugin(plugin); + remmina_plugin = python_wrapper_create_pref_plugin(plugin); } else if (g_str_equal(pluginType, "secret")) { - remmina_plugin = remmina_plugin_python_create_secret_plugin(plugin); + remmina_plugin = python_wrapper_create_secret_plugin(plugin); } else { @@ -820,13 +808,18 @@ static PyObject* remmina_register_plugin_wrapper(PyObject* self, PyObject* plugi { if (remmina_plugin->type == REMMINA_PLUGIN_TYPE_PROTOCOL) { - plugin->gp = remmina_plugin_python_protocol_widget_create(); + plugin->gp = python_wrapper_protocol_widget_create(); } - remmina_plugin_manager_service.register_plugin((RemminaPlugin*)remmina_plugin); + if (python_wrapper_get_service()->register_plugin((RemminaPlugin*)remmina_plugin)) { + g_print("%s: Successfully reigstered!\n", remmina_plugin->name); + } else { + g_print("%s: Failed to reigster!\n", remmina_plugin->name); + } } } + PyErr_Clear(); return Py_None; } @@ -835,14 +828,14 @@ static PyObject* remmina_file_get_datadir_wrapper(PyObject* self, PyObject* plug TRACE_CALL(__func__); PyObject* result = Py_None; - const gchar* datadir = remmina_file_get_datadir(); + const gchar* datadir = python_wrapper_get_service()->file_get_user_datadir(); if (datadir) { result = PyUnicode_FromFormat("%s", datadir); } - remmina_plugin_python_check_error(); + python_wrapper_check_error(); return result; } @@ -850,13 +843,13 @@ static PyObject* remmina_file_new_wrapper(PyObject* self, PyObject* args, PyObje { TRACE_CALL(__func__); - RemminaFile* file = remmina_file_new(); + RemminaFile* file = python_wrapper_get_service()->file_new(); if (file) { - return (PyObject*)remmina_plugin_python_remmina_file_to_python(file); + return (PyObject*)python_wrapper_remmina_file_to_python(file); } - remmina_plugin_python_check_error(); + python_wrapper_check_error(); return Py_None; } @@ -874,10 +867,10 @@ static PyObject* remmina_pref_set_value_wrapper(PyObject* self, PyObject* args, if (key) { - remmina_pref_set_value(key, value); + python_wrapper_get_service()->pref_set_value(key, value); } - remmina_plugin_python_check_error(); + python_wrapper_check_error(); return Py_None; } @@ -896,14 +889,14 @@ static PyObject* remmina_pref_get_value_wrapper(PyObject* self, PyObject* args, if (key) { - const gchar* value = remmina_pref_get_value(key); + const gchar* value = python_wrapper_get_service()->pref_get_value(key); if (value) { result = PyUnicode_FromFormat("%s", result); } } - remmina_plugin_python_check_error(); + python_wrapper_check_error(); return result; } @@ -911,8 +904,8 @@ static PyObject* remmina_pref_get_scale_quality_wrapper(PyObject* self, PyObject { TRACE_CALL(__func__); - PyObject* result = PyLong_FromLong(remmina_pref_get_scale_quality()); - remmina_plugin_python_check_error(); + PyObject* result = PyLong_FromLong(python_wrapper_get_service()->pref_get_scale_quality()); + python_wrapper_check_error(); return result; } @@ -920,8 +913,8 @@ static PyObject* remmina_pref_get_sshtunnel_port_wrapper(PyObject* self, PyObjec { TRACE_CALL(__func__); - PyObject* result = PyLong_FromLong(remmina_pref_get_sshtunnel_port()); - remmina_plugin_python_check_error(); + PyObject* result = PyLong_FromLong(python_wrapper_get_service()->pref_get_sshtunnel_port()); + python_wrapper_check_error(); return result; } @@ -929,8 +922,8 @@ static PyObject* remmina_pref_get_ssh_loglevel_wrapper(PyObject* self, PyObject* { TRACE_CALL(__func__); - PyObject* result = PyLong_FromLong(remmina_pref_get_ssh_loglevel()); - remmina_plugin_python_check_error(); + PyObject* result = PyLong_FromLong(python_wrapper_get_service()->pref_get_ssh_loglevel()); + python_wrapper_check_error(); return result; } @@ -938,8 +931,8 @@ static PyObject* remmina_pref_get_ssh_parseconfig_wrapper(PyObject* self, PyObje { TRACE_CALL(__func__); - PyObject* result = PyLong_FromLong(remmina_pref_get_ssh_parseconfig()); - remmina_plugin_python_check_error(); + PyObject* result = PyLong_FromLong(python_wrapper_get_service()->pref_get_ssh_parseconfig()); + python_wrapper_check_error(); return result; } @@ -959,15 +952,15 @@ static PyObject* remmina_pref_keymap_get_keyval_wrapper(PyObject* self, PyObject if (keymap) { - const guint value = remmina_pref_keymap_get_keyval(keymap, keyval); + const guint value = python_wrapper_get_service()->pref_keymap_get_keyval(keymap, keyval); result = PyLong_FromUnsignedLong(value); } - remmina_plugin_python_check_error(); + python_wrapper_check_error(); return result; } -static PyObject* remmina_plugin_python_log_print_wrapper(PyObject* self, PyObject* args) +static PyObject* python_wrapper_log_print_wrapper(PyObject* self, PyObject* args) { TRACE_CALL(__func__); @@ -977,11 +970,11 @@ static PyObject* remmina_plugin_python_log_print_wrapper(PyObject* self, PyObjec return Py_None; } - remmina_log_print(text); + python_wrapper_get_service()->log_print(text); return Py_None; } -static PyObject* remmina_plugin_python_debug_wrapper(PyObject* self, PyObject* args) +static PyObject* python_wrapper_debug_wrapper(PyObject* self, PyObject* args) { TRACE_CALL(__func__); @@ -991,7 +984,7 @@ static PyObject* remmina_plugin_python_debug_wrapper(PyObject* self, PyObject* a return Py_None; } - remmina_plugin_manager_service._remmina_debug("python", "%s", text); + python_wrapper_get_service()->_remmina_debug("python", "%s", text); return Py_None; } @@ -1004,7 +997,7 @@ static PyObject* remmina_widget_pool_register_wrapper(PyObject* self, PyObject* if (PyArg_ParseTupleAndKeywords(args, kwargs, "O", kwlist, &widget) && widget) { - remmina_widget_pool_register(get_pywidget(widget)); + python_wrapper_get_service()->widget_pool_register(get_pywidget(widget)); } return Py_None; @@ -1020,7 +1013,7 @@ static PyObject* rcw_open_from_file_full_wrapper(PyObject* self, PyObject* args, if (PyArg_ParseTupleAndKeywords(args, kwargs, "OOO", kwlist, &pyremminafile, &data) && pyremminafile && data) { - rcw_open_from_file_full((RemminaFile*)pyremminafile, NULL, (void*)data, NULL); + python_wrapper_get_service()->rcw_open_from_file_full((RemminaFile*)pyremminafile, NULL, (void*)data, NULL); } return Py_None; @@ -1038,7 +1031,7 @@ static PyObject* remmina_public_get_server_port_wrapper(PyObject* self, PyObject { gchar* host; gint port; - remmina_public_get_server_port(server, defaultport, &host, &port); + python_wrapper_get_service()->get_server_port(server, defaultport, &host, &port); PyObject* result = PyList_New(2); PyList_Append(result, PyUnicode_FromString(host)); @@ -1053,14 +1046,14 @@ static PyObject* remmina_masterthread_exec_is_main_thread_wrapper(PyObject* self { TRACE_CALL(__func__); - return PyBool_FromLong(remmina_masterthread_exec_is_main_thread()); + return PyBool_FromLong(python_wrapper_get_service()->is_main_thread()); } static PyObject* remmina_gtksocket_available_wrapper(PyObject* self, PyObject* plugin) { TRACE_CALL(__func__); - return PyBool_FromLong(remmina_gtksocket_available()); + return PyBool_FromLong(python_wrapper_get_service()->gtksocket_available()); } static PyObject* @@ -1073,7 +1066,7 @@ remmina_protocol_widget_get_profile_remote_height_wrapper(PyObject* self, PyObje if (PyArg_ParseTupleAndKeywords(args, kwargs, "O", kwlist, &plugin) && plugin && plugin->gp) { - remmina_protocol_widget_get_profile_remote_height(plugin->gp->gp); + python_wrapper_get_service()->get_profile_remote_height(plugin->gp->gp); } return Py_None; @@ -1089,13 +1082,13 @@ remmina_protocol_widget_get_profile_remote_width_wrapper(PyObject* self, PyObjec if (PyArg_ParseTupleAndKeywords(args, kwargs, "O", kwlist, &plugin) && plugin && plugin->gp) { - remmina_protocol_widget_get_profile_remote_width(plugin->gp->gp); + python_wrapper_get_service()->get_profile_remote_width(plugin->gp->gp); } return Py_None; } -void remmina_plugin_python_to_protocol_setting(RemminaProtocolSetting* dest, PyObject* setting) +void python_wrapper_to_protocol_setting(RemminaProtocolSetting* dest, PyObject* setting) { TRACE_CALL(__func__); @@ -1107,11 +1100,11 @@ void remmina_plugin_python_to_protocol_setting(RemminaProtocolSetting* dest, PyO dest->type = src->settingType; dest->validator = NULL; dest->validator_data = NULL; - remmina_plugin_python_to_generic(src->opt1, &dest->opt1); - remmina_plugin_python_to_generic(src->opt2, &dest->opt2); + python_wrapper_to_generic(src->opt1, &dest->opt1); + python_wrapper_to_generic(src->opt2, &dest->opt2); } -void remmina_plugin_python_to_protocol_feature(RemminaProtocolFeature* dest, PyObject* feature) +void python_wrapper_to_protocol_feature(RemminaProtocolFeature* dest, PyObject* feature) { TRACE_CALL(__func__); @@ -1127,7 +1120,7 @@ void remmina_plugin_python_to_protocol_feature(RemminaProtocolFeature* dest, PyO dest->opt3_type_hint = src->opt3->type_hint; } -PyObject* remmina_plugin_python_show_dialog_wrapper(PyObject* self, PyObject* args, PyObject* kwargs) +PyObject* python_wrapper_show_dialog_wrapper(PyObject* self, PyObject* args, PyObject* kwargs) { TRACE_CALL(__func__); @@ -1141,16 +1134,16 @@ PyObject* remmina_plugin_python_show_dialog_wrapper(PyObject* self, PyObject* ar return PyLong_FromLong(-1); } - remmina_main_show_dialog(msgType, btnType, message); + python_wrapper_get_service()->show_dialog(msgType, btnType, message); return Py_None; } -PyObject* remmina_plugin_python_get_mainwindow_wrapper(PyObject* self, PyObject* args) +PyObject* python_wrapper_get_mainwindow_wrapper(PyObject* self, PyObject* args) { TRACE_CALL(__func__); - GtkWindow* result = remmina_main_get_window(); + GtkWindow* result = python_wrapper_get_service()->get_window(); if (!result) { @@ -1171,7 +1164,7 @@ static PyObject* remmina_protocol_plugin_signal_connection_closed_wrapper(PyObje return Py_None; } - remmina_plugin_manager_service.protocol_plugin_signal_connection_closed(((PyRemminaProtocolWidget*)pygp)->gp); + python_wrapper_get_service()->protocol_plugin_signal_connection_closed(((PyRemminaProtocolWidget*)pygp)->gp); return Py_None; } @@ -1199,7 +1192,7 @@ static PyObject* remmina_protocol_plugin_init_auth_wrapper(PyObject* module, PyO } else { - return Py_BuildValue("i", remmina_protocol_widget_panel_auth(self + return Py_BuildValue("i", python_wrapper_get_service()->protocol_widget_panel_auth(self ->gp, pflags, title, default_username, default_password, default_domain, password_prompt)); } } @@ -1220,6 +1213,6 @@ static PyObject* remmina_protocol_plugin_signal_connection_opened_wrapper(PyObje return Py_None; } - remmina_plugin_manager_service.protocol_plugin_signal_connection_opened(((PyRemminaProtocolWidget*)pygp)->gp); + python_wrapper_get_service()->protocol_plugin_signal_connection_opened(((PyRemminaProtocolWidget*)pygp)->gp); return Py_None; } diff --git a/src/remmina_plugin_python_remmina.h b/plugins/python_wrapper/python_wrapper_remmina.h index 25869d58a..bdad92498 100644 --- a/src/remmina_plugin_python_remmina.h +++ b/plugins/python_wrapper/python_wrapper_remmina.h @@ -32,13 +32,13 @@ */ /** - * @file remmina_plugin_python_remmina.h + * @file python_wrapper_remmina.h * * @brief Contains the implementation of the Python module 'remmina', provided to interface with the application from * the Python plugin source. * * @detail In contrast to the wrapper functions that exist in the plugin specialisation files (e.g. - * remmina_plugin_python_protocol.c or remmina_plugin_python_entry.c), this file contains the API for the + * python_wrapper_protocol.c or python_wrapper_entry.c), this file contains the API for the * communication in the direction, from Python to Remmina. This means, if in the Python plugin a function * is called, that is defined in Remmina, C code, at least in this file, is executed. */ @@ -49,7 +49,7 @@ // I N C L U D E S //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#include "remmina_plugin_python_protocol_widget.h" +#include "python_wrapper_protocol_widget.h" //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // A P I @@ -60,7 +60,7 @@ G_BEGIN_DECLS /** * Initializes the 'remmina' module in the Python engine. */ -void remmina_plugin_python_module_init(void); +void python_wrapper_module_init(void); /** * @brief Returns a pointer to the Python instance, mapped to the RemminaProtocolWidget or null if not found. @@ -71,7 +71,7 @@ void remmina_plugin_python_module_init(void); * is explicitly passed. To bridge that, this function can be used to retrieve the very plugin instance owning * the given RemminaProtocolWidget. */ -PyPlugin* remmina_plugin_python_module_get_plugin(RemminaProtocolWidget* gp); +PyPlugin* python_wrapper_module_get_plugin(RemminaProtocolWidget* gp); /** * @brief Converts the PyObject to RemminaProtocolSetting. @@ -79,7 +79,7 @@ PyPlugin* remmina_plugin_python_module_get_plugin(RemminaProtocolWidget* gp); * @param dest A target for the converted value. * @param setting The source value to convert. */ -void remmina_plugin_python_to_protocol_setting(RemminaProtocolSetting* dest, PyObject* setting); +void python_wrapper_to_protocol_setting(RemminaProtocolSetting* dest, PyObject* setting); /** * @brief Converts the PyObject to RemminaProtocolFeature. @@ -87,6 +87,6 @@ void remmina_plugin_python_to_protocol_setting(RemminaProtocolSetting* dest, PyO * @param dest A target for the converted value. * @param setting The source value to convert. */ -void remmina_plugin_python_to_protocol_feature(RemminaProtocolFeature* dest, PyObject* feature); +void python_wrapper_to_protocol_feature(RemminaProtocolFeature* dest, PyObject* feature); G_END_DECLS diff --git a/src/remmina_plugin_python_remmina_file.c b/plugins/python_wrapper/python_wrapper_remmina_file.c index 1c417129a..4b4184c47 100644 --- a/src/remmina_plugin_python_remmina_file.c +++ b/plugins/python_wrapper/python_wrapper_remmina_file.c @@ -35,10 +35,10 @@ // I N C L U D E S //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + #include "remmina/remmina_trace_calls.h" -#include "remmina_file.h" -#include "remmina_plugin_python_common.h" -#include "remmina_plugin_python_remmina_file.h" +#include "python_wrapper_common.h" +#include "python_wrapper_remmina_file.h" //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // D E C L A R A T I O N S @@ -82,12 +82,12 @@ static PyTypeObject python_remmina_file_type = { // A P I //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void remmina_plugin_python_remmina_init_types(void) +void python_wrapper_remmina_init_types(void) { PyType_Ready(&python_remmina_file_type); } -PyRemminaFile* remmina_plugin_python_remmina_file_to_python(RemminaFile* file) +PyRemminaFile* python_wrapper_remmina_file_to_python(RemminaFile* file) { TRACE_CALL(__func__); @@ -101,7 +101,7 @@ static PyObject* file_get_path(PyRemminaFile* self, PyObject* args) { TRACE_CALL(__func__); - return Py_BuildValue("s", remmina_file_get_filename(self->file)); + return Py_BuildValue("s", python_wrapper_get_service()->file_get_path(self->file)); } static PyObject* file_set_setting(PyRemminaFile* self, PyObject* args, PyObject* kwds) @@ -116,11 +116,11 @@ static PyObject* file_set_setting(PyRemminaFile* self, PyObject* args, PyObject* { if (PyUnicode_Check(value)) { - remmina_file_set_string(self->file, key, PyUnicode_AsUTF8(value)); + python_wrapper_get_service()->file_set_string(self->file, key, PyUnicode_AsUTF8(value)); } else if (PyLong_Check(value)) { - remmina_file_set_int(self->file, key, PyLong_AsLong(value)); + python_wrapper_get_service()->file_set_int(self->file, key, PyLong_AsLong(value)); } else { @@ -148,15 +148,15 @@ static PyObject* file_get_setting(PyRemminaFile* self, PyObject* args, PyObject* { if (PyUnicode_Check(def)) { - return Py_BuildValue("s", remmina_file_get_string(self->file, key)); + return Py_BuildValue("s", python_wrapper_get_service()->file_get_string(self->file, key)); } else if (PyBool_Check(def)) { - return remmina_file_get_int(self->file, key, (gint)PyLong_AsLong(def)) ? Py_True : Py_False; + return python_wrapper_get_service()->file_get_int(self->file, key, (gint)PyLong_AsLong(def)) ? Py_True : Py_False; } else if (PyLong_Check(def)) { - return Py_BuildValue("i", remmina_file_get_int(self->file, key, (gint)PyLong_AsLong(def))); + return Py_BuildValue("i", python_wrapper_get_service()->file_get_int(self->file, key, (gint)PyLong_AsLong(def))); } else { @@ -178,7 +178,7 @@ static PyObject* file_get_secret(PyRemminaFile* self, PyObject* key) if (key && PyUnicode_Check(key)) { - return Py_BuildValue("s", remmina_file_get_secret(self->file, PyUnicode_AsUTF8(key))); + return Py_BuildValue("s", python_wrapper_get_service()->file_get_secret(self->file, PyUnicode_AsUTF8(key))); } else { @@ -194,7 +194,7 @@ static PyObject* file_unsave_passwords(PyRemminaFile* self, PyObject* args) if (self) { - remmina_file_unsave_passwords(self->file); + python_wrapper_get_service()->file_unsave_passwords(self->file); return Py_None; } else diff --git a/src/remmina_plugin_python_remmina_file.h b/plugins/python_wrapper/python_wrapper_remmina_file.h index a2e7a53d3..437973be6 100644 --- a/src/remmina_plugin_python_remmina_file.h +++ b/plugins/python_wrapper/python_wrapper_remmina_file.h @@ -33,7 +33,7 @@ /** - * @file remmina_plugin_python_protocol.h + * @file python_wrapper_protocol.h * * @brief Contains the implementation of the Python type remmina.RemminaFile. */ @@ -53,9 +53,9 @@ typedef struct RemminaFile* file; } PyRemminaFile; -void remmina_plugin_python_remmina_init_types(void); +void python_wrapper_remmina_init_types(void); /** * Converts the instance of RemminaFile to a Python object that can be passed to the Python engine. */ -PyRemminaFile* remmina_plugin_python_remmina_file_to_python(RemminaFile* file); +PyRemminaFile* python_wrapper_remmina_file_to_python(RemminaFile* file); diff --git a/src/remmina_plugin_python_secret.c b/plugins/python_wrapper/python_wrapper_secret.c index be659fdbb..1f341764c 100644 --- a/src/remmina_plugin_python_secret.c +++ b/plugins/python_wrapper/python_wrapper_secret.c @@ -35,86 +35,86 @@ // I N L U C E S //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#include "remmina_plugin_python_common.h" -#include "remmina_plugin_python_secret.h" -#include "remmina_plugin_python_remmina_file.h" +#include "python_wrapper_common.h" +#include "python_wrapper_secret.h" +#include "python_wrapper_remmina_file.h" //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // A P I //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void remmina_plugin_python_secret_init(void) +void python_wrapper_secret_init(void) { TRACE_CALL(__func__); } -gboolean remmina_plugin_python_secret_init_wrapper(RemminaSecretPlugin* instance) +gboolean python_wrapper_secret_init_wrapper(RemminaSecretPlugin* instance) { TRACE_CALL(__func__); - PyPlugin* plugin = remmina_plugin_python_get_plugin(instance->name); + PyPlugin* plugin = python_wrapper_get_plugin(instance->name); PyObject* result = CallPythonMethod(plugin->instance, "init", NULL); return result == Py_None || result != Py_False; } -gboolean remmina_plugin_python_secret_is_service_available_wrapper(RemminaSecretPlugin* instance) +gboolean python_wrapper_secret_is_service_available_wrapper(RemminaSecretPlugin* instance) { TRACE_CALL(__func__); - PyPlugin* plugin = remmina_plugin_python_get_plugin(instance->name); + PyPlugin* plugin = python_wrapper_get_plugin(instance->name); PyObject* result = CallPythonMethod(plugin->instance, "is_service_available", NULL); return result == Py_None || result != Py_False; } void -remmina_plugin_python_secret_store_password_wrapper(RemminaSecretPlugin* instance, RemminaFile* file, const gchar* key, const gchar* password) +python_wrapper_secret_store_password_wrapper(RemminaSecretPlugin* instance, RemminaFile* file, const gchar* key, const gchar* password) { TRACE_CALL(__func__); - PyPlugin* plugin = remmina_plugin_python_get_plugin(instance->name); + PyPlugin* plugin = python_wrapper_get_plugin(instance->name); CallPythonMethod(plugin - ->instance, "store_password", "Oss", (PyObject*)remmina_plugin_python_remmina_file_to_python(file), key, password); + ->instance, "store_password", "Oss", (PyObject*)python_wrapper_remmina_file_to_python(file), key, password); } gchar* -remmina_plugin_python_secret_get_password_wrapper(RemminaSecretPlugin* instance, RemminaFile* file, const gchar* key) +python_wrapper_secret_get_password_wrapper(RemminaSecretPlugin* instance, RemminaFile* file, const gchar* key) { TRACE_CALL(__func__); - PyPlugin* plugin = remmina_plugin_python_get_plugin(instance->name); + PyPlugin* plugin = python_wrapper_get_plugin(instance->name); PyObject* result = CallPythonMethod(plugin - ->instance, "get_password", "Os", (PyObject*)remmina_plugin_python_remmina_file_to_python(file), key); + ->instance, "get_password", "Os", (PyObject*)python_wrapper_remmina_file_to_python(file), key); Py_ssize_t len = PyUnicode_GetLength(result); if (len == 0) { return NULL; } - return remmina_plugin_python_copy_string_from_python(result, len); + return python_wrapper_copy_string_from_python(result, len); } void -remmina_plugin_python_secret_delete_password_wrapper(RemminaSecretPlugin* instance, RemminaFile* file, const gchar* key) +python_wrapper_secret_delete_password_wrapper(RemminaSecretPlugin* instance, RemminaFile* file, const gchar* key) { TRACE_CALL(__func__); - PyPlugin* plugin = remmina_plugin_python_get_plugin(instance->name); + PyPlugin* plugin = python_wrapper_get_plugin(instance->name); CallPythonMethod(plugin - ->instance, "delete_password", "Os", (PyObject*)remmina_plugin_python_remmina_file_to_python(file), key); + ->instance, "delete_password", "Os", (PyObject*)python_wrapper_remmina_file_to_python(file), key); } -RemminaPlugin* remmina_plugin_python_create_secret_plugin(PyPlugin* plugin) +RemminaPlugin* python_wrapper_create_secret_plugin(PyPlugin* plugin) { TRACE_CALL(__func__); PyObject* instance = plugin->instance; - if (!remmina_plugin_python_check_attribute(instance, ATTR_NAME)) + if (!python_wrapper_check_attribute(instance, ATTR_NAME)) { return NULL; } - RemminaSecretPlugin* remmina_plugin = (RemminaSecretPlugin*)remmina_plugin_python_malloc(sizeof(RemminaSecretPlugin)); + RemminaSecretPlugin* remmina_plugin = (RemminaSecretPlugin*)python_wrapper_malloc(sizeof(RemminaSecretPlugin)); remmina_plugin->type = REMMINA_PLUGIN_TYPE_SECRET; remmina_plugin->domain = GETTEXT_PACKAGE; @@ -123,16 +123,16 @@ RemminaPlugin* remmina_plugin_python_create_secret_plugin(PyPlugin* plugin) remmina_plugin->description = PyUnicode_AsUTF8(PyObject_GetAttrString(instance, ATTR_DESCRIPTION)); remmina_plugin->init_order = PyLong_AsLong(PyObject_GetAttrString(instance, ATTR_INIT_ORDER)); - remmina_plugin->init = remmina_plugin_python_secret_init_wrapper; - remmina_plugin->is_service_available = remmina_plugin_python_secret_is_service_available_wrapper; - remmina_plugin->store_password = remmina_plugin_python_secret_store_password_wrapper; - remmina_plugin->get_password = remmina_plugin_python_secret_get_password_wrapper; - remmina_plugin->delete_password = remmina_plugin_python_secret_delete_password_wrapper; + remmina_plugin->init = python_wrapper_secret_init_wrapper; + remmina_plugin->is_service_available = python_wrapper_secret_is_service_available_wrapper; + remmina_plugin->store_password = python_wrapper_secret_store_password_wrapper; + remmina_plugin->get_password = python_wrapper_secret_get_password_wrapper; + remmina_plugin->delete_password = python_wrapper_secret_delete_password_wrapper; plugin->secret_plugin = remmina_plugin; plugin->generic_plugin = (RemminaPlugin*)remmina_plugin; - remmina_plugin_python_add_plugin(plugin); + python_wrapper_add_plugin(plugin); return (RemminaPlugin*)remmina_plugin; }
\ No newline at end of file diff --git a/src/remmina_plugin_python_secret.h b/plugins/python_wrapper/python_wrapper_secret.h index c627d2a49..192bd05fe 100644 --- a/src/remmina_plugin_python_secret.h +++ b/plugins/python_wrapper/python_wrapper_secret.h @@ -32,7 +32,7 @@ */ /** - * @file remmina_plugin_python_entry.h + * @file python_wrapper_entry.h * * @brief Contains the specialisation of RemminaPluginEntry plugins in Python. */ @@ -54,7 +54,7 @@ G_BEGIN_DECLS /** * Initializes the Python plugin specialisation for secret plugins. */ -void remmina_plugin_python_secret_init(void); +void python_wrapper_secret_init(void); /** * @brief Creates a new instance of the RemminaPluginSecret, initializes its members and references the wrapper @@ -62,6 +62,6 @@ void remmina_plugin_python_secret_init(void); * @param instance The instance of the Python plugin. * @return Returns a new instance of the RemminaPlugin (must be freed!). */ -RemminaPlugin* remmina_plugin_python_create_secret_plugin(PyPlugin* instance); +RemminaPlugin* python_wrapper_create_secret_plugin(PyPlugin* instance); G_END_DECLS diff --git a/src/remmina_plugin_python_tool.c b/plugins/python_wrapper/python_wrapper_tool.c index a951291f2..db721b65c 100644 --- a/src/remmina_plugin_python_tool.c +++ b/plugins/python_wrapper/python_wrapper_tool.c @@ -35,50 +35,50 @@ // I N L U C E S //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#include "remmina_plugin_python_common.h" -#include "remmina_plugin_python_tool.h" +#include "python_wrapper_common.h" +#include "python_wrapper_tool.h" //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // A P I //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void remmina_plugin_python_tool_init(void) +void python_wrapper_tool_init(void) { TRACE_CALL(__func__); } -void remmina_plugin_python_tool_exec_func_wrapper(GtkMenuItem* self, RemminaToolPlugin* instance) +void python_wrapper_tool_exec_func_wrapper(GtkMenuItem* self, RemminaToolPlugin* instance) { TRACE_CALL(__func__); - PyPlugin* plugin = remmina_plugin_python_get_plugin(instance->name); + PyPlugin* plugin = python_wrapper_get_plugin(instance->name); CallPythonMethod(plugin->instance, "exec_func", NULL); } -RemminaPlugin* remmina_plugin_python_create_tool_plugin(PyPlugin* plugin) +RemminaPlugin* python_wrapper_create_tool_plugin(PyPlugin* plugin) { TRACE_CALL(__func__); PyObject* instance = plugin->instance; - if (!remmina_plugin_python_check_attribute(instance, ATTR_NAME)) + if (!python_wrapper_check_attribute(instance, ATTR_NAME)) { return NULL; } - RemminaToolPlugin* remmina_plugin = (RemminaToolPlugin*)remmina_plugin_python_malloc(sizeof(RemminaToolPlugin)); + RemminaToolPlugin* remmina_plugin = (RemminaToolPlugin*)python_wrapper_malloc(sizeof(RemminaToolPlugin)); remmina_plugin->type = REMMINA_PLUGIN_TYPE_TOOL; remmina_plugin->domain = GETTEXT_PACKAGE; remmina_plugin->name = PyUnicode_AsUTF8(PyObject_GetAttrString(instance, ATTR_NAME)); remmina_plugin->version = PyUnicode_AsUTF8(PyObject_GetAttrString(instance, ATTR_VERSION)); remmina_plugin->description = PyUnicode_AsUTF8(PyObject_GetAttrString(instance, ATTR_DESCRIPTION)); - remmina_plugin->exec_func = remmina_plugin_python_tool_exec_func_wrapper; + remmina_plugin->exec_func = python_wrapper_tool_exec_func_wrapper; plugin->tool_plugin = remmina_plugin; plugin->generic_plugin = (RemminaPlugin*)remmina_plugin; - remmina_plugin_python_add_plugin(plugin); + python_wrapper_add_plugin(plugin); return (RemminaPlugin*)remmina_plugin; } diff --git a/src/remmina_plugin_python_tool.h b/plugins/python_wrapper/python_wrapper_tool.h index 08852bdc4..eba1857b1 100644 --- a/src/remmina_plugin_python_tool.h +++ b/plugins/python_wrapper/python_wrapper_tool.h @@ -32,7 +32,7 @@ */ /** - * @file remmina_plugin_python_entry.h + * @file python_wrapper_entry.h * * @brief Contains the specialisation of RemminaPluginEntry plugins in Python. */ @@ -54,7 +54,7 @@ G_BEGIN_DECLS /** * Initializes the Python plugin specialisation for tool plugins. */ -void remmina_plugin_python_tool_init(void); +void python_wrapper_tool_init(void); /** * @brief Creates a new instance of the RemminaPluginTool, initializes its members and references the wrapper @@ -62,7 +62,7 @@ void remmina_plugin_python_tool_init(void); * @param instance The instance of the Python plugin. * @return Returns a new instance of the RemminaPlugin (must be freed!). */ -RemminaPlugin* remmina_plugin_python_create_tool_plugin(PyPlugin* instance); +RemminaPlugin* python_wrapper_create_tool_plugin(PyPlugin* instance); G_END_DECLS diff --git a/plugins/rdp/rdp_file.c b/plugins/rdp/rdp_file.c index e86740df0..f2578509d 100644 --- a/plugins/rdp/rdp_file.c +++ b/plugins/rdp/rdp_file.c @@ -35,10 +35,11 @@ */ #include "common/remmina_plugin.h" +#include "remmina/plugin.h" #include "rdp_plugin.h" #include "rdp_file.h" -gboolean remmina_rdp_file_import_test(const gchar *from_file) +gboolean remmina_rdp_file_import_test(RemminaFilePlugin *plugin, const gchar *from_file) { TRACE_CALL(__func__); gchar *ext; @@ -182,7 +183,7 @@ static RemminaFile *remmina_rdp_file_import_channel(GIOChannel *channel) return remminafile; } -RemminaFile *remmina_rdp_file_import(const gchar *from_file) +RemminaFile *remmina_rdp_file_import(RemminaFilePlugin *plugin,const gchar *from_file) { TRACE_CALL(__func__); GIOChannel *channel; @@ -202,7 +203,7 @@ RemminaFile *remmina_rdp_file_import(const gchar *from_file) return remminafile; } -gboolean remmina_rdp_file_export_test(RemminaFile *remminafile) +gboolean remmina_rdp_file_export_test(RemminaFilePlugin *plugin, RemminaFile *remminafile) { TRACE_CALL(__func__); if (g_strcmp0(remmina_plugin_service->file_get_string(remminafile, "protocol"), "RDP") == 0) @@ -279,7 +280,7 @@ gboolean remmina_rdp_file_export_channel(RemminaFile *remminafile, FILE *fp) return TRUE; } -gboolean remmina_rdp_file_export(RemminaFile *remminafile, const gchar *to_file) +gboolean remmina_rdp_file_export(RemminaFilePlugin *plugin, RemminaFile *remminafile, const gchar *to_file) { TRACE_CALL(__func__); FILE *fp; diff --git a/plugins/rdp/rdp_file.h b/plugins/rdp/rdp_file.h index 795da65ba..f02cb8dce 100644 --- a/plugins/rdp/rdp_file.h +++ b/plugins/rdp/rdp_file.h @@ -37,9 +37,9 @@ G_BEGIN_DECLS -gboolean remmina_rdp_file_import_test(const gchar *from_file); -RemminaFile *remmina_rdp_file_import(const gchar *from_file); -gboolean remmina_rdp_file_export_test(RemminaFile *remminafile); -gboolean remmina_rdp_file_export(RemminaFile *remminafile, const gchar *to_file); +gboolean remmina_rdp_file_import_test(RemminaFilePlugin *plugin, const gchar *from_file); +RemminaFile *remmina_rdp_file_import(RemminaFilePlugin *plugin, const gchar *from_file); +gboolean remmina_rdp_file_export_test(RemminaFilePlugin *plugin, RemminaFile *remminafile); +gboolean remmina_rdp_file_export(RemminaFilePlugin *plugin, RemminaFile *remminafile, const gchar *to_file); G_END_DECLS diff --git a/plugins/rdp/rdp_plugin.c b/plugins/rdp/rdp_plugin.c index a01e4cc68..88f8f936c 100644 --- a/plugins/rdp/rdp_plugin.c +++ b/plugins/rdp/rdp_plugin.c @@ -37,6 +37,7 @@ #define _GNU_SOURCE +#include "remmina/plugin.h" #include "rdp_plugin.h" #include "rdp_event.h" #include "rdp_graphics.h" diff --git a/plugins/rdp/rdp_settings.c b/plugins/rdp/rdp_settings.c index 41b3cc105..18d685443 100644 --- a/plugins/rdp/rdp_settings.c +++ b/plugins/rdp/rdp_settings.c @@ -695,7 +695,7 @@ static void remmina_rdp_settings_grid_init(RemminaPluginRdpsetGrid *grid) } -GtkWidget *remmina_rdp_settings_new(void) +GtkWidget *remmina_rdp_settings_new(RemminaPrefPlugin* plugin) { TRACE_CALL(__func__); GtkWidget *widget; diff --git a/plugins/rdp/rdp_settings.h b/plugins/rdp/rdp_settings.h index 93e388238..2f3a08faf 100644 --- a/plugins/rdp/rdp_settings.h +++ b/plugins/rdp/rdp_settings.h @@ -39,7 +39,7 @@ G_BEGIN_DECLS void remmina_rdp_settings_init(void); guint remmina_rdp_settings_get_keyboard_layout(void); -GtkWidget *remmina_rdp_settings_new(void); +GtkWidget *remmina_rdp_settings_new(RemminaPrefPlugin* plugin); void remmina_rdp_settings_get_orientation_scale_prefs(int *desktopOrientation, int *desktopScaleFactor, int *deviceScaleFactor); diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index c9d0133b2..71a0dac00 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -191,6 +191,7 @@ parts: - libvte-2.91-dev - libwebkit2gtk-4.0-dev - libxkbfile-dev + - python3-dev - pyhoca-cli - xdg-utils stage-packages: @@ -229,6 +230,7 @@ parts: - -DWITH_KF5WALLET=ON - -DWITH_GVNC=ON - -DWITH_X2GO=ON + - -DWITH_PYTHON=ON - -DCMAKE_PREFIX_PATH=$SNAPCRAFT_STAGE/usr - -DSNAP_BUILD=on diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a743f5d9a..8d7ddadbb 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -141,50 +141,6 @@ set(RESOURCE_LIST ${CMAKE_CURRENT_SOURCE_DIR}/../data/ui/remmina_spinner.glade ${CMAKE_CURRENT_SOURCE_DIR}/../data/ui/remmina_string_list.glade ${CMAKE_CURRENT_SOURCE_DIR}/../data/ui/remmina_unlock.glade) - -option(WITH_PYTHONLIBS "Enable Python plugins support" OFF) -if(WITH_PYTHONLIBS) - message(STATUS "Python plugins support enabled") - find_suggested_package(PythonLibs) - if(PythonLibs_FOUND) - message(STATUS "Python libs found, Python support enabled") - add_definitions(-DWITH_PYTHONLIBS) - list(FIND REMMINA_SRCS "remmina_exec.c" SRCINDEX) - message(DEBUG "remmina_exec.c found at index: " ${SRCINDEX}) - # Index calculated at "remmina_exec.c" position (43 as of today) - list( - INSERT - REMMINA_SRCS - ${SRCINDEX} - "remmina_plugin_python.c" - "remmina_plugin_python.h" - "remmina_plugin_python_protocol.c" - "remmina_plugin_python_protocol.h" - "remmina_plugin_python_entry.c" - "remmina_plugin_python_entry.h" - "remmina_plugin_python_file.c" - "remmina_plugin_python_file.h" - "remmina_plugin_python_secret.c" - "remmina_plugin_python_secret.h" - "remmina_plugin_python_tool.c" - "remmina_plugin_python_tool.h" - "remmina_plugin_python_pref.c" - "remmina_plugin_python_pref.h" - "remmina_plugin_python_common.c" - "remmina_plugin_python_common.h" - "remmina_plugin_python_remmina.c" - "remmina_plugin_python_remmina.h" - "remmina_plugin_python_protocol_widget.c" - "remmina_plugin_python_protocol_widget.h" - "remmina_plugin_python_remmina_file.c" - "remmina_plugin_python_remmina_file.h") - else() - message(STATUS "Python plugins support enabled, but Python libs not found") - endif() -else() - message(STATUS "Python plugins support disabled") -endif() - message(DEBUG "Source list set to: " ${REMMINA_SRCS}) compile_gresources( diff --git a/src/include/remmina/plugin.h b/src/include/remmina/plugin.h index c75289af8..5f5b92e71 100644 --- a/src/include/remmina/plugin.h +++ b/src/include/remmina/plugin.h @@ -36,6 +36,7 @@ #pragma once +#include <gtk/gtk.h> #include <stdarg.h> #include <remmina/types.h> #include "remmina/remmina_trace_calls.h" @@ -48,7 +49,8 @@ typedef enum { REMMINA_PLUGIN_TYPE_FILE = 2, REMMINA_PLUGIN_TYPE_TOOL = 3, REMMINA_PLUGIN_TYPE_PREF = 4, - REMMINA_PLUGIN_TYPE_SECRET = 5 + REMMINA_PLUGIN_TYPE_SECRET = 5, + REMMINA_PLUGIN_TYPE_LANGUAGE_WRAPPER = 6 } RemminaPluginType; typedef struct _RemminaPlugin { @@ -145,6 +147,18 @@ typedef struct _RemminaSecretPlugin { void (*delete_password)(struct _RemminaSecretPlugin* instance, RemminaFile *remminafile, const gchar *key); } RemminaSecretPlugin; +typedef struct _RemminaLanguageWrapperPlugin { + RemminaPluginType type; + const gchar * name; + const gchar * description; + const gchar * domain; + const gchar * version; + const gchar ** supported_extentions; + + gboolean (*init)(struct _RemminaLanguageWrapperPlugin* instance); + gboolean (*load)(struct _RemminaLanguageWrapperPlugin* instance, const gchar* plugin_file); +} RemminaLanguageWrapperPlugin; + /* Plugin Service is a struct containing a list of function pointers, * which is passed from Remmina main program to the plugin module * through the plugin entry function remmina_plugin_entry() */ @@ -236,6 +250,56 @@ typedef struct _RemminaPluginService { gboolean (*gtksocket_available)(void); gint (*get_profile_remote_width)(RemminaProtocolWidget *gp); gint (*get_profile_remote_height)(RemminaProtocolWidget *gp); + const gchar*(*protocol_widget_get_name)(RemminaProtocolWidget *gp); + gint(*protocol_widget_get_width)(RemminaProtocolWidget *gp); + gint(*protocol_widget_get_height)(RemminaProtocolWidget *gp); + void(*protocol_widget_set_width)(RemminaProtocolWidget *gp, gint width); + void(*protocol_widget_set_height)(RemminaProtocolWidget *gp, gint height); + RemminaScaleMode(*protocol_widget_get_current_scale_mode)(RemminaProtocolWidget *gp); + gboolean (*protocol_widget_get_expand)(RemminaProtocolWidget *gp); + void (*protocol_widget_set_expand)(RemminaProtocolWidget *gp, gboolean expand); + void (*protocol_widget_set_error)(RemminaProtocolWidget *gp, const gchar *fmt, ...); + gboolean (*protocol_widget_has_error)(RemminaProtocolWidget *gp); + GtkWidget *(*protocol_widget_gtkviewport)(RemminaProtocolWidget *gp); + gboolean (*protocol_widget_is_closed)(RemminaProtocolWidget *gp); + RemminaFile *(*protocol_widget_get_file)(RemminaProtocolWidget *gp); + gint (*protocol_widget_panel_auth)(RemminaProtocolWidget *gp, RemminaMessagePanelFlags pflags, + const gchar *title, const gchar *default_username, const gchar *default_password, const gchar *default_domain, const gchar *password_prompt); + void (*protocol_widget_register_hostkey)(RemminaProtocolWidget *gp, GtkWidget *widget); + gchar *(*protocol_widget_start_direct_tunnel)(RemminaProtocolWidget *gp, gint default_port, gboolean port_plus); + gboolean (*protocol_widget_start_reverse_tunnel)(RemminaProtocolWidget *gp, gint local_port); + void (*protocol_widget_send_keys_signals)(GtkWidget *widget, const guint *keyvals, int keyvals_length, GdkEventType action); + void (*protocol_widget_chat_receive)(RemminaProtocolWidget *gp, const gchar *text); + void (*protocol_widget_panel_hide)(RemminaProtocolWidget *gp); + void (*protocol_widget_chat_open)(RemminaProtocolWidget *gp, const gchar *name, + void (*on_send)(RemminaProtocolWidget *gp, const gchar *text), void (*on_destroy)(RemminaProtocolWidget *gp)); + gboolean (*protocol_widget_ssh_exec)(RemminaProtocolWidget *gp, gboolean wait, const gchar *fmt, ...); + void (*protocol_widget_panel_show)(RemminaProtocolWidget *gp); + void (*protocol_widget_panel_show_retry)(RemminaProtocolWidget *gp); + gboolean (*protocol_widget_start_xport_tunnel)(RemminaProtocolWidget *gp, RemminaXPortTunnelInitFunc init_func); + void (*protocol_widget_set_display)(RemminaProtocolWidget *gp, gint display); + void (*protocol_widget_signal_connection_closed)(RemminaProtocolWidget *gp); + void (*protocol_widget_signal_connection_opened)(RemminaProtocolWidget *gp); + void (*protocol_widget_update_align)(RemminaProtocolWidget *gp); + void (*protocol_widget_unlock_dynres)(RemminaProtocolWidget *gp); + void (*protocol_widget_desktop_resize)(RemminaProtocolWidget *gp); + gint (*protocol_widget_panel_new_certificate)(RemminaProtocolWidget *gp, const gchar *subject, const gchar *issuer, const gchar *fingerprint); + gint (*protocol_widget_panel_changed_certificate)(RemminaProtocolWidget *gp, const gchar *subject, const gchar *issuer, const gchar *new_fingerprint, const gchar *old_fingerprint); + gchar *(*protocol_widget_get_username)(RemminaProtocolWidget *gp); + gchar *(*protocol_widget_get_password)(RemminaProtocolWidget *gp); + gchar *(*protocol_widget_get_domain)(RemminaProtocolWidget *gp); + gboolean (*protocol_widget_get_savepassword)(RemminaProtocolWidget *gp); + gint (*protocol_widget_panel_authx509)(RemminaProtocolWidget *gp); + gchar *(*protocol_widget_get_cacert)(RemminaProtocolWidget *gp); + gchar *(*protocol_widget_get_cacrl)(RemminaProtocolWidget *gp); + gchar *(*protocol_widget_get_clientcert)(RemminaProtocolWidget *gp); + gchar *(*protocol_widget_get_clientkey)(RemminaProtocolWidget *gp); + void (*protocol_widget_save_cred)(RemminaProtocolWidget *gp); + void (*protocol_widget_panel_show_listen)(RemminaProtocolWidget *gp, gint port); + void (*widget_pool_register)(GtkWidget *widget); + GtkWidget *(*rcw_open_from_file_full)(RemminaFile *remminafile, GCallback disconnect_cb, gpointer data, guint *handler); + void (*show_dialog)(GtkMessageType msg, GtkButtonsType buttons, const gchar* message); + GtkWindow *(*get_window)(void); } RemminaPluginService; /* "Prototype" of the plugin entry function */ diff --git a/src/remmina_plugin_manager.c b/src/remmina_plugin_manager.c index f61f236d4..98189a6eb 100644 --- a/src/remmina_plugin_manager.c +++ b/src/remmina_plugin_manager.c @@ -46,6 +46,7 @@ #include <gdk/gdkx.h> #include "remmina_public.h" +#include "remmina_main.h" #include "remmina_file_manager.h" #include "remmina_pref.h" #include "remmina_protocol_widget.h" @@ -54,9 +55,6 @@ #include "rcw.h" #include "remmina_plugin_manager.h" #include "remmina_plugin_native.h" -#ifdef WITH_PYTHONLIBS -#include "remmina_plugin_python.h" -#endif #include "remmina_public.h" #include "remmina_masterthread_exec.h" #include "remmina/remmina_trace_calls.h" @@ -70,7 +68,7 @@ static GHashTable *encrypted_settings_cache = NULL; static RemminaSecretPlugin *remmina_secret_plugin = NULL; static const gchar *remmina_plugin_type_name[] = -{ N_("Protocol"), N_("Entry"), N_("File"), N_("Tool"), N_("Preference"), N_("Secret"), NULL }; +{ N_("Protocol"), N_("Entry"), N_("File"), N_("Tool"), N_("Preference"), N_("Secret"), N_("Language Wrapper"), NULL }; static gint remmina_plugin_manager_compare_func(RemminaPlugin **a, RemminaPlugin **b) { @@ -257,7 +255,55 @@ RemminaPluginService remmina_plugin_manager_service = remmina_masterthread_exec_is_main_thread, remmina_gtksocket_available, remmina_protocol_widget_get_profile_remote_width, - remmina_protocol_widget_get_profile_remote_height + remmina_protocol_widget_get_profile_remote_height, + remmina_protocol_widget_get_name, + remmina_protocol_widget_get_width, + remmina_protocol_widget_get_height, + remmina_protocol_widget_set_width, + remmina_protocol_widget_set_height, + remmina_protocol_widget_get_current_scale_mode, + remmina_protocol_widget_get_expand, + remmina_protocol_widget_set_expand, + remmina_protocol_widget_set_error, + remmina_protocol_widget_has_error, + remmina_protocol_widget_gtkviewport, + remmina_protocol_widget_is_closed, + remmina_protocol_widget_get_file, + remmina_protocol_widget_panel_auth, + remmina_protocol_widget_register_hostkey, + remmina_protocol_widget_start_direct_tunnel, + remmina_protocol_widget_start_reverse_tunnel, + remmina_protocol_widget_send_keys_signals, + remmina_protocol_widget_chat_receive, + remmina_protocol_widget_panel_hide, + remmina_protocol_widget_chat_open, + remmina_protocol_widget_ssh_exec, + remmina_protocol_widget_panel_show, + remmina_protocol_widget_panel_show_retry, + remmina_protocol_widget_start_xport_tunnel, + remmina_protocol_widget_set_display, + remmina_protocol_widget_signal_connection_closed, + remmina_protocol_widget_signal_connection_opened, + remmina_protocol_widget_update_align, + remmina_protocol_widget_unlock_dynres, + remmina_protocol_widget_desktop_resize, + remmina_protocol_widget_panel_new_certificate, + remmina_protocol_widget_panel_changed_certificate, + remmina_protocol_widget_get_username, + remmina_protocol_widget_get_password, + remmina_protocol_widget_get_domain, + remmina_protocol_widget_get_savepassword, + remmina_protocol_widget_panel_authx509, + remmina_protocol_widget_get_cacert, + remmina_protocol_widget_get_cacrl, + remmina_protocol_widget_get_clientcert, + remmina_protocol_widget_get_clientkey, + remmina_protocol_widget_save_cred, + remmina_protocol_widget_panel_show_listen, + remmina_widget_pool_register, + rcw_open_from_file_full, + remmina_main_show_dialog, + remmina_main_get_window, }; const char *get_filename_ext(const char *filename) { @@ -267,23 +313,6 @@ const char *get_filename_ext(const char *filename) { return dot + 1; } -static void remmina_plugin_manager_load_plugin(const gchar *name) -{ - const char* ext = get_filename_ext(name); - - if (g_str_equal(G_MODULE_SUFFIX, ext)) { - remmina_plugin_native_load(&remmina_plugin_manager_service, name); - } else if (g_str_equal("py", ext)) { -#ifdef WITH_PYTHONLIBS - remmina_plugin_python_load(&remmina_plugin_manager_service, name); -#else - REMMINA_DEBUG("Python support not compiled, cannot load Python plugins"); -#endif - } else { - g_print("%s: Skip unsupported file type '%s'\n", name, ext); - } -} - static gint compare_secret_plugin_init_order(gconstpointer a, gconstpointer b) { RemminaSecretPlugin *sa, *sb; @@ -306,14 +335,13 @@ void remmina_plugin_manager_init() gchar *fullpath; RemminaPlugin *plugin; RemminaSecretPlugin *sp; - int i; + int i, j; GSList *secret_plugins; GSList *sple; + GPtrArray *alternative_language_plugins; remmina_plugin_table = g_ptr_array_new(); -#ifdef WITH_PYTHONLIBS - remmina_plugin_python_init(); -#endif + alternative_language_plugins = g_ptr_array_new(); if (!g_module_supported()) { g_print("Dynamic loading of plugins is not supported on this platform!\n"); @@ -329,14 +357,46 @@ void remmina_plugin_manager_init() if ((ptr = strrchr(name, '.')) == NULL) continue; ptr++; - if (!remmina_plugin_manager_loader_supported(ptr)) - continue; fullpath = g_strdup_printf(REMMINA_RUNTIME_PLUGINDIR "/%s", name); - remmina_plugin_manager_load_plugin(fullpath); + if (!remmina_plugin_manager_loader_supported(ptr)) { + g_ptr_array_add(alternative_language_plugins, g_strdup_printf(REMMINA_RUNTIME_PLUGINDIR "/%s", name)); + continue; + } + remmina_plugin_native_load(&remmina_plugin_manager_service, fullpath); g_free(fullpath); } g_dir_close(dir); + while (alternative_language_plugins->len > 0) { + gboolean has_loaded = FALSE; + gchar* name = (gchar*)g_ptr_array_remove_index(alternative_language_plugins, 0); + const gchar* ext = get_filename_ext(name); + + for (j = 0; j < remmina_plugin_table->len && !has_loaded; j++) { + plugin = (RemminaPlugin*)g_ptr_array_index(remmina_plugin_table, j); + if (plugin->type == REMMINA_PLUGIN_TYPE_LANGUAGE_WRAPPER) { + RemminaLanguageWrapperPlugin* wrapper_plugin = (RemminaLanguageWrapperPlugin*)plugin; + const gchar** supported_extention = wrapper_plugin->supported_extentions; + while (*supported_extention) { + if (g_str_equal(*supported_extention, ext)) { + has_loaded = wrapper_plugin->load(wrapper_plugin, name); + if (has_loaded) { + break; + } + } + supported_extention++; + } + if (has_loaded) break; + } + } + + if (!has_loaded) { + g_print("%s: Skip unsupported file type '%s'\n", name, ext); + } + + g_free(name); + } + /* Now all secret plugins needs to initialize, following their init_order. * The 1st plugin which will initialize correctly will be * the default remmina_secret_plugin */ @@ -369,7 +429,7 @@ void remmina_plugin_manager_init() gboolean remmina_plugin_manager_loader_supported(const char *filetype) { TRACE_CALL(__func__); - return g_str_equal("py", filetype) || g_str_equal(G_MODULE_SUFFIX, filetype); + return g_str_equal(G_MODULE_SUFFIX, filetype); } RemminaPlugin* remmina_plugin_manager_get_plugin(RemminaPluginType type, const gchar *name) diff --git a/src/remmina_protocol_widget.c b/src/remmina_protocol_widget.c index 9703d4cc5..5db892820 100644 --- a/src/remmina_protocol_widget.c +++ b/src/remmina_protocol_widget.c @@ -1372,6 +1372,11 @@ gint remmina_protocol_widget_get_profile_remote_height(RemminaProtocolWidget *gp return gp->priv->profile_remote_height; } +const gchar* remmina_protocol_widget_get_name(RemminaProtocolWidget *gp) +{ + TRACE_CALL(__func__); + return gp ? gp->plugin ? gp->plugin->name : NULL : NULL; +} gint remmina_protocol_widget_get_width(RemminaProtocolWidget *gp) { diff --git a/src/remmina_protocol_widget.h b/src/remmina_protocol_widget.h index e1a8f9987..c356df9c5 100644 --- a/src/remmina_protocol_widget.h +++ b/src/remmina_protocol_widget.h @@ -82,6 +82,7 @@ GtkWidget* remmina_protocol_widget_gtkviewport(RemminaProtocolWidget *gp); GtkWidget *remmina_protocol_widget_new(void); void remmina_protocol_widget_setup(RemminaProtocolWidget *gp, RemminaFile *remminafile, RemminaConnectionObject *cnnobj); +const gchar* remmina_protocol_widget_get_name(RemminaProtocolWidget *gp); gint remmina_protocol_widget_get_width(RemminaProtocolWidget *gp); void remmina_protocol_widget_set_width(RemminaProtocolWidget *gp, gint width); gint remmina_protocol_widget_get_height(RemminaProtocolWidget *gp); |