diff --git a/CMakeLists.txt b/CMakeLists.txt
index 89d7503..4f01d76 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,10 +1,10 @@
cmake_minimum_required(VERSION 3.16.0)
project(pipedal
- VERSION 1.3.59
+ VERSION 1.3.60
DESCRIPTION "PiPedal Guitar Effect Pedal For Raspberry Pi"
HOMEPAGE_URL "https://rerdavies.github.io/pipedal"
)
-set (DISPLAY_VERSION "PiPedal v1.3.59-Release")
+set (DISPLAY_VERSION "PiPedal v1.3.60-Release")
set (PACKAGE_ARCHITECTURE "arm64")
set (CMAKE_INSTALL_PREFIX "/usr/")
diff --git a/README.md b/README.md
index 16fe6df..a3fc0f5 100644
--- a/README.md
+++ b/README.md
@@ -6,13 +6,13 @@
-Download: v1.3.59
+Download: v1.3.60
Website: [https://rerdavies.github.io/pipedal](https://rerdavies.github.io/pipedal).
Documentation: [https://rerdavies.github.io/pipedal/Documentation.html](https://rerdavies.github.io/pipedal/Documentation.html).
-#### NEW version 1.3.59 Release, providing [snapshots](https://rerdavies.github.io/pipedal/Snaphots.html), and a new Performance View. See the [release notes](https://rerdavies.github.io/pipedal/ReleaseNotes) for details.
+#### NEW version 1.3.60 Release, providing [snapshots](https://rerdavies.github.io/pipedal/Snaphots.html), and a new Performance View. See the [release notes](https://rerdavies.github.io/pipedal/ReleaseNotes) for details.
diff --git a/docs/Installing.md b/docs/Installing.md
index 4855311..4af51c5 100644
--- a/docs/Installing.md
+++ b/docs/Installing.md
@@ -13,17 +13,17 @@ page_icon: img/Install4.jpg
Download the most recent Debian (.deb) package for your platform:
-- [Raspberry Pi OS bookworm (64-bit) v1.3.59](https://github.com/rerdavies/pipedal/releases/download/)
+- [Raspberry Pi OS bookworm (64-bit) v1.3.60](https://github.com/rerdavies/pipedal/releases/download/)
- [Ubuntu/Raspberry Pi OS bullseyeye (64-bit) v1.2.31](https://github.com/rerdavies/pipedal/releases/download/v1.1.31/pipedal_1.1.31_arm64.deb)
-Version 1.3.59 has not yet been tested on Ubuntu or Raspberry Pi OS bullseye. On these platforms, we recommend that you use version 1.1.31.
+Version 1.3.60 has not yet been tested on Ubuntu or Raspberry Pi OS bullseye. On these platforms, we recommend that you use version 1.1.31.
Install the package by running
```
sudo apt update
cd ~/Downloads
- sudo apt-get install pipedal_1.3.59_arm64.deb
+ sudo apt-get install pipedal_1.3.60_arm64.deb
```
Adjust accordingly if you have downloaded v1.1.31.
diff --git a/docs/ReleaseNotes.md b/docs/ReleaseNotes.md
index 8ab10d2..0d7e5be 100644
--- a/docs/ReleaseNotes.md
+++ b/docs/ReleaseNotes.md
@@ -1,5 +1,11 @@
# Release Notes
+## PiPedal 1.3.60 Release
+
+Bug fixes:
+- Uploading of preset and bank files now work properly.
+- Uploaded plugin presets are merged with existing presets, instead of overwriting existing presets.
+
## PiPedal 1.3.59 Release
20% performance improvement when using Toob Neural Amp Modeller with large Wavenet models.
diff --git a/docs/download.md b/docs/download.md
index f858180..ab98513 100644
--- a/docs/download.md
+++ b/docs/download.md
@@ -4,7 +4,7 @@
Download the most recent Debian (.deb) package for your platform:
-- Raspberry Pi OS Bookworm (64-bit) v1.3.59
+- Raspberry Pi OS Bookworm (64-bit) v1.3.60
Install the package by running
@@ -12,7 +12,7 @@ Install the package by running
```
sudo apt update
cd ~/Downloads
- sudo apt-get install ./pipedal_1.3.59_arm64.deb
+ sudo apt-get install ./pipedal_1.3.60_arm64.deb
```
Follow the instructions in [_Configuring PiPedal After Installation_](https://rerdavies.github.io/pipedal/Configuring.html) to complete the installation.
diff --git a/docs/index.md b/docs/index.md
index dcb02f7..76bb850 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -1,7 +1,7 @@
-v1.3.59
+v1.3.60
@@ -9,7 +9,7 @@ To download PiPedal, click [here](download.md).
To view PiPedal documentation, click [here](Documentation.md).
-#### NEW version 1.3.59 Release. See the [release notes](https://rerdavies.github.io/pipedal/ReleaseNotes) for details.
+#### NEW version 1.3.60 Release. See the [release notes](https://rerdavies.github.io/pipedal/ReleaseNotes) for details.
diff --git a/react/src/PluginPresetsDialog.tsx b/react/src/PluginPresetsDialog.tsx
index 9e012c9..0ab5dac 100644
--- a/react/src/PluginPresetsDialog.tsx
+++ b/react/src/PluginPresetsDialog.tsx
@@ -354,7 +354,7 @@ const PluginPresetsDialog = withStyles(styles, { withTheme: true })(
let pluginUri = this.getPluginUri();
let plugin = this.model.getUiPlugin(pluginUri);
if (plugin) {
- title = "Presets - " + plugin.name;
+ title = "Plugin Presets - " + plugin.name;
}
@@ -440,7 +440,7 @@ const PluginPresetsDialog = withStyles(styles, { withTheme: true })(
- Download presets
+ Download plugin presets
@@ -449,7 +449,7 @@ const PluginPresetsDialog = withStyles(styles, { withTheme: true })(
- Upload presets
+ Upload plugin presets
diff --git a/react/src/SnapshotDialog.tsx b/react/src/SnapshotDialog.tsx
index 8c1b973..9207334 100644
--- a/react/src/SnapshotDialog.tsx
+++ b/react/src/SnapshotDialog.tsx
@@ -35,6 +35,7 @@ import ResizeResponsiveComponent from './ResizeResponsiveComponent';
import { TransitionProps } from '@mui/material/transitions';
import Fade from '@mui/material/Fade';
+import Slide from '@mui/material/Slide';
import SnapshotPanel from './SnapshotPanel';
const styles = {
@@ -45,7 +46,7 @@ const styles = {
};
-const Transition = React.forwardRef(function Transition(
+const FadeTransition = React.forwardRef(function Transition(
props: TransitionProps & {
children: React.ReactElement;
},
@@ -55,6 +56,17 @@ const Transition = React.forwardRef(function Transition(
});
+const SlideTransition = React.forwardRef(function Transition(
+ props: TransitionProps & {
+ children: React.ReactElement;
+ },
+ ref: React.Ref,
+ ) {
+ return ;
+ });
+
+
+
export interface SnapshotDialogProps {
open: boolean,
@@ -100,11 +112,10 @@ export default class SnapshotDialog extends ResizeResponsiveComponent this.props.onOk()} fullScreen={this.state.fullScreen}
- TransitionComponent={Transition} keepMounted
+ TransitionComponent={this.state.fullScreen? SlideTransition: FadeTransition} keepMounted
style={{ userSelect: "none", }}
PaperProps={{
style: {
- maxWidth: '1000px'
},
}}
diff --git a/src/PiPedalModel.cpp b/src/PiPedalModel.cpp
index 8f7f1a3..6cbe83f 100644
--- a/src/PiPedalModel.cpp
+++ b/src/PiPedalModel.cpp
@@ -844,7 +844,7 @@ void PiPedalModel::UploadPluginPresets(const PluginPresets &pluginPresets)
throw PiPedalException("Invalid plugin presets.");
}
std::lock_guard guard{mutex};
- storage.SavePluginPresets(pluginPresets.pluginUri_, pluginPresets);
+ storage.MergePluginPresets(pluginPresets.pluginUri_, pluginPresets);
FirePluginPresetsChanged(pluginPresets.pluginUri_);
}
int64_t PiPedalModel::UploadPreset(const BankFile &bankFile, int64_t uploadAfter)
diff --git a/src/PluginPreset.cpp b/src/PluginPreset.cpp
index e41166b..2d34e47 100644
--- a/src/PluginPreset.cpp
+++ b/src/PluginPreset.cpp
@@ -2,6 +2,77 @@
using namespace pipedal;
+
+static std::string GetUnversionedLabel(const std::string label)
+{
+ size_t pos = label.length();
+ if (pos != 0 && label.at(pos-1) == ')')
+ {
+ --pos;
+ while (true)
+ {
+ if (pos == 0)
+ {
+ return label; // not versioned. return the original.
+ }
+ --pos;
+ char c = label[pos];
+ if (c >= '0' && c <= '9')
+ {
+ continue; // eat the number.
+ }
+ else if (c == '(')
+ {
+ return label.substr(0,pos);
+
+ } else {
+ return label; // failure. return the unmodified original
+ }
+ }
+ }
+ return label;
+}
+
+bool PluginPreset::equals(const PluginPreset&other) const
+{
+ // everything EXCEPT instanceId (since preset may be from another PluginPresets collection)
+ return label_ == other.label_ &&
+ lilvPresetUri_ == other.lilvPresetUri_ &&
+ controlValues_ == other.controlValues_ &&
+ state_ == other.state_;
+}
+
+void PluginPresets::MergePreset(const PluginPreset&preset)
+{
+ int existingPresetIndex = Find(preset.label_);
+ if (existingPresetIndex != -1)
+ {
+ if (this->presets_[existingPresetIndex].equals(preset))
+ {
+ // an exact duplicate. discard the new preset.
+ return;
+ }
+ std::string baseLabel = GetUnversionedLabel(preset.label_);
+
+ for (int i = 1; i < 1000; ++i)
+ {
+ std::string newLabel = SS(baseLabel << "(" << i << ")");
+ if (Find(newLabel) == -1)
+ {
+ PluginPreset versionedPreset = preset;
+ versionedPreset.label_ = newLabel;
+ MergePreset(versionedPreset);
+ return;
+ }
+ }
+ // A thousand duplicates?! Heck. just add a duplicate label. :-/
+ }
+ this->presets_.push_back(preset);
+ this->presets_.back().instanceId_ = this->nextInstanceId_++;
+
+}
+
+
JSON_MAP_BEGIN(PluginUiPreset)
JSON_MAP_REFERENCE(PluginUiPreset,label)
JSON_MAP_REFERENCE(PluginUiPreset,instanceId)
diff --git a/src/PluginPreset.hpp b/src/PluginPreset.hpp
index e27dec1..d53906e 100644
--- a/src/PluginPreset.hpp
+++ b/src/PluginPreset.hpp
@@ -111,6 +111,8 @@ public:
return preset;
}
+ bool equals(const PluginPreset&other) const;
+
uint64_t instanceId_;
std::string label_;
std::string lilvPresetUri_;
@@ -158,6 +160,9 @@ public:
return -1;
}
+ void MergePreset(const PluginPreset&preset);
+
+
DECLARE_JSON_MAP(PluginPresets);
};
diff --git a/src/PresetBundle.cpp b/src/PresetBundle.cpp
index f7e6904..27ae4da 100644
--- a/src/PresetBundle.cpp
+++ b/src/PresetBundle.cpp
@@ -214,17 +214,17 @@ public:
{
this->pluginUploadDirectory = model.GetPluginUploadDirectory();
zipFile = ZipFileReader::Create(path);
- auto s = zipFile->GetFileInputStream("pluginPresets.json");
+ auto s = zipFile->GetFileInputStream("bankFile.json");
json_reader reader(s);
- reader.read(&pluginPresets);
+ reader.read(&bankFile);
}
void LoadPluginPresetFile(PiPedalModel &model, const std::filesystem::path &path)
{
this->pluginUploadDirectory = model.GetPluginUploadDirectory();
zipFile = ZipFileReader::Create(path);
- auto s = zipFile->GetFileInputStream("bankFile.json");
+ auto s = zipFile->GetFileInputStream("pluginPresets.json");
json_reader reader(s);
- reader.read(&bankFile);
+ reader.read(&pluginPresets);
}
virtual ~PresetBundleReaderImpl() noexcept;
@@ -296,7 +296,7 @@ PresetBundleReader::ptr PresetBundleReader::LoadPresetsFile(PiPedalModel &model,
PresetBundleReader::ptr PresetBundleReader::LoadPluginPresetsFile(PiPedalModel &model, const std::filesystem::path &filePath)
{
std::unique_ptr result = std::make_unique();
- result->LoadPluginPresetsFile(model, filePath);
+ result->LoadPluginPresetFile(model, filePath);
return result;
}
diff --git a/src/Storage.cpp b/src/Storage.cpp
index 92f49cc..fbea14f 100644
--- a/src/Storage.cpp
+++ b/src/Storage.cpp
@@ -1107,6 +1107,67 @@ std::filesystem::path Storage::GetPluginPresetPath(const std::string &pluginUri)
}
throw PiPedalArgumentException("Plugin preset file not found.");
}
+
+void Storage::MergePluginPresets(const std::string &pluginUri, const PluginPresets &presets)
+{
+ std::string name;
+ std::filesystem::path path;
+ bool presetAdded = false;
+ PluginPresets existingPresets;
+ if (!HasPluginPresets(pluginUri))
+ {
+ name = SS(pluginPresetIndex.nextInstanceId_ << ".json");
+ path = GetPluginPresetsDirectory() / name;
+ presetAdded = true;
+ }
+ else
+ {
+ path = GetPluginPresetPath(pluginUri);
+ try {
+ std::ifstream f(path);
+ if (f.is_open())
+ {
+ json_reader reader(f);
+ reader.read(&existingPresets);
+ }
+ } catch (const std::exception &e)
+ {
+ Lv2Log::error(SS("Storage::MergePluginPresets: Can't reading existing plugin presets." << e.what()));
+ }
+ }
+ for (const PluginPreset &preset: presets.presets_)
+ {
+
+ existingPresets.MergePreset(preset);
+ }
+ auto tempPath = path.string() + ".$$$";
+ {
+ pipedal::ofstream_synced os;
+ os.open(tempPath, std::ios_base::trunc);
+ if (os.fail())
+ {
+ throw PiPedalException(SS("Can't write to " << path));
+ }
+ json_writer writer(os, true);
+ writer.write(existingPresets);
+ }
+ if (std::filesystem::exists(path))
+ {
+ std::filesystem::remove(path);
+ }
+ std::filesystem::rename(tempPath, path);
+
+ if (presetAdded)
+ {
+ pluginPresetIndex.entries_.push_back(
+ PluginPresetIndexEntry(
+ pluginUri, name));
+ pluginPresetIndex.nextInstanceId_++;
+ this->pluginPresetIndexChanged = true;
+ SavePluginPresetIndex();
+ }
+}
+
void Storage::SavePluginPresets(const std::string &pluginUri, const PluginPresets &presets)
{
std::string name;
diff --git a/src/Storage.hpp b/src/Storage.hpp
index b129852..e00da98 100644
--- a/src/Storage.hpp
+++ b/src/Storage.hpp
@@ -187,6 +187,7 @@ private:
public:
bool HasPluginPresets(const std::string&pluginUri) const;
void SavePluginPresets(const std::string&pluginUri, const PluginPresets&presets);
+ void MergePluginPresets(const std::string&pluginUri, const PluginPresets&presets);
PluginPresets GetPluginPresets(const std::string&pluginUri) const;
const PluginPresetIndex& GetPluginPresetIndex();
diff --git a/src/WebServerConfig.cpp b/src/WebServerConfig.cpp
index e453a5e..e516139 100644
--- a/src/WebServerConfig.cpp
+++ b/src/WebServerConfig.cpp
@@ -37,7 +37,7 @@
#define OLD_PRESET_EXTENSION ".piPreset"
#define PRESET_EXTENSION ".piPreset"
#define OLD_BANK_EXTENSION ".piBank"
-#define BANK_EXTENSION ".piBankBundle"
+#define BANK_EXTENSION ".piBank"
#define PLUGIN_PRESETS_EXTENSION ".piPluginPresets"
static const std::filesystem::path WEB_TEMP_DIR{"/var/pipedal/web_temp"};
@@ -598,6 +598,7 @@ public:
}
catch (const std::exception &e)
{
+ Lv2Log::error(SS("Error uploading file: " << e.what()) );
if (strcmp(e.what(), "Not found") == 0)
{
ec = boost::system::errc::make_error_code(boost::system::errc::no_such_file_or_directory);