Startup crash; crash when no audio device

This commit is contained in:
Robin Davies
2021-10-18 14:57:10 -04:00
parent 11b2a94b17
commit 416f9ff3cf
9 changed files with 93 additions and 50 deletions
+1 -1
View File
@@ -1,5 +1,5 @@
{ {
"socket_server_port": 8080, "socket_server_port": 80,
"socket_server_address": "*", "socket_server_address": "*",
"max_upload_size": 1048576, "max_upload_size": 1048576,
+35 -4
View File
@@ -648,7 +648,7 @@ const PedalBoardView =
isTouchDevice(): boolean { isTouchDevice(): boolean {
return (('ontouchstart' in window) || return (('ontouchstart' in window) ||
(navigator.maxTouchPoints > 0) || (navigator.maxTouchPoints > 0) ||
(navigator.msMaxTouchPoints > 0)); (navigator["msMaxTouchPoints"] > 0));
} }
onItemDoubleClick(event: SyntheticEvent, instanceId?: number): void { 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 xEnd = shortSplitOutput ? item.bounds.right : item.bounds.right + CELL_WIDTH / 2;
let xTee0 = item.bounds.right - CELL_WIDTH / 2; let xTee0 = item.bounds.right - CELL_WIDTH / 2;
let firstPath: string; let firstPath: string; // top or bottom depending on draw order.
let secondPath: string; let secondPath: string; // top or bottom depending on draw order.
let firstPathStereo: boolean; let firstPathStereo: boolean;
let secondPathStereo: boolean; let secondPathStereo: boolean;
@@ -751,7 +751,24 @@ const PedalBoardView =
let bottomPathFirst = topEnabled && !bottomEnabled; let bottomPathFirst = topEnabled && !bottomEnabled;
let topPathFirst = bottomEnabled && !topEnabled; 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. // draw the bottom path first.
firstPathStereo = item.stereoOutput && lastBottom.stereoOutput; firstPathStereo = item.stereoOutput && lastBottom.stereoOutput;
secondPathStereo = item.stereoOutput && lastTop.stereoOutput; secondPathStereo = item.stereoOutput && lastTop.stereoOutput;
@@ -840,6 +857,18 @@ const PedalBoardView =
} }
} }
if (thirdPath != null)
{
// stereo output of L/R splitter
output.push((
<path d={thirdPath} stroke={secondPathColor} strokeWidth={SVG_STEREO_STROKE_WIDTH} />
));
output.push((
<path d={thirdPath} stroke="white" strokeWidth={SVG_STROKE_WIDTH} />
));
}
} }
getScrollContainer() getScrollContainer()
{ {
@@ -1078,6 +1107,8 @@ const PedalBoardView =
} else { } else {
item.stereoOutput = bottomStereo; item.stereoOutput = bottomStereo;
} }
} else if (splitter.getSplitType() === SplitType.Lr) {
item.stereoOutput = true;
} else { } else {
item.stereoOutput = topStereo || bottomStereo; item.stereoOutput = topStereo || bottomStereo;
} }
+3 -1
View File
@@ -214,7 +214,9 @@ set (DEBIAN_COPYRIGHT_FILE ${CMAKE_CURRENT_SOURCE_DIR}/../debian/copyright)
# generate Copyright section of settings page. # generate Copyright section of settings page.
# warning: there may be multiple versions. Pick the latest. # 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") set (BOOST_COPYRIGHT_DIR "libboost1.71-dev")
elseif(EXISTS "/usr/share/doc/libboost1.67-dev") elseif(EXISTS "/usr/share/doc/libboost1.67-dev")
set (BOOST_COPYRIGHT_DIR "libboost1.67-dev") set (BOOST_COPYRIGHT_DIR "libboost1.67-dev")
+2 -2
View File
@@ -176,12 +176,12 @@ void JackConfiguration::Initialize()
JackChannelSelection JackChannelSelection::MakeDefault(const JackConfiguration&config){ JackChannelSelection JackChannelSelection::MakeDefault(const JackConfiguration&config){
JackChannelSelection result; 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]); 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]); result.outputAudioPorts_.push_back(config.GetOutputAudioPorts()[i]);
} }
+5
View File
@@ -917,6 +917,11 @@ public:
{ {
std::lock_guard guard(mutex); std::lock_guard guard(mutex);
if (channelSelection.GetInputAudioPorts().size() == 0
|| channelSelection.getOutputAudioPorts().size() == 0)
{
return;
}
this->currentSample = 0; this->currentSample = 0;
this->underruns = 0; this->underruns = 0;
+3 -4
View File
@@ -352,13 +352,12 @@ void Lv2Host::Load(const char *lv2Path)
pWorld = lilv_world_new(); pWorld = lilv_world_new();
lilv_world_load_all(pWorld); lilv_world_load_all(pWorld);
if (!classesLoaded)
{
LoadPluginClassesFromLilv();
}
const LilvPlugins *plugins = lilv_world_get_all_plugins(pWorld); const LilvPlugins *plugins = lilv_world_get_all_plugins(pWorld);
LoadPluginClassesFromLilv();
LILV_FOREACH(plugins, iPlugin, plugins) LILV_FOREACH(plugins, iPlugin, plugins)
{ {
const LilvPlugin *lilvPlugin = lilv_plugins_get(plugins, iPlugin); const LilvPlugin *lilvPlugin = lilv_plugins_get(plugins, iPlugin);
+1 -1
View File
@@ -81,7 +81,7 @@ class Lv2PluginClass {
public: public:
friend class Lv2Host; friend class Lv2Host;
private: private:
Lv2PluginClass* parent_; // NOT SERIALIZED! Lv2PluginClass* parent_ = nullptr; // NOT SERIALIZED!
std::string parent_uri_; std::string parent_uri_;
std::string display_name_; std::string display_name_;
std::string uri_; std::string uri_;
+14 -13
View File
@@ -92,19 +92,6 @@ PiPedalModel::~PiPedalModel()
void PiPedalModel::LoadLv2PluginInfo(const PiPedalConfiguration&configuration) 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. // 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"; std::filesystem::path pluginClassesPath = configuration.GetDocRoot() / "plugin_classes.json";
try try
@@ -119,6 +106,20 @@ void PiPedalModel::Load(const PiPedalConfiguration &configuration)
s << "Unable to load " << pluginClassesPath << ". " << e.what(); s << "Unable to load " << pluginClassesPath << ". " << e.what();
throw PiPedalException(s.str().c_str()); 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()); // lv2Host.Load(configuration.GetLv2Path().c_str());
this->pedalBoard = storage.GetCurrentPreset(); // the current *saved* preset. this->pedalBoard = storage.GetCurrentPreset(); // the current *saved* preset.
+29 -24
View File
@@ -552,39 +552,44 @@ int main(int argc, char *argv[])
} }
} }
} }
// pre-cache device info before we let audio services run. // pre-cache device info before we let audio services run.
model.GetAlsaDevices(); model.GetAlsaDevices();
}
// Get heavy IO out of the way before letting dependent (Jack) services run. // Get heavy IO out of the way before letting dependent (Jack) services run.
model.LoadLv2PluginInfo(configuration); model.LoadLv2PluginInfo(configuration);
if (systemd)
{
// Tell systemd we're done. // 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."); // use the time to prepopulate ALSA device cache before jack
// wait up to 15 seconds for the jack service to come online. // opens the device and we can't read properties.
for (int i = 0; i < 15; ++i) 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); sleep(1);
if (isJackServiceRunning()) if (isJackServiceRunning())
{ {
break; break;
}
} }
} }
if (isJackServiceRunning()) }
{ if (isJackServiceRunning())
Lv2Log::info("Found Jack service."); {
sleep(3); // jack needs a little time to get up to speed. Lv2Log::info("Found Jack service.");
} else { sleep(3); // jack needs a little time to get up to speed.
Lv2Log::info("Jack service not started."); } else {
} Lv2Log::info("Jack service not started.");
} }
model.Load(configuration); model.Load(configuration);