Chris@4
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
Chris@5
|
2 /*
|
Chris@35
|
3 Copyright (c) 2016-2018 Queen Mary, University of London
|
Chris@5
|
4
|
Chris@20
|
5 Permission is hereby granted, free of charge, to any person
|
Chris@20
|
6 obtaining a copy of this software and associated documentation
|
Chris@20
|
7 files (the "Software"), to deal in the Software without
|
Chris@20
|
8 restriction, including without limitation the rights to use, copy,
|
Chris@20
|
9 modify, merge, publish, distribute, sublicense, and/or sell copies
|
Chris@20
|
10 of the Software, and to permit persons to whom the Software is
|
Chris@20
|
11 furnished to do so, subject to the following conditions:
|
Chris@5
|
12
|
Chris@20
|
13 The above copyright notice and this permission notice shall be
|
Chris@20
|
14 included in all copies or substantial portions of the Software.
|
Chris@5
|
15
|
Chris@20
|
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
Chris@20
|
17 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
Chris@20
|
18 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
Chris@20
|
19 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
Chris@20
|
20 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
Chris@20
|
21 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
Chris@20
|
22 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
Chris@5
|
23
|
Chris@20
|
24 Except as contained in this notice, the names of the Centre for
|
Chris@20
|
25 Digital Music and Queen Mary, University of London shall not be
|
Chris@20
|
26 used in advertising or otherwise to promote the sale, use or other
|
Chris@20
|
27 dealings in this Software without prior written authorization.
|
Chris@5
|
28 */
|
Chris@4
|
29
|
Chris@4
|
30 #include "knownplugins.h"
|
Chris@4
|
31
|
Chris@36
|
32 #include <iostream>
|
Chris@36
|
33
|
Chris@4
|
34 using namespace std;
|
Chris@4
|
35
|
Chris@4
|
36 #if defined(_WIN32)
|
Chris@36
|
37 #include <windows.h>
|
Chris@4
|
38 #define PATH_SEPARATOR ';'
|
Chris@4
|
39 #else
|
Chris@4
|
40 #define PATH_SEPARATOR ':'
|
Chris@4
|
41 #endif
|
Chris@4
|
42
|
Chris@36
|
43 static bool
|
Chris@36
|
44 getEnvUtf8(std::string variable, std::string &value)
|
Chris@36
|
45 {
|
Chris@36
|
46 value = "";
|
Chris@36
|
47
|
Chris@36
|
48 #ifdef _WIN32
|
Chris@36
|
49 int wvarlen = MultiByteToWideChar(CP_UTF8, 0,
|
Chris@36
|
50 variable.c_str(), int(variable.length()),
|
Chris@36
|
51 0, 0);
|
Chris@36
|
52 if (wvarlen < 0) {
|
Chris@36
|
53 cerr << "WARNING: Unable to convert environment variable name "
|
Chris@36
|
54 << variable << " to wide characters" << endl;
|
Chris@36
|
55 return false;
|
Chris@36
|
56 }
|
Chris@36
|
57
|
Chris@36
|
58 wchar_t *wvarbuf = new wchar_t[wvarlen + 1];
|
Chris@36
|
59 (void)MultiByteToWideChar(CP_UTF8, 0,
|
Chris@36
|
60 variable.c_str(), int(variable.length()),
|
Chris@36
|
61 wvarbuf, wvarlen);
|
Chris@36
|
62 wvarbuf[wvarlen] = L'\0';
|
Chris@36
|
63
|
Chris@36
|
64 wchar_t *wvalue = _wgetenv(wvarbuf);
|
Chris@36
|
65
|
Chris@36
|
66 delete[] wvarbuf;
|
Chris@36
|
67
|
Chris@36
|
68 if (!wvalue) {
|
Chris@36
|
69 return false;
|
Chris@36
|
70 }
|
Chris@36
|
71
|
Chris@36
|
72 int wvallen = int(wcslen(wvalue));
|
Chris@36
|
73 int vallen = WideCharToMultiByte(CP_UTF8, 0,
|
Chris@36
|
74 wvalue, wvallen,
|
Chris@36
|
75 0, 0, 0, 0);
|
Chris@36
|
76 if (vallen < 0) {
|
Chris@36
|
77 cerr << "WARNING: Unable to convert environment value to UTF-8" << endl;
|
Chris@36
|
78 return false;
|
Chris@36
|
79 }
|
Chris@36
|
80
|
Chris@36
|
81 char *val = new char[vallen + 1];
|
Chris@36
|
82 (void)WideCharToMultiByte(CP_UTF8, 0,
|
Chris@36
|
83 wvalue, wvallen,
|
Chris@36
|
84 val, vallen, 0, 0);
|
Chris@36
|
85 val[vallen] = '\0';
|
Chris@36
|
86
|
Chris@36
|
87 value = val;
|
Chris@36
|
88
|
Chris@36
|
89 delete[] val;
|
Chris@36
|
90 return true;
|
Chris@36
|
91
|
Chris@36
|
92 #else
|
Chris@36
|
93
|
Chris@36
|
94 char *val = getenv(variable.c_str());
|
Chris@36
|
95 if (!val) {
|
Chris@36
|
96 return false;
|
Chris@36
|
97 }
|
Chris@36
|
98
|
Chris@36
|
99 value = val;
|
Chris@36
|
100 return true;
|
Chris@36
|
101
|
Chris@36
|
102 #endif
|
Chris@36
|
103 }
|
Chris@36
|
104
|
Chris@35
|
105 KnownPlugins::KnownPlugins(BinaryFormat format) :
|
Chris@35
|
106 m_format(format)
|
Chris@4
|
107 {
|
Chris@35
|
108 string variableSuffix = "";
|
Chris@35
|
109 if (m_format == FormatNonNative32Bit) {
|
Chris@34
|
110 variableSuffix = "_32";
|
Chris@34
|
111 }
|
Chris@6
|
112
|
Chris@34
|
113 m_known[VampPlugin] = {
|
Chris@34
|
114 "vamp",
|
Chris@34
|
115 "VAMP_PATH" + variableSuffix,
|
Chris@35
|
116 {}, {},
|
Chris@34
|
117 "vampGetPluginDescriptor"
|
Chris@34
|
118 };
|
Chris@34
|
119
|
Chris@34
|
120 m_known[LADSPAPlugin] = {
|
Chris@34
|
121 "ladspa",
|
Chris@34
|
122 "LADSPA_PATH" + variableSuffix,
|
Chris@35
|
123 {}, {},
|
Chris@34
|
124 "ladspa_descriptor"
|
Chris@34
|
125 };
|
Chris@34
|
126
|
Chris@34
|
127 m_known[DSSIPlugin] = {
|
Chris@34
|
128 "dssi",
|
Chris@34
|
129 "DSSI_PATH" + variableSuffix,
|
Chris@35
|
130 {}, {},
|
Chris@34
|
131 "dssi_descriptor"
|
Chris@4
|
132 };
|
Chris@4
|
133
|
Chris@35
|
134 for (auto &k: m_known) {
|
Chris@35
|
135 k.second.defaultPath = expandPathString(getDefaultPathString(k.first));
|
Chris@35
|
136 k.second.path = expandConventionalPath(k.first, k.second.variable);
|
Chris@4
|
137 }
|
Chris@4
|
138 }
|
Chris@4
|
139
|
Chris@35
|
140 vector<KnownPlugins::PluginType>
|
Chris@34
|
141 KnownPlugins::getKnownPluginTypes() const
|
Chris@34
|
142 {
|
Chris@35
|
143 vector<PluginType> kt;
|
Chris@34
|
144
|
Chris@34
|
145 for (const auto &k: m_known) {
|
Chris@34
|
146 kt.push_back(k.first);
|
Chris@34
|
147 }
|
Chris@34
|
148
|
Chris@34
|
149 return kt;
|
Chris@34
|
150 }
|
Chris@34
|
151
|
Chris@4
|
152 string
|
Chris@35
|
153 KnownPlugins::getUnexpandedDefaultPathString(PluginType type)
|
Chris@4
|
154 {
|
Chris@4
|
155 switch (type) {
|
Chris@4
|
156
|
Chris@4
|
157 #if defined(_WIN32)
|
Chris@4
|
158
|
Chris@4
|
159 case VampPlugin:
|
Chris@19
|
160 return "%ProgramFiles%\\Vamp Plugins";
|
Chris@4
|
161 case LADSPAPlugin:
|
Chris@19
|
162 return "%ProgramFiles%\\LADSPA Plugins;%ProgramFiles%\\Audacity\\Plug-Ins";
|
Chris@4
|
163 case DSSIPlugin:
|
Chris@19
|
164 return "%ProgramFiles%\\DSSI Plugins";
|
Chris@19
|
165
|
Chris@4
|
166 #elif defined(__APPLE__)
|
Chris@19
|
167
|
Chris@4
|
168 case VampPlugin:
|
Chris@19
|
169 return "$HOME/Library/Audio/Plug-Ins/Vamp:/Library/Audio/Plug-Ins/Vamp";
|
Chris@4
|
170 case LADSPAPlugin:
|
Chris@19
|
171 return "$HOME/Library/Audio/Plug-Ins/LADSPA:/Library/Audio/Plug-Ins/LADSPA";
|
Chris@4
|
172 case DSSIPlugin:
|
Chris@19
|
173 return "$HOME/Library/Audio/Plug-Ins/DSSI:/Library/Audio/Plug-Ins/DSSI";
|
Chris@19
|
174
|
Chris@4
|
175 #else /* Linux, BSDs, etc */
|
Chris@19
|
176
|
Chris@4
|
177 case VampPlugin:
|
Chris@19
|
178 return "$HOME/vamp:$HOME/.vamp:/usr/local/lib/vamp:/usr/lib/vamp";
|
Chris@4
|
179 case LADSPAPlugin:
|
Chris@19
|
180 return "$HOME/ladspa:$HOME/.ladspa:/usr/local/lib/ladspa:/usr/lib/ladspa";
|
Chris@4
|
181 case DSSIPlugin:
|
Chris@19
|
182 return "$HOME/dssi:$HOME/.dssi:/usr/local/lib/dssi:/usr/lib/dssi";
|
Chris@4
|
183 #endif
|
Chris@4
|
184 }
|
Chris@4
|
185
|
Chris@4
|
186 throw logic_error("unknown or unhandled plugin type");
|
Chris@4
|
187 }
|
Chris@4
|
188
|
Chris@35
|
189 string
|
Chris@35
|
190 KnownPlugins::getDefaultPathString(PluginType type)
|
Chris@35
|
191 {
|
Chris@35
|
192 string path = getUnexpandedDefaultPathString(type);
|
Chris@35
|
193
|
Chris@35
|
194 if (path == "") {
|
Chris@35
|
195 return path;
|
Chris@35
|
196 }
|
Chris@35
|
197
|
Chris@36
|
198 string home;
|
Chris@36
|
199 if (getEnvUtf8("HOME", home)) {
|
Chris@35
|
200 string::size_type f;
|
Chris@35
|
201 while ((f = path.find("$HOME")) != string::npos &&
|
Chris@35
|
202 f < path.length()) {
|
Chris@35
|
203 path.replace(f, 5, home);
|
Chris@35
|
204 }
|
Chris@35
|
205 }
|
Chris@35
|
206
|
Chris@35
|
207 #ifdef _WIN32
|
Chris@36
|
208 string pfiles, pfiles32;
|
Chris@36
|
209 if (!getEnvUtf8("ProgramFiles", pfiles)) {
|
Chris@35
|
210 pfiles = "C:\\Program Files";
|
Chris@35
|
211 }
|
Chris@36
|
212 if (!getEnvUtf8("ProgramFiles(x86)", pfiles32)) {
|
Chris@35
|
213 pfiles32 = "C:\\Program Files (x86)";
|
Chris@35
|
214 }
|
Chris@35
|
215
|
Chris@35
|
216 string::size_type f;
|
Chris@35
|
217 while ((f = path.find("%ProgramFiles%")) != string::npos &&
|
Chris@35
|
218 f < path.length()) {
|
Chris@35
|
219 if (m_format == FormatNonNative32Bit) {
|
Chris@35
|
220 path.replace(f, 14, pfiles32);
|
Chris@35
|
221 } else {
|
Chris@35
|
222 path.replace(f, 14, pfiles);
|
Chris@35
|
223 }
|
Chris@35
|
224 }
|
Chris@35
|
225 #endif
|
Chris@35
|
226
|
Chris@35
|
227 return path;
|
Chris@35
|
228 }
|
Chris@35
|
229
|
Chris@4
|
230 vector<string>
|
Chris@35
|
231 KnownPlugins::expandPathString(string path)
|
Chris@4
|
232 {
|
Chris@4
|
233 vector<string> pathList;
|
Chris@4
|
234
|
Chris@4
|
235 string::size_type index = 0, newindex = 0;
|
Chris@4
|
236
|
Chris@4
|
237 while ((newindex = path.find(PATH_SEPARATOR, index)) < path.size()) {
|
Chris@19
|
238 pathList.push_back(path.substr(index, newindex - index).c_str());
|
Chris@19
|
239 index = newindex + 1;
|
Chris@4
|
240 }
|
Chris@4
|
241
|
Chris@4
|
242 pathList.push_back(path.substr(index));
|
Chris@4
|
243
|
Chris@4
|
244 return pathList;
|
Chris@4
|
245 }
|
Chris@4
|
246
|
Chris@35
|
247 vector<string>
|
Chris@35
|
248 KnownPlugins::expandConventionalPath(PluginType type, string var)
|
Chris@4
|
249 {
|
Chris@35
|
250 string path;
|
Chris@4
|
251
|
Chris@36
|
252 if (!getEnvUtf8(var, path)) {
|
Chris@35
|
253 path = getDefaultPathString(type);
|
Chris@4
|
254 }
|
Chris@4
|
255
|
Chris@35
|
256 return expandPathString(path);
|
Chris@4
|
257 }
|