Hotspot: no scanning if not required.

This commit is contained in:
Robin E. R. Davies
2025-06-29 20:27:43 -04:00
parent 03cb18e065
commit 79aa1441c3
11 changed files with 553 additions and 206 deletions
+103 -80
View File
@@ -292,16 +292,12 @@ void PiPedalModel::Load()
this->audioHost->SetNotificationCallbacks(this);
this->systemMidiBindings = storage.GetSystemMidiBindings();
this->audioHost->SetSystemMidiBindings(this->systemMidiBindings);
audioHost->SetAlsaSequencerConfiguration(storage.GetAlsaSequencerConfiguration());
if (configuration.GetMLock())
{
#ifndef NO_MLOCK
@@ -515,7 +511,6 @@ void PiPedalModel::FireBanksChanged(int64_t clientId)
}
}
void PiPedalModel::FirePedalboardChanged(int64_t clientId, bool loadAudioThread)
{
if (loadAudioThread)
@@ -601,14 +596,11 @@ void PiPedalModel::UpdateCurrentPedalboard(int64_t clientId, Pedalboard &pedalbo
UpdateVst3Settings(pedalboard);
Lv2PedalboardErrorList errorMessages;
std::shared_ptr<Lv2Pedalboard> lv2Pedalboard{
this->pluginHost.UpdateLv2PedalboardStructure(pedalboard, this->lv2Pedalboard.get(), errorMessages)
};
this->pluginHost.UpdateLv2PedalboardStructure(pedalboard, this->lv2Pedalboard.get(), errorMessages)};
this->lv2Pedalboard = lv2Pedalboard;
// apply the error messages to the lv2Pedalboard.
// return true if the error messages have changed
audioHost->SetPedalboard(lv2Pedalboard);
@@ -620,9 +612,7 @@ void PiPedalModel::UpdateCurrentPedalboard(int64_t clientId, Pedalboard &pedalbo
UpdateRealtimeVuSubscriptions();
UpdateRealtimeMonitorPortSubscriptions();
this->FirePedalboardChanged(clientId,false);
this->FirePedalboardChanged(clientId, false);
this->SetPresetChanged(clientId, true);
}
}
@@ -1406,6 +1396,38 @@ void PiPedalModel::RestartAudio(bool useDummyAudioDriver)
}
}
void PiPedalModel::OnAlsaSequencerDeviceAdded(int client, const std::string &clientName)
{
std::lock_guard<std::recursive_mutex> lock(mutex);
auto alsaSequencerConfiguration = this->storage.GetAlsaSequencerConfiguration();
std::string key = "seq:" + clientName;
bool interested = false;
for (const auto &port : alsaSequencerConfiguration.connections())
{
if (port.id().starts_with(key))
{
interested = true;
break;
}
}
if (interested)
{
Post(
[this]
{
// reconfigure connections.
std::lock_guard<std::recursive_mutex> lock(this->mutex);
if (this->audioHost) {
this->audioHost->SetAlsaSequencerConfiguration(this->storage.GetAlsaSequencerConfiguration());
}
});
}
}
void PiPedalModel::OnAlsaSequencerDeviceRemoved(int client)
{
// no action required.
}
void PiPedalModel::SetAlsaSequencerConfiguration(const AlsaSequencerConfiguration &alsaSequencerConfiguration)
{
std::lock_guard<std::recursive_mutex> lock(mutex);
@@ -1424,7 +1446,6 @@ void PiPedalModel::SetAlsaSequencerConfiguration(const AlsaSequencerConfiguratio
subscriber->OnAlsaSequencerConfigurationChanged(alsaSequencerConfiguration);
}
}
}
AlsaSequencerConfiguration PiPedalModel::GetAlsaSequencerConfiguration()
{
@@ -1441,14 +1462,11 @@ std::vector<AlsaSequencerPortSelection> PiPedalModel::GetAlsaSequencerPorts()
result.push_back(AlsaSequencerPortSelection{
port.id,
port.name,
port.displaySortOrder
});
port.displaySortOrder});
}
return result;
}
void PiPedalModel::SetJackChannelSelection(int64_t clientId, const JackChannelSelection &channelSelection)
{
{
@@ -1667,7 +1685,7 @@ void PiPedalModel::SendSetPatchProperty(
std::lock_guard<std::recursive_mutex> lock(mutex);
if (!audioHost)
{
onError("Audio not running.");
onError("Audio not running.");
return;
}
@@ -1678,8 +1696,9 @@ void PiPedalModel::SendSetPatchProperty(
std::shared_ptr<Lv2PluginInfo> pluginInfo = GetPluginInfo(pedalboardItem->uri_);
auto pipedalUi = pluginInfo->piPedalUI();
auto fileProperty = pipedalUi->GetFileProperty(propertyUri);
if (fileProperty && value.is_string()) {
if (fileProperty && value.is_string())
{
json_variant abstractPath = pluginHost.AbstractPath(value);
std::ostringstream ss;
json_writer writer(ss);
@@ -1729,12 +1748,11 @@ void PiPedalModel::SendSetPatchProperty(
}};
LV2_URID urid = this->pluginHost.GetLv2Urid(propertyUri.c_str());
size_t sampleTimeout = 0.5*audioHost->GetSampleRate();
size_t sampleTimeout = 0.5 * audioHost->GetSampleRate();
RealtimePatchPropertyRequest *request = new RealtimePatchPropertyRequest(
onRequestComplete,
clientId, instanceId, urid, atomValue, nullptr, onError,
sampleTimeout
);
sampleTimeout);
outstandingParameterRequests.push_back(request);
if (this->audioHost)
@@ -1802,10 +1820,10 @@ void PiPedalModel::SendGetPatchProperty(
{
onError("Audio stopped.");
}
size_t sampleTimeout = 0.3*audioHost->GetSampleRate();
size_t sampleTimeout = 0.3 * audioHost->GetSampleRate();
RealtimePatchPropertyRequest *request = new RealtimePatchPropertyRequest(
onRequestComplete,
clientId, instanceId, urid, onSuccess, onError,sampleTimeout);
clientId, instanceId, urid, onSuccess, onError, sampleTimeout);
outstandingParameterRequests.push_back(request);
this->audioHost->sendRealtimeParameterRequest(request);
@@ -1969,7 +1987,9 @@ void PiPedalModel::UpdateDefaults(PedalboardItem *pedalboardItem, std::unordered
{
pedalboardItem->midiChannelBinding(MidiChannelBinding::DefaultForMissingValue());
}
} else {
}
else
{
if (pedalboardItem->midiChannelBinding())
{
pedalboardItem->midiChannelBinding(std::optional<MidiChannelBinding>()); // clear it.
@@ -2245,22 +2265,23 @@ void PiPedalModel::OnNotifyMidiListen(uint8_t cc0, uint8_t cc1, uint8_t cc2)
{
std::lock_guard<std::recursive_mutex> lock(mutex);
bool isNote = (cc0 & 0xF0) == 0x90; // Note On
if (isNote && cc2 == 0) {
if (isNote && cc2 == 0)
{
return; // Note off. Oopsie.
}
bool isControl = (cc0 & 0xF0) == 0xB0; // Control Change
if (!isNote && !isControl) {
bool isControl = (cc0 & 0xF0) == 0xB0; // Control Change
if (!isNote && !isControl)
{
return; // Not a note on or control change.
}
for (int i = 0; i < midiEventListeners.size(); ++i)
for (int i = 0; i < midiEventListeners.size(); ++i)
{
auto &listener = midiEventListeners[i];
auto subscriber = this->GetNotificationSubscriber(listener.clientId);
if (subscriber)
{
subscriber->OnNotifyMidiListener(listener.clientHandle, cc0,cc1,cc2);
subscriber->OnNotifyMidiListener(listener.clientHandle, cc0, cc1, cc2);
}
else
{
@@ -2345,6 +2366,7 @@ void PiPedalModel::CancelMonitorPatchProperty(int64_t clientId, int64_t clientHa
audioHost->SetListenForMidiEvent(false);
}
}
std::vector<AlsaDeviceInfo> PiPedalModel::GetAlsaDevices()
{
std::vector<AlsaDeviceInfo> result = this->alsaDevices.GetAlsaDevices();
@@ -2402,9 +2424,9 @@ void PiPedalModel::SetSystemMidiBindings(std::vector<MidiBinding> &bindings)
}
}
PedalboardItem*PiPedalModel::GetPedalboardItemForFileProperty(const UiFileProperty& fileProperty)
PedalboardItem *PiPedalModel::GetPedalboardItemForFileProperty(const UiFileProperty &fileProperty)
{
for (PedalboardItem*pedalboardItem: this->pedalboard.GetAllPlugins())
for (PedalboardItem *pedalboardItem : this->pedalboard.GetAllPlugins())
{
if (pedalboardItem->pathProperties_.contains(fileProperty.patchProperty()))
{
@@ -2418,25 +2440,24 @@ FileRequestResult PiPedalModel::GetFileList2(const std::string &relativePath_, c
std::string relativePath = relativePath_;
try
{
if (!storage.IsInUploadsDirectory(relativePath))
if (!storage.IsInUploadsDirectory(relativePath))
{
// if relativePath is in a resource directory of the plugin, then we have loaded a factory preset or are using a default property.
// map the resource path to the corresponding file in the uploads directory.
// map the resource path to the corresponding file in the uploads directory.
// :-(
PedalboardItem *pedalboardItem = GetPedalboardItemForFileProperty(fileProperty);
if (pedalboardItem)
{
auto pluginInfo = GetPluginInfo(pedalboardItem->uri());
if (pluginInfo) {
std::filesystem::path resourcePath = fs::path(pluginInfo->bundle_path())
/ fileProperty.resourceDirectory();
if (IsSubdirectory(relativePath,resourcePath))
if (pluginInfo)
{
std::filesystem::path resourcePath = fs::path(pluginInfo->bundle_path()) / fileProperty.resourceDirectory();
if (IsSubdirectory(relativePath, resourcePath))
{
fs::path t = MakeRelativePath(relativePath,resourcePath);
t = fileProperty.directory() / t;
if (fs::exists(t))
fs::path t = MakeRelativePath(relativePath, resourcePath);
t = fileProperty.directory() / t;
if (fs::exists(t))
{
relativePath = t;
}
@@ -2469,10 +2490,9 @@ std::string PiPedalModel::CopyFilePropertyFile(
bool overwrite)
{
std::lock_guard<std::recursive_mutex> lock(mutex);
return storage.CopyFilePropertyFile(oldRelativePath, newRelativePath, uiFileProperty,overwrite);
return storage.CopyFilePropertyFile(oldRelativePath, newRelativePath, uiFileProperty, overwrite);
}
void PiPedalModel::DeleteSampleFile(const std::filesystem::path &fileName)
{
std::lock_guard<std::recursive_mutex> lock(mutex);
@@ -2484,28 +2504,29 @@ std::string PiPedalModel::CreateNewSampleDirectory(const std::string &relativePa
std::lock_guard<std::recursive_mutex> lock(mutex);
return storage.CreateNewSampleDirectory(relativePath, uiFileProperty);
}
FilePropertyDirectoryTree::ptr PiPedalModel::GetFilePropertydirectoryTree(const UiFileProperty &uiFileProperty,const std::string&selectedPath)
FilePropertyDirectoryTree::ptr PiPedalModel::GetFilePropertydirectoryTree(const UiFileProperty &uiFileProperty, const std::string &selectedPath)
{
std::lock_guard<std::recursive_mutex> lock(mutex);
return storage.GetFilePropertydirectoryTree(uiFileProperty,selectedPath);
return storage.GetFilePropertydirectoryTree(uiFileProperty, selectedPath);
}
UiFileProperty::ptr PiPedalModel::FindLoadedPatchProperty(int64_t instanceId,const std::string&patchPropertyUri)
UiFileProperty::ptr PiPedalModel::FindLoadedPatchProperty(int64_t instanceId, const std::string &patchPropertyUri)
{
auto pedalboardItems = pedalboard.GetAllPlugins();
for (const auto&pedalboardItem: pedalboardItems) {
for (const auto &pedalboardItem : pedalboardItems)
{
if (pedalboardItem->instanceId() == instanceId)
{
Lv2PluginInfo::ptr pluginInfo = GetPluginInfo(pedalboardItem->uri());
if (pluginInfo && pluginInfo->piPedalUI())
{
for (const auto&fileProperty: pluginInfo->piPedalUI()->fileProperties())
if (fileProperty->patchProperty() == patchPropertyUri)
{
return fileProperty;
}
for (const auto &fileProperty : pluginInfo->piPedalUI()->fileProperties())
if (fileProperty->patchProperty() == patchPropertyUri)
{
return fileProperty;
}
}
}
}
@@ -2513,9 +2534,9 @@ UiFileProperty::ptr PiPedalModel::FindLoadedPatchProperty(int64_t instanceId,con
throw std::runtime_error("Permission denied. Plugin not currently loaded.");
}
std::string PiPedalModel::UploadUserFile(const std::string &directory, int64_t instanceId,const std::string &patchProperty, const std::string &filename, std::istream &stream, size_t contentLength)
std::string PiPedalModel::UploadUserFile(const std::string &directory, int64_t instanceId, const std::string &patchProperty, const std::string &filename, std::istream &stream, size_t contentLength)
{
UiFileProperty::ptr fileProperty = FindLoadedPatchProperty(instanceId,patchProperty);
UiFileProperty::ptr fileProperty = FindLoadedPatchProperty(instanceId, patchProperty);
if (!fileProperty)
{
Lv2Log::error(SS("Upload fle: Permission denied. No currently-loaded plugin provides that patch property: " << patchProperty));
@@ -2905,35 +2926,40 @@ bool PiPedalModel::GetHasWifi()
return hasWifi;
}
std::map<std::string,std::string> PiPedalModel::GetWifiRegulatoryDomains()
std::map<std::string, std::string> PiPedalModel::GetWifiRegulatoryDomains()
{
std::map<std::string,std::string> result;
try {
auto& regDb = RegDb::GetInstance();
std::map<std::string, std::string> result;
try
{
auto &regDb = RegDb::GetInstance();
result = regDb.getRegulatoryDomains(storage.GetConfigRoot() / "iso_codes.json");
} catch (const std::exception&e)
}
catch (const std::exception &e)
{
Lv2Log::warning(SS("Unable to query Wifi Regulatory domains. " << e.what()));
}
return result;
}
void PiPedalModel::CancelAudioRetry() {
void PiPedalModel::CancelAudioRetry()
{
std::lock_guard<std::recursive_mutex> lock(mutex);
if (audioRetryPostHandle)
if (audioRetryPostHandle)
{
// don't think this can ever happen, but if it did, it would be bad.
this->CancelPost(audioRetryPostHandle);
audioRetryPostHandle = 0;
}
}
void PiPedalModel::OnAlsaDriverTerminatedAbnormally() {
// notification from the realtime thread, via the audiohost that the
void PiPedalModel::OnAlsaDriverTerminatedAbnormally()
{
// notification from the realtime thread, via the audiohost that the
// ALSA stream has broken. We want to restart.
// get off the service thread as promptly as possible
this->Post([&]() {
this->Post([&]()
{
std::lock_guard<std::recursive_mutex> lock(mutex);
if (closed) return;
@@ -2981,8 +3007,7 @@ void PiPedalModel::OnAlsaDriverTerminatedAbnormally() {
} else {
Lv2Log::error(SS("Unable to reastart audio."));
}
});
} });
}
bool PiPedalModel::IsInUploadsDirectory(const std::string &path)
@@ -2992,26 +3017,24 @@ bool PiPedalModel::IsInUploadsDirectory(const std::string &path)
void PiPedalModel::MoveAudioFile(
const std::string &directory,
int32_t fromPosition,
int32_t toPosition
) {
int32_t fromPosition,
int32_t toPosition)
{
if (directory.empty())
{
throw std::runtime_error("Directory is empty.");
}
AudioDirectoryInfo::Ptr dir = AudioDirectoryInfo::Create(directory);
dir->MoveAudioFile(directory, fromPosition, toPosition);
dir->MoveAudioFile(directory, fromPosition, toPosition);
}
void PiPedalModel::SetPedalboardItemTitle(int64_t instanceId, const std::string &title)
{
std::lock_guard<std::recursive_mutex> lock(mutex);
if (!this->pedalboard.SetItemTitle(instanceId,title))
if (!this->pedalboard.SetItemTitle(instanceId, title))
{
return;
}
// no need to reload the pedalboard, but we do need to notify subscribers.
this->SetPresetChanged(-1, true);
this->FirePedalboardChanged(-1,false);
this->SetPresetChanged(-1, true);
this->FirePedalboardChanged(-1, false);
}