Misc bug fixes

Alsa trace, NAM legacy flag,
This commit is contained in:
Robin E. R. Davies
2025-09-02 09:50:14 -04:00
parent 5434f40ca1
commit faca1d1ea1
8 changed files with 122 additions and 54 deletions
+59 -5
View File
@@ -37,6 +37,8 @@
#include "DummyAudioDriver.hpp" #include "DummyAudioDriver.hpp"
#include "SchedulerPriority.hpp" #include "SchedulerPriority.hpp"
#include "CrashGuard.hpp" #include "CrashGuard.hpp"
#include <iostream>
#include <iomanip>
#include "CpuUse.hpp" #include "CpuUse.hpp"
@@ -260,6 +262,8 @@ namespace pipedal
std::vector<BufferTrace> bufferTraces{1000}; std::vector<BufferTrace> bufferTraces{1000};
size_t bufferTraceIndex = 0; size_t bufferTraceIndex = 0;
virtual void DumpBufferTrace(size_t nEntries) override;
inline void TraceBufferPositions(size_t framesInBuffer, char code = ' ') inline void TraceBufferPositions(size_t framesInBuffer, char code = ' ')
{ {
#if TRACE_BUFFER_POSITIONS #if TRACE_BUFFER_POSITIONS
@@ -1077,7 +1081,7 @@ namespace pipedal
float *p = (float *)rawPlaybackBuffer.data(); float *p = (float *)rawPlaybackBuffer.data();
std::vector<float *> &buffers = this->playbackBuffers; std::vector<float *> &buffers = this->playbackBuffers;
int channels = this->captureChannels; int channels = this->playbackChannels;
for (size_t frame = 0; frame < frames; ++frame) for (size_t frame = 0; frame < frames; ++frame)
{ {
for (int channel = 0; channel < channels; ++channel) for (int channel = 0; channel < channels; ++channel)
@@ -1092,7 +1096,7 @@ namespace pipedal
float *p = (float *)rawPlaybackBuffer.data(); float *p = (float *)rawPlaybackBuffer.data();
std::vector<float *> &buffers = this->playbackBuffers; std::vector<float *> &buffers = this->playbackBuffers;
int channels = this->captureChannels; int channels = this->playbackChannels;
for (size_t frame = 0; frame < frames; ++frame) for (size_t frame = 0; frame < frames; ++frame)
{ {
for (int channel = 0; channel < channels; ++channel) for (int channel = 0; channel < channels; ++channel)
@@ -1167,7 +1171,6 @@ namespace pipedal
OpenAudio(this->jackServerSettings, this->channelSelection); OpenAudio(this->jackServerSettings, this->channelSelection);
validate_capture_handle(); validate_capture_handle();
FillOutputBuffer(); FillOutputBuffer();
audioRunning = true;
} }
catch (const std::exception &e) catch (const std::exception &e)
{ {
@@ -1180,6 +1183,7 @@ namespace pipedal
Lv2Log::error(SS("Unable to restart ALSA capture: " << snd_strerror(err))); Lv2Log::error(SS("Unable to restart ALSA capture: " << snd_strerror(err)));
throw PiPedalStateException("Unable to restart ALSA capture."); throw PiPedalStateException("Unable to restart ALSA capture.");
} }
audioRunning = true;
} }
void PrepareCaptureFunctions(snd_pcm_format_t captureFormat) void PrepareCaptureFunctions(snd_pcm_format_t captureFormat)
@@ -1617,6 +1621,8 @@ namespace pipedal
auto frame_bytes = this->captureFrameSize; auto frame_bytes = this->captureFrameSize;
do do
{ {
TraceBufferPositions(framesRead,'1');
framesRead = snd_pcm_readi(handle, buffer, frames); framesRead = snd_pcm_readi(handle, buffer, frames);
if (framesRead < 0) if (framesRead < 0)
{ {
@@ -1629,10 +1635,12 @@ namespace pipedal
} }
if (framesRead == 0) if (framesRead == 0)
{ {
snd_pcm_wait(captureHandle, 1); snd_pcm_wait(handle, frames);
} }
TraceBufferPositions(framesRead);
} while (frames > 0); } while (frames > 0);
TraceBufferPositions(framesRead,'2');
return framesRead; return framesRead;
} }
@@ -2331,4 +2339,50 @@ namespace pipedal
{ {
snd_config_update_free_global(); // to get a clean Valgrind report. snd_config_update_free_global(); // to get a clean Valgrind report.
} }
void AlsaDriverImpl::DumpBufferTrace(size_t nEntries)
{
using namespace std;
int savedPrecision = cout.precision();
auto savedFlags = cout.flags();
size_t ix = bufferTraceIndex;
if (ix < nEntries)
{
ix = ix + bufferTraces.size()-nEntries;
} else {
ix -= nEntries;
}
uint64_t t0;
if (bufferTraceIndex == 0) {
t0 = bufferTraces[bufferTraces.size()-1].time;
} else {
t0 = bufferTraces[bufferTraceIndex-1].time;
}
while (ix != bufferTraceIndex)
{
auto&bufferTrace = bufferTraces[ix];
int64_t dt = (int64_t)bufferTrace.time - (int64_t)t0;
cout << bufferTrace.code << " "
<< fixed << setprecision(3) << dt*0.001
<< " " << "inAvail: " << bufferTrace.inAvail
<< " " << "outAvail: " << bufferTrace.outAvail
<< " " << "bufferd: " << bufferTrace.buffered
<< " " << "total: " << bufferTrace.total
<< endl;
++ix;
if (ix == bufferTraces.size())
{
ix = 0;
}
}
cout.precision(savedPrecision);
cout.flags(savedFlags);
}
} // namespace } // namespace
+1
View File
@@ -80,6 +80,7 @@ namespace pipedal {
virtual void Close() = 0; virtual void Close() = 0;
virtual std::string GetConfigurationDescription() = 0; virtual std::string GetConfigurationDescription() = 0;
virtual void DumpBufferTrace(size_t nEntries) {}
}; };
+6 -1
View File
@@ -91,10 +91,15 @@ ControlValue* PedalboardItem::GetControlValue(const std::string&symbol)
} }
bool PedalboardItem::SetControlValue(const std::string&symbol, float value) bool PedalboardItem::SetControlValue(const std::string&symbol, float value)
{ {
ControlValue*controlValue = GetControlValue(symbol); ControlValue*controlValue = GetControlValue(symbol);
if (controlValue == nullptr) return false; if (controlValue == nullptr)
{
this->controlValues().push_back(ControlValue(symbol.c_str(),value));
return true;
}
if (controlValue->value() != value) if (controlValue->value() != value)
{ {
controlValue->value(value); controlValue->value(value);
+1 -1
View File
@@ -108,7 +108,6 @@ public:
const ControlValue*GetControlValue(const std::string&symbol) const; const ControlValue*GetControlValue(const std::string&symbol) const;
bool SetControlValue(const std::string&key, float value); bool SetControlValue(const std::string&key, float value);
bool IsStructurallyIdentical(const PedalboardItem&other) const; bool IsStructurallyIdentical(const PedalboardItem&other) const;
void ApplySnapshotValue(SnapshotValue*snapshotValue); void ApplySnapshotValue(SnapshotValue*snapshotValue);
@@ -161,6 +160,7 @@ public:
// } // }
DECLARE_JSON_MAP(PedalboardItem); DECLARE_JSON_MAP(PedalboardItem);
}; };
class SnapshotValue { class SnapshotValue {
+26 -34
View File
@@ -272,16 +272,17 @@ void PiPedalModel::Load()
this->pedalboard = storage.GetCurrentPreset(); // the current *saved* preset. this->pedalboard = storage.GetCurrentPreset(); // the current *saved* preset.
// the current edited preset, saved only across orderly shutdowns. // the current edited preset, saved only across orderly shutdowns.
CrashGuard::SetCrashGuardFileName(storage.GetDataRoot() / "crash_guard.data"); CrashGuard::SetCrashGuardFileName(storage.GetDataRoot() / "crash_guard.data");
if (CrashGuard::HasCrashed()) { if (CrashGuard::HasCrashed())
{
// ignore the current preset, and load a blank pedalboard in order to avoid a potential plugin crash. // ignore the current preset, and load a blank pedalboard in order to avoid a potential plugin crash.
this->pedalboard = Pedalboard::MakeDefault(); this->pedalboard = Pedalboard::MakeDefault();
} else { }
else
{
CurrentPreset currentPreset; CurrentPreset currentPreset;
try try
{ {
@@ -289,7 +290,7 @@ void PiPedalModel::Load()
{ {
this->pedalboard = currentPreset.preset_; this->pedalboard = currentPreset.preset_;
this->hasPresetChanged = currentPreset.modified_; this->hasPresetChanged = currentPreset.modified_;
} }
} }
catch (const std::exception &e) catch (const std::exception &e)
{ {
@@ -297,8 +298,6 @@ void PiPedalModel::Load()
} }
} }
UpdateDefaults(&this->pedalboard); UpdateDefaults(&this->pedalboard);
std::unique_ptr<AudioHost> p{AudioHost::CreateInstance(pluginHost.asIHost())}; std::unique_ptr<AudioHost> p{AudioHost::CreateInstance(pluginHost.asIHost())};
@@ -644,11 +643,9 @@ void PiPedalModel::SetPedalboardItemUseModUi(int64_t clientId, int64_t instanceI
subscriber->OnItemUseModUiChanged(clientId, instanceId, enabled); subscriber->OnItemUseModUiChanged(clientId, instanceId, enabled);
} }
this->SetPresetChanged(clientId, true); this->SetPresetChanged(clientId, true);
} }
} }
void PiPedalModel::SetPedalboardItemEnable(int64_t clientId, int64_t pedalItemId, bool enabled) void PiPedalModel::SetPedalboardItemEnable(int64_t clientId, int64_t pedalItemId, bool enabled)
{ {
std::lock_guard<std::recursive_mutex> guard{mutex}; std::lock_guard<std::recursive_mutex> guard{mutex};
@@ -1449,7 +1446,8 @@ void PiPedalModel::OnAlsaSequencerDeviceAdded(int client, const std::string &cli
{ {
// reconfigure connections. // reconfigure connections.
std::lock_guard<std::recursive_mutex> lock(this->mutex); std::lock_guard<std::recursive_mutex> lock(this->mutex);
if (this->audioHost) { if (this->audioHost)
{
this->audioHost->SetAlsaSequencerConfiguration(this->storage.GetAlsaSequencerConfiguration()); this->audioHost->SetAlsaSequencerConfiguration(this->storage.GetAlsaSequencerConfiguration());
} }
}); });
@@ -1457,7 +1455,7 @@ void PiPedalModel::OnAlsaSequencerDeviceAdded(int client, const std::string &cli
} }
void PiPedalModel::OnAlsaSequencerDeviceRemoved(int client) void PiPedalModel::OnAlsaSequencerDeviceRemoved(int client)
{ {
// no action required. // no action required.
} }
void PiPedalModel::SetAlsaSequencerConfiguration(const AlsaSequencerConfiguration &alsaSequencerConfiguration) void PiPedalModel::SetAlsaSequencerConfiguration(const AlsaSequencerConfiguration &alsaSequencerConfiguration)
@@ -2027,27 +2025,25 @@ void PiPedalModel::UpdateDefaults(PedalboardItem *pedalboardItem, std::unordered
pedalboardItem->midiChannelBinding(std::optional<MidiChannelBinding>()); // clear it. pedalboardItem->midiChannelBinding(std::optional<MidiChannelBinding>()); // clear it.
} }
} }
//////// PLUGIN SPECIFIC UPGRADES //////////////////////
if (pPlugin->uri() == "http://two-play.com/plugins/toob-nam")
{
ControlValue *pValue = pedalboardItem->GetControlValue("inputCalibrationMode");
if (pValue == nullptr)
{
// calibration is OFF when upgrading.
pedalboardItem->SetControlValue("inputCalibrationMode", 0.0f);
}
pValue = pedalboardItem->GetControlValue("version");
if (pValue == nullptr)
{
pedalboardItem->SetControlValue("version", 0.0f);
}
}
for (size_t i = 0; i < pPlugin->ports().size(); ++i) for (size_t i = 0; i < pPlugin->ports().size(); ++i)
{ {
auto port = pPlugin->ports()[i]; auto port = pPlugin->ports()[i];
//////// PLUGIN SPECIFIC UPGRADES //////////////////////
if (pPlugin->uri() == "http://two-play.com/plugins/toob-nam")
{
ControlValue *pValue = pedalboardItem->GetControlValue("inputCalibrationMode");
if (pValue == nullptr)
{
// calibration is OFF when upgrading.
pedalboardItem->SetControlValue("inputCalibrationMode",0.0f);
}
pValue = pedalboardItem->GetControlValue("version");
if (pValue == nullptr)
{
pedalboardItem->SetControlValue("version",0.0f);
}
}
if (port->is_control_port() && port->is_input()) if (port->is_control_port() && port->is_input())
{ {
ControlValue *pValue = pedalboardItem->GetControlValue(port->symbol()); ControlValue *pValue = pedalboardItem->GetControlValue(port->symbol());
@@ -3107,19 +3103,15 @@ void PiPedalModel::SetTone3000Auth(const std::string &apiKey)
{ {
std::lock_guard<std::recursive_mutex> lock(mutex); std::lock_guard<std::recursive_mutex> lock(mutex);
storage.SetTone3000Auth(apiKey); storage.SetTone3000Auth(apiKey);
std::vector<IPiPedalModelSubscriber::ptr> t{subscribers.begin(), subscribers.end()}; std::vector<IPiPedalModelSubscriber::ptr> t{subscribers.begin(), subscribers.end()};
bool hasAuth = apiKey != ""; bool hasAuth = apiKey != "";
for (auto &subscriber : t) for (auto &subscriber : t)
{ {
subscriber->OnTone3000AuthChanged(hasAuth); subscriber->OnTone3000AuthChanged(hasAuth);
} }
} }
bool PiPedalModel::HasTone3000Auth() const bool PiPedalModel::HasTone3000Auth() const
{ {
return storage.GetTone3000Auth() != ""; return storage.GetTone3000Auth() != "";
} }
+1 -1
View File
@@ -539,7 +539,7 @@ UiFrequencyPlot::UiFrequencyPlot(PluginHost*pHost, const LilvNode*node,
this->yTop_ = GetFloat(pWorld,node,pHost->lilvUris->pipedalUI__yTop,5); this->yTop_ = GetFloat(pWorld,node,pHost->lilvUris->pipedalUI__yTop,5);
this->yBottom_ = GetFloat(pWorld,node,pHost->lilvUris->pipedalUI__yBottom,-35); this->yBottom_ = GetFloat(pWorld,node,pHost->lilvUris->pipedalUI__yBottom,-35);
this->xLog_ = GetFloat(pWorld,node,pHost->lilvUris->pipedalUI__xLog,-35); this->xLog_ = GetFloat(pWorld,node,pHost->lilvUris->pipedalUI__xLog,-35);
this->width_ = GetFloat(pWorld,node,pHost->lilvUris->pipedalUI__width,60); this->width_ = GetFloat(pWorld,node,pHost->lilvUris->pipedalUI__width,176);
} }
+1 -1
View File
@@ -1,5 +1,5 @@
Check ToOB Cab SIM F/R range.
Versioning for legacy NAM presets!
Convert CRVB presets! Convert CRVB presets!
double select on double-click/ok in file dialog. double select on double-click/ok in file dialog.
+27 -11
View File
@@ -451,7 +451,7 @@ const ToobParametricEqView =
if (isLandscape) { if (isLandscape) {
panelStyle = { display: "flex", flexDirection: "row", alignItems: "stretch", width: "100%" }; panelStyle = { display: "flex", flexDirection: "row", alignItems: "stretch", width: "100%" };
scrollStyle = { flex: "1 1 auto", overflowX: "auto", overflowY: "hidden", whiteSpace: "nowrap" }; scrollStyle = { flex: "1 1 auto", overflowX: "auto", overflowY: "hidden", whiteSpace: "nowrap" };
frameStyle = { display: "flex", flexFlow: "row nowrap", alignItems: "center",paddingTop: 8 }; frameStyle = { display: "flex", flexFlow: "row nowrap", alignItems: "center", paddingTop: 8 };
} else { } else {
panelStyle = { display: "flex", flexDirection: "column", alignItems: "stretch", height: "100%" }; panelStyle = { display: "flex", flexDirection: "column", alignItems: "stretch", height: "100%" };
scrollStyle = { flex: "1 1 auto", overflowX: "hidden", overflowY: "auto", whiteSpace: "nowrap" }; scrollStyle = { flex: "1 1 auto", overflowX: "hidden", overflowY: "auto", whiteSpace: "nowrap" };
@@ -460,17 +460,33 @@ const ToobParametricEqView =
return [( return [(
<div key={"vtc_container"} style={panelStyle}> <div key={"vtc_container"} style={panelStyle}>
<div key={"vtc_panel"} style={{ flex: " 0 0 auto", paddingBottom: 8, display: "flex", alignItems: "center", flexFlow: "row nowrap" }}> {host.isLandscapeGrid() ? (
{controls[0] as React.ReactNode} <div key={"vtc_panel"} style={{ flex: " 0 0 auto", paddingBottom: 8, display: "flex", alignItems: "center", flexFlow: "row nowrap" }}>
<div style={{ alignSelf: "flex-start", marginTop: 8 }}> <div style={{ alignSelf: "flex-start", marginTop: 8 }}>
<IconButton onClick={(e) => { <IconButton
e.stopPropagation(); style={{marginTop: 24}}
this.setState({ maximized: true }); onClick={(e) => {
}}> e.stopPropagation();
<CircleUpIcon className={classes.upIcon} /> this.setState({ maximized: true });
</IconButton> }}>
<CircleUpIcon className={classes.upIcon} />
</IconButton>
</div>
{controls[0] as React.ReactNode}
</div> </div>
</div> ) : (
<div key={"vtc_panel"} style={{ flex: " 0 0 auto", paddingBottom: 8, display: "flex", alignItems: "center", flexFlow: "row nowrap" }}>
{controls[0] as React.ReactNode}
<div style={{ alignSelf: "flex-start", marginTop: 8 }}>
<IconButton onClick={(e) => {
e.stopPropagation();
this.setState({ maximized: true });
}}>
<CircleUpIcon className={classes.upIcon} />
</IconButton>
</div>
</div>
)}
<div style={scrollStyle}> <div style={scrollStyle}>
<div style={frameStyle}> <div style={frameStyle}>
{panelControls} {panelControls}