annotate plugin/PluginPathSetter.cpp @ 1838:403e961ec6ab

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