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 }