OpenCPN Partial API docs
Loading...
Searching...
No Matches
plugin_paths.cpp
1#include <sstream>
2
3#include <wx/filename.h>
4#include <wx/platinfo.h>
5#include <wx/string.h>
6
7#include "config.h"
8
9#include "model/base_platform.h"
10#include "model/cmdline.h"
11#include "model/ocpn_utils.h"
12#include "model/plugin_paths.h"
13#include "ocpn_plugin.h"
14
15/*
16 * The user-writable paths for libraries, binaries and plugin data,
17 * one path each. And the list of paths used fo loading plugin
18 * plugin libraries, locating helper binaries and storing plugin
19 * data.
20 */
21
22static std::vector<std::string> split(const std::string& s, char delimiter) {
23 std::vector<std::string> tokens;
24 std::string token;
25 std::istringstream tokenStream(s);
26 while (std::getline(tokenStream, token, delimiter)) {
27 tokens.push_back(token);
28 }
29 return tokens;
30}
31
32static std::string expand(const std::string& s) {
33 wxFileName fn(s);
34 fn.Normalize();
35 return fn.GetFullPath().ToStdString();
36}
37
39 static PluginPaths* instance = 0;
40 if (!instance) {
41 instance = new (PluginPaths);
42 }
43 return instance;
44}
45
46void PluginPaths::initWindowsPaths() {
47 using namespace std;
48
49 if (g_bportable) {
50 m_userLibdir =
51 g_BasePlatform->GetPrivateDataDir().ToStdString() + "\\plugins";
52 m_libdirs.push_back(m_userLibdir);
53 m_userBindir =
54 g_BasePlatform->GetPrivateDataDir().ToStdString() + "\\plugins";
55 m_bindirs = m_libdirs;
56 m_userDatadir =
57 g_BasePlatform->GetPrivateDataDir().ToStdString() + "\\plugins";
58 m_datadirs.push_back(m_userDatadir);
59 return;
60 }
61
62 const string platform_dir = g_BasePlatform->GetPluginDir().ToStdString();
63 const string winPluginBaseDir =
64 g_BasePlatform->GetWinPluginBaseDir().ToStdString();
65 m_userLibdir = winPluginBaseDir;
66 m_userBindir = winPluginBaseDir;
67 m_userDatadir = winPluginBaseDir;
68
69 m_libdirs.push_back(m_userLibdir);
70 m_libdirs.push_back(g_BasePlatform->GetPluginDir().ToStdString());
71 m_bindirs = m_libdirs;
72
73 m_datadirs.push_back(platform_dir + "\\plugins");
74 m_datadirs.push_back(winPluginBaseDir);
75}
76
77void PluginPaths::initFlatpackPaths() {
78 using namespace std;
79
80 const string flathome = m_home + "/.var/app/org.opencpn.OpenCPN";
81 m_userLibdir = flathome + "/lib";
82 m_userBindir = flathome + "/bin";
83 m_userDatadir = flathome + "/data";
84
85 m_libdirs.push_back(flathome + "/lib");
86 m_libdirs.push_back("/app/extensions/lib/opencpn");
87 m_libdirs.push_back("/app/lib/opencpn");
88
89 m_bindirs.push_back(flathome + "/bin");
90 m_bindirs.push_back("/app/extensions/bin");
91 m_bindirs.push_back("/app/bin");
92
93 m_datadirs.push_back(flathome + "/data/plugins");
94 m_datadirs.push_back("/app/extensions/share/opencpn/plugins");
95 m_datadirs.push_back("/app/share/opencpn/plugins");
96}
97
98void PluginPaths::initLinuxPaths() {
99 using namespace std;
100
101 if (g_bportable) {
102 m_userLibdir = g_BasePlatform->GetPrivateDataDir().ToStdString() +
103 "/plugins/lib"; // m_home + "/.local/lib";
104 m_libdirs.push_back(m_userLibdir);
105 m_userBindir = g_BasePlatform->GetPrivateDataDir().ToStdString() +
106 "/plugins/bin"; // m_home + "/.local/bin";
107 m_bindirs = m_libdirs;
108 m_userDatadir = g_BasePlatform->GetPrivateDataDir().ToStdString() +
109 "/plugins/share"; // m_home + "/.local/share";
110 m_datadirs.push_back(m_userDatadir);
111 return;
112 }
113
114 m_userLibdir = m_home + "/.local/lib";
115 m_userBindir = m_home + "/.local/bin";
116 m_userDatadir = m_home + "/.local/share";
117
118 std::vector<std::string> base_plugin_paths;
119#if defined(__WXGTK__) || defined(__WXQT__)
120 char exe_buf[100] = {0};
121 ssize_t len = readlink("/proc/self/exe", exe_buf, 99);
122 if (len > 0) {
123 exe_buf[len] = '\0';
124 wxFileName fn(exe_buf);
125 std::string path = fn.GetPath().ToStdString();
126 base_plugin_paths.push_back(expand(path + "/../lib/opencpn"));
127 if (g_BasePlatform->GetOSDetail()->osd_arch.find("64") != string::npos) {
128 base_plugin_paths.push_back(expand(path + "/../lib64/opencpn"));
129 } else {
130 base_plugin_paths.push_back(expand(path + "/../lib32/opencpn"));
131 }
132 }
133#endif
134
135 const char* const envdirs = getenv("OPENCPN_PLUGIN_DIRS");
136 string dirlist = envdirs ? envdirs : "~/.local/lib/opencpn";
137 m_libdirs = split(dirlist, ':');
138 for (auto& dir : m_libdirs) {
139 dir = expand(dir);
140 }
141 for (auto& base_plugin_path : base_plugin_paths) {
142 if (envdirs == 0 && dirlist.find(base_plugin_path) == string::npos) {
143 if (ocpn::exists(base_plugin_path)) {
144 m_libdirs.push_back(base_plugin_path);
145 }
146 }
147 }
148 m_bindirs = m_libdirs;
149 for (auto& dir : m_bindirs) {
150 // Fails on Debian multilib paths like /usr/lib/x86_64-linux-gnu.
151 // But we don't use those even on Debian.
152 size_t pos = dir.rfind("/lib/opencpn");
153 if (pos == string::npos) {
154 pos = dir.rfind("/lib64/opencpn");
155 }
156 dir = pos == string::npos ? dir : dir.substr(0, pos) + "/bin";
157 }
158 const char* const xdg_data_dirs = getenv("XDG_DATA_DIRS");
159 dirlist = xdg_data_dirs ? xdg_data_dirs : "~/.local/lib";
160 m_datadirs = split(dirlist, ':');
161 for (auto& dir : m_datadirs) {
162 dir += "/opencpn/plugins";
163 }
164 for (auto& base_plugin_path : base_plugin_paths) {
165 if (xdg_data_dirs == 0 && dirlist.find(base_plugin_path) == string::npos) {
166 m_datadirs.push_back(base_plugin_path + "/plugins");
167 }
168 }
169}
170
171void PluginPaths::initApplePaths() {
172 using namespace std;
173
174 const string mac_home = m_home + "/Library/Application Support/OpenCPN";
175 m_userLibdir = mac_home + "/Contents/PlugIns";
176 m_userBindir = m_userLibdir;
177 m_userDatadir = mac_home + "/Contents";
178
179 m_libdirs.push_back(m_userLibdir);
180 wxFileName fn_exe(g_BasePlatform->GetExePath());
181 fn_exe.RemoveLastDir();
182 string exeLibDir =
183 fn_exe.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR).ToStdString() +
184 "PlugIns";
185 m_libdirs.push_back(exeLibDir);
186 // m_libdirs.push_back("/Applications/OpenCPN.app/Contents/Plugins");
187 m_bindirs = m_libdirs;
188
189 m_datadirs.push_back(m_userDatadir);
190 m_datadirs.push_back("/Applications/OpenCPN.app/Contents/PlugIns");
191}
192
193void PluginPaths::initAndroidPaths() {
194 using namespace std;
195
196 const string platform_dir = g_BasePlatform->GetPluginDir().ToStdString();
197
198 m_userLibdir =
199 platform_dir + "/manPlug"; //("/data/user/0/org.opencpn.opencpn");
200 m_userBindir =
201 platform_dir + "/manPlug"; //("/data/user/0/org.opencpn.opencpn");
202 m_userDatadir =
203 g_BasePlatform->GetPrivateDataDir()
204 .ToStdString(); //(
205 //"/storage/emulated/0/android/data/org.opencpn.opencpn/files");
206
207 m_libdirs.push_back(m_userLibdir); // Load managed plugins first...
208 m_libdirs.push_back(expand(platform_dir));
209
210 m_bindirs = m_libdirs;
211}
212
213PluginPaths::PluginPaths() {
214 using namespace std;
215
216 wxString wxHome("unusable-$HOME");
217 wxGetEnv("HOME", &wxHome);
218 m_home = wxHome.ToStdString();
219
220 auto osSystemId = wxPlatformInfo::Get().GetOperatingSystemId();
221 if (osSystemId & wxOS_WINDOWS) {
222 initWindowsPaths();
223 } else if (g_BasePlatform->isFlatpacked()) {
224 initFlatpackPaths();
225 } else if (osSystemId & wxOS_UNIX_LINUX) {
226#ifdef __OCPN__ANDROID__
227 initAndroidPaths();
228#else
229 initLinuxPaths();
230#endif
231 } else if (osSystemId & wxOS_MAC) {
232 initApplePaths();
233 } else {
234 wxString os_name = wxPlatformInfo::Get().GetPortIdName();
235 wxLogMessage(_T("OS_NAME: ") + os_name);
236 if (os_name.Contains(_T("wxQT"))) {
237 initAndroidPaths();
238 } else
239 wxLogWarning("PluginPaths: Unknown platform");
240 }
241}
wxString & GetPluginDir()
The original in-tree plugin directory, sometimes not user-writable.
wxString GetWinPluginBaseDir()
Base directory for user writable windows plugins, reflects winPluginDir option, defaults to LOCALAPPD...
wxString & GetPrivateDataDir()
Return dir path for opencpn.log, etc., respecting -c cli option.
static PluginPaths * getInstance()
Return the singleton instance.
Global variables reflecting command line options and arguments.
PlugIn Object Definition/API.