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