Chris@4: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@5: /* Chris@5: Copyright (c) 2016 Queen Mary, University of London Chris@5: Chris@5: Permission is hereby granted, free of charge, to any person Chris@5: obtaining a copy of this software and associated documentation Chris@5: files (the "Software"), to deal in the Software without Chris@5: restriction, including without limitation the rights to use, copy, Chris@5: modify, merge, publish, distribute, sublicense, and/or sell copies Chris@5: of the Software, and to permit persons to whom the Software is Chris@5: furnished to do so, subject to the following conditions: Chris@5: Chris@5: The above copyright notice and this permission notice shall be Chris@5: included in all copies or substantial portions of the Software. Chris@5: Chris@5: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, Chris@5: EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF Chris@5: MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND Chris@5: NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY Chris@5: CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF Chris@5: CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION Chris@5: WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Chris@5: Chris@5: Except as contained in this notice, the names of the Centre for Chris@5: Digital Music and Queen Mary, University of London shall not be Chris@5: used in advertising or otherwise to promote the sale, use or other Chris@5: dealings in this Software without prior written authorization. Chris@5: */ Chris@4: Chris@4: #include "knownplugins.h" Chris@4: Chris@4: #include Chris@4: Chris@4: using namespace std; Chris@4: Chris@4: #if defined(_WIN32) Chris@4: #define PATH_SEPARATOR ';' Chris@4: #else Chris@4: #define PATH_SEPARATOR ':' Chris@4: #endif Chris@4: Chris@6: KnownPlugins::KnownPlugins(string helperExecutableName, Chris@6: PluginCandidates::LogCallback *cb) : Chris@6: m_candidates(helperExecutableName) Chris@4: { Chris@6: m_candidates.setLogCallback(cb); Chris@6: Chris@4: m_known = { Chris@19: { Chris@19: VampPlugin, Chris@19: { Chris@19: "vamp", Chris@19: expandConventionalPath(VampPlugin, "VAMP_PATH"), Chris@19: "vampGetPluginDescriptor" Chris@19: }, Chris@19: }, { Chris@19: LADSPAPlugin, Chris@19: { Chris@19: "ladspa", Chris@19: expandConventionalPath(LADSPAPlugin, "LADSPA_PATH"), Chris@19: "ladspa_descriptor" Chris@19: }, Chris@19: }, { Chris@19: DSSIPlugin, Chris@19: { Chris@19: "dssi", Chris@19: expandConventionalPath(DSSIPlugin, "DSSI_PATH"), Chris@19: "dssi_descriptor" Chris@19: } Chris@19: } Chris@4: }; Chris@4: Chris@4: for (const auto &k: m_known) { Chris@19: m_candidates.scan(k.second.tag, k.second.path, k.second.descriptor); Chris@4: } Chris@4: } Chris@4: Chris@4: string Chris@4: KnownPlugins::getDefaultPath(PluginType type) Chris@4: { Chris@4: switch (type) { Chris@4: Chris@4: #if defined(_WIN32) Chris@4: Chris@4: case VampPlugin: Chris@19: return "%ProgramFiles%\\Vamp Plugins"; Chris@4: case LADSPAPlugin: Chris@19: return "%ProgramFiles%\\LADSPA Plugins;%ProgramFiles%\\Audacity\\Plug-Ins"; Chris@4: case DSSIPlugin: Chris@19: return "%ProgramFiles%\\DSSI Plugins"; Chris@19: Chris@4: #elif defined(__APPLE__) Chris@19: Chris@4: case VampPlugin: Chris@19: return "$HOME/Library/Audio/Plug-Ins/Vamp:/Library/Audio/Plug-Ins/Vamp"; Chris@4: case LADSPAPlugin: Chris@19: return "$HOME/Library/Audio/Plug-Ins/LADSPA:/Library/Audio/Plug-Ins/LADSPA"; Chris@4: case DSSIPlugin: Chris@19: return "$HOME/Library/Audio/Plug-Ins/DSSI:/Library/Audio/Plug-Ins/DSSI"; Chris@19: Chris@4: #else /* Linux, BSDs, etc */ Chris@19: Chris@4: case VampPlugin: Chris@19: return "$HOME/vamp:$HOME/.vamp:/usr/local/lib/vamp:/usr/lib/vamp"; Chris@4: case LADSPAPlugin: Chris@19: return "$HOME/ladspa:$HOME/.ladspa:/usr/local/lib/ladspa:/usr/lib/ladspa"; Chris@4: case DSSIPlugin: Chris@19: return "$HOME/dssi:$HOME/.dssi:/usr/local/lib/dssi:/usr/lib/dssi"; Chris@4: #endif Chris@4: } Chris@4: Chris@4: throw logic_error("unknown or unhandled plugin type"); Chris@4: } Chris@4: Chris@4: vector Chris@4: KnownPlugins::expandConventionalPath(PluginType type, string var) Chris@4: { Chris@4: vector pathList; Chris@4: string path; Chris@4: Chris@4: char *cpath = getenv(var.c_str()); Chris@4: if (cpath) path = cpath; Chris@4: Chris@4: if (path == "") { Chris@4: Chris@4: path = getDefaultPath(type); Chris@4: Chris@19: if (path != "") { Chris@4: Chris@19: char *home = getenv("HOME"); Chris@19: if (home) { Chris@19: string::size_type f; Chris@19: while ((f = path.find("$HOME")) != string::npos && Chris@19: f < path.length()) { Chris@19: path.replace(f, 5, home); Chris@19: } Chris@19: } Chris@4: Chris@4: #ifdef _WIN32 Chris@12: const char *pfiles = getenv("ProgramFiles"); Chris@19: if (!pfiles) pfiles = "C:\\Program Files"; Chris@19: { Chris@19: string::size_type f; Chris@19: while ((f = path.find("%ProgramFiles%")) != string::npos && Chris@19: f < path.length()) { Chris@19: path.replace(f, 14, pfiles); Chris@19: } Chris@19: } Chris@4: #endif Chris@19: } Chris@4: } Chris@4: Chris@4: string::size_type index = 0, newindex = 0; Chris@4: Chris@4: while ((newindex = path.find(PATH_SEPARATOR, index)) < path.size()) { Chris@19: pathList.push_back(path.substr(index, newindex - index).c_str()); Chris@19: index = newindex + 1; Chris@4: } Chris@4: Chris@4: pathList.push_back(path.substr(index)); Chris@4: Chris@4: return pathList; Chris@4: } Chris@4: Chris@4: string Chris@4: KnownPlugins::getFailureReport() const Chris@4: { Chris@4: vector failures; Chris@4: Chris@4: for (auto t: getKnownPluginTypes()) { Chris@19: auto ff = m_candidates.getFailedLibrariesFor(getTagFor(t)); Chris@19: failures.insert(failures.end(), ff.begin(), ff.end()); Chris@4: } Chris@4: Chris@4: if (failures.empty()) return ""; Chris@4: Chris@15: int n = int(failures.size()); Chris@4: int i = 0; Chris@4: Chris@4: ostringstream os; Chris@4: Chris@4: os << "
    "; Chris@4: for (auto f: failures) { Chris@19: os << "
  • " + f.library; Chris@19: if (f.message != "") { Chris@19: os << "
    " + f.message + ""; Chris@19: } else { Chris@19: os << "
    unknown error"; Chris@19: } Chris@19: os << "
  • "; Chris@4: Chris@19: if (n > 10) { Chris@19: if (++i == 5) { Chris@19: os << "
  • (... and " << (n - i) << " further failures)
  • "; Chris@19: break; Chris@19: } Chris@19: } Chris@4: } Chris@4: os << "
"; Chris@4: Chris@4: return os.str(); Chris@4: }