Snapshot file model, Hotspot restart on config change.
This commit is contained in:
+16
-8
@@ -177,16 +177,24 @@ namespace pipedal
|
||||
std::istringstream ss(pathProperty.second);
|
||||
json_reader reader(ss);
|
||||
reader.read(&vProperty);
|
||||
vProperty = pluginHost.MapPath(vProperty);
|
||||
if (!vProperty.is_null())
|
||||
{
|
||||
try {
|
||||
vProperty = pluginHost.MapPath(vProperty);
|
||||
|
||||
// now to atom format (what we want on the rt thread0)
|
||||
AtomConverter atomConverter(pluginHost.GetMapFeature());
|
||||
LV2_Atom *atomValue = atomConverter.ToAtom(vProperty);
|
||||
// now to atom format (what we want on the rt thread0)
|
||||
AtomConverter atomConverter(pluginHost.GetMapFeature());
|
||||
LV2_Atom *atomValue = atomConverter.ToAtom(vProperty);
|
||||
|
||||
size_t atomBufferSize = (atomValue->size + sizeof(LV2_Atom) + 3) / 4 * 4;
|
||||
pathPatchProperty.atomBuffer.resize(atomValue->size + sizeof(LV2_Atom));
|
||||
memcpy(pathPatchProperty.atomBuffer.data(), atomValue, pathPatchProperty.atomBuffer.size());
|
||||
this->pathPatchProperties.push_back(std::move(pathPatchProperty));
|
||||
size_t atomBufferSize = (atomValue->size + sizeof(LV2_Atom) + 3) / 4 * 4;
|
||||
pathPatchProperty.atomBuffer.resize(atomValue->size + sizeof(LV2_Atom));
|
||||
memcpy(pathPatchProperty.atomBuffer.data(), atomValue, pathPatchProperty.atomBuffer.size());
|
||||
this->pathPatchProperties.push_back(std::move(pathPatchProperty));
|
||||
} catch (const std::exception &e)
|
||||
{
|
||||
Lv2Log::info(SS("IndexedSnapshotValue: Failed to map path property " << pathProperty.first << ". " << e.what()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+55
-14
@@ -37,7 +37,7 @@ using namespace dbus::networkmanager;
|
||||
namespace pipedal::impl
|
||||
{
|
||||
|
||||
#define PIPEDAL_HOTSPOT_NAME "PiPedal Hotspot"
|
||||
#define PIPEDAL_HOTSPOT_NAME "PiPedal Hotspot"
|
||||
|
||||
class HotspotManagerImpl : public HotspotManager
|
||||
{
|
||||
@@ -164,19 +164,20 @@ void HotspotManagerImpl::Open()
|
||||
|
||||
void HotspotManagerImpl::onClose()
|
||||
{
|
||||
this->closed = true; // avoids a memory barrier probelm.
|
||||
this->closed = true; // avoids a memory barrier probelm.
|
||||
|
||||
CancelDeviceChangedTimer();
|
||||
CancelWaitForNetworkManagerTimer();
|
||||
CancelAccessPointsChangedTimer();
|
||||
|
||||
|
||||
if (networkManager && activeConnection)
|
||||
{
|
||||
try {
|
||||
try
|
||||
{
|
||||
networkManager->DeactivateConnection(activeConnection->getObjectPath());
|
||||
activeConnection = nullptr;
|
||||
} catch (const std::exception&e)
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
// nothrow.
|
||||
}
|
||||
@@ -443,16 +444,31 @@ void HotspotManagerImpl::onReload()
|
||||
if (closed)
|
||||
return;
|
||||
WifiConfigSettings oldSettings = this->wifiConfigSettings;
|
||||
;
|
||||
wifiConfigSettings.Load();
|
||||
this->wifiConfigSettings.Load();
|
||||
if (wifiConfigSettings == oldSettings)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case State::Initial:
|
||||
case State::Error:
|
||||
// ignore.
|
||||
Lv2Log::error("NetworkManager is in an error state. Reboot and try again.");
|
||||
return;
|
||||
case State::Initial:
|
||||
case State::WaitingForNetworkManager:
|
||||
// ignore. new config will be picked up once initialization completes.
|
||||
return;
|
||||
|
||||
case State::Closed:
|
||||
return;
|
||||
|
||||
case State::HotspotConnecting:
|
||||
case State::HotspotConnected:
|
||||
default:
|
||||
// force a reload.
|
||||
StopHotspot();
|
||||
SetState(State::Monitoring);
|
||||
MaybeStartHotspot();
|
||||
return;
|
||||
}
|
||||
@@ -536,7 +552,8 @@ void HotspotManagerImpl::UpdateKnownNetworks(
|
||||
}
|
||||
for (auto &accessPoint : allAccessPoints)
|
||||
{
|
||||
try {
|
||||
try
|
||||
{
|
||||
uint8_t strength = accessPoint->Strength();
|
||||
auto vSsid = accessPoint->Ssid();
|
||||
std::string ssid = ssidToString(vSsid);
|
||||
@@ -547,7 +564,8 @@ void HotspotManagerImpl::UpdateKnownNetworks(
|
||||
record.visibleNetwork = true;
|
||||
record.strength = strength;
|
||||
}
|
||||
} catch (const std::exception&ignored)
|
||||
}
|
||||
catch (const std::exception &ignored)
|
||||
{
|
||||
// race to get the info before it changes. np.
|
||||
}
|
||||
@@ -819,8 +837,6 @@ void HotspotManagerImpl::StartHotspot()
|
||||
std::vector<uint8_t> vSsid{ssid.begin(), ssid.end()};
|
||||
wireless["ssid"] = vSsid;
|
||||
wireless["mode"] = "ap";
|
||||
wireless["band"] = "a";
|
||||
wireless["band"] = "bg";
|
||||
|
||||
uint32_t iChannel = 0;
|
||||
auto channel = this->wifiConfigSettings.channel_;
|
||||
@@ -829,9 +845,14 @@ void HotspotManagerImpl::StartHotspot()
|
||||
std::stringstream ss{channel};
|
||||
ss >> iChannel;
|
||||
}
|
||||
if (iChannel != 0)
|
||||
if (iChannel <= 1)
|
||||
{
|
||||
wireless["channel"] = iChannel;
|
||||
wireless["band"] = iChannel > 14 ? "a" : "bg";
|
||||
}
|
||||
else
|
||||
{
|
||||
wireless["band"] = iChannel == 0 ? "bg" : "a";
|
||||
}
|
||||
|
||||
std::map<std::string, sdbus::Variant> &wirelessSecurity = settings["802-11-wireless-security"];
|
||||
@@ -840,6 +861,26 @@ void HotspotManagerImpl::StartHotspot()
|
||||
|
||||
settings["ipv4"]["method"] = "shared";
|
||||
settings["ipv6"]["method"] = "shared";
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
// Create connection
|
||||
settings["ipv4"]["method"] = sdbus::Variant(std::string("shared"));
|
||||
//settings["ipv6"]["method"] = sdbus::Variant(std::string("ignore"));
|
||||
|
||||
settings["ipv4"]["address-data"] = sdbus::Variant(std::vector<std::map<std::string, sdbus::Variant>>{{{"address", sdbus::Variant("192.168.60.1")},
|
||||
{"prefix", sdbus::Variant(uint32_t(24))}}});
|
||||
settings["ipv4"]["dhcp-send-hostname"] = sdbus::Variant(true);
|
||||
settings["ipv4"]["dhcp-hostname"] = sdbus::Variant("raspberrypi");
|
||||
// settings["ipv4"]["dhcp-options"] = sdbus::Variant(std::vector<std::string>{
|
||||
// "option:classless-static-route,192.168.60.0/24,0.0.0.0,0.0.0.0/0,192.168.60.1"});
|
||||
|
||||
settings["ipv4"]["route-data"] = sdbus::Variant(std::vector<std::map<std::string, sdbus::Variant>>{{
|
||||
{"dest", sdbus::Variant("192.168.4.0")},
|
||||
{"prefix", sdbus::Variant(uint32_t(24))},
|
||||
{"metric", sdbus::Variant((uint32_t)99)}
|
||||
}});
|
||||
////////////////////////////////////////////////////////////
|
||||
// settings["ipv6"]["addr-gen-mode"] = "stable-privacy";
|
||||
|
||||
std::map<std::string, sdbus::Variant> options;
|
||||
|
||||
@@ -385,6 +385,34 @@ static std::string GetNonLinkLocalAddressForIp4Interface(const std::string &name
|
||||
return result;
|
||||
}
|
||||
|
||||
bool pipedal::IsLinkLocalAddress(const std::string fromAddress)
|
||||
{
|
||||
std::string address = fromAddress;
|
||||
std::string result;
|
||||
if (address[0] != '[')
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// ipv6
|
||||
if (address[0] != '[' || address[address.length() - 1] != ']')
|
||||
throw std::invalid_argument("Bad address.");
|
||||
address = address.substr(1, address.length() - 2);
|
||||
|
||||
struct in6_addr inetAddr6;
|
||||
memset(&inetAddr6, 0, sizeof(inetAddr6));
|
||||
if (inet_pton(AF_INET6, address.c_str(), &inetAddr6) == 1)
|
||||
{
|
||||
if (IN6_IS_ADDR_LINKLOCAL(&inetAddr6))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string pipedal::GetNonLinkLocalAddress(const std::string fromAddress)
|
||||
{
|
||||
std::string address = fromAddress;
|
||||
|
||||
@@ -27,6 +27,8 @@ namespace pipedal {
|
||||
std::string GetInterfaceIpv4Address(const std::string& interfaceName);
|
||||
|
||||
|
||||
bool IsLinkLocalAddress(const std::string fromAddress);
|
||||
|
||||
std::string GetNonLinkLocalAddress(const std::string fromAddress);
|
||||
|
||||
bool IsOnLocalSubnet(const std::string&fromAddress);
|
||||
|
||||
@@ -87,6 +87,18 @@ ControlValue* PedalboardItem::GetControlValue(const std::string&symbol)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const ControlValue* PedalboardItem::GetControlValue(const std::string&symbol) const
|
||||
{
|
||||
for (size_t i = 0; i < this->controlValues().size(); ++i)
|
||||
{
|
||||
if (this->controlValues()[i].key() == symbol)
|
||||
{
|
||||
return &(this->controlValues()[i]);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool Pedalboard::SetItemEnabled(int64_t pedalItemId, bool enabled)
|
||||
{
|
||||
PedalboardItem*item = GetItem(pedalItemId);
|
||||
@@ -266,6 +278,17 @@ bool PedalboardItem::IsStructurallyIdentical(const PedalboardItem&other) const
|
||||
}
|
||||
if (this->isSplit()) // so is the other by virtue of idential uris.
|
||||
{
|
||||
auto myValue = this->GetControlValue("splitType");
|
||||
auto otherValue = other.GetControlValue("splitType");
|
||||
if (myValue == nullptr || otherValue == nullptr) // actually an error.
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// split type changes potentially trigger buffer allocation changes,
|
||||
// so different split types are not structurally identical.
|
||||
if (myValue->value() != otherValue->value()) {
|
||||
return false;
|
||||
}
|
||||
if (topChain().size() != other.topChain().size())
|
||||
{
|
||||
return false;
|
||||
@@ -356,6 +379,30 @@ void PedalboardItem::AddResetsForMissingProperties(Snapshot&snapshot, size_t*ind
|
||||
|
||||
}
|
||||
|
||||
Pedalboard Pedalboard::DeepCopy()
|
||||
{
|
||||
Pedalboard result = *this;
|
||||
for (size_t i= 0; i < snapshots_.size(); ++i)
|
||||
{
|
||||
if (snapshots_[i])
|
||||
{
|
||||
result.snapshots_[i] = std::make_shared<Snapshot>(*(snapshots_[i]));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
void Pedalboard::SetCurrentSnapshotModified(bool modified)
|
||||
{
|
||||
if (selectedSnapshot() != -1)
|
||||
{
|
||||
auto& snapshot = snapshots_[selectedSnapshot_];
|
||||
if (snapshot)
|
||||
{
|
||||
snapshot->isModified_ = modified;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Snapshot Pedalboard::MakeSnapshotFromCurrentSettings(const Pedalboard &previousPedalboard)
|
||||
{
|
||||
Snapshot snapshot;
|
||||
|
||||
+5
-1
@@ -101,6 +101,7 @@ public:
|
||||
PropertyMap patchProperties;
|
||||
public:
|
||||
ControlValue*GetControlValue(const std::string&symbol);
|
||||
const ControlValue*GetControlValue(const std::string&symbol) const;
|
||||
|
||||
bool IsStructurallyIdentical(const PedalboardItem&other) const;
|
||||
|
||||
@@ -166,7 +167,7 @@ class Snapshot {
|
||||
public:
|
||||
std::string name_;
|
||||
std::string color_;
|
||||
bool isModified_ = true;
|
||||
bool isModified_ = false;
|
||||
std::vector<SnapshotValue> values_;
|
||||
|
||||
DECLARE_JSON_MAP(Snapshot);
|
||||
@@ -186,10 +187,13 @@ class Pedalboard {
|
||||
int64_t selectedSnapshot_ = -1;
|
||||
|
||||
public:
|
||||
// deep copy, breaking shared pointers.
|
||||
Pedalboard DeepCopy();
|
||||
static constexpr int64_t INPUT_VOLUME_ID = -2; // synthetic PedalboardItem for input volume.
|
||||
static constexpr int64_t OUTPUT_VOLUME_ID = -3; // synthetic PedalboardItem for output volume.
|
||||
bool SetControlValue(int64_t pedalItemId, const std::string &symbol, float value);
|
||||
bool SetItemEnabled(int64_t pedalItemId, bool enabled);
|
||||
void SetCurrentSnapshotModified(bool modified);
|
||||
|
||||
bool IsStructureIdentical(const Pedalboard &other) const; // caan we just send a snapshot-style uddate instead of reloading plugins? All settings are ignored.
|
||||
Snapshot MakeSnapshotFromCurrentSettings(const Pedalboard &previousPedalboard);
|
||||
|
||||
+66
-34
@@ -101,6 +101,26 @@ PiPedalModel::PiPedalModel()
|
||||
// don't actuall start the hotspotManager until after LV2 is initialized (in order to avoid logging oddities)
|
||||
}
|
||||
|
||||
void PrepareSnapshostsForSave(Pedalboard&pedalboard)
|
||||
{
|
||||
if (pedalboard.selectedSnapshot() != -1) {
|
||||
auto¤tSnapshot = pedalboard.snapshots()[pedalboard.selectedSnapshot()];
|
||||
if (!currentSnapshot || currentSnapshot->isModified_)
|
||||
{
|
||||
pedalboard.selectedSnapshot(-1);
|
||||
|
||||
}
|
||||
}
|
||||
for (auto &snapshot: pedalboard.snapshots())
|
||||
{
|
||||
if (snapshot) {
|
||||
snapshot->isModified_ = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void PiPedalModel::Close()
|
||||
{
|
||||
std::unique_ptr<AudioHost> oldAudioHost;
|
||||
@@ -515,15 +535,19 @@ void PiPedalModel::SetPedalboard(int64_t clientId, Pedalboard &pedalboard)
|
||||
void PiPedalModel::SetSnapshot(int64_t selectedSnapshot)
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(mutex);
|
||||
if (this->pedalboard.selectedSnapshot() == selectedSnapshot)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (this->pedalboard.ApplySnapshot(selectedSnapshot))
|
||||
{
|
||||
this->pedalboard.SetCurrentSnapshotModified(false);
|
||||
this->FireSnapshotModified(selectedSnapshot,false);
|
||||
if (this->audioHost)
|
||||
{
|
||||
this->audioHost->LoadSnapshot(*(this->pedalboard.snapshots()[selectedSnapshot]), this->pluginHost); // no longer own it.
|
||||
if (this->previousPedalboardLoaded && this->pedalboard.IsStructureIdentical(this->previousPedalboard))
|
||||
{
|
||||
this->audioHost->LoadSnapshot(*(this->pedalboard.snapshots()[selectedSnapshot]), this->pluginHost); // no longer own it.
|
||||
} else {
|
||||
LoadCurrentPedalboard();
|
||||
}
|
||||
|
||||
}
|
||||
SetPresetChanged(-1, true, false);
|
||||
this->pedalboard.selectedSnapshot(selectedSnapshot);
|
||||
@@ -535,43 +559,21 @@ void PiPedalModel::SetSnapshots(std::vector<std::shared_ptr<Snapshot>> &snapshot
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(mutex);
|
||||
|
||||
// notionally, snapshots are saved whenever they are modified, but pedalboards are not.
|
||||
// so we must add the current snapshots BOTH to the current pedalbaoard, AND to the
|
||||
// current saved instance of the pedalboard to create the illusion that the are stored separately.
|
||||
// In practice, snapshots have to track structure changes (delete pedalboard items that have been deleted,
|
||||
// and set default settings for pedalboard items that have ben added since the snapshots was last saved.
|
||||
//
|
||||
// This is acheived by:
|
||||
// 1. updating BOTH the current pedalboard, and its saved instance.
|
||||
// 2. discarding references to dangling instances as plugins are loaded (see UpdateDefaults).
|
||||
// 3. Setting missing snapshot controls to default values (NOT the current pedalboard values)
|
||||
// 4. (We currently don't do the right thing with patch properties if the patch property has never been set).
|
||||
|
||||
UpdateVst3Settings(pedalboard);
|
||||
|
||||
{
|
||||
// stealth update of the saved snapshots.
|
||||
auto savedPedalboard = storage.GetCurrentPreset();
|
||||
savedPedalboard.snapshots(snapshots); // makes a shallow copy
|
||||
|
||||
if (selectedSnapshot != -1)
|
||||
{
|
||||
// implies that this is a snapshot of the currently running pedalboard. so we can mark it as the selected pedalboard.
|
||||
this->pedalboard.selectedSnapshot(selectedSnapshot);
|
||||
}
|
||||
// UpdateDefaults(&savedPedalboard); // The update is awfully fresh. wait until it gets loaded again before pruning.
|
||||
storage.SaveCurrentPreset(savedPedalboard);
|
||||
}
|
||||
|
||||
this->pedalboard.snapshots(std::move(snapshots));
|
||||
|
||||
if (selectedSnapshot != -1)
|
||||
{
|
||||
this->pedalboard.selectedSnapshot(selectedSnapshot);
|
||||
}
|
||||
|
||||
|
||||
this->FirePedalboardChanged(-1, false); // notify clients (but don't change the running pedalboard, because it's still the same)
|
||||
// this means that all clients get an up-to-date copy of the snapshots AND the currently selected snapshot if that applies
|
||||
// (and a fresh copy of the pedalboard settings as well, which is harmless, since they have not changed)
|
||||
this->SetPresetChanged(-1, true,false);
|
||||
|
||||
}
|
||||
|
||||
void PiPedalModel::UpdateCurrentPedalboard(int64_t clientId, Pedalboard &pedalboard)
|
||||
@@ -634,8 +636,16 @@ void PiPedalModel::SetPresetChanged(int64_t clientId, bool value, bool changeSna
|
||||
{
|
||||
if (changeSnapshotSelect && value && this->pedalboard.selectedSnapshot() != -1)
|
||||
{
|
||||
this->pedalboard.selectedSnapshot(-1);
|
||||
FireSelectedSnapshotChanged(-1);
|
||||
auto & snapshot = this->pedalboard.snapshots()[pedalboard.selectedSnapshot()];
|
||||
if (snapshot) {
|
||||
if (!snapshot->isModified_)
|
||||
{
|
||||
snapshot->isModified_ = true;
|
||||
FireSnapshotModified(pedalboard.selectedSnapshot(),true);
|
||||
}
|
||||
}
|
||||
|
||||
this->pedalboard.SetCurrentSnapshotModified(true);
|
||||
}
|
||||
if (value != this->hasPresetChanged)
|
||||
{
|
||||
@@ -644,6 +654,20 @@ void PiPedalModel::SetPresetChanged(int64_t clientId, bool value, bool changeSna
|
||||
}
|
||||
}
|
||||
|
||||
void PiPedalModel::FireSnapshotModified(int64_t snapshotIndex, bool modified)
|
||||
{
|
||||
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)
|
||||
std::vector<IPiPedalModelSubscriber::ptr> t{subscribers.begin(), subscribers.end()};
|
||||
for (auto &subscriber : t)
|
||||
{
|
||||
subscriber->OnSnapshotModified(snapshotIndex,modified);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void PiPedalModel::FireSelectedSnapshotChanged(int64_t selectedSnapshot)
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> guard{mutex};
|
||||
@@ -762,6 +786,8 @@ void PiPedalModel::SaveCurrentPreset(int64_t clientId)
|
||||
|
||||
UpdateVst3Settings(this->pedalboard);
|
||||
SyncLv2State();
|
||||
PrepareSnapshostsForSave(pedalboard);
|
||||
|
||||
|
||||
storage.SaveCurrentPreset(this->pedalboard);
|
||||
this->SetPresetChanged(clientId, false);
|
||||
@@ -791,12 +817,15 @@ int64_t PiPedalModel::SavePluginPresetAs(int64_t instanceId, const std::string &
|
||||
return presetId;
|
||||
}
|
||||
|
||||
|
||||
int64_t PiPedalModel::SaveCurrentPresetAs(int64_t clientId, const std::string &name, int64_t saveAfterInstanceId)
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> guard{mutex};
|
||||
|
||||
SyncLv2State();
|
||||
auto pedalboard = this->pedalboard;
|
||||
auto pedalboard = this->pedalboard.DeepCopy();
|
||||
PrepareSnapshostsForSave(pedalboard);
|
||||
|
||||
UpdateVst3Settings(pedalboard);
|
||||
pedalboard.name(name);
|
||||
int64_t result = storage.SaveCurrentPresetAs(pedalboard, name, saveAfterInstanceId);
|
||||
@@ -1280,6 +1309,7 @@ void PiPedalModel::RestartAudio(bool useDummyAudioDriver)
|
||||
|
||||
this->audioHost->SetPedalboard(nullptr);
|
||||
|
||||
previousPedalboardLoaded = false;
|
||||
auto jackServerSettings = this->jackServerSettings;
|
||||
if (useDummyAudioDriver)
|
||||
{
|
||||
@@ -2359,6 +2389,8 @@ bool PiPedalModel::LoadCurrentPedalboard()
|
||||
// return true if the error messages have changed
|
||||
CheckForResourceInitialization(this->pedalboard);
|
||||
audioHost->SetPedalboard(lv2Pedalboard);
|
||||
previousPedalboard = this->pedalboard;
|
||||
previousPedalboardLoaded = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -68,6 +68,7 @@ namespace pipedal
|
||||
virtual void OnPedalboardChanged(int64_t clientId, const Pedalboard &pedalboard) = 0;
|
||||
virtual void OnPresetsChanged(int64_t clientId, const PresetIndex &presets) = 0;
|
||||
virtual void OnPresetChanged(bool changed) = 0;
|
||||
virtual void OnSnapshotModified(int64_t selectedSnapshot, bool modified) = 0;
|
||||
virtual void OnSelectedSnapshotChanged(int64_t selectedSnapshot) = 0;
|
||||
virtual void OnPluginPresetsChanged(const std::string &pluginUri) = 0;
|
||||
virtual void OnChannelSelectionChanged(int64_t clientId, const JackChannelSelection &channelSelection) = 0;
|
||||
@@ -180,6 +181,7 @@ namespace pipedal
|
||||
|
||||
std::vector<std::shared_ptr<IPiPedalModelSubscriber>> subscribers;
|
||||
void SetPresetChanged(int64_t clientId, bool value, bool changeSnapshotSelect = true);
|
||||
void FireSnapshotModified(int64_t snapshotIndex, bool modified);
|
||||
void FireSelectedSnapshotChanged(int64_t selectedSnapshot);
|
||||
void FirePresetsChanged(int64_t clientId);
|
||||
void FirePresetChanged(bool changed);
|
||||
|
||||
@@ -396,6 +396,19 @@ JSON_MAP_REFERENCE(SetSnapshotsBody, snapshots)
|
||||
JSON_MAP_REFERENCE(SetSnapshotsBody, selectedSnapshot)
|
||||
JSON_MAP_END()
|
||||
|
||||
class SnapshotModifiedBody {
|
||||
public:
|
||||
int64_t snapshotIndex_;
|
||||
bool modified_;
|
||||
|
||||
DECLARE_JSON_MAP(SnapshotModifiedBody);
|
||||
};
|
||||
|
||||
JSON_MAP_BEGIN(SnapshotModifiedBody)
|
||||
JSON_MAP_REFERENCE(SnapshotModifiedBody, snapshotIndex)
|
||||
JSON_MAP_REFERENCE(SnapshotModifiedBody, modified)
|
||||
JSON_MAP_END()
|
||||
|
||||
class ChannelSelectionChangedBody
|
||||
{
|
||||
public:
|
||||
@@ -1762,6 +1775,15 @@ private:
|
||||
body.jackChannelSelection_ = const_cast<JackChannelSelection *>(&channelSelection);
|
||||
Send("onChannelSelectionChanged", body);
|
||||
}
|
||||
|
||||
virtual void OnSnapshotModified(int64_t snapshotIndex, bool modified)
|
||||
{
|
||||
SnapshotModifiedBody body;
|
||||
body.snapshotIndex_ = snapshotIndex;
|
||||
body.modified_ = modified;
|
||||
Send("onSnapshotModified", body);
|
||||
}
|
||||
|
||||
virtual void OnSelectedSnapshotChanged(int64_t selectedSnapshot) override
|
||||
{
|
||||
Send("onSelectedSnapshotChanged", selectedSnapshot);
|
||||
|
||||
@@ -936,6 +936,20 @@ namespace pipedal
|
||||
return result.str();
|
||||
}
|
||||
|
||||
static void splitAddressAndPort(const std::string &address, std::string&addrOnly, std::string&port)
|
||||
{
|
||||
size_t portPos = address.length();
|
||||
for (size_t i = address.length(); i > 0; --i)
|
||||
{
|
||||
if (address[i-1] == ':')
|
||||
{
|
||||
portPos = i-1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
addrOnly = address.substr(0,portPos);
|
||||
port = address.substr(portPos);
|
||||
}
|
||||
void on_http(connection_hdl hdl)
|
||||
{
|
||||
// Upgrade our connection handle to a full connection_ptr
|
||||
@@ -974,6 +988,31 @@ namespace pipedal
|
||||
|
||||
std::string fromAddress = SS(con->get_remote_endpoint());
|
||||
|
||||
// redirect requests to IPV6 local connections to a better address.
|
||||
|
||||
std::string addrOnly,portStr;
|
||||
splitAddressAndPort(fromAddress,addrOnly,portStr);
|
||||
|
||||
if (IsLinkLocalAddress(addrOnly))
|
||||
{
|
||||
try {
|
||||
uri_builder builder(requestUri);
|
||||
|
||||
std::string redirectAddress = GetNonLinkLocalAddress(addrOnly);
|
||||
builder.set_authority(redirectAddress+portStr);
|
||||
std::string redirectUri = builder.str();
|
||||
|
||||
res.set(HttpField::location,redirectUri.c_str());
|
||||
Lv2Log::info(SS("Redirecting from " << fromAddress << " to " << redirectUri));
|
||||
res.keepAlive(false);
|
||||
con->set_status(websocketpp::http::status_code::temporary_redirect);
|
||||
return;
|
||||
} catch (const std::exception&e)
|
||||
{
|
||||
ServerError(*con,"Invalid request on link-local address.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (req.method() == HttpVerb::options)
|
||||
{
|
||||
res.set(HttpField::access_control_allow_origin, origin);
|
||||
@@ -984,6 +1023,7 @@ namespace pipedal
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
for (auto requestHandler : this->request_handlers)
|
||||
{
|
||||
|
||||
|
||||
@@ -70,6 +70,7 @@ public:
|
||||
constexpr static const char* origin = "Origin";
|
||||
constexpr static const char* date = "Date";
|
||||
constexpr static const char* referer = "Referer";
|
||||
constexpr static const char * location = "Location";
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -74,12 +74,12 @@ std::vector<WifiChannelSelector> pipedal::getWifiChannelSelectors(const char*cou
|
||||
if (forCommandline) {
|
||||
WifiChannelSelector autoSelect;
|
||||
autoSelect.channelId_ = "0";
|
||||
autoSelect.channelName_ = "0 Select automatically";
|
||||
autoSelect.channelName_ = "0 Automatic";
|
||||
result.push_back(autoSelect);
|
||||
} else {
|
||||
WifiChannelSelector autoSelect;
|
||||
autoSelect.channelId_ = "0";
|
||||
autoSelect.channelName_ = "Select automatically";
|
||||
autoSelect.channelName_ = "Automatic";
|
||||
result.push_back(autoSelect);
|
||||
}
|
||||
WifiInfo wifiInfo = getWifiInfo(countryIso3661);
|
||||
|
||||
Reference in New Issue
Block a user