Split IO dialog fixes.

This commit is contained in:
Robin E. R. Davies
2025-09-09 15:25:26 -04:00
parent c5a8345192
commit 367394843a
6 changed files with 443 additions and 474 deletions
+17 -10
View File
@@ -271,7 +271,7 @@ namespace pipedal
auto inAvail = snd_pcm_avail_update(this->captureHandle);
auto outAvail = snd_pcm_avail_update(this->playbackHandle);
auto total = inAvail + outAvail + framesInBuffer;
auto total = (inAvail >= 0? inAvail: 0) + (outAvail >= 0 ? outAvail: 0) + framesInBuffer;
bufferTraces[bufferTraceIndex++] = {
time,
inAvail,
@@ -1180,11 +1180,13 @@ namespace pipedal
throw std::runtime_error("Unable to restart the audio stream.");
}
int err;
if ((err = snd_pcm_start(captureHandle)) < 0)
{
Lv2Log::error(SS("Unable to restart ALSA capture: " << snd_strerror(err)));
throw PiPedalStateException("Unable to restart ALSA capture.");
}
TraceBufferPositions(0,'+');
audioRunning = true;
}
@@ -1518,9 +1520,11 @@ namespace pipedal
}
snd_pcm_drain(capture_handle);
FillOutputBuffer();
TraceBufferPositions(framesRead, 'x');
}
else
{
TraceBufferPositions(framesRead, 'z');
Lv2Log::error(SS("Can't recover from ALSA output underrun. (" << snd_strerror(err) << ")"));
throw PiPedalStateException(SS("Can't recover from ALSA output error. (" << snd_strerror(err) << ")"));
}
@@ -1621,7 +1625,7 @@ namespace pipedal
// expand running status if neccessary.
// deal with regular and sysex messages split across
// buffer boundaries (but discard them)
snd_pcm_sframes_t framesRead;
snd_pcm_sframes_t framesRead = 0;
auto state = snd_pcm_state(handle);
auto frame_bytes = this->captureFrameSize;
@@ -2369,16 +2373,19 @@ namespace pipedal
{
auto&bufferTrace = bufferTraces[ix];
int64_t dt = (int64_t)bufferTrace.time - (int64_t)t0;
if (bufferTrace.time != 0)
{
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;
cout << bufferTrace.code << " "
<< fixed << setprecision(3) << dt*0.001
<< " " << "inAvail: " << bufferTrace.inAvail
<< " " << "outAvail: " << bufferTrace.outAvail
<< " " << "buffered: " << bufferTrace.buffered
<< " " << "total: " << bufferTrace.total
<< endl;
}
++ix;
if (ix == bufferTraces.size())
+71 -64
View File
@@ -108,102 +108,107 @@ std::vector<AlsaDeviceInfo> PiPedalAlsaDevices::GetAlsaDevices()
info.cardId_ = cardNum;
info.id_ = std::string("hw:") + snd_ctl_card_info_get_id(alsaInfo);
const char *driver = snd_ctl_card_info_get_driver(alsaInfo);
(void)driver;
info.name_ = snd_ctl_card_info_get_name(alsaInfo);
info.longName_ = snd_ctl_card_info_get_longname(alsaInfo);
snd_pcm_t *captureDevice = nullptr;
snd_pcm_t *playbackDevice = nullptr;
bool captureOk = snd_pcm_open(&captureDevice, cardId.c_str(), SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK) == 0;
bool playbackOk = snd_pcm_open(&playbackDevice, cardId.c_str(), SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK) == 0;
Finally ffCaptureDevice{
[captureDevice]
{ if (captureDevice) snd_pcm_close(captureDevice); }};
Finally ffPlaybackDevice{
[playbackDevice]
{ if (playbackDevice) snd_pcm_close(playbackDevice); }};
// we can't read our own device if it's open so use data that gets
// cached before we open audio devices.
info.supportsCapture_ = captureOk;
info.supportsPlayback_ = playbackOk;
if (captureOk || playbackOk)
AlsaDeviceInfo cachedInfo;
if (getCachedDevice(info.name_, &cachedInfo))
{
snd_pcm_t *hDevice = captureOk ? captureDevice : playbackDevice;
snd_pcm_hw_params_t *params = nullptr;
err = snd_pcm_hw_params_malloc(&params);
// may have been plugged into a different USB connector.
cachedInfo.cardId_ = info.cardId_;
cachedInfo.id_ = info.id_;
result.push_back(cachedInfo);
if (err == 0)
}
else
{
snd_pcm_t *captureDevice = nullptr;
snd_pcm_t *playbackDevice = nullptr;
bool captureOk = snd_pcm_open(&captureDevice, cardId.c_str(), SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK) == 0;
bool playbackOk = snd_pcm_open(&playbackDevice, cardId.c_str(), SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK) == 0;
Finally ffCaptureDevice{
[captureDevice]
{ if (captureDevice) snd_pcm_close(captureDevice); }};
Finally ffPlaybackDevice{
[playbackDevice]
{ if (playbackDevice) snd_pcm_close(playbackDevice); }};
info.supportsCapture_ = captureOk;
info.supportsPlayback_ = playbackOk;
if (captureOk || playbackOk)
{
Finally ffParams{[params]
{ snd_pcm_hw_params_free(params); }};
snd_pcm_t *hDevice = captureOk ? captureDevice : playbackDevice;
snd_pcm_hw_params_t *params = nullptr;
err = snd_pcm_hw_params_malloc(&params);
err = snd_pcm_hw_params_any(hDevice, params);
if (err == 0)
{
unsigned int minRate = 0, maxRate = 0;
snd_pcm_uframes_t minBufferSize = 0, maxBufferSize = 0;
int dir;
Finally ffParams{[params]
{ snd_pcm_hw_params_free(params); }};
err = snd_pcm_hw_params_get_rate_min(params, &minRate, &dir);
err = snd_pcm_hw_params_any(hDevice, params);
if (err == 0)
{
err = snd_pcm_hw_params_get_rate_max(params, &maxRate, &dir);
unsigned int minRate = 0, maxRate = 0;
snd_pcm_uframes_t minBufferSize = 0, maxBufferSize = 0;
int dir;
err = snd_pcm_hw_params_get_rate_min(params, &minRate, &dir);
if (err == 0)
{
for (size_t i = 0; i < sizeof(RATES) / sizeof(RATES[0]); ++i)
err = snd_pcm_hw_params_get_rate_max(params, &maxRate, &dir);
if (err == 0)
{
uint32_t rate = RATES[i];
if (rate >= minRate && rate <= maxRate)
for (size_t i = 0; i < sizeof(RATES) / sizeof(RATES[0]); ++i)
{
info.sampleRates_.push_back(rate);
uint32_t rate = RATES[i];
if (rate >= minRate && rate <= maxRate)
{
info.sampleRates_.push_back(rate);
}
}
}
else
{
Lv2Log::warning(SS("Failed to get maximum sample rate for device '" << info.name_ << "'."));
}
}
else
{
Lv2Log::warning(SS("Failed to get maximum sample rate for device '" << info.name_ << "'."));
Lv2Log::warning(SS("Failed to get minimum sample rate for device '" << info.name_ << "'."));
}
}
else
{
Lv2Log::warning(SS("Failed to get minimum sample rate for device '" << info.name_ << "'."));
}
if (err == 0)
{
err = snd_pcm_hw_params_get_buffer_size_min(params, &minBufferSize);
if (err == 0)
{
err = snd_pcm_hw_params_get_buffer_size_max(params, &maxBufferSize);
err = snd_pcm_hw_params_get_buffer_size_min(params, &minBufferSize);
if (err == 0)
{
err = snd_pcm_hw_params_get_buffer_size_max(params, &maxBufferSize);
}
}
}
if (err == 0)
{
if (minBufferSize < 16)
if (err == 0)
{
minBufferSize = 16;
}
if (minBufferSize < 16)
{
minBufferSize = 16;
}
info.minBufferSize_ = (uint32_t)minBufferSize;
info.maxBufferSize_ = (uint32_t)maxBufferSize;
info.minBufferSize_ = (uint32_t)minBufferSize;
info.maxBufferSize_ = (uint32_t)maxBufferSize;
}
}
}
}
if (err == 0)
{
cacheDevice(info.name_, info);
result.push_back(info);
}
else if (getCachedDevice(info.name_, &info))
{
result.push_back(info);
}
}
else
{
if (getCachedDevice(info.name_, &info))
{
result.push_back(info);
if (err == 0)
{
cacheDevice(info.name_, info);
result.push_back(info);
}
}
}
}
@@ -528,6 +533,8 @@ JSON_MAP_REFERENCE(AlsaDeviceInfo, longName)
JSON_MAP_REFERENCE(AlsaDeviceInfo, sampleRates)
JSON_MAP_REFERENCE(AlsaDeviceInfo, minBufferSize)
JSON_MAP_REFERENCE(AlsaDeviceInfo, maxBufferSize)
JSON_MAP_REFERENCE(AlsaDeviceInfo, supportsCapture)
JSON_MAP_REFERENCE(AlsaDeviceInfo, supportsPlayback)
JSON_MAP_END()
JSON_MAP_BEGIN(AlsaMidiDeviceInfo)
+12 -4
View File
@@ -237,6 +237,14 @@ void Storage::MaybeCopyDefaultPresets()
}
}
static void removeFileNoThrow(const std::filesystem::path &path)
{
try {
fs::remove(path);
} catch (const std::exception&)
{
}
}
void Storage::UpgradeFactoryPresets()
{
auto presetsDirectory = this->GetPresetsDirectory();
@@ -256,11 +264,11 @@ void Storage::UpgradeFactoryPresets()
if (defaultConfigPresetsVersion.Version() > presetsVersion.Version() || defaultConfigPresetsVersion.Version() == 0)
{
// remove TooB ML README.md
fs::remove("/usr/lib/lv2/ToobAmp.lv2/models/tones/README.md");
fs::remove("/var/pipedal/audio_uploads/ToobMlModels/model.index");
removeFileNoThrow("/usr/lib/lv2/ToobAmp.lv2/models/tones/README.md");
removeFileNoThrow("/var/pipedal/audio_uploads/ToobMlModels/model.index");
fs::remove("/var/pipedal/audio_uploads/ToobMlModels/README.md");
fs::remove("/var/pipedal/audio_uploads/ToobMlModels/model.index");
removeFileNoThrow("/var/pipedal/audio_uploads/ToobMlModels/README.md");
removeFileNoThrow("/var/pipedal/audio_uploads/ToobMlModels/model.index");
std::string name = "Factory Presets";
BankFile newFactoryPresets;