diff --git a/react/public/var/config.json b/react/public/var/config.json
index a16e5a4..c1902a0 100644
--- a/react/public/var/config.json
+++ b/react/public/var/config.json
@@ -1,5 +1,5 @@
{
- "socket_server_port": 8080,
+ "socket_server_port": 80,
"socket_server_address": "*",
"max_upload_size": 1048576,
diff --git a/react/src/PedalBoardView.tsx b/react/src/PedalBoardView.tsx
index a96d79d..042a399 100644
--- a/react/src/PedalBoardView.tsx
+++ b/react/src/PedalBoardView.tsx
@@ -648,7 +648,7 @@ const PedalBoardView =
isTouchDevice(): boolean {
return (('ontouchstart' in window) ||
(navigator.maxTouchPoints > 0) ||
- (navigator.msMaxTouchPoints > 0));
+ (navigator["msMaxTouchPoints"] > 0));
}
onItemDoubleClick(event: SyntheticEvent, instanceId?: number): void {
@@ -737,8 +737,8 @@ const PedalBoardView =
let xEnd = shortSplitOutput ? item.bounds.right : item.bounds.right + CELL_WIDTH / 2;
let xTee0 = item.bounds.right - CELL_WIDTH / 2;
- let firstPath: string;
- let secondPath: string;
+ let firstPath: string; // top or bottom depending on draw order.
+ let secondPath: string; // top or bottom depending on draw order.
let firstPathStereo: boolean;
let secondPathStereo: boolean;
@@ -751,7 +751,24 @@ const PedalBoardView =
let bottomPathFirst = topEnabled && !bottomEnabled;
let topPathFirst = bottomEnabled && !topEnabled;
- if (bottomPathFirst || (topEnabled && lastTop.stereoOutput)) {
+
+ // Third case: L/R stereo output, when both outputs are mono, requires a third stroke.
+ let thirdPath: string | null = null; // for L/R stereo output (which can be stereo even if both outputs are mono)
+ let hasThirdPath = item.stereoOutput && (!lastTop.stereoOutput) && (!lastBottom.stereoOutput);
+
+ if (hasThirdPath) {
+ firstPathStereo = false;
+ secondPathStereo = false;
+ xTee = xTee0 - monoAdjustment;
+ firstPath = new SvgPathBuilder().moveTo(xBottom, yBottom).lineTo(xTee, yBottom).lineTo(xTee, y_).toString();
+
+ secondPath = new SvgPathBuilder().moveTo(xTop, yTop).lineTo(xTee, yTop).lineTo(xTee, y_).toString();
+
+ hasThirdPath = true;
+ thirdPath= new SvgPathBuilder().moveTo(xTee0,y_).lineTo(xEnd,y_).toString();
+ firstPathEnabled = bottomEnabled;
+ secondPathEnabled = topEnabled;
+ } else if (bottomPathFirst || (topEnabled && lastTop.stereoOutput)) {
// draw the bottom path first.
firstPathStereo = item.stereoOutput && lastBottom.stereoOutput;
secondPathStereo = item.stereoOutput && lastTop.stereoOutput;
@@ -840,6 +857,18 @@ const PedalBoardView =
}
}
+ if (thirdPath != null)
+ {
+ // stereo output of L/R splitter
+ output.push((
+
+ ));
+ output.push((
+
+ ));
+
+
+ }
}
getScrollContainer()
{
@@ -1078,6 +1107,8 @@ const PedalBoardView =
} else {
item.stereoOutput = bottomStereo;
}
+ } else if (splitter.getSplitType() === SplitType.Lr) {
+ item.stereoOutput = true;
} else {
item.stereoOutput = topStereo || bottomStereo;
}
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 0a219dc..6d5c72e 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -214,7 +214,9 @@ set (DEBIAN_COPYRIGHT_FILE ${CMAKE_CURRENT_SOURCE_DIR}/../debian/copyright)
# generate Copyright section of settings page.
# warning: there may be multiple versions. Pick the latest.
-if(EXISTS "/usr/share/doc/libboost1.71-dev")
+if(EXISTS "/usr/share/doc/libboost1.74-dev")
+ set (BOOST_COPYRIGHT_DIR "libboost1.74-dev")
+elseif(EXISTS "/usr/share/doc/libboost1.71-dev")
set (BOOST_COPYRIGHT_DIR "libboost1.71-dev")
elseif(EXISTS "/usr/share/doc/libboost1.67-dev")
set (BOOST_COPYRIGHT_DIR "libboost1.67-dev")
diff --git a/src/JackConfiguration.cpp b/src/JackConfiguration.cpp
index f0478b7..a84021d 100644
--- a/src/JackConfiguration.cpp
+++ b/src/JackConfiguration.cpp
@@ -176,12 +176,12 @@ void JackConfiguration::Initialize()
JackChannelSelection JackChannelSelection::MakeDefault(const JackConfiguration&config){
JackChannelSelection result;
- for (size_t i = 0; i < std::max((size_t)2,config.GetInputAudioPorts().size()); ++i)
+ for (size_t i = 0; i < std::min((size_t)2,config.GetInputAudioPorts().size()); ++i)
{
result.inputAudioPorts_.push_back(config.GetInputAudioPorts()[i]);
}
- for (size_t i = 0; i < std::max((size_t)2,config.GetOutputAudioPorts().size()); ++i)
+ for (size_t i = 0; i < std::min((size_t)2,config.GetOutputAudioPorts().size()); ++i)
{
result.outputAudioPorts_.push_back(config.GetOutputAudioPorts()[i]);
}
diff --git a/src/JackHost.cpp b/src/JackHost.cpp
index 2536a42..2afb47e 100644
--- a/src/JackHost.cpp
+++ b/src/JackHost.cpp
@@ -917,6 +917,11 @@ public:
{
std::lock_guard guard(mutex);
+ if (channelSelection.GetInputAudioPorts().size() == 0
+ || channelSelection.getOutputAudioPorts().size() == 0)
+ {
+ return;
+ }
this->currentSample = 0;
this->underruns = 0;
diff --git a/src/Lv2Host.cpp b/src/Lv2Host.cpp
index fde6853..0ecf244 100644
--- a/src/Lv2Host.cpp
+++ b/src/Lv2Host.cpp
@@ -352,13 +352,12 @@ void Lv2Host::Load(const char *lv2Path)
pWorld = lilv_world_new();
lilv_world_load_all(pWorld);
- if (!classesLoaded)
- {
- LoadPluginClassesFromLilv();
- }
const LilvPlugins *plugins = lilv_world_get_all_plugins(pWorld);
+ LoadPluginClassesFromLilv();
+
+
LILV_FOREACH(plugins, iPlugin, plugins)
{
const LilvPlugin *lilvPlugin = lilv_plugins_get(plugins, iPlugin);
diff --git a/src/Lv2Host.hpp b/src/Lv2Host.hpp
index 9a9c4f7..f1b0d2b 100644
--- a/src/Lv2Host.hpp
+++ b/src/Lv2Host.hpp
@@ -81,7 +81,7 @@ class Lv2PluginClass {
public:
friend class Lv2Host;
private:
- Lv2PluginClass* parent_; // NOT SERIALIZED!
+ Lv2PluginClass* parent_ = nullptr; // NOT SERIALIZED!
std::string parent_uri_;
std::string display_name_;
std::string uri_;
diff --git a/src/PiPedalModel.cpp b/src/PiPedalModel.cpp
index b066c97..0d14fd8 100644
--- a/src/PiPedalModel.cpp
+++ b/src/PiPedalModel.cpp
@@ -92,19 +92,6 @@ PiPedalModel::~PiPedalModel()
void PiPedalModel::LoadLv2PluginInfo(const PiPedalConfiguration&configuration)
{
- lv2Host.Load(configuration.GetLv2Path().c_str());
-
-}
-
-void PiPedalModel::Load(const PiPedalConfiguration &configuration)
-{
-
- this->jackServerSettings.ReadJackConfiguration();
-
-
- storage.SetDataRoot(configuration.GetLocalStoragePath().c_str());
- storage.Initialize();
-
// Not all Lv2 directories have the lv2 base declarations. Load a full set of plugin classes generated on a default /usr/local/lib/lv2 directory.
std::filesystem::path pluginClassesPath = configuration.GetDocRoot() / "plugin_classes.json";
try
@@ -119,6 +106,20 @@ void PiPedalModel::Load(const PiPedalConfiguration &configuration)
s << "Unable to load " << pluginClassesPath << ". " << e.what();
throw PiPedalException(s.str().c_str());
}
+
+ lv2Host.Load(configuration.GetLv2Path().c_str());
+
+}
+
+void PiPedalModel::Load(const PiPedalConfiguration &configuration)
+{
+
+ this->jackServerSettings.ReadJackConfiguration();
+
+
+ storage.SetDataRoot(configuration.GetLocalStoragePath().c_str());
+ storage.Initialize();
+
// lv2Host.Load(configuration.GetLv2Path().c_str());
this->pedalBoard = storage.GetCurrentPreset(); // the current *saved* preset.
diff --git a/src/main.cpp b/src/main.cpp
index 637454d..cd9488b 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -552,39 +552,44 @@ int main(int argc, char *argv[])
}
}
}
-
+
// pre-cache device info before we let audio services run.
model.GetAlsaDevices();
+ }
- // Get heavy IO out of the way before letting dependent (Jack) services run.
- model.LoadLv2PluginInfo(configuration);
+ // Get heavy IO out of the way before letting dependent (Jack) services run.
+ model.LoadLv2PluginInfo(configuration);
+ if (systemd)
+ {
// Tell systemd we're done.
- sd_notify(0, "READY=1");
+ sd_notifyf(0, "READY=1\n"
+ "MAINPID=%lu",
+ (unsigned long) getpid());
+ }
- if (!isJackServiceRunning())
+ if (!isJackServiceRunning())
+ {
+ Lv2Log::info("Waiting for Jack service.");
+ // wait up to 15 seconds for the jack service to come online.
+ for (int i = 0; i < 15; ++i)
{
- Lv2Log::info("Waiting for Jack service.");
- // wait up to 15 seconds for the jack service to come online.
- for (int i = 0; i < 15; ++i)
- {
- // use the time to prepopulate ALSA device cache before jack
- // opens the device and we can't read properties.
- model.GetAlsaDevices();
+ // use the time to prepopulate ALSA device cache before jack
+ // opens the device and we can't read properties.
+ model.GetAlsaDevices();
- sleep(1);
- if (isJackServiceRunning())
- {
- break;
- }
+ sleep(1);
+ if (isJackServiceRunning())
+ {
+ break;
}
}
- if (isJackServiceRunning())
- {
- Lv2Log::info("Found Jack service.");
- sleep(3); // jack needs a little time to get up to speed.
- } else {
- Lv2Log::info("Jack service not started.");
- }
+ }
+ if (isJackServiceRunning())
+ {
+ Lv2Log::info("Found Jack service.");
+ sleep(3); // jack needs a little time to get up to speed.
+ } else {
+ Lv2Log::info("Jack service not started.");
}
model.Load(configuration);