OpenCPN Partial API docs
plugin_loader.h
1 /***************************************************************************
2  *
3  *
4  * Project: OpenCPN
5  * Purpose: PlugIn Manager Object
6  * Author: David Register
7  *
8  ***************************************************************************
9  * Copyright (C) 2010-2023 by David S. Register *
10  * Copyright (C) 2023 Alec Leamas
11  * *
12  * This program is free software; you can redistribute it and/or modify *
13  * it under the terms of the GNU General Public License as published by *
14  * the Free Software Foundation; either version 2 of the License, or *
15  * (at your option) any later version. *
16  * *
17  * This program is distributed in the hope that it will be useful, *
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
20  * GNU General Public License for more details. *
21  * *
22  * You should have received a copy of the GNU General Public License *
23  * along with this program; if not, write to the *
24  * Free Software Foundation, Inc., *
25  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
26  **************************************************************************/
27 
28 #ifndef PLUGIN_LOADER_H_GUARD
29 #define PLUGIN_LOADER_H_GUARD
30 
31 #include <functional>
32 
33 #include <wx/wx.h>
34 #include <wx/bitmap.h>
35 #include <wx/dynarray.h>
36 #include <wx/dynlib.h>
37 
38 #include "config.h"
39 
40 #include "model/catalog_parser.h"
41 #include "model/plugin_blacklist.h"
42 #include "model/semantic_vers.h"
43 #include "observable_evtvar.h"
44 #include "ocpn_plugin.h"
45 
46 enum class PluginStatus {
47  System,
48  Managed,
49  Unmanaged,
50  Ghost,
51  Unknown,
52  LegacyUpdateAvailable,
53  ManagedInstallAvailable,
54  ManagedInstalledUpdateAvailable,
55  ManagedInstalledCurrentVersion,
56  ManagedInstalledDowngradeAvailable,
57  PendingListRemoval
58 };
59 
60 class PlugInContainer; // forward
61 class PlugInData; // forward
62 
64 class PlugInData {
65 public:
67  explicit PlugInData(const PluginMetadata& md);
68 
69  PlugInData();
70 
72  bool m_enabled;
73  bool m_init_state;
74  bool m_toolbox_panel;
75  int m_cap_flag;
76  wxString m_plugin_file;
77  wxString m_plugin_filename;
78  wxDateTime m_plugin_modification;
79  wxString m_common_name;
80  wxString m_short_description;
81  wxString m_long_description;
82  int m_api_version;
83  int m_version_major;
84  int m_version_minor;
85  PluginStatus m_status;
86  PluginMetadata m_managed_metadata;
87  wxBitmap m_bitmap;
88  wxString m_version_str;
89  std::string m_manifest_version;
90 
92  std::string Key() const;
93 };
94 
99 class PlugInContainer : public PlugInData {
100 public:
101  PlugInContainer();
102 
103  ~PlugInContainer() = default;
104 
105  opencpn_plugin* m_pplugin;
106  wxDynamicLibrary m_library;
107  destroy_t* m_destroy_fn;
108 };
109 
110 class LoadError {
111 public:
112  enum class Type {
113  Unloadable, //<! wrong magic, wrong type of binary...
114  Unreadable,
115  Incompatible,
116  NoCreate, //<! Missing linkage (is this a plugin?)
117  NoDestroy, //<! Missing linkage (is this a plugin?)
118  Blacklisted
119  } type;
120  const std::string lib_path; //<! Complete path to failing library
121  //<! As determined from plugin API
122  const SemanticVersion plugin_version; //<! As determined from plugin API
123 
124  LoadError(Type t, const std::string& l, SemanticVersion pv)
125  : type(t), lib_path(l), plugin_version(pv) {}
126 
127  LoadError(Type t, std::string l)
128  : type(t), lib_path(std::move(l)), plugin_version(SemanticVersion()) {}
129 };
130 
131 // Declare an array of PlugIn Containers
132 WX_DEFINE_ARRAY_PTR(PlugInContainer*, ArrayOfPlugIns);
133 
155 public:
156  static PluginLoader* getInstance();
157  virtual ~PluginLoader() = default;
161  static void UpdatePlugin(PlugInContainer* plugin, const PluginMetadata& md);
162 
164  static std::string GetPluginVersion(
165  const PlugInData pd,
166  std::function<const PluginMetadata(const std::string&)> get_metadata);
167 
169  static PluginMetadata MetadataByName(const std::string& name);
170 
171  EventVar evt_blacklisted_plugin;
172 
173  EventVar evt_load_directory;
174  EventVar evt_load_plugin;
175  EventVar evt_plugin_unload;
176  EventVar evt_pluglist_change;
177  EventVar evt_unreadable_plugin;
178 
183 
184  EventVar evt_update_chart_types;
185 
191 
192  EventVar evt_version_incompatible_plugin;
193 
202  bool LoadAllPlugIns(bool enabled_plugins, bool keep_orphans = false);
203 
204  const wxBitmap* GetPluginDefaultIcon();
205  void SetPluginDefaultIcon(const wxBitmap* bitmap);
206 
208  void SetOnDeactivateCb(std::function<void(const PlugInContainer*)> cb) {
209  m_on_deactivate_cb = cb;
210  }
212  void ShowPreferencesDialog(const PlugInData& pd, wxWindow* parent);
213 
214  void NotifySetupOptionsPlugin(const PlugInData* pic);
215 
217  void RemovePlugin(const PlugInData& pd);
218 
220  void SortPlugins(int (*cmp_func)(PlugInContainer**, PlugInContainer**));
221 
223  bool UnLoadPlugIn(size_t ix);
224 
225  bool UnLoadAllPlugIns();
226  bool DeactivateAllPlugIns();
227  bool DeactivatePlugIn(PlugInContainer* pic);
228  bool DeactivatePlugIn(const PlugInData& pic);
229  bool UpdatePlugIns();
230  void UpdateManagedPlugins(bool keep_orphans);
231  PlugInContainer* LoadPlugIn(const wxString& plugin_file);
232  PlugInContainer* LoadPlugIn(const wxString& plugin_file,
233  PlugInContainer* pic);
234 
235  const ArrayOfPlugIns* GetPlugInArray() { return &plugin_array; }
236  bool IsPlugInAvailable(const wxString& commonName);
237  bool CheckPluginCompatibility(const wxString& plugin_file);
238 
240  void SetEnabled(const wxString& common_name, bool enabled);
241 
243  void SetToolboxPanel(const wxString& common_name, bool value);
244 
245 private:
246  PluginLoader();
247  bool LoadPlugInDirectory(const wxString& plugin_dir, bool load_enabled);
248  bool LoadPluginCandidate(const wxString& file_name, bool load_enabled);
249  std::unique_ptr<AbstractBlacklist> m_blacklist;
250  ArrayOfPlugIns plugin_array;
251  wxString m_last_error_string;
252  wxString m_plugin_location;
253 
254 #ifdef __WXMSW__
255  wxString m_module_name;
256  bool m_found_wxwidgets;
257 #endif
258 
259  const wxBitmap* m_default_plugin_icon;
260  std::function<void(const PlugInContainer*)> m_on_deactivate_cb;
261 
262  std::vector<LoadError> load_errors;
263 };
264 
265 #endif // PLUGIN_LOADER_H_GUARD
Generic event handling between MVC Model and Controller based on a shared EventVar variable.
Data for a loaded plugin, including dl-loaded library.
Definition: plugin_loader.h:99
Basic data for a loaded plugin, trivially copyable.
Definition: plugin_loader.h:64
wxString m_plugin_filename
The short file path.
Definition: plugin_loader.h:77
wxString m_plugin_file
The full file path.
Definition: plugin_loader.h:76
int m_cap_flag
PlugIn Capabilities descriptor.
Definition: plugin_loader.h:75
wxString m_common_name
A common name string for the plugin.
Definition: plugin_loader.h:79
bool m_has_setup_options
Has run NotifySetupOptionsPlugin()
Definition: plugin_loader.h:71
std::string Key() const
sort key.
std::string m_manifest_version
As detected from manifest.
Definition: plugin_loader.h:89
wxDateTime m_plugin_modification
used to detect upgraded plugins
Definition: plugin_loader.h:78
wxString m_version_str
Complete version as of semantic_vers.
Definition: plugin_loader.h:88
PluginLoader is a backend module without any direct GUI functionality.
void SetOnDeactivateCb(std::function< void(const PlugInContainer *)> cb)
Callback invoked in late stage on deactivating a plugin.
bool LoadAllPlugIns(bool enabled_plugins, bool keep_orphans=false)
Update catalog with imported metadata and load all plugin library files.
EventVar evt_plugin_loadall_finalize
Emitted after all plugins are loaded.
static std::string GetPluginVersion(const PlugInData pd, std::function< const PluginMetadata(const std::string &)> get_metadata)
Return version string for a plugin, possibly with an "Imported" suffix.
bool UnLoadPlugIn(size_t ix)
Unload, delete and remove item ix in GetPlugInArray().
void SortPlugins(int(*cmp_func)(PlugInContainer **, PlugInContainer **))
Sort GetPluginArray().
static void UpdatePlugin(PlugInContainer *plugin, const PluginMetadata &md)
Update PlugInContainer status using data from PluginMetadata and manifest.
void SetEnabled(const wxString &common_name, bool enabled)
Update enabled/disabled state for plugin with given name.
void SetToolboxPanel(const wxString &common_name, bool value)
Update m_toolbox_panel state for plugin with given name.
static PluginMetadata MetadataByName(const std::string &name)
Find metadata for given plugin.
void RemovePlugin(const PlugInData &pd)
Remove a plugin from *GetPluginArray().
void ShowPreferencesDialog(const PlugInData &pd, wxWindow *parent)
Display the preferences dialog for a plugin.
EventVar evt_deactivate_plugin
Carries a malloc'ed read-only copy of a PlugInContainer owned by listener.
Plugin metadata, reflects the xml format directly.
Versions uses a modified semantic versioning scheme: major.minor.revision.post-tag+build.
Definition: semantic_vers.h:51