From 416f9ff3cfb4b1c74b23efa4ab5c48a6e9b5e731 Mon Sep 17 00:00:00 2001 From: Robin Davies Date: Mon, 18 Oct 2021 14:57:10 -0400 Subject: [PATCH] Startup crash; crash when no audio device --- react/public/var/config.json | 2 +- react/src/PedalBoardView.tsx | 39 +++++++++++++++++++++++--- src/CMakeLists.txt | 4 ++- src/JackConfiguration.cpp | 4 +-- src/JackHost.cpp | 5 ++++ src/Lv2Host.cpp | 7 ++--- src/Lv2Host.hpp | 2 +- src/PiPedalModel.cpp | 27 +++++++++--------- src/main.cpp | 53 ++++++++++++++++++++---------------- 9 files changed, 93 insertions(+), 50 deletions(-) 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);