PluginPathSetter.cpp
Go to the documentation of this file.
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2 
3 /*
4  Sonic Visualiser
5  An audio file viewer and annotation editor.
6  Centre for Digital Music, Queen Mary, University of London.
7 
8  This program is free software; you can redistribute it and/or
9  modify it under the terms of the GNU General Public License as
10  published by the Free Software Foundation; either version 2 of the
11  License, or (at your option) any later version. See the file
12  COPYING included with this distribution for more information.
13 */
14 
15 #include "PluginPathSetter.h"
16 
17 #include <vamp-hostsdk/PluginHostAdapter.h>
18 
19 #include "RealTimePluginFactory.h"
20 #include "LADSPAPluginFactory.h"
21 #include "DSSIPluginFactory.h"
22 
23 #include <QSettings>
24 #include <QMutexLocker>
25 
26 #include "system/System.h"
27 #include "base/Preferences.h"
28 #include "base/HelperExecPath.h"
29 
30 QMutex
32 
35 
38 
39 std::map<QString, QString>
41 
44 
45 using namespace std;
46 
49 {
50  QMutexLocker locker(&m_mutex);
51 
52  if (!m_supportedKeys.empty()) {
53  return m_supportedKeys;
54  }
55 
56  TypeKeys keys;
57  keys.push_back({ KnownPlugins::VampPlugin, KnownPlugins::FormatNative });
58 
60  HelperExecPath hep(inProcess ?
63  auto execs = hep.getHelperExecutables("vamp-plugin-load-checker");
64  if (execs.size() > 1) {
65  keys.push_back({
66  KnownPlugins::VampPlugin, KnownPlugins::FormatNonNative32Bit });
67  }
68 
69  keys.push_back({ KnownPlugins::LADSPAPlugin, KnownPlugins::FormatNative });
70  keys.push_back({ KnownPlugins::DSSIPlugin, KnownPlugins::FormatNative });
71 
72  m_supportedKeys = keys;
73  return keys;
74 }
75 
76 // call with mutex held please
79 {
80  Paths paths;
81 
82  for (auto k: keys) {
83 
84  KnownPlugins kp(k.second);
85 
86  auto path = kp.getPathFor(k.first);
87  QStringList qPath;
88  for (auto s: path) {
89  qPath.push_back(QString::fromStdString(s));
90  }
91 
92  auto var = kp.getPathEnvironmentVariableFor(k.first);
93  QString qVar = QString::fromStdString(var);
94 
95  paths[k] = { qPath, qVar, true };
96  }
97 
98  return paths;
99 }
100 
103 {
104  TypeKeys keys = getSupportedKeys();
105 
106  QMutexLocker locker(&m_mutex);
107 
108  Paths paths;
109 
110  for (auto k: keys) {
111 
112  KnownPlugins kp(k.second);
113 
114  auto path = kp.getDefaultPathFor(k.first);
115  QStringList qPath;
116  for (auto s: path) {
117  qPath.push_back(QString::fromStdString(s));
118  }
119 
120  auto var = kp.getPathEnvironmentVariableFor(k.first);
121  QString qVar = QString::fromStdString(var);
122 
123  paths[k] = { qPath, qVar, true };
124  }
125 
126  return paths;
127 }
128 
131 {
132  TypeKeys keys = getSupportedKeys();
133 
134  QMutexLocker locker(&m_mutex);
135 
136  if (!m_environmentPaths.empty()) {
137  return m_environmentPaths;
138  }
139 
140  m_environmentPaths = getEnvironmentPathsUncached(keys);
141  return m_environmentPaths;
142 }
143 
144 QString
146 {
147  string tag = KnownPlugins(tk.second).getTagFor(tk.first);
148  if (tk.second == KnownPlugins::FormatNonNative32Bit) {
149  tag += "-32";
150  }
151  return QString::fromStdString(tag);
152 }
153 
156 {
157  Paths paths = getEnvironmentPaths();
158 
159  QSettings settings;
160  settings.beginGroup("Plugins");
161 
162  for (auto p: paths) {
163 
164  TypeKey tk = p.first;
165 
166  QString settingTag = getSettingTagFor(tk);
167 
168  QStringList directories =
169  settings.value(QString("directories-%1").arg(settingTag),
170  p.second.directories)
171  .toStringList();
172  QString envVariable =
173  settings.value(QString("env-variable-%1").arg(settingTag),
174  p.second.envVariable)
175  .toString();
176  bool useEnvVariable =
177  settings.value(QString("use-env-variable-%1").arg(settingTag),
178  p.second.useEnvVariable)
179  .toBool();
180 
181  string envVarStr = envVariable.toStdString();
182  string currentValue;
183  (void)getEnvUtf8(envVarStr, currentValue);
184 
185  if (currentValue != "" && useEnvVariable) {
186  directories = QString::fromStdString(currentValue).split(
187 #ifdef Q_OS_WIN
188  ";"
189 #else
190  ":"
191 #endif
192  );
193  }
194 
195  paths[tk] = { directories, envVariable, useEnvVariable };
196  }
197 
198  settings.endGroup();
199 
200  return paths;
201 }
202 
203 void
205 {
206  QSettings settings;
207  settings.beginGroup("Plugins");
208 
209  for (auto p: paths) {
210  QString settingTag = getSettingTagFor(p.first);
211  settings.setValue(QString("directories-%1").arg(settingTag),
212  p.second.directories);
213  settings.setValue(QString("env-variable-%1").arg(settingTag),
214  p.second.envVariable);
215  settings.setValue(QString("use-env-variable-%1").arg(settingTag),
216  p.second.useEnvVariable);
217  }
218 
219  settings.endGroup();
220 }
221 
222 QString
224 {
225  if (m_originalEnvValues.find(envVariable) != m_originalEnvValues.end()) {
226  return m_originalEnvValues.at(envVariable);
227  } else {
228  return QString();
229  }
230 }
231 
232 void
234 {
235  // Set the relevant environment variables from user configuration,
236  // so that later lookups through the standard APIs will follow the
237  // same paths as we have in the user config
238 
239  // First ensure the default paths have been recorded for later, so
240  // we don't erroneously re-read them from the environment
241  // variables we've just set
242  (void)getDefaultPaths();
243  (void)getEnvironmentPaths();
244 
245  Paths paths = getPaths();
246 
247  for (auto p: paths) {
248  QString envVariable = p.second.envVariable;
249  string envVarStr = envVariable.toStdString();
250  string currentValue;
251  getEnvUtf8(envVarStr, currentValue);
252  m_originalEnvValues[envVariable] = QString::fromStdString(currentValue);
253  if (currentValue != "" && p.second.useEnvVariable) {
254  // don't override
255  SVDEBUG << "PluginPathSetter: for environment variable "
256  << envVariable << ", useEnvVariable setting is false; "
257  << "leaving current value alone: it is \""
258  << currentValue << "\"" << endl;
259  continue;
260  }
261  QString separator =
262 #ifdef Q_OS_WIN
263  ";"
264 #else
265  ":"
266 #endif
267  ;
268  QString proposedValue = p.second.directories.join(separator);
269  SVDEBUG << "PluginPathSetter: for environment variable "
270  << envVariable << ", useEnvVariable setting is true or "
271  << "variable is currently unset; "
272  << "changing value from \"" << currentValue
273  << "\" to setting preference of \"" << proposedValue
274  << "\"" << endl;
275  putEnvUtf8(envVarStr, proposedValue.toStdString());
276  }
277 }
278 
bool putEnvUtf8(std::string variable, std::string value)
Set the value of the given environment variable.
Definition: System.cpp:407
static std::vector< TypeKey > getSupportedKeys()
static QString getSettingTagFor(TypeKey)
static void initialiseEnvironmentVariables()
Update *_PATH environment variables from the settings, on application startup.
bool getEnvUtf8(std::string variable, std::string &value)
Return the value of the given environment variable by reference.
Definition: System.cpp:344
bool getRunPluginsInProcess() const
Definition: Preferences.h:53
static Preferences * getInstance()
Definition: Preferences.cpp:31
std::vector< TypeKey > TypeKeys
static QMutex m_mutex
Class to find helper executables that have been installed alongside the application.
static QString getOriginalEnvironmentValue(QString envVariable)
Return the original value observed on startup for the given environment variable, if it is one of the...
static std::map< QString, QString > m_originalEnvValues
static Paths getDefaultPaths()
Return default values of paths only, without any environment variables or user-defined preferences...
static Paths getPaths()
Return paths arising from user settings + environment variables + defaults as appropriate.
static Paths m_environmentPaths
std::pair< KnownPlugins::PluginType, KnownPlugins::BinaryFormat > TypeKey
#define SVDEBUG
Definition: Debug.h:106
static TypeKeys m_supportedKeys
static void savePathSettings(Paths paths)
Save the given paths to the settings.
QList< HelperExec > getHelperExecutables(QString basename)
Find all helper executables with the given base name in the bundle directory or installation location...
static Paths getEnvironmentPathsUncached(const TypeKeys &keys)
static Paths getEnvironmentPaths()
Return paths arising from environment variables only, falling back to the defaults, without any user-defined preferences.
static Paths m_defaultPaths
std::map< TypeKey, PathConfig > Paths