Shared ptr lifetime management for sockets.

This commit is contained in:
Robin Davies
2024-10-05 02:13:49 -04:00
parent db03a7e47f
commit 6f268daec9
3 changed files with 152 additions and 316 deletions
+129 -306
View File
@@ -118,18 +118,11 @@ void PiPedalModel::Close()
} }
// take a snapshot incase a client unsusbscribes in the notification handler (in which case the mutex won't protect us) // take a snapshot incase a client unsusbscribes in the notification handler (in which case the mutex won't protect us)
IPiPedalModelSubscriber **t = new IPiPedalModelSubscriber *[this->subscribers.size()]; std::vector<IPiPedalModelSubscriber::ptr> t {subscribers.begin(),subscribers.end()};
for (size_t i = 0; i < subscribers.size(); ++i) for (auto&subscriber: t)
{ {
t[i] = this->subscribers[i]; subscriber->Close();
} }
size_t n = this->subscribers.size();
for (size_t i = 0; i < n; ++i)
{
t[i]->Close();
}
delete[] t;
this->subscribers.resize(0); this->subscribers.resize(0);
oldAudioHost = std::move(this->audioHost); oldAudioHost = std::move(this->audioHost);
@@ -299,25 +292,25 @@ IPiPedalModelSubscriber *PiPedalModel::GetNotificationSubscriber(int64_t clientI
{ {
if (subscribers[i]->GetClientId() == clientId) if (subscribers[i]->GetClientId() == clientId)
{ {
return subscribers[i]; return subscribers[i].get();
} }
} }
return nullptr; return nullptr;
} }
void PiPedalModel::AddNotificationSubscription(IPiPedalModelSubscriber *pSubscriber) void PiPedalModel::AddNotificationSubscription(std::shared_ptr<IPiPedalModelSubscriber> pSubscriber)
{ {
std::lock_guard<std::recursive_mutex> lock(mutex); std::lock_guard<std::recursive_mutex> lock(mutex);
this->subscribers.push_back(pSubscriber); this->subscribers.push_back(pSubscriber);
} }
void PiPedalModel::RemoveNotificationSubsription(IPiPedalModelSubscriber *pSubscriber) void PiPedalModel::RemoveNotificationSubsription(std::shared_ptr<IPiPedalModelSubscriber> pSubscriber)
{ {
{ {
std::lock_guard<std::recursive_mutex> lock(mutex); std::lock_guard<std::recursive_mutex> lock(mutex);
for (auto it = this->subscribers.begin(); it != this->subscribers.end(); ++it) for (auto it = this->subscribers.begin(); it != this->subscribers.end(); ++it)
{ {
if ((*it) == pSubscriber) if ((*it).get() == pSubscriber.get())
{ {
this->subscribers.erase(it); this->subscribers.erase(it);
break; break;
@@ -378,19 +371,11 @@ void PiPedalModel::OnNotifyMaybeLv2StateChanged(uint64_t instanceId)
item->stateUpdateCount(item->stateUpdateCount() + 1); item->stateUpdateCount(item->stateUpdateCount() + 1);
Lv2PluginState newState = item->lv2State(); Lv2PluginState newState = item->lv2State();
IPiPedalModelSubscriber **t = new IPiPedalModelSubscriber *[this->subscribers.size()]; std::vector<IPiPedalModelSubscriber::ptr> t{subscribers.begin(), subscribers.end()};
for (size_t i = 0; i < subscribers.size(); ++i) for (auto &subscriber : t)
{ {
t[i] = this->subscribers[i]; subscriber->OnLv2StateChanged(instanceId, newState);
} }
size_t n = this->subscribers.size();
{
for (size_t i = 0; i < n; ++i)
{
t[i]->OnLv2StateChanged(instanceId, newState);
}
}
delete[] t;
} }
} }
} }
@@ -403,19 +388,11 @@ void PiPedalModel::SetInputVolume(float value)
this->pedalboard.input_volume_db(value); this->pedalboard.input_volume_db(value);
// take a snapshot incase a client unsusbscribes in the notification handler (in which case the mutex won't protect us) // take a snapshot incase a client unsusbscribes in the notification handler (in which case the mutex won't protect us)
IPiPedalModelSubscriber **t = new IPiPedalModelSubscriber *[this->subscribers.size()]; std::vector<IPiPedalModelSubscriber::ptr> t{subscribers.begin(), subscribers.end()};
for (size_t i = 0; i < subscribers.size(); ++i) for (auto &subscriber : t)
{ {
t[i] = this->subscribers[i]; subscriber->OnInputVolumeChanged(value);
} }
size_t n = this->subscribers.size();
{
for (size_t i = 0; i < n; ++i)
{
t[i]->OnInputVolumeChanged(value);
}
}
delete[] t;
this->SetPresetChanged(-1, true); this->SetPresetChanged(-1, true);
} }
@@ -427,19 +404,11 @@ void PiPedalModel::SetOutputVolume(float value)
std::lock_guard<std::recursive_mutex> lock(mutex); std::lock_guard<std::recursive_mutex> lock(mutex);
this->pedalboard.output_volume_db(value); this->pedalboard.output_volume_db(value);
// take a snapshot incase a client unsusbscribes in the notification handler (in which case the mutex won't protect us) // take a snapshot incase a client unsusbscribes in the notification handler (in which case the mutex won't protect us)
IPiPedalModelSubscriber **t = new IPiPedalModelSubscriber *[this->subscribers.size()]; std::vector<IPiPedalModelSubscriber::ptr> t{subscribers.begin(), subscribers.end()};
for (size_t i = 0; i < subscribers.size(); ++i) for (auto &subscriber : t)
{ {
t[i] = this->subscribers[i]; subscriber->OnOutputVolumeChanged(value);
} }
size_t n = this->subscribers.size();
{
for (size_t i = 0; i < n; ++i)
{
t[i]->OnOutputVolumeChanged(value);
}
}
delete[] t;
this->SetPresetChanged(-1, true); this->SetPresetChanged(-1, true);
} }
@@ -477,19 +446,11 @@ void PiPedalModel::SetControl(int64_t clientId, int64_t pedalItemId, const std::
{ {
// take a snapshot incase a client unsusbscribes in the notification handler (in which case the mutex won't protect us) // take a snapshot incase a client unsusbscribes in the notification handler (in which case the mutex won't protect us)
IPiPedalModelSubscriber **t = new IPiPedalModelSubscriber *[this->subscribers.size()]; std::vector<IPiPedalModelSubscriber::ptr> t{subscribers.begin(), subscribers.end()};
for (size_t i = 0; i < subscribers.size(); ++i) for (auto &subscriber : t)
{ {
t[i] = this->subscribers[i]; subscriber->OnControlChanged(clientId, pedalItemId, symbol, value);
} }
size_t n = this->subscribers.size();
{
for (size_t i = 0; i < n; ++i)
{
t[i]->OnControlChanged(clientId, pedalItemId, symbol, value);
}
}
delete[] t;
this->SetPresetChanged(clientId, true); this->SetPresetChanged(clientId, true);
} }
@@ -499,33 +460,21 @@ void PiPedalModel::SetControl(int64_t clientId, int64_t pedalItemId, const std::
void PiPedalModel::FireJackConfigurationChanged(const JackConfiguration &jackConfiguration) void PiPedalModel::FireJackConfigurationChanged(const JackConfiguration &jackConfiguration)
{ {
// noify subscribers. // noify subscribers.
IPiPedalModelSubscriber **t = new IPiPedalModelSubscriber *[this->subscribers.size()]; std::vector<IPiPedalModelSubscriber::ptr> t{subscribers.begin(), subscribers.end()};
for (size_t i = 0; i < subscribers.size(); ++i) for (auto &subscriber : t)
{ {
t[i] = this->subscribers[i]; subscriber->OnJackConfigurationChanged(jackConfiguration);
} }
size_t n = this->subscribers.size();
for (size_t i = 0; i < n; ++i)
{
t[i]->OnJackConfigurationChanged(jackConfiguration);
}
delete[] t;
} }
void PiPedalModel::FireBanksChanged(int64_t clientId) void PiPedalModel::FireBanksChanged(int64_t clientId)
{ {
// noify subscribers. // noify subscribers.
IPiPedalModelSubscriber **t = new IPiPedalModelSubscriber *[this->subscribers.size()]; std::vector<IPiPedalModelSubscriber::ptr> t{subscribers.begin(), subscribers.end()};
for (size_t i = 0; i < subscribers.size(); ++i) for (auto &subscriber : t)
{ {
t[i] = this->subscribers[i]; subscriber->OnBankIndexChanged(this->storage.GetBanks());
} }
size_t n = this->subscribers.size();
for (size_t i = 0; i < n; ++i)
{
t[i]->OnBankIndexChanged(this->storage.GetBanks());
}
delete[] t;
} }
void PiPedalModel::FirePedalboardChanged(int64_t clientId, bool loadAudioThread) void PiPedalModel::FirePedalboardChanged(int64_t clientId, bool loadAudioThread)
@@ -542,17 +491,11 @@ void PiPedalModel::FirePedalboardChanged(int64_t clientId, bool loadAudioThread)
} }
} }
// noify subscribers. // noify subscribers.
IPiPedalModelSubscriber **t = new IPiPedalModelSubscriber *[this->subscribers.size()]; std::vector<IPiPedalModelSubscriber::ptr> t{subscribers.begin(), subscribers.end()};
for (size_t i = 0; i < subscribers.size(); ++i) for (auto &subscriber : t)
{ {
t[i] = this->subscribers[i]; subscriber->OnPedalboardChanged(clientId, this->pedalboard);
} }
size_t n = this->subscribers.size();
for (size_t i = 0; i < n; ++i)
{
t[i]->OnPedalboardChanged(clientId, this->pedalboard);
}
delete[] t;
} }
void PiPedalModel::SetPedalboard(int64_t clientId, Pedalboard &pedalboard) void PiPedalModel::SetPedalboard(int64_t clientId, Pedalboard &pedalboard)
{ {
@@ -653,17 +596,11 @@ void PiPedalModel::SetPedalboardItemEnable(int64_t clientId, int64_t pedalItemId
this->pedalboard.SetItemEnabled(pedalItemId, enabled); this->pedalboard.SetItemEnabled(pedalItemId, enabled);
// Notify clients. // Notify clients.
IPiPedalModelSubscriber **t = new IPiPedalModelSubscriber *[this->subscribers.size()]; std::vector<IPiPedalModelSubscriber::ptr> t{subscribers.begin(), subscribers.end()};
for (size_t i = 0; i < subscribers.size(); ++i) for (auto &subscriber : t)
{ {
t[i] = this->subscribers[i]; subscriber->OnItemEnabledChanged(clientId, pedalItemId, enabled);
} }
size_t n = this->subscribers.size();
for (size_t i = 0; i < n; ++i)
{
t[i]->OnItemEnabledChanged(clientId, pedalItemId, enabled);
}
delete[] t;
this->SetPresetChanged(clientId, true); this->SetPresetChanged(clientId, true);
// Notify audo thread. // Notify audo thread.
@@ -709,18 +646,11 @@ void PiPedalModel::FireSelectedSnapshotChanged(int64_t selectedSnapshot)
std::lock_guard<std::recursive_mutex> guard{mutex}; std::lock_guard<std::recursive_mutex> guard{mutex};
{ {
// take a snapshot incase a client unsusbscribes in the notification handler (in which case the mutex won't protect us) // take a snapshot incase a client unsusbscribes in the notification handler (in which case the mutex won't protect us)
IPiPedalModelSubscriber **t = new IPiPedalModelSubscriber *[this->subscribers.size()]; std::vector<IPiPedalModelSubscriber::ptr> t{subscribers.begin(), subscribers.end()};
for (size_t i = 0; i < subscribers.size(); ++i) for (auto &subscriber : t)
{ {
t[i] = this->subscribers[i]; subscriber->OnSelectedSnapshotChanged(selectedSnapshot);
} }
size_t n = this->subscribers.size();
for (size_t i = 0; i < n; ++i)
{
t[i]->OnSelectedSnapshotChanged(selectedSnapshot);
}
delete[] t;
} }
} }
@@ -729,21 +659,15 @@ void PiPedalModel::FirePresetChanged(bool changed)
std::lock_guard<std::recursive_mutex> guard{mutex}; std::lock_guard<std::recursive_mutex> guard{mutex};
{ {
// take a snapshot incase a client unsusbscribes in the notification handler (in which case the mutex won't protect us) // take a snapshot incase a client unsusbscribes in the notification handler (in which case the mutex won't protect us)
IPiPedalModelSubscriber **t = new IPiPedalModelSubscriber *[this->subscribers.size()];
for (size_t i = 0; i < subscribers.size(); ++i)
{
t[i] = this->subscribers[i];
}
size_t n = this->subscribers.size();
PresetIndex presets; PresetIndex presets;
GetPresets(&presets); GetPresets(&presets);
for (size_t i = 0; i < n; ++i) std::vector<IPiPedalModelSubscriber::ptr> t{subscribers.begin(), subscribers.end()};
for (auto &subscriber : t)
{ {
t[i]->OnPresetChanged(changed); subscriber->OnPresetChanged(changed);
} }
delete[] t;
} }
} }
@@ -751,22 +675,15 @@ void PiPedalModel::FirePresetsChanged(int64_t clientId)
{ {
std::lock_guard<std::recursive_mutex> guard{mutex}; std::lock_guard<std::recursive_mutex> guard{mutex};
{ {
// take a snapshot incase a client unsusbscribes in the notification handler (in which case the mutex won't protect us)
IPiPedalModelSubscriber **t = new IPiPedalModelSubscriber *[this->subscribers.size()];
for (size_t i = 0; i < subscribers.size(); ++i)
{
t[i] = this->subscribers[i];
}
size_t n = this->subscribers.size();
PresetIndex presets; PresetIndex presets;
GetPresets(&presets); GetPresets(&presets);
for (size_t i = 0; i < n; ++i) std::vector<IPiPedalModelSubscriber::ptr> t{subscribers.begin(), subscribers.end()};
for (auto &subscriber : t)
{ {
t[i]->OnPresetsChanged(clientId, presets); subscriber->OnPresetsChanged(clientId, presets);
} }
delete[] t;
} }
} }
void PiPedalModel::FirePluginPresetsChanged(const std::string &pluginUri) void PiPedalModel::FirePluginPresetsChanged(const std::string &pluginUri)
@@ -774,18 +691,11 @@ void PiPedalModel::FirePluginPresetsChanged(const std::string &pluginUri)
std::lock_guard<std::recursive_mutex> guard{mutex}; std::lock_guard<std::recursive_mutex> guard{mutex};
{ {
// take a snapshot incase a client unsusbscribes in the notification handler (in which case the mutex won't protect us) // take a snapshot incase a client unsusbscribes in the notification handler (in which case the mutex won't protect us)
IPiPedalModelSubscriber **t = new IPiPedalModelSubscriber *[this->subscribers.size()]; std::vector<IPiPedalModelSubscriber::ptr> t{subscribers.begin(), subscribers.end()};
for (size_t i = 0; i < subscribers.size(); ++i) for (auto &subscriber : t)
{ {
t[i] = this->subscribers[i]; subscriber->OnPluginPresetsChanged(pluginUri);
} }
size_t n = this->subscribers.size();
for (size_t i = 0; i < n; ++i)
{
t[i]->OnPluginPresetsChanged(pluginUri);
}
delete[] t;
} }
} }
@@ -888,7 +798,39 @@ int64_t PiPedalModel::UploadBank(BankFile &bankFile, int64_t uploadAfter)
void PiPedalModel::NextBank(Direction direction) void PiPedalModel::NextBank(Direction direction)
{ {
std::lock_guard<std::recursive_mutex> guard{mutex};
auto bankIndex = this->GetBankIndex();
if (bankIndex.entries().size() == 0)
{
return;
}
size_t index = 0;
for (size_t i = 0; i < bankIndex.entries().size(); ++i)
{
auto&entry = bankIndex.entries()[i];
if (entry.instanceId() == bankIndex.selectedBank())
{
index = i;
break;
}
}
if (direction == Direction::Increase)
{
++index;
if (index >= bankIndex.entries().size())
{
index = 0;
}
} else {
if (index == 0)
{
index = bankIndex.entries().size()-1;
} else {
--index;
}
}
this->OpenBank(-1,bankIndex.entries()[index].instanceId());
} }
void PiPedalModel::NextPreset(Direction direction) void PiPedalModel::NextPreset(Direction direction)
{ {
@@ -932,7 +874,6 @@ void PiPedalModel::NextPreset(Direction direction)
LoadPreset(-1, index.presets()[currentPresetIndex].instanceId()); LoadPreset(-1, index.presets()[currentPresetIndex].instanceId());
} }
void PiPedalModel::OnNotifyNextMidiProgram(const RealtimeNextMidiProgramRequest &request) void PiPedalModel::OnNotifyNextMidiProgram(const RealtimeNextMidiProgramRequest &request)
{ {
std::lock_guard<std::recursive_mutex> guard{mutex}; std::lock_guard<std::recursive_mutex> guard{mutex};
@@ -942,7 +883,9 @@ void PiPedalModel::OnNotifyNextMidiProgram(const RealtimeNextMidiProgramRequest
if (request.direction < 0) if (request.direction < 0)
{ {
NextPreset(); NextPreset();
} else { }
else
{
PreviousPreset(); PreviousPreset();
} }
} }
@@ -1102,18 +1045,10 @@ void PiPedalModel::SetGovernorSettings(const std::string &governor)
this->storage.SetGovernorSettings(governor); this->storage.SetGovernorSettings(governor);
IPiPedalModelSubscriber **t = new IPiPedalModelSubscriber *[this->subscribers.size()]; std::vector<IPiPedalModelSubscriber::ptr> t{subscribers.begin(), subscribers.end()};
for (auto &subscriber : t)
{ {
for (size_t i = 0; i < subscribers.size(); ++i) subscriber->OnGovernorSettingsChanged(governor);
{
t[i] = this->subscribers[i];
}
size_t n = this->subscribers.size();
for (size_t i = 0; i < n; ++i)
{
t[i]->OnGovernorSettingsChanged(governor);
}
delete[] t;
} }
} }
@@ -1136,21 +1071,13 @@ void PiPedalModel::SetWifiConfigSettings(const WifiConfigSettings &wifiConfigSet
#endif #endif
{ {
// yyy: review locking semantics here. This is wrong. Convert to shared pointers?
IPiPedalModelSubscriber **t = new IPiPedalModelSubscriber *[this->subscribers.size()];
for (size_t i = 0; i < subscribers.size(); ++i)
{
t[i] = this->subscribers[i];
}
size_t n = this->subscribers.size();
WifiConfigSettings settingsWithNoSecrets = storage.GetWifiConfigSettings(); // (the passwordless version) WifiConfigSettings settingsWithNoSecrets = storage.GetWifiConfigSettings(); // (the passwordless version)
for (size_t i = 0; i < n; ++i) std::vector<IPiPedalModelSubscriber::ptr> t{subscribers.begin(), subscribers.end()};
for (auto &subscriber : t)
{ {
t[i]->OnWifiConfigSettingsChanged(settingsWithNoSecrets); subscriber->OnWifiConfigSettingsChanged(settingsWithNoSecrets);
} }
delete[] t;
} }
} }
@@ -1209,20 +1136,13 @@ void PiPedalModel::SetWifiDirectConfigSettings(const WifiDirectConfigSettings &w
this->storage.SetWifiDirectConfigSettings(wifiDirectConfigSettings); this->storage.SetWifiDirectConfigSettings(wifiDirectConfigSettings);
{ {
IPiPedalModelSubscriber **t = new IPiPedalModelSubscriber *[this->subscribers.size()];
for (size_t i = 0; i < subscribers.size(); ++i)
{
t[i] = this->subscribers[i];
}
size_t n = this->subscribers.size();
WifiDirectConfigSettings tWifiDirectConfigSettings = storage.GetWifiDirectConfigSettings(); // (the passwordless version) WifiDirectConfigSettings tWifiDirectConfigSettings = storage.GetWifiDirectConfigSettings(); // (the passwordless version)
for (size_t i = 0; i < n; ++i) std::vector<IPiPedalModelSubscriber::ptr> t{subscribers.begin(), subscribers.end()};
for (auto &subscriber : t)
{ {
t[i]->OnWifiDirectConfigSettingsChanged(tWifiDirectConfigSettings); subscriber->OnWifiDirectConfigSettingsChanged(tWifiDirectConfigSettings);
} }
delete[] t;
// update NSD-SD announement. // update NSD-SD announement.
UpdateDnsSd(); UpdateDnsSd();
@@ -1242,25 +1162,16 @@ WifiDirectConfigSettings PiPedalModel::GetWifiDirectConfigSettings()
void PiPedalModel::SetShowStatusMonitor(bool show) void PiPedalModel::SetShowStatusMonitor(bool show)
{ {
IPiPedalModelSubscriber **t;
size_t n;
{ {
std::lock_guard<std::recursive_mutex> lock(mutex); // copy atomically. std::lock_guard<std::recursive_mutex> lock(mutex); // copy atomically.
t = new IPiPedalModelSubscriber *[this->subscribers.size()];
n = this->subscribers.size();
storage.SetShowStatusMonitor(show); storage.SetShowStatusMonitor(show);
// Notify clients. // Notify clients.
IPiPedalModelSubscriber **t = new IPiPedalModelSubscriber *[this->subscribers.size()]; std::vector<IPiPedalModelSubscriber::ptr> t{subscribers.begin(), subscribers.end()};
for (size_t i = 0; i < subscribers.size(); ++i) for (auto &subscriber : t)
{ {
t[i] = this->subscribers[i]; subscriber->OnShowStatusMonitorChanged(show);
} }
for (size_t i = 0; i < n; ++i)
{
t[i]->OnShowStatusMonitorChanged(show);
}
delete[] t;
} }
} }
bool PiPedalModel::GetShowStatusMonitor() bool PiPedalModel::GetShowStatusMonitor()
@@ -1376,20 +1287,13 @@ void PiPedalModel::FireChannelSelectionChanged(int64_t clientId)
std::lock_guard<std::recursive_mutex> guard{mutex}; std::lock_guard<std::recursive_mutex> guard{mutex};
{ {
// take a snapshot incase a client unsusbscribes in the notification handler (in which case the mutex won't protect us) // take a snapshot incase a client unsusbscribes in the notification handler (in which case the mutex won't protect us)
IPiPedalModelSubscriber **t = new IPiPedalModelSubscriber *[this->subscribers.size()];
for (size_t i = 0; i < subscribers.size(); ++i)
{
t[i] = this->subscribers[i];
}
size_t n = this->subscribers.size();
JackChannelSelection channelSelection = storage.GetJackChannelSelection(this->jackConfiguration); JackChannelSelection channelSelection = storage.GetJackChannelSelection(this->jackConfiguration);
for (size_t i = 0; i < n; ++i) std::vector<IPiPedalModelSubscriber::ptr> t{subscribers.begin(), subscribers.end()};
for (auto &subscriber : t)
{ {
t[i]->OnChannelSelectionChanged(clientId, channelSelection); subscriber->OnChannelSelectionChanged(clientId, channelSelection);
} }
delete[] t;
} }
} }
@@ -1449,17 +1353,11 @@ void PiPedalModel::OnNotifyMidiValueChanged(int64_t instanceId, int portIndex, f
{ {
this->pedalboard.SetItemEnabled(instanceId, value != 0); this->pedalboard.SetItemEnabled(instanceId, value != 0);
// take a snapshot incase a client unsusbscribes in the notification handler (in which case the mutex won't protect us) // take a snapshot incase a client unsusbscribes in the notification handler (in which case the mutex won't protect us)
IPiPedalModelSubscriber **t = new IPiPedalModelSubscriber *[this->subscribers.size()]; std::vector<IPiPedalModelSubscriber::ptr> t{subscribers.begin(), subscribers.end()};
for (size_t i = 0; i < subscribers.size(); ++i) for (auto &subscriber : t)
{ {
t[i] = this->subscribers[i]; subscriber->OnItemEnabledChanged(-1, instanceId, value != 0);
} }
size_t n = this->subscribers.size();
for (size_t i = 0; i < n; ++i)
{
t[i]->OnItemEnabledChanged(-1, instanceId, value != 0);
}
delete[] t;
this->SetPresetChanged(-1, true); this->SetPresetChanged(-1, true);
return; return;
@@ -1477,17 +1375,11 @@ void PiPedalModel::OnNotifyMidiValueChanged(int64_t instanceId, int portIndex, f
{ {
// take a snapshot incase a client unsusbscribes in the notification handler (in which case the mutex won't protect us) // take a snapshot incase a client unsusbscribes in the notification handler (in which case the mutex won't protect us)
IPiPedalModelSubscriber **t = new IPiPedalModelSubscriber *[this->subscribers.size()]; std::vector<IPiPedalModelSubscriber::ptr> t{subscribers.begin(), subscribers.end()};
for (size_t i = 0; i < subscribers.size(); ++i) for (auto &subscriber : t)
{
t[i] = this->subscribers[i];
}
size_t n = this->subscribers.size();
for (size_t i = 0; i < n; ++i)
{ {
t[i]->OnMidiValueChanged(instanceId, symbol, value); t[i]->OnMidiValueChanged(instanceId, symbol, value);
} }
delete[] t;
this->SetPresetChanged(-1, true); this->SetPresetChanged(-1, true);
return; return;
@@ -1505,17 +1397,11 @@ void PiPedalModel::OnNotifyVusSubscription(const std::vector<VuUpdate> &updates)
for (size_t i = 0; i < updates.size(); ++i) for (size_t i = 0; i < updates.size(); ++i)
{ {
// take a snapshot incase a client unsusbscribes in the notification handler (in which case the mutex won't protect us) // take a snapshot incase a client unsusbscribes in the notification handler (in which case the mutex won't protect us)
IPiPedalModelSubscriber **t = new IPiPedalModelSubscriber *[this->subscribers.size()]; std::vector<IPiPedalModelSubscriber::ptr> t{subscribers.begin(), subscribers.end()};
for (size_t i = 0; i < subscribers.size(); ++i) for (auto &subscriber : t)
{ {
t[i] = this->subscribers[i]; subscriber->OnVuMeterUpdate(updates);
} }
size_t n = this->subscribers.size();
for (size_t i = 0; i < n; ++i)
{
t[i]->OnVuMeterUpdate(updates);
}
delete[] t;
} }
} }
@@ -1792,17 +1678,11 @@ void PiPedalModel::SetJackServerSettings(const JackServerSettings &jackServerSet
this->jackServerSettings = jackServerSettings; this->jackServerSettings = jackServerSettings;
// take a snapshot incase a client unsusbscribes in the notification handler (in which case the mutex won't protect us) // take a snapshot incase a client unsusbscribes in the notification handler (in which case the mutex won't protect us)
IPiPedalModelSubscriber **t = new IPiPedalModelSubscriber *[this->subscribers.size()]; std::vector<IPiPedalModelSubscriber::ptr> t{subscribers.begin(), subscribers.end()};
for (size_t i = 0; i < subscribers.size(); ++i) for (auto &subscriber : t)
{ {
t[i] = this->subscribers[i]; subscriber->OnJackServerSettingsChanged(jackServerSettings);
} }
size_t n = this->subscribers.size();
for (size_t i = 0; i < n; ++i)
{
t[i]->OnJackServerSettingsChanged(jackServerSettings);
}
delete[] t;
#if ALSA_HOST #if ALSA_HOST
storage.SetJackServerSettings(jackServerSettings); storage.SetJackServerSettings(jackServerSettings);
@@ -2009,17 +1889,11 @@ void PiPedalModel::LoadPluginPreset(int64_t pluginInstanceId, uint64_t presetIns
{ {
audioHost->SetPluginPreset(pluginInstanceId, presetValues.controls); audioHost->SetPluginPreset(pluginInstanceId, presetValues.controls);
IPiPedalModelSubscriber **t = new IPiPedalModelSubscriber *[this->subscribers.size()]; std::vector<IPiPedalModelSubscriber::ptr> t{subscribers.begin(), subscribers.end()};
for (size_t i = 0; i < subscribers.size(); ++i) for (auto &subscriber : t)
{ {
t[i] = this->subscribers[i]; subscriber->OnLoadPluginPreset(pluginInstanceId, presetValues.controls);
} }
size_t n = this->subscribers.size();
for (size_t i = 0; i < n; ++i)
{
t[i]->OnLoadPluginPreset(pluginInstanceId, presetValues.controls);
}
delete[] t;
} }
else else
{ {
@@ -2130,40 +2004,27 @@ void PiPedalModel::OnNotifyPathPatchPropertyReceived(
if (this->audioHost) if (this->audioHost)
{ {
this->audioHost->OnNotifyPathPatchPropertyReceived(instanceId,pathPatchPropertyUri,atomString); this->audioHost->OnNotifyPathPatchPropertyReceived(instanceId, pathPatchPropertyUri, atomString);
} }
if (pedalboardItem == nullptr) if (pedalboardItem == nullptr)
{ {
Lv2Log::error(SS("OnNotifyPathPatchPropertyReceived: " << pathPatchPropertyUri << " discarded.")); return;
return;
} }
Lv2Log::error(SS("OnNotifyPathPatchPropertyReceived: " << pathPatchPropertyUri <<": " << atomString));
auto i = pedalboardItem->pathProperties_.find(pathPatchPropertyUri); auto i = pedalboardItem->pathProperties_.find(pathPatchPropertyUri);
if (i != pedalboardItem->pathProperties_.end()) if (i != pedalboardItem->pathProperties_.end())
{ {
pedalboardItem->pathProperties_[pathPatchPropertyUri] = atomString; pedalboardItem->pathProperties_[pathPatchPropertyUri] = atomString;
std::vector<IPiPedalModelSubscriber *> t; std::vector<IPiPedalModelSubscriber::ptr> t{subscribers.begin(), subscribers.end()};
t.reserve(subscribers.size()); for (auto &subscriber : t)
for (auto subscriber : subscribers)
{
t.push_back(subscriber);
}
for (auto subscriber : t)
{ {
subscriber->OnNotifyPathPatchPropertyChanged( subscriber->OnNotifyPathPatchPropertyChanged(
instanceId, instanceId,
pathPatchPropertyUri, pathPatchPropertyUri,
atomString); atomString);
} }
} }
} }
@@ -2287,16 +2148,10 @@ void PiPedalModel::SetFavorites(const std::map<std::string, bool> &favorites)
storage.SetFavorites(favorites); storage.SetFavorites(favorites);
// take a snapshot incase a client unsusbscribes in the notification handler (in which case the mutex won't protect us) // take a snapshot incase a client unsusbscribes in the notification handler (in which case the mutex won't protect us)
std::vector<IPiPedalModelSubscriber *> t; std::vector<IPiPedalModelSubscriber::ptr> t{subscribers.begin(), subscribers.end()};
t.reserve(this->subscribers.size()); for (auto &subscriber : t)
for (size_t i = 0; i < subscribers.size(); ++i)
{ {
t.push_back(this->subscribers[i]); subscriber->OnFavoritesChanged(favorites);
}
for (size_t i = 0; i < t.size(); ++i)
{
t[i]->OnFavoritesChanged(favorites);
} }
} }
std::vector<MidiBinding> PiPedalModel::GetSystemMidiBidings() std::vector<MidiBinding> PiPedalModel::GetSystemMidiBidings()
@@ -2314,17 +2169,11 @@ void PiPedalModel::SetSystemMidiBindings(std::vector<MidiBinding> &bindings)
this->audioHost->SetSystemMidiBindings(bindings); this->audioHost->SetSystemMidiBindings(bindings);
} }
IPiPedalModelSubscriber **t = new IPiPedalModelSubscriber *[this->subscribers.size()]; std::vector<IPiPedalModelSubscriber::ptr> t{subscribers.begin(), subscribers.end()};
for (size_t i = 0; i < subscribers.size(); ++i) for (auto &subscriber : t)
{ {
t[i] = this->subscribers[i]; subscriber->OnSystemMidiBindingsChanged(bindings);
} }
size_t n = this->subscribers.size();
for (size_t i = 0; i < n; ++i)
{
t[i]->OnSystemMidiBindingsChanged(bindings);
}
delete[] t;
} }
std::vector<std::string> PiPedalModel::GetFileList(const UiFileProperty &fileProperty) std::vector<std::string> PiPedalModel::GetFileList(const UiFileProperty &fileProperty)
@@ -2421,7 +2270,7 @@ bool PiPedalModel::LoadCurrentPedalboard()
{ {
// then we can send a snapshot update instead! // then we can send a snapshot update instead!
Snapshot snapshot = pedalboard.MakeSnapshotFromCurrentSettings(previousPedalboard); Snapshot snapshot = pedalboard.MakeSnapshotFromCurrentSettings(previousPedalboard);
audioHost->LoadSnapshot(snapshot,pluginHost); audioHost->LoadSnapshot(snapshot, pluginHost);
this->previousPedalboard = this->pedalboard; this->previousPedalboard = this->pedalboard;
return true; return true;
} }
@@ -2443,16 +2292,11 @@ void PiPedalModel::OnNotifyLv2RealtimeError(int64_t instanceId, const std::strin
// Notify clients. // Notify clients.
size_t n = subscribers.size(); size_t n = subscribers.size();
IPiPedalModelSubscriber **t = new IPiPedalModelSubscriber *[n]; std::vector<IPiPedalModelSubscriber::ptr> t{subscribers.begin(), subscribers.end()};
for (size_t i = 0; i < n; ++i) for (auto &subscriber : t)
{ {
t[i] = this->subscribers[i]; subscriber->OnErrorMessage(error);
} }
for (size_t i = 0; i < n; ++i)
{
t[i]->OnErrorMessage(error);
}
delete[] t;
} }
std::filesystem::path PiPedalModel::GetPluginUploadDirectory() const std::filesystem::path PiPedalModel::GetPluginUploadDirectory() const
{ {
@@ -2465,17 +2309,11 @@ void PiPedalModel::OnLv2PluginsChanged()
std::lock_guard<std::recursive_mutex> lock(mutex); std::lock_guard<std::recursive_mutex> lock(mutex);
{ {
// Notify clients. // Notify clients.
size_t n = subscribers.size(); std::vector<IPiPedalModelSubscriber::ptr> t{subscribers.begin(), subscribers.end()};
IPiPedalModelSubscriber **t = new IPiPedalModelSubscriber *[n]; for (auto &subscriber : t)
for (size_t i = 0; i < n; ++i)
{ {
t[i] = this->subscribers[i]; subscriber->OnLv2PluginsChanging();
} }
for (size_t i = 0; i < n; ++i)
{
t[i]->OnLv2PluginsChanging();
}
delete[] t;
} }
std::thread( std::thread(
[this]() [this]()
@@ -2506,15 +2344,8 @@ void PiPedalModel::FireUpdateStatusChanged(const UpdateStatus &updateStatus)
{ {
std::lock_guard<std::recursive_mutex> lock(mutex); std::lock_guard<std::recursive_mutex> lock(mutex);
std::vector<IPiPedalModelSubscriber *> t; std::vector<IPiPedalModelSubscriber::ptr> t{subscribers.begin(), subscribers.end()};
t.reserve(subscribers.size()); for (auto &subscriber : t)
for (auto subscriber : subscribers)
{
t.push_back(subscriber);
}
for (auto subscriber : t)
{ {
subscriber->OnUpdateStatusChanged(updateStatus); subscriber->OnUpdateStatusChanged(updateStatus);
} }
@@ -2667,16 +2498,10 @@ void PiPedalModel::OnNetworkChanging(bool ethernetConnected, bool hotspotConnect
}); });
// take a snapshot incase a client unsusbscribes in the notification handler (in which case the mutex won't protect us) // take a snapshot incase a client unsusbscribes in the notification handler (in which case the mutex won't protect us)
std::vector<IPiPedalModelSubscriber *> t; std::vector<IPiPedalModelSubscriber::ptr> t{subscribers.begin(), subscribers.end()};
t.reserve(this->subscribers.size()); for (auto &subscriber : t)
for (size_t i = 0; i < subscribers.size(); ++i)
{ {
t.push_back(this->subscribers[i]); subscriber->OnNetworkChanging(hotspotConnected);
}
for (size_t i = 0; i < t.size(); ++i)
{
t[i]->OnNetworkChanging(hotspotConnected);
} }
} }
void PiPedalModel::OnNetworkChanged(bool ethernetConnected, bool hotspotConnected) void PiPedalModel::OnNetworkChanged(bool ethernetConnected, bool hotspotConnected)
@@ -2764,5 +2589,3 @@ void PiPedalModel::RequestShutdown(bool restart)
} }
} }
} }
+5 -3
View File
@@ -54,6 +54,8 @@ namespace pipedal
class IPiPedalModelSubscriber class IPiPedalModelSubscriber
{ {
public: public:
using ptr = std::shared_ptr<IPiPedalModelSubscriber>;
virtual int64_t GetClientId() = 0; virtual int64_t GetClientId() = 0;
virtual void OnItemEnabledChanged(int64_t clientId, int64_t pedalItemId, bool enabled) = 0; virtual void OnItemEnabledChanged(int64_t clientId, int64_t pedalItemId, bool enabled) = 0;
virtual void OnControlChanged(int64_t clientId, int64_t pedalItemId, const std::string &symbol, float value) = 0; virtual void OnControlChanged(int64_t clientId, int64_t pedalItemId, const std::string &symbol, float value) = 0;
@@ -175,7 +177,7 @@ namespace pipedal
std::shared_ptr<Lv2Pedalboard> lv2Pedalboard; std::shared_ptr<Lv2Pedalboard> lv2Pedalboard;
std::filesystem::path webRoot; std::filesystem::path webRoot;
std::vector<IPiPedalModelSubscriber *> subscribers; std::vector<std::shared_ptr<IPiPedalModelSubscriber>> subscribers;
void SetPresetChanged(int64_t clientId, bool value, bool changeSnapshotSelect = true); void SetPresetChanged(int64_t clientId, bool value, bool changeSnapshotSelect = true);
void FireSelectedSnapshotChanged(int64_t selectedSnapshot); void FireSelectedSnapshotChanged(int64_t selectedSnapshot);
void FirePresetsChanged(int64_t clientId); void FirePresetsChanged(int64_t clientId);
@@ -311,8 +313,8 @@ namespace pipedal
void LoadPluginPreset(int64_t pluginInstanceId, uint64_t presetInstanceId); void LoadPluginPreset(int64_t pluginInstanceId, uint64_t presetInstanceId);
void AddNotificationSubscription(IPiPedalModelSubscriber *pSubscriber); void AddNotificationSubscription(std::shared_ptr<IPiPedalModelSubscriber> pSubscriber);
void RemoveNotificationSubsription(IPiPedalModelSubscriber *pSubscriber); void RemoveNotificationSubsription(std::shared_ptr<IPiPedalModelSubscriber> pSubscriber);
void SetPedalboardItemEnable(int64_t clientId, int64_t instanceId, bool enabled); void SetPedalboardItemEnable(int64_t clientId, int64_t instanceId, bool enabled);
void SetControl(int64_t clientId, int64_t pedalItemId, const std::string &symbol, float value); void SetControl(int64_t clientId, int64_t pedalItemId, const std::string &symbol, float value);
+18 -7
View File
@@ -477,7 +477,7 @@ JSON_MAP_REFERENCE(Vst3ControlChangedBody, value)
JSON_MAP_REFERENCE(Vst3ControlChangedBody, state) JSON_MAP_REFERENCE(Vst3ControlChangedBody, state)
JSON_MAP_END() JSON_MAP_END()
class PiPedalSocketHandler : public SocketHandler, public IPiPedalModelSubscriber class PiPedalSocketHandler : public SocketHandler, public IPiPedalModelSubscriber, public std::enable_shared_from_this<PiPedalSocketHandler>
{ {
private: private:
AdminClient &GetAdminClient() const AdminClient &GetAdminClient() const
@@ -552,6 +552,8 @@ public:
{ {
FinalCleanup(); FinalCleanup();
} }
Lv2Log::error("PiPedalSocketHandler deleted");
} }
bool finalCleanup = false; bool finalCleanup = false;
@@ -572,18 +574,21 @@ public:
} }
activeVuSubscriptions.resize(0); activeVuSubscriptions.resize(0);
model.RemoveNotificationSubsription(this); model.RemoveNotificationSubsription(shared_from_this());
// Warning: potentially deleted after return.
} }
virtual void Close() virtual void Close()
{ {
if (closed) if (closed)
return; return;
closed = true; {
auto selfHolder = shared_from_this(); // keep ourselves alive until we return.
closed = true;
FinalCleanup(); // do it while we can. &model will no longer be valid after this. ( :-( ) FinalCleanup(); // do it while we can. &model will no longer be valid after this. ( :-( )
SocketHandler::Close();
SocketHandler::Close(); }
} }
PiPedalSocketHandler(PiPedalModel &model) PiPedalSocketHandler(PiPedalModel &model)
@@ -1259,7 +1264,7 @@ public:
} }
else if (message == "hello") else if (message == "hello")
{ {
this->model.AddNotificationSubscription(this); this->model.AddNotificationSubscription(shared_from_this());
Reply(replyTo, "ehlo", clientId); Reply(replyTo, "ehlo", clientId);
} }
else if (message == "setJackSettings") else if (message == "setJackSettings")
@@ -1626,6 +1631,10 @@ public:
} }
protected: protected:
virtual void onSocketClosed() override {
SocketHandler::OnSocketClosed();
this->Close();
}
virtual void onReceive(const std::string_view &text) virtual void onReceive(const std::string_view &text)
{ {
view_istream<char> s(text); view_istream<char> s(text);
@@ -2061,6 +2070,7 @@ private:
std::atomic<uint64_t> PiPedalSocketHandler::nextClientId = 0; std::atomic<uint64_t> PiPedalSocketHandler::nextClientId = 0;
class PiPedalSocketFactory : public ISocketFactory class PiPedalSocketFactory : public ISocketFactory
{ {
private: private:
@@ -2088,6 +2098,7 @@ public:
} }
}; };
std::shared_ptr<ISocketFactory> pipedal::MakePiPedalSocketFactory(PiPedalModel &model) std::shared_ptr<ISocketFactory> pipedal::MakePiPedalSocketFactory(PiPedalModel &model)
{ {
return std::make_shared<PiPedalSocketFactory>(model); return std::make_shared<PiPedalSocketFactory>(model);