Mercurial > hg > vamp-plugin-load-checker
comparison src/knownplugins.cpp @ 37:3ccc384c0161
Merge from branch plugin-path-config
author | Chris Cannam |
---|---|
date | Mon, 11 Jun 2018 17:46:50 +0100 |
parents | ae74d39e9e4e |
children |
comparison
equal
deleted
inserted
replaced
33:cf18645ff411 | 37:3ccc384c0161 |
---|---|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ | 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ |
2 /* | 2 /* |
3 Copyright (c) 2016 Queen Mary, University of London | 3 Copyright (c) 2016-2018 Queen Mary, University of London |
4 | 4 |
5 Permission is hereby granted, free of charge, to any person | 5 Permission is hereby granted, free of charge, to any person |
6 obtaining a copy of this software and associated documentation | 6 obtaining a copy of this software and associated documentation |
7 files (the "Software"), to deal in the Software without | 7 files (the "Software"), to deal in the Software without |
8 restriction, including without limitation the rights to use, copy, | 8 restriction, including without limitation the rights to use, copy, |
27 dealings in this Software without prior written authorization. | 27 dealings in this Software without prior written authorization. |
28 */ | 28 */ |
29 | 29 |
30 #include "knownplugins.h" | 30 #include "knownplugins.h" |
31 | 31 |
32 #include <sstream> | 32 #include <iostream> |
33 | 33 |
34 using namespace std; | 34 using namespace std; |
35 | 35 |
36 #if defined(_WIN32) | 36 #if defined(_WIN32) |
37 #include <windows.h> | |
37 #define PATH_SEPARATOR ';' | 38 #define PATH_SEPARATOR ';' |
38 #else | 39 #else |
39 #define PATH_SEPARATOR ':' | 40 #define PATH_SEPARATOR ':' |
40 #endif | 41 #endif |
41 | 42 |
42 KnownPlugins::KnownPlugins(string helperExecutableName, | 43 static bool |
43 PluginCandidates::LogCallback *cb) : | 44 getEnvUtf8(std::string variable, std::string &value) |
44 m_candidates(helperExecutableName), | 45 { |
45 m_helperExecutableName(helperExecutableName) | 46 value = ""; |
46 { | 47 |
47 m_candidates.setLogCallback(cb); | 48 #ifdef _WIN32 |
48 | 49 int wvarlen = MultiByteToWideChar(CP_UTF8, 0, |
49 m_known = { | 50 variable.c_str(), int(variable.length()), |
50 { | 51 0, 0); |
51 VampPlugin, | 52 if (wvarlen < 0) { |
52 { | 53 cerr << "WARNING: Unable to convert environment variable name " |
53 "vamp", | 54 << variable << " to wide characters" << endl; |
54 expandConventionalPath(VampPlugin, "VAMP_PATH"), | 55 return false; |
55 "vampGetPluginDescriptor" | 56 } |
56 }, | 57 |
57 }, { | 58 wchar_t *wvarbuf = new wchar_t[wvarlen + 1]; |
58 LADSPAPlugin, | 59 (void)MultiByteToWideChar(CP_UTF8, 0, |
59 { | 60 variable.c_str(), int(variable.length()), |
60 "ladspa", | 61 wvarbuf, wvarlen); |
61 expandConventionalPath(LADSPAPlugin, "LADSPA_PATH"), | 62 wvarbuf[wvarlen] = L'\0'; |
62 "ladspa_descriptor" | 63 |
63 }, | 64 wchar_t *wvalue = _wgetenv(wvarbuf); |
64 }, { | 65 |
65 DSSIPlugin, | 66 delete[] wvarbuf; |
66 { | 67 |
67 "dssi", | 68 if (!wvalue) { |
68 expandConventionalPath(DSSIPlugin, "DSSI_PATH"), | 69 return false; |
69 "dssi_descriptor" | 70 } |
70 } | 71 |
71 } | 72 int wvallen = int(wcslen(wvalue)); |
73 int vallen = WideCharToMultiByte(CP_UTF8, 0, | |
74 wvalue, wvallen, | |
75 0, 0, 0, 0); | |
76 if (vallen < 0) { | |
77 cerr << "WARNING: Unable to convert environment value to UTF-8" << endl; | |
78 return false; | |
79 } | |
80 | |
81 char *val = new char[vallen + 1]; | |
82 (void)WideCharToMultiByte(CP_UTF8, 0, | |
83 wvalue, wvallen, | |
84 val, vallen, 0, 0); | |
85 val[vallen] = '\0'; | |
86 | |
87 value = val; | |
88 | |
89 delete[] val; | |
90 return true; | |
91 | |
92 #else | |
93 | |
94 char *val = getenv(variable.c_str()); | |
95 if (!val) { | |
96 return false; | |
97 } | |
98 | |
99 value = val; | |
100 return true; | |
101 | |
102 #endif | |
103 } | |
104 | |
105 KnownPlugins::KnownPlugins(BinaryFormat format) : | |
106 m_format(format) | |
107 { | |
108 string variableSuffix = ""; | |
109 if (m_format == FormatNonNative32Bit) { | |
110 variableSuffix = "_32"; | |
111 } | |
112 | |
113 m_known[VampPlugin] = { | |
114 "vamp", | |
115 "VAMP_PATH" + variableSuffix, | |
116 {}, {}, | |
117 "vampGetPluginDescriptor" | |
72 }; | 118 }; |
119 | |
120 m_known[LADSPAPlugin] = { | |
121 "ladspa", | |
122 "LADSPA_PATH" + variableSuffix, | |
123 {}, {}, | |
124 "ladspa_descriptor" | |
125 }; | |
126 | |
127 m_known[DSSIPlugin] = { | |
128 "dssi", | |
129 "DSSI_PATH" + variableSuffix, | |
130 {}, {}, | |
131 "dssi_descriptor" | |
132 }; | |
133 | |
134 for (auto &k: m_known) { | |
135 k.second.defaultPath = expandPathString(getDefaultPathString(k.first)); | |
136 k.second.path = expandConventionalPath(k.first, k.second.variable); | |
137 } | |
138 } | |
139 | |
140 vector<KnownPlugins::PluginType> | |
141 KnownPlugins::getKnownPluginTypes() const | |
142 { | |
143 vector<PluginType> kt; | |
73 | 144 |
74 for (const auto &k: m_known) { | 145 for (const auto &k: m_known) { |
75 m_candidates.scan(k.second.tag, k.second.path, k.second.descriptor); | 146 kt.push_back(k.first); |
76 } | 147 } |
77 } | 148 |
78 | 149 return kt; |
79 bool | |
80 KnownPlugins::is32bit() const | |
81 { | |
82 return m_helperExecutableName.find("-32") != std::string::npos; | |
83 } | 150 } |
84 | 151 |
85 string | 152 string |
86 KnownPlugins::getDefaultPath(PluginType type) | 153 KnownPlugins::getUnexpandedDefaultPathString(PluginType type) |
87 { | 154 { |
88 switch (type) { | 155 switch (type) { |
89 | 156 |
90 #if defined(_WIN32) | 157 #if defined(_WIN32) |
91 | 158 |
117 } | 184 } |
118 | 185 |
119 throw logic_error("unknown or unhandled plugin type"); | 186 throw logic_error("unknown or unhandled plugin type"); |
120 } | 187 } |
121 | 188 |
189 string | |
190 KnownPlugins::getDefaultPathString(PluginType type) | |
191 { | |
192 string path = getUnexpandedDefaultPathString(type); | |
193 | |
194 if (path == "") { | |
195 return path; | |
196 } | |
197 | |
198 string home; | |
199 if (getEnvUtf8("HOME", home)) { | |
200 string::size_type f; | |
201 while ((f = path.find("$HOME")) != string::npos && | |
202 f < path.length()) { | |
203 path.replace(f, 5, home); | |
204 } | |
205 } | |
206 | |
207 #ifdef _WIN32 | |
208 string pfiles, pfiles32; | |
209 if (!getEnvUtf8("ProgramFiles", pfiles)) { | |
210 pfiles = "C:\\Program Files"; | |
211 } | |
212 if (!getEnvUtf8("ProgramFiles(x86)", pfiles32)) { | |
213 pfiles32 = "C:\\Program Files (x86)"; | |
214 } | |
215 | |
216 string::size_type f; | |
217 while ((f = path.find("%ProgramFiles%")) != string::npos && | |
218 f < path.length()) { | |
219 if (m_format == FormatNonNative32Bit) { | |
220 path.replace(f, 14, pfiles32); | |
221 } else { | |
222 path.replace(f, 14, pfiles); | |
223 } | |
224 } | |
225 #endif | |
226 | |
227 return path; | |
228 } | |
229 | |
122 vector<string> | 230 vector<string> |
123 KnownPlugins::expandConventionalPath(PluginType type, string var) | 231 KnownPlugins::expandPathString(string path) |
124 { | 232 { |
125 vector<string> pathList; | 233 vector<string> pathList; |
126 string path; | |
127 | |
128 char *cpath = getenv(var.c_str()); | |
129 if (cpath) path = cpath; | |
130 | |
131 #ifdef _WIN32 | |
132 bool is32 = is32bit(); | |
133 #endif | |
134 | |
135 if (path == "") { | |
136 | |
137 path = getDefaultPath(type); | |
138 | |
139 if (path != "") { | |
140 | |
141 char *home = getenv("HOME"); | |
142 if (home) { | |
143 string::size_type f; | |
144 while ((f = path.find("$HOME")) != string::npos && | |
145 f < path.length()) { | |
146 path.replace(f, 5, home); | |
147 } | |
148 } | |
149 | |
150 #ifdef _WIN32 | |
151 const char *pfiles = 0; | |
152 if (is32) { | |
153 pfiles = getenv("ProgramFiles(x86)"); | |
154 } | |
155 if (!pfiles) { | |
156 pfiles = getenv("ProgramFiles"); | |
157 } | |
158 if (!pfiles) { | |
159 if (is32) { | |
160 pfiles = "C:\\Program Files (x86)"; | |
161 } else { | |
162 pfiles = "C:\\Program Files"; | |
163 } | |
164 } | |
165 string::size_type f; | |
166 while ((f = path.find("%ProgramFiles%")) != string::npos && | |
167 f < path.length()) { | |
168 path.replace(f, 14, pfiles); | |
169 } | |
170 #endif | |
171 } | |
172 } | |
173 | 234 |
174 string::size_type index = 0, newindex = 0; | 235 string::size_type index = 0, newindex = 0; |
175 | 236 |
176 while ((newindex = path.find(PATH_SEPARATOR, index)) < path.size()) { | 237 while ((newindex = path.find(PATH_SEPARATOR, index)) < path.size()) { |
177 pathList.push_back(path.substr(index, newindex - index).c_str()); | 238 pathList.push_back(path.substr(index, newindex - index).c_str()); |
181 pathList.push_back(path.substr(index)); | 242 pathList.push_back(path.substr(index)); |
182 | 243 |
183 return pathList; | 244 return pathList; |
184 } | 245 } |
185 | 246 |
186 string | 247 vector<string> |
187 KnownPlugins::getFailureReport() const | 248 KnownPlugins::expandConventionalPath(PluginType type, string var) |
188 { | 249 { |
189 vector<PluginCandidates::FailureRec> failures; | 250 string path; |
190 | 251 |
191 for (auto t: getKnownPluginTypes()) { | 252 if (!getEnvUtf8(var, path)) { |
192 auto ff = m_candidates.getFailedLibrariesFor(getTagFor(t)); | 253 path = getDefaultPathString(type); |
193 failures.insert(failures.end(), ff.begin(), ff.end()); | 254 } |
194 } | 255 |
195 | 256 return expandPathString(path); |
196 if (failures.empty()) return ""; | 257 } |
197 | |
198 int n = int(failures.size()); | |
199 int i = 0; | |
200 | |
201 ostringstream os; | |
202 | |
203 os << "<ul>"; | |
204 for (auto f: failures) { | |
205 os << "<li>" + f.library; | |
206 if (f.message != "") { | |
207 os << "<br><i>" + f.message + "</i>"; | |
208 } else { | |
209 os << "<br><i>unknown error</i>"; | |
210 } | |
211 os << "</li>"; | |
212 | |
213 if (n > 10) { | |
214 if (++i == 5) { | |
215 os << "<li>(... and " << (n - i) << " further failures)</li>"; | |
216 break; | |
217 } | |
218 } | |
219 } | |
220 os << "</ul>"; | |
221 | |
222 return os.str(); | |
223 } |