Skip to content

Commit

Permalink
Merge pull request #1172 from DC-codes/linuxbuild
Browse files Browse the repository at this point in the history
LV2 plugin format support
  • Loading branch information
apohl79 authored Mar 13, 2023
2 parents 50325ac + fa674bc commit 22654e2
Show file tree
Hide file tree
Showing 9 changed files with 134 additions and 29 deletions.
34 changes: 22 additions & 12 deletions Common/Source/Utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -646,27 +646,37 @@ inline int getLayoutNumChannels(const AudioProcessor::BusesLayout& l, bool isInp
}
#endif

inline String getPluginType(const String& id) {
inline String getPluginType(const String& id, const PluginDescription* pdesc) {
String type;
File f(id);
if (f.exists()) {
if (f.getFileExtension().toLowerCase() == ".dll") {
type = "vst";
if (pdesc != nullptr) {
if (pdesc->pluginFormatName == "AudioUnit") {
type = "au";
} else {
type = f.getFileExtension().toLowerCase().substring(1);
type = pdesc->pluginFormatName.toLowerCase();
}
} else if (id.startsWith("AudioUnit")) {
type = "au";
} else {
type = "unknown";
File f(id);
if (f.exists()) {
if (f.getFileExtension().toLowerCase() == ".dll") {
type = "vst";
} else {
type = f.getFileExtension().toLowerCase().substring(1);
}
} else if (id.startsWith("AudioUnit")) {
type = "au";
} else {
type = "lv2";
}
}
return type;
}

inline String getPluginName(const String& id, bool withType = true) {
inline String getPluginName(const String& id, const PluginDescription* pdesc, bool withType = true) {
String name;
File f(id);
if (f.exists()) {
if (pdesc != nullptr) {
name = pdesc->name;
} else if (f.exists()) {
name = f.getFileNameWithoutExtension();
#if JUCE_MAC && AG_SERVER
} else if (id.startsWith("AudioUnit")) {
Expand All @@ -677,7 +687,7 @@ inline String getPluginName(const String& id, bool withType = true) {
name = id;
}
if (withType) {
name << " (" << getPluginType(id) << ")";
name << " (" << getPluginType(id, pdesc) << ")";
}
return name;
}
Expand Down
1 change: 1 addition & 0 deletions Server/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ target_compile_definitions(AudioGridderServer PRIVATE
AG_SENTRY_CRASHPAD_PATH="${AG_SENTRY_CRASHPAD_PATH}"
JUCE_PLUGINHOST_VST3=1
JUCE_PLUGINHOST_VST=${AG_PLUGINHOST_VST}
JUCE_PLUGINHOST_LV2=1
JUCE_WEB_BROWSER=0
JUCE_USE_CURL=0
JUCE_MODAL_LOOPS_PERMITTED=1
Expand Down
3 changes: 2 additions & 1 deletion Server/Source/PluginListComponent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ class PluginListComponent::TableModel : public TableListBoxModel {

File f(name);
String type;
if (f.getFileExtension().toLowerCase() == ".vst" || f.getFileExtension().toLowerCase() == ".vst3") {
if (f.getFileExtension().toLowerCase() == ".lv2" || f.getFileExtension().toLowerCase() == ".vst" ||
f.getFileExtension().toLowerCase() == ".vst3") {
name = f.getFileNameWithoutExtension();
type = f.getFileExtension().toUpperCase().substring(1);
} else if (f.getFileExtension().toLowerCase() == ".dll") {
Expand Down
9 changes: 8 additions & 1 deletion Server/Source/Processor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ Processor::Processor(ProcessorChain& chain, const String& id, double sampleRate,
m_isClient(isClient),
m_fmt(id.startsWith("VST3") ? VST3
: id.startsWith("VST") ? VST
: id.startsWith("LV2") ? LV2
: AU) {
initAsyncFunctors();

Expand Down Expand Up @@ -93,7 +94,7 @@ String Processor::convertJUCEtoAGPluginID(const String& id) {

if ((pos = id.indexOfChar(0, '-')) > -1) {
format = id.substring(0, pos);
if (format != "AudioUnit" && format != "VST" && format != "VST3") {
if (format != "AudioUnit" && format != "VST" && format != "VST3" && format != "LV2") {
return {};
}
name = id.substring(pos + 1);
Expand Down Expand Up @@ -307,6 +308,12 @@ std::shared_ptr<AudioPluginInstance> Processor::loadPlugin(const PluginDescripti
String err2;
AudioPluginFormatManager plugmgr;
plugmgr.addDefaultFormats();
#if JUCE_PLUGINHOST_LV2
if (plugdesc.pluginFormatName == "LV2") {
AudioPluginFormat* fmt = new LV2PluginFormat();
plugmgr.addFormat(fmt);
}
#endif
std::shared_ptr<AudioPluginInstance> inst;
runOnMsgThreadSync([&] {
traceScope();
Expand Down
2 changes: 1 addition & 1 deletion Server/Source/Processor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ class Processor : public LogTagDelegate, public std::enable_shared_from_this<Pro
int m_lastKnownLatency = 0;
Point<int> m_lastPosition = {0, 0};

enum FormatType { VST, VST3, AU };
enum FormatType { VST, VST3, AU, LV2 };
FormatType m_fmt;

std::shared_ptr<AudioPluginInstance> getPlugin(int channel) {
Expand Down
63 changes: 52 additions & 11 deletions Server/Source/Server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,20 @@ void Server::loadConfig() {
}
m_vstNoStandardFolders = jsonGetValue(cfg, "VSTNoStandardFolders", false);
logln("include VST standard folders is " << (m_vstNoStandardFolders ? "disabled" : "enabled"));

m_enableLV2 = jsonGetValue(cfg, "LV2", m_enableLV2);
logln("LV2 support " << (m_enableLV2 ? "enabled" : "disabled"));
m_lv2Folders.clear();
if (jsonHasValue(cfg, "LV2Folders") && cfg["LV2Folders"].size() > 0) {
logln("LV2 custom folders:");
for (auto& s : cfg["LV2Folders"]) {
if (s.get<std::string>().length() > 0) {
logln(" " << s.get<std::string>());
m_lv2Folders.add(s.get<std::string>());
}
}
}

m_screenCapturingFFmpeg = jsonGetValue(cfg, "ScreenCapturingFFmpeg", m_screenCapturingFFmpeg);
String encoder = "webp";
m_screenCapturingFFmpegEncMode = ScreenRecorder::WEBP;
Expand Down Expand Up @@ -184,6 +198,11 @@ void Server::saveConfig() {
for (auto& f : m_vst2Folders) {
j["VST2Folders"].push_back(f.toStdString());
}
j["LV2"] = m_enableLV2;
j["LV2Folders"] = json::array();
for (auto& f : m_lv2Folders) {
j["LV2Folders"].push_back(f.toStdString());
}
j["VSTNoStandardFolders"] = m_vstNoStandardFolders;
j["ScreenCapturingFFmpeg"] = m_screenCapturingFFmpeg;
switch (m_screenCapturingFFmpegEncMode) {
Expand Down Expand Up @@ -251,6 +270,10 @@ void Server::loadKnownPluginList() {
#endif
} else if (desc.pluginFormatName == "VST3") {
fmt = std::make_unique<VST3PluginFormat>();
#if JUCE_PLUGINHOST_LV2
} else if (desc.pluginFormatName == "LV2") {
fmt = std::make_unique<LV2PluginFormat>();
#endif
}

if (nullptr != fmt) {
Expand Down Expand Up @@ -545,6 +568,10 @@ bool Server::scanPlugin(const String& id, const String& format, int srvId, bool
#if JUCE_MAC
} else if (!format.compare("AudioUnit")) {
fmt = std::make_unique<AudioUnitPluginFormat>();
#endif
#if JUCE_PLUGINHOST_LV2
} else if (!format.compare("LV2")) {
fmt = std::make_unique<LV2PluginFormat>();
#endif
} else {
return false;
Expand Down Expand Up @@ -818,7 +845,7 @@ void Server::scanForPlugins(const std::vector<String>& include) {
traceScope();
logln("scanning for plugins...");
std::vector<std::unique_ptr<AudioPluginFormat>> fmts;
size_t fmtAU = 0, fmtVST = 0, fmtVST3 = 0;
size_t fmtAU = 0, fmtVST = 0, fmtVST3 = 0, fmtLV2 = 0;

#if JUCE_MAC
if (m_enableAU) {
Expand All @@ -836,6 +863,12 @@ void Server::scanForPlugins(const std::vector<String>& include) {
fmts.push_back(std::make_unique<VSTPluginFormat>());
}
#endif
#if JUCE_PLUGINHOST_LV2
if (m_enableLV2) {
fmtLV2 = fmts.size();
fmts.push_back(std::make_unique<LV2PluginFormat>());
}
#endif

std::set<String> neverSeenList = m_pluginExclude;
std::set<String> newBlacklistedPlugins;
Expand Down Expand Up @@ -863,20 +896,25 @@ void Server::scanForPlugins(const std::vector<String>& include) {
std::atomic<float> progress{0};

StringArray fileOrIds;
KnownPluginList pluginList;

for (auto& fmt : fmts) {
FileSearchPath searchPaths;
if (fmt->getName().compare("AudioUnit") && !m_vstNoStandardFolders) {
if (fmt->getName() != "AudioUnit" && (!fmt->getName().startsWith("VST") || !m_vstNoStandardFolders)) {
searchPaths = fmt->getDefaultLocationsToSearch();
}
if (!fmt->getName().compare("VST3")) {
if (fmt->getName() == "VST3") {
for (auto& f : m_vst3Folders) {
searchPaths.addIfNotAlreadyThere(f);
}
} else if (!fmt->getName().compare("VST")) {
} else if (fmt->getName() == "VST") {
for (auto& f : m_vst2Folders) {
searchPaths.addIfNotAlreadyThere(f);
}
} else if (fmt->getName() == "LV2") {
for (auto& f : m_lv2Folders) {
searchPaths.addIfNotAlreadyThere(f);
}
}
searchPaths.removeRedundantPaths();
searchPaths.removeNonExistentPaths();
Expand All @@ -885,21 +923,23 @@ void Server::scanForPlugins(const std::vector<String>& include) {

for (int idx = 0; idx < fileOrIds.size(); idx++) {
auto& fileOrId = fileOrIds.getReference(idx);
auto name = getPluginName(fileOrId, false);
auto type = getPluginType(fileOrId);
auto pluginDesc = m_pluginList.getTypeForFile(fileOrId);
auto name = getPluginName(fileOrId, pluginDesc.get(), false);
auto type = getPluginType(fileOrId, pluginDesc.get());

auto* fmt = type == "au" ? fmts[fmtAU].get()
: type == "vst3" ? fmts[fmtVST3].get()
: type == "vst" ? fmts[fmtVST].get()
: type == "lv2" ? fmts[fmtLV2].get()
: nullptr;

if (nullptr == fmt) {
logln("error: can't detect plugin format for " << fileOrId);
continue;
}

auto plugindesc = m_pluginList.getTypeForFile(fileOrId);
bool excluded = shouldExclude(name, fileOrId, include);
if ((nullptr == plugindesc || fmt->pluginNeedsRescanning(*plugindesc)) &&
if ((nullptr == pluginDesc || fmt->pluginNeedsRescanning(*pluginDesc)) &&
!m_pluginList.getBlacklistedFiles().contains(fileOrId) && newBlacklistedPlugins.count(fileOrId) == 0 &&
!excluded) {
ScanThread* scanThread = nullptr;
Expand All @@ -915,7 +955,7 @@ void Server::scanForPlugins(const std::vector<String>& include) {
}
} while (scanThread == nullptr);

String splashName = getPluginName(fileOrId);
String splashName = getPluginName(fileOrId, pluginDesc.get());

progress = (float)idx / fileOrIds.size() * 100.0f;

Expand Down Expand Up @@ -999,7 +1039,8 @@ void Server::processScanResults(int id, std::set<String>& newBlacklistedPlugins)
for (auto& p : plist.getBlacklistedFiles()) {
if (!m_pluginList.getBlacklistedFiles().contains(p)) {
m_pluginList.addToBlacklist(p);
newBlacklistedPlugins.insert(getPluginName(p));
auto pdesc = plist.getTypeForIdentifierString(p);
newBlacklistedPlugins.insert(getPluginName(p, pdesc.get()));
}
}

Expand All @@ -1022,7 +1063,7 @@ void Server::processScanResults(int id, std::set<String>& newBlacklistedPlugins)
deadmanFile.readLines(lines);

for (auto& line : lines) {
newBlacklistedPlugins.insert(getPluginName(line));
newBlacklistedPlugins.insert(getPluginName(line, nullptr));
}

deadmanFile.deleteFile();
Expand Down
6 changes: 6 additions & 0 deletions Server/Source/Server.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ class Server : public Thread, public LogTag {
void setEnableVST3(bool b) { m_enableVST3 = b; }
bool getEnableVST2() const { return m_enableVST2; }
void setEnableVST2(bool b) { m_enableVST2 = b; }
bool getEnableLV2() const { return m_enableLV2; }
void setEnableLV2(bool b) { m_enableLV2 = b; }
const StringArray& getLV2Folders() const { return m_lv2Folders; }
void setLV2Folders(const StringArray& folders) { m_lv2Folders = folders; }
const StringArray& getVST3Folders() const { return m_vst3Folders; }
void setVST3Folders(const StringArray& folders) { m_vst3Folders = folders; }
const StringArray& getVST2Folders() const { return m_vst2Folders; }
Expand Down Expand Up @@ -154,6 +158,7 @@ class Server : public Thread, public LogTag {
bool m_enableAU = true;
bool m_enableVST3 = true;
bool m_enableVST2 = true;
bool m_enableLV2 = true;
float m_screenJpgQuality = 0.9f;
bool m_screenDiffDetection = true;
bool m_screenCapturingFFmpeg = true;
Expand All @@ -170,6 +175,7 @@ class Server : public Thread, public LogTag {
ScreenRecorder::EncoderQuality m_screenCapturingFFmpegQuality = ScreenRecorder::ENC_QUALITY_MEDIUM;
StringArray m_vst3Folders;
StringArray m_vst2Folders;
StringArray m_lv2Folders;
bool m_vstNoStandardFolders;
bool m_scanForPlugins = true;
bool m_crashReporting = true;
Expand Down
38 changes: 38 additions & 0 deletions Server/Source/ServerSettingsWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,39 @@ ServerSettingsWindow::ServerSettingsWindow(App* app)
tooltip.clear();
row++;

label = std::make_unique<Label>();
label->setText("LV2 Support:", NotificationType::dontSendNotification);
label->setBounds(getLabelBounds(row));
addChildAndSetID(label.get(), "lbl");
m_components.push_back(std::move(label));

m_lv2Support.setBounds(getCheckBoxBounds(row));
m_lv2Support.setToggleState(srv->getEnableLV2(), NotificationType::dontSendNotification);
addChildAndSetID(&m_lv2Support, "lv2");

row++;

label = std::make_unique<Label>();
tmpStr = "LV2 Custom Folders";
tmpStr << newLine << "(one folder per line):";
label->setText(tmpStr, NotificationType::dontSendNotification);
label->setBounds(getLabelBounds(row));
addChildAndSetID(label.get(), "lbl");
m_components.push_back(std::move(label));

m_lv2Folders.setBounds(getLargeFieldBounds(row));
m_lv2Folders.setMultiLine(true, false);
m_lv2Folders.setReturnKeyStartsNewLine(true);
addChildAndSetID(&m_lv2Folders, "lv2fold");

tmpStr = "";
for (auto& folder : srv->getLV2Folders()) {
tmpStr << folder << newLine;
}
m_lv2Folders.setText(tmpStr);

row += largeFieldRows;

label = std::make_unique<Label>();
label->setText("Screen Capturing", NotificationType::dontSendNotification);
label->setJustificationType(Justification::centredTop);
Expand Down Expand Up @@ -552,6 +585,7 @@ ServerSettingsWindow::ServerSettingsWindow(App* app)
srv2->setEnableAU(m_auSupport.getToggleState());
srv2->setEnableVST3(m_vst3Support.getToggleState());
srv2->setEnableVST2(m_vst2Support.getToggleState());
srv2->setEnableLV2(m_lv2Support.getToggleState());
srv2->setScanForPlugins(m_scanForPlugins.getToggleState());
srv2->setSandboxMode((Server::SandboxMode)m_sandboxMode.getSelectedItemIndex());
srv2->setCrashReporting(m_crashReporting.getToggleState());
Expand Down Expand Up @@ -611,6 +645,10 @@ ServerSettingsWindow::ServerSettingsWindow(App* app)
}
srv2->setVSTNoStandardFolders(m_vstNoStandardFolders.getToggleState());

if (m_lv2Folders.getText().length() > 0) {
srv2->setLV2Folders(StringArray::fromLines(m_lv2Folders.getText()));
}

auto offsetParts = StringArray::fromTokens(m_screenMouseOffsetXY.getText(), "x", "");
if (offsetParts.size() >= 2) {
srv2->setScreenMouseOffsetX(offsetParts[0].getIntValue());
Expand Down
7 changes: 4 additions & 3 deletions Server/Source/ServerSettingsWindow.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,10 @@ class ServerSettingsWindow : public DocumentWindow, public LogTag {
private:
App* m_app;
std::vector<std::unique_ptr<Component>> m_components;
TextEditor m_idText, m_nameText, m_screenJpgQuality, m_vst2Folders, m_vst3Folders, m_screenMouseOffsetXY;
ToggleButton m_auSupport, m_vst3Support, m_vst2Support, m_screenDiffDetection, m_scanForPlugins, m_tracer, m_logger,
m_vstNoStandardFolders, m_pluginWindowsOnTop, m_crashReporting;
TextEditor m_idText, m_nameText, m_screenJpgQuality, m_vst2Folders, m_vst3Folders, m_lv2Folders,
m_screenMouseOffsetXY;
ToggleButton m_auSupport, m_vst3Support, m_vst2Support, m_lv2Support, m_screenDiffDetection, m_scanForPlugins,
m_tracer, m_logger, m_vstNoStandardFolders, m_pluginWindowsOnTop, m_crashReporting;
TextButton m_saveButton;
Label m_screenJpgQualityLbl, m_screenDiffDetectionLbl, m_screenCapturingQualityLbl, m_pluginWindowsOnTopLbl;
ComboBox m_screenCapturingMode, m_screenCapturingQuality, m_sandboxMode;
Expand Down

0 comments on commit 22654e2

Please sign in to comment.