diff --git a/CMakeLists.txt b/CMakeLists.txt
index 564358c..1d6f9bb 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,10 +1,10 @@
cmake_minimum_required(VERSION 3.16.0)
project(pipedal
- VERSION 1.3.54
+ VERSION 1.3.55
DESCRIPTION "PiPedal Guitar Effect Pedal For Raspberry Pi"
HOMEPAGE_URL "https://rerdavies.github.io/pipedal"
)
-set (DISPLAY_VERSION "PiPedal v1.3.54-Release")
+set (DISPLAY_VERSION "PiPedal v1.3.55-Release")
set (PACKAGE_ARCHITECTURE "arm64")
set (CMAKE_INSTALL_PREFIX "/usr/")
diff --git a/NetworkManagerP2P/src/SignalHandler.cpp b/NetworkManagerP2P/src/SignalHandler.cpp
index 35357cc..f1fe2fc 100644
--- a/NetworkManagerP2P/src/SignalHandler.cpp
+++ b/NetworkManagerP2P/src/SignalHandler.cpp
@@ -20,7 +20,7 @@ static int ToOsSignalType(SignalHandler::SignalType signalType)
case SignalHandler::Hangup: result = SIGHUP; break;
default:
- throw std::runtime_error("INvalid signal type");
+ throw std::runtime_error("Invalid signal type");
}
return result;
}
diff --git a/README.md b/README.md
index 86f94e4..7375c72 100644
--- a/README.md
+++ b/README.md
@@ -6,13 +6,13 @@
-Download: v1.3.54
+Download: v1.3.55
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.54 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.55 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 083e737..f875466 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.54](https://github.com/rerdavies/pipedal/releases/download/)
+- [Raspberry Pi OS bookworm (64-bit) v1.3.55](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.54 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.55 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.54_arm64.deb
+ sudo apt-get install pipedal_1.3.55_arm64.deb
```
Adjust accordingly if you have downloaded v1.1.31.
diff --git a/docs/ReleaseNotes.md b/docs/ReleaseNotes.md
index 9d76cfa..df6523f 100644
--- a/docs/ReleaseNotes.md
+++ b/docs/ReleaseNotes.md
@@ -1,4 +1,14 @@
# Release Notes
+
+## PiPedal 1.3.55 Release
+
+More snapshot problems.
+
+Bug fixes:
+- Crashes related to snapshots and split controls.
+- Loading/reloading/error screens go on top of Snapshot dialogs.
+
+
## PiPedal 1.3.54 Release
Improvements to and fixes for hotspot functionality. Fixes for problems with snapshots.
@@ -8,7 +18,7 @@ Minor features;
- Uploaded .zip files create a top-level directory with the name of the zip file if the zip file doesn't contain a single root-level directory. (released in 1.3.53)
-Bug fixes.
+Bug fixes:
- Various crashes related to snapshots.
- Applying changes to Wi-Fi hotspot configuration would not change the configuration until PiPedal was rebooted (a regression).
diff --git a/docs/download.md b/docs/download.md
index b1ebd8b..e8782e7 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.54
+- Raspberry Pi OS Bookworm (64-bit) v1.3.55
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.54_arm64.deb
+ sudo apt-get install ./pipedal_1.3.55_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 5e19088..6d15d6a 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -1,7 +1,7 @@
-v1.3.54
+v1.3.55
@@ -9,7 +9,7 @@ To download PiPedal, click [here](download.md).
To view PiPedal documentation, click [here](Documentation.md).
-#### NEW version 1.3.54 Release. See the [release notes](https://rerdavies.github.io/pipedal/ReleaseNotes) for details.
+#### NEW version 1.3.55 Release. See the [release notes](https://rerdavies.github.io/pipedal/ReleaseNotes) for details.
diff --git a/react/src/AppThemed.tsx b/react/src/AppThemed.tsx
index 4845347..3b54b8e 100644
--- a/react/src/AppThemed.tsx
+++ b/react/src/AppThemed.tsx
@@ -17,12 +17,12 @@
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-import { SyntheticEvent } from 'react';
import { WithStyles } from '@mui/styles';
import './AppThemed.css';
-
+//import {alpha} from '@mui/material/styles';
import AppBar from '@mui/material/AppBar';
+import Modal from '@mui/material/Modal';
import Toolbar from '@mui/material/Toolbar';
import CssBaseline from '@mui/material/CssBaseline';
import Typography from '@mui/material/Typography';
@@ -36,7 +36,9 @@ import FullscreenIcon from '@mui/icons-material/Fullscreen';
import FullscreenExitIcon from '@mui/icons-material/FullscreenExit';
import List from '@mui/material/List';
import Divider from '@mui/material/Divider';
-import ListItem from '@mui/material/ListItem';
+// import ListItem from '@mui/material/ListItem';
+import ListItemButton from '@mui/material/ListItemButton';
+
import ListItemIcon from '@mui/material/ListItemIcon';
import ListItemText from '@mui/material/ListItemText';
import CircularProgress from '@mui/material/CircularProgress';
@@ -92,6 +94,17 @@ const appStyles = (theme: Theme) => createStyles({
listSubheader: {
backgroundImage: "linear-gradient(255,255,255,0.15),rgba(255,255,255,0.15)"
},
+ loadingMask: {
+ position: "absolute",
+ minHeight: "10em",
+ left: "0px",
+ top: "0px",
+ right: "0px",
+ bottom: "0px",
+ opacity: 0.8,
+ background:
+ isDarkMode() ? "#222" : "#DDD",
+ },
loadingContent: {
display: "block",
position: "absolute",
@@ -100,7 +113,6 @@ const appStyles = (theme: Theme) => createStyles({
top: "0px",
width: "100%",
height: "100%",
- background: isDarkMode() ? "#222" : "#DDD",
opacity: "0.95",
justifyContent: "center",
textAlign: "center",
@@ -166,22 +178,22 @@ const appStyles = (theme: Theme) => createStyles({
},
loadingBox: {
- position: "relative",
+ display: "flex",
+ flexFlow: "column nowrap",
+ position: "absolute",
top: "20%",
+ left: 0, right: 0,
color: isDarkMode() ? theme.palette.text.secondary : "#888",
// border: "3px solid #888",
- borderRadius: "12px",
- padding: "12px",
- justifyContent: "center",
+ alignItems: "center",
textAlign: "center",
opacity: 0.8,
- zIndex: 2010
},
loadingBoxItem: {
- justifyContent: "center",
+ display: "flex", flexFlow: "row nowrap",
+ alignItems: "center",
textAlign: "center",
- zIndex: 2010
},
@@ -247,9 +259,8 @@ function setFullScreen(value: boolean) {
if (docEl.requestFullscren) // the latest offical api.
{
- if (value)
- {
- window.document.documentElement.requestFullscreen({navigationUI: "show"});
+ if (value) {
+ window.document.documentElement.requestFullscreen({ navigationUI: "show" });
} else {
window.document.exitFullscreen();
}
@@ -267,10 +278,10 @@ function setFullScreen(value: boolean) {
}
-function preventDefault(e: SyntheticEvent): void {
- e.stopPropagation();
- e.preventDefault();
-}
+// function preventDefault(e: SyntheticEvent): void {
+// e.stopPropagation();
+// e.preventDefault();
+// }
type AppState = {
zoomedControlInfo: ZoomedControlInfo | undefined;
@@ -403,7 +414,8 @@ const AppThemed = withStyles(appStyles)(class extends ResizeResponsiveComponent<
return false;
}
- onOpenBank(bankId: number) {
+ handleSpecificBank(bankId: number) {
+
this.model_.openBank(bankId)
.catch((error) => this.model_.showAlert(error.toString()));
@@ -491,17 +503,15 @@ const AppThemed = withStyles(appStyles)(class extends ResizeResponsiveComponent<
}
handleDrawerSelectBank() {
+
this.setState({
- isDrawerOpen: false,
bankDialogOpen: true,
editBankDialogOpen: false
});
}
handleDrawerDonationClick() {
- this.setState({
- isDrawerOpen: false,
- });
+ this.hideDrawer(false);
if (this.model_.isAndroidHosted()) {
this.model_.showAndroidDonationActivity();
} else {
@@ -514,14 +524,12 @@ const AppThemed = withStyles(appStyles)(class extends ResizeResponsiveComponent<
handleDrawerAboutClick() {
this.setState({
- isDrawerOpen: false,
aboutDialogOpen: true
});
}
handleDrawerRenameBank() {
this.setState({
- isDrawerOpen: false,
renameBankDialogOpen: true,
saveBankAsDialogOpen: false
});
@@ -529,7 +537,6 @@ const AppThemed = withStyles(appStyles)(class extends ResizeResponsiveComponent<
}
handleDrawerSaveBankAs() {
this.setState({
- isDrawerOpen: false,
renameBankDialogOpen: false,
saveBankAsDialogOpen: true
});
@@ -657,6 +664,8 @@ const AppThemed = withStyles(appStyles)(class extends ResizeResponsiveComponent<
let bankEntries = Math.floor((height - K) / ENTRY_HEIGHT);
if (bankEntries < 1) bankEntries = 1;
if (bankEntries > 7) bankEntries = 7;
+ if (bankEntries === 2) bankEntries = 1;
+
this.setState({ bankDisplayItems: bankEntries });
}
@@ -686,27 +695,33 @@ const AppThemed = withStyles(appStyles)(class extends ResizeResponsiveComponent<
}
shortBankList(banks: BankIndex): BankIndexEntry[] {
- let n = this.state.bankDisplayItems;
+ let nDisplayEntries = this.state.bankDisplayItems;
let entries = banks.entries;
- if (entries.length < n + 1) { // +1 for the .... entry.
- return entries;
- }
+ let nListEntries = entries.length;
+
let result: BankIndexEntry[] = [];
- let selectedIndex = -1;
- for (let i = 0; i < entries.length; ++i) {
- if (entries[i].instanceId === banks.selectedBank) {
- selectedIndex = i;
- break;
- }
- }
- if (n > entries.length) n = entries.length;
- if (selectedIndex > n) {
- for (let i = 0; i < n - 1; ++i) {
+
+ if (nListEntries <= nDisplayEntries) {
+ for (let i = 0; i < nListEntries; ++i) {
result.push(entries[i]);
}
- result.push(entries[selectedIndex]);
} else {
- for (let i = 0; i < n; ++i) {
+ // a subset of the list CENTERED on the currently selected entry.
+ let selectedIndex = 0;
+ for (let i = 0; i < nListEntries; ++i) {
+ if (entries[i].instanceId === banks.selectedBank) {
+ selectedIndex = i;
+ break;
+ }
+ }
+
+ let minN = selectedIndex - Math.floor(nDisplayEntries / 2);
+ if (minN < 0) minN = 0;
+ let maxN = minN + nDisplayEntries;
+ if (maxN > entries.length) {
+ maxN = entries.length;
+ }
+ for (let i = minN; i < maxN; ++i) {
result.push(entries[i]);
}
}
@@ -747,7 +762,7 @@ const AppThemed = withStyles(appStyles)(class extends ResizeResponsiveComponent<
{
@@ -831,11 +846,11 @@ const AppThemed = withStyles(appStyles)(class extends ResizeResponsiveComponent<
)}
{ this.hideDrawer(); }} >
+ is_open={this.state.isDrawerOpen} onClose={() => { this.hideDrawer(false); }} >
- {
+ {
ev.stopPropagation();
this.hideDrawer(true);
this.setState({ performanceView: true });
@@ -844,7 +859,7 @@ const AppThemed = withStyles(appStyles)(class extends ResizeResponsiveComponent<
-
+
@@ -1040,67 +1058,62 @@ const AppThemed = withStyles(appStyles)(class extends ResizeResponsiveComponent<
-
-
-
-
-
-
-
-
-
- Error: {this.state.errorMessage}
-
-
-
-
+
+
+
+
+
+
+
+
+
+ Error: {this.state.errorMessage}
+
+
+
+
+
-
+
-
-
-
- {/* initial load mask*/}
-
+
{/* Reloading mask */}
-
-
-
-
-
-
+
+
+
+
+
+
+
+ {
+ this.state.displayState === State.Loading ?
+ "Loading..."
+ :this.getReloadingMessage()
+ }
+
-
- {this.getReloadingMessage()}
-
-
-
+
+
);
}
});
diff --git a/react/src/Pedalboard.tsx b/react/src/Pedalboard.tsx
index 414d060..f1d6faf 100644
--- a/react/src/Pedalboard.tsx
+++ b/react/src/Pedalboard.tsx
@@ -206,6 +206,7 @@ export class PedalboardItem implements Deserializable
{
export class SnapshotValue {
deserialize(input: any): SnapshotValue {
+ this.isEnabled = input.isEnabled;
this.instanceId = input.instanceId;
this.controlValues = ControlValue.deserializeArray(input.controlValues);
this.lv2State = input.lv2state;
diff --git a/src/AudioHost.cpp b/src/AudioHost.cpp
index 0e559b4..f909380 100644
--- a/src/AudioHost.cpp
+++ b/src/AudioHost.cpp
@@ -135,7 +135,7 @@ namespace pipedal
{
auto maxInputControl = effect->GetMaxInputControl();
inputControlValues.resize(maxInputControl);
-
+ this->enabled = true;
for (uint64_t i = 0; i < maxInputControl; ++i)
{
bool isInputControl = effect->IsInputControl(i);
@@ -150,6 +150,7 @@ namespace pipedal
}
if (snapshotValue)
{
+ this->enabled = snapshotValue->isEnabled_;
for (auto &controlValue : snapshotValue->controlValues_)
{
auto index = effect->GetControlIndex(controlValue.key());
@@ -202,6 +203,8 @@ namespace pipedal
}
void ApplyValues(IEffect *effect)
{
+
+ effect->SetBypass(this->enabled);
if (effect != pEffect)
{
throw std::runtime_error("Wrong effect");
@@ -226,6 +229,7 @@ namespace pipedal
private:
IEffect *pEffect;
Lv2PluginState lv2State;
+ bool enabled;
std::vector inputControlValues;
std::vector pathPatchProperties;
};
diff --git a/src/AvahiService.cpp b/src/AvahiService.cpp
index 02f54cc..b56d432 100644
--- a/src/AvahiService.cpp
+++ b/src/AvahiService.cpp
@@ -482,8 +482,8 @@ void AvahiService::Wait()
{
default:
case ServiceState::Unitialized:
- throw std::runtime_error("Invalid state");
-
+ done = true;
+ break;
case ServiceState::Initializing:
case ServiceState::Settling:
case ServiceState::Requested:
@@ -503,6 +503,8 @@ void AvahiService::Wait()
if (clock::now() > waitTime)
{
Lv2Log::error("DNS/SD announcement timed out.");
+ done = true;
+ break;
}
std::this_thread::sleep_for(std::chrono::milliseconds(20));
diff --git a/src/ConfigMain.cpp b/src/ConfigMain.cpp
index 9c953ca..6b5e159 100644
--- a/src/ConfigMain.cpp
+++ b/src/ConfigMain.cpp
@@ -155,6 +155,49 @@ void DisableService()
#endif
}
+bool disableAvahiConfigLine(SystemConfigFile &avahi, const std::string §ion, const std::string &lineStart)
+{
+ bool changed = false;
+ // use-ipv6=no
+ int line = avahi.GetLineThatStartsWith(lineStart + "yes");
+ if (line != -1)
+ {
+ avahi.UndoableReplaceLine(line, lineStart + "no");
+ changed = true;
+ }
+ else
+ {
+ if (avahi.GetLineThatStartsWith(lineStart + "no") == -1)
+ {
+ line = avahi.GetLineThatStartsWith(section);
+ if (line == -1)
+ {
+ throw std::runtime_error("Unable to find [server] section.");
+ }
+ {
+ ++line;
+ // increment to end of section.
+ while (line < avahi.GetLineCount())
+ {
+ const auto &txt = avahi.Get(line);
+ if (txt.empty())
+ {
+ break;
+ }
+ if (txt.starts_with("[")) // start of next section.
+ {
+ break;
+ }
+ ++line;
+ }
+ }
+ avahi.UndoableAddLine(line,lineStart+"no");
+ changed = true;
+ }
+ }
+ return changed;
+}
+
static void RestartAvahiService()
{
silentSysExec(SS(SYSTEMCTL_BIN << " restart avahi-daemon.service").c_str());
@@ -169,41 +212,10 @@ static void AvahiInstall()
SystemConfigFile avahi(avahiConfig);
bool changed = avahi.RemoveUndoableActions();
- int line = avahi.GetLineThatStartsWith("use-ipv6=yes");
- if (line != -1)
- {
- avahi.UndoableReplaceLine(line, "use-ipv6=no");
- changed = true;
- }
- else
- {
- if (avahi.GetLineThatStartsWith("use-ipv6=no") == -1)
- {
- line = avahi.GetLineThatStartsWith("[server]");
- if (line == 1)
- {
- throw std::runtime_error("Unable to find [server] section.");
- }
- {
- // increment to end of section.
- while (line < avahi.GetLineCount())
- {
- const auto &txt = avahi.Get(line);
- if (txt.empty())
- {
- break;
- }
- if (txt.starts_with("[")) // start of next section.
- {
- break;
- }
- ++line;
- }
- }
- avahi.UndoableAddLine(avahi.GetLineCount(), "use-ipv6=no");
- changed = true;
- }
- }
+
+ changed |= disableAvahiConfigLine(avahi, "[server]", "use-ipv6=");
+ changed |= disableAvahiConfigLine(avahi, "[publish]", "publish-aaaa-on-ipv4=");
+
if (changed)
{
avahi.Save();
@@ -914,7 +926,7 @@ void Install(const fs::path &programPrefix, const std::string endpointAddress)
try
{
// apply policy changes we dropped into the polkit configuration files (allows pipedal_d to use NetworkManager dbus apis).
- silentSysExec(SYSTEMCTL_BIN " restart polkit");
+ silentSysExec(SYSTEMCTL_BIN " restart polkit");
DeployVarConfig();
@@ -995,7 +1007,6 @@ void Install(const fs::path &programPrefix, const std::string endpointAddress)
// add to netdev group
sysExec(USERMOD_BIN " -a -G " NETDEV_GROUP_NAME " " SERVICE_ACCOUNT_NAME);
-
// create and configure /var directory.
fs::path varDirectory("/var/pipedal");
@@ -1211,11 +1222,11 @@ static void PrintHelp()
<< "\n\n"
<< "One of the following hotspot options can be specifed. If no hotspot option is given, the hotspot will always be enabled. "
<< "If one of the hotspot options are given, the PiPedal server will turn the hotspot on or off automatically, as conditions change."
- << "\n\n"
+ << "\n\n"
<< "--home-network \n"
<< AddIndent(4) << "Hotspot is disabled if the specificed Wi-Fi network is detected.\n"
<< AddIndent(-4)
- << "--no-ethernet\n"
+ << "--no-ethernet\n"
<< AddIndent(4) << "Hotspot is disabled if an ethernet network is connected.\n"
<< AddIndent(-4)
<< "--no-wifi\n"
@@ -1336,9 +1347,9 @@ int main(int argc, char **argv)
parser.AddOption("--port", &portOption);
parser.AddOption("--enable-hotspot", &enable_hotspot);
parser.AddOption("--disable-hotspot", &disable_hotspot);
- parser.AddOption("--home-network",&homeNetwork);
- parser.AddOption("--no-ethernet",&noEthernet);
- parser.AddOption("--no-wifi",&noWifi);
+ parser.AddOption("--home-network", &homeNetwork);
+ parser.AddOption("--no-ethernet", &noEthernet);
+ parser.AddOption("--no-wifi", &noWifi);
try
{
parser.Parse(argc, (const char **)argv);
@@ -1367,9 +1378,7 @@ int main(int argc, char **argv)
}
}
int hotspotOptionCount =
- (homeNetwork.length() != 0 ? 1: 0)
- + noEthernet
- + noWifi;
+ (homeNetwork.length() != 0 ? 1 : 0) + noEthernet + noWifi;
if (enable_hotspot)
{
@@ -1377,7 +1386,9 @@ int main(int argc, char **argv)
{
throw std::runtime_error("Only one hotspot option at a time can be specified.");
}
- } else {
+ }
+ else
+ {
if (hotspotOptionCount > 0)
{
throw std::runtime_error("Hotspot options only only valid when the --enable-hotspot option has been supplied.");
@@ -1432,7 +1443,8 @@ int main(int argc, char **argv)
}
if (install)
{
- try {
+ try
+ {
fs::path prefix;
if (prefixOption.length() != 0)
{
@@ -1465,8 +1477,8 @@ int main(int argc, char **argv)
}
Install(prefix, portOption);
FileSystemSync();
-
- } catch (const std::exception&e)
+ }
+ catch (const std::exception &e)
{
cout << "ERROR: " << e.what() << endl;
FileSystemSync();
@@ -1475,10 +1487,12 @@ int main(int argc, char **argv)
}
else if (uninstall)
{
- try {
+ try
+ {
Uninstall();
FileSystemSync();
- } catch (const std::exception &e)
+ }
+ catch (const std::exception &e)
{
cout << "ERROR: " << e.what() << endl;
FileSystemSync();
@@ -1489,7 +1503,6 @@ int main(int argc, char **argv)
{
RequireNetworkManager();
StopService();
-
}
else if (start)
{
@@ -1506,14 +1519,12 @@ int main(int argc, char **argv)
RequireNetworkManager();
EnableService();
FileSystemSync();
-
}
else if (disable)
{
RequireNetworkManager();
DisableService();
FileSystemSync();
-
}
else if (enable_p2p)
{
@@ -1541,8 +1552,7 @@ int main(int argc, char **argv)
settings.Load();
settings.enable_ = false;
SetWifiDirectConfig(settings);
-
-
+
RestartService(true);
return EXIT_SUCCESS;
}
@@ -1557,15 +1567,17 @@ int main(int argc, char **argv)
if (homeNetwork.length() != 0)
{
startMode = HotspotAutoStartMode::NotAtHome;
- } else if (noEthernet)
+ }
+ else if (noEthernet)
{
startMode = HotspotAutoStartMode::NoEthernetConnection;
- } else if (noWifi)
+ }
+ else if (noWifi)
{
startMode = HotspotAutoStartMode::NoRememberedWifiConections;
}
- settings.ParseArguments(argv,startMode,homeNetwork);
+ settings.ParseArguments(argv, startMode, homeNetwork);
if (settings.hasPassword_)
{
diff --git a/src/Lv2Effect.hpp b/src/Lv2Effect.hpp
index 2fed630..a85e5ae 100644
--- a/src/Lv2Effect.hpp
+++ b/src/Lv2Effect.hpp
@@ -293,7 +293,10 @@ namespace pipedal
virtual float GetOutputControlValue(int portIndex) const
{
- return controlValues[portIndex];
+ if (portIndex >= 0 && portIndex < controlValues.size()) {
+ return controlValues[portIndex];
+ }
+ return 0;
}
virtual void SetBypass(bool bypass)
diff --git a/src/Pedalboard.cpp b/src/Pedalboard.cpp
index 5349a96..77a334a 100644
--- a/src/Pedalboard.cpp
+++ b/src/Pedalboard.cpp
@@ -20,6 +20,9 @@
#include "pch.h"
#include "Pedalboard.hpp"
#include "AtomConverter.hpp"
+#include "PluginHost.hpp"
+#include "AtomConverter.hpp"
+#include "SplitEffect.hpp"
using namespace pipedal;
@@ -87,6 +90,19 @@ ControlValue* PedalboardItem::GetControlValue(const std::string&symbol)
return nullptr;
}
+
+bool PedalboardItem::SetControlValue(const std::string&symbol, float value)
+{
+ ControlValue*controlValue = GetControlValue(symbol);
+ if (controlValue == nullptr) return false;
+ if (controlValue->value() != value)
+ {
+ controlValue->value(value);
+ return true;
+ }
+ return false;
+}
+
const ControlValue* PedalboardItem::GetControlValue(const std::string&symbol) const
{
for (size_t i = 0; i < this->controlValues().size(); ++i)
@@ -117,14 +133,7 @@ bool Pedalboard::SetControlValue(int64_t pedalItemId, const std::string &symbol,
{
PedalboardItem*item = GetItem(pedalItemId);
if (!item) return false;
- ControlValue*controlValue = item->GetControlValue(symbol);
- if (controlValue == nullptr) return false;
- if (controlValue->value() != value)
- {
- controlValue->value(value);
- return true;
- }
- return false;
+ return item->SetControlValue(symbol,value);
}
@@ -190,12 +199,12 @@ bool IsPedalboardSplitItem(const PedalboardItem*self, const std::vectoruri() == SPLIT_PEDALBOARD_ITEM_URI;
}
-bool Pedalboard::ApplySnapshot(int64_t snapshotIndex)
+bool Pedalboard::ApplySnapshot(int64_t snapshotIndex, PluginHost&pluginHost)
{
if (snapshotIndex < 0 ||
snapshotIndex >= this->snapshots_.size() ||
- this->snapshots_[snapshotIndex] == nullptr ||
- this->selectedSnapshot() == snapshotIndex)
+ this->snapshots_[snapshotIndex] == nullptr
+ )
{
return false;
}
@@ -210,15 +219,47 @@ bool Pedalboard::ApplySnapshot(int64_t snapshotIndex)
auto plugins = this->GetAllPlugins();
for (PedalboardItem *pedalboardItem: plugins)
{
- SnapshotValue*snapshotValue = indexedValues[pedalboardItem->instanceId()];
- if (snapshotValue)
+ if (!pedalboardItem->isEmpty())
{
- pedalboardItem->ApplySnapshotValue(snapshotValue);
+ SnapshotValue*snapshotValue = indexedValues[pedalboardItem->instanceId()];
+ if (snapshotValue)
+ {
+ pedalboardItem->ApplySnapshotValue(snapshotValue);
+ } else {
+ pedalboardItem->ApplyDefaultValues(pluginHost);
+ }
}
}
return true;
}
+void PedalboardItem::ApplyDefaultValues(PluginHost&pluginHost)
+{
+ if (isEmpty()) return;
+ auto pluginInfo = pluginHost.GetPluginInfo(this->uri());
+ if (!pluginInfo)
+ {
+ if (this->isSplit())
+ {
+ pluginInfo = GetSplitterPluginInfo();
+ }
+ }
+ this->isEnabled(true);
+ if (pluginInfo)
+ {
+ for (auto &port: pluginInfo->ports())
+ {
+ this->SetControlValue(port->symbol(),port->default_value());
+ }
+ // a cheat. this isn't actually true, but close enough.
+ for (auto &pathProperty: this->pathProperties_)
+ {
+ pathProperties_[pathProperty.first] = AtomConverter::EmptyPathstring();
+ }
+ }
+}
+
+
void PedalboardItem::ApplySnapshotValue(SnapshotValue*snapshotValue)
{
std::map cumulativeValues;
@@ -240,6 +281,16 @@ void PedalboardItem::ApplySnapshotValue(SnapshotValue*snapshotValue)
this->lv2State(snapshotValue->lv2State_);
this->stateUpdateCount(this->stateUpdateCount()+1);
}
+ for (auto&property: snapshotValue->pathProperties_)
+ {
+ if (property.second == "null")
+ {
+ this->pathProperties_[property.first] = AtomConverter::EmptyPathstring();
+
+ } else {
+ this->pathProperties_[property.first] = property.second;
+ }
+ }
this->isEnabled(snapshotValue->isEnabled_);
}
@@ -278,17 +329,19 @@ 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;
- }
+ // provisionally, it seems ok to change the split type.
+ // 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;
@@ -407,17 +460,19 @@ Snapshot Pedalboard::MakeSnapshotFromCurrentSettings(const Pedalboard &previousP
{
Snapshot snapshot;
// name and color don't matter. this is strictly for loading purposes.
- for (auto &item : this->items())
+ auto items = this->GetAllPlugins();
+ for (auto item : items)
{
- item.AddToSnapshotFromCurrentSettings(snapshot);
+ item->AddToSnapshotFromCurrentSettings(snapshot);
}
// a neccesary precondition: the previous pedalboard must have identical structure,
// so we can just
- size_t index = 0;
- for (auto&item: previousPedalboard.items_)
- {
- item.AddResetsForMissingProperties(snapshot,&index);
- }
+ // auto items = this->GetAllPlugins();
+
+ // for (auto&item: previousPedalboard.items_)
+ // {
+ // item.AddResetsForMissingProperties(snapshot,&index);
+ // }
return snapshot;
}
diff --git a/src/Pedalboard.hpp b/src/Pedalboard.hpp
index 7e67f67..9ae3565 100644
--- a/src/Pedalboard.hpp
+++ b/src/Pedalboard.hpp
@@ -28,6 +28,7 @@
namespace pipedal {
class SnapshotValue;
class Snapshot;
+ class PluginHost;
#define SPLIT_PEDALBOARD_ITEM_URI "uri://two-play/pipedal/pedalboard#Split"
#define EMPTY_PEDALBOARD_ITEM_URI "uri://two-play/pipedal/pedalboard#Empty"
@@ -102,10 +103,13 @@ public:
public:
ControlValue*GetControlValue(const std::string&symbol);
const ControlValue*GetControlValue(const std::string&symbol) const;
+ bool SetControlValue(const std::string&key, float value);
+
bool IsStructurallyIdentical(const PedalboardItem&other) const;
void ApplySnapshotValue(SnapshotValue*snapshotValue);
+ void ApplyDefaultValues(PluginHost&pluginHost);
bool hasLv2State() const {
return lv2State_.isValid_ != 0;
}
@@ -203,7 +207,7 @@ public:
std::vectorGetAllPlugins();
bool HasItem(int64_t pedalItemid) const { return GetItem(pedalItemid) != nullptr; }
- bool ApplySnapshot(int64_t snapshotIndex);
+ bool ApplySnapshot(int64_t snapshotIndex, PluginHost &pluginHost);
GETTER_SETTER_REF(name)
GETTER_SETTER_VEC(items)
diff --git a/src/PiPedalModel.cpp b/src/PiPedalModel.cpp
index e1d46e3..8860bfe 100644
--- a/src/PiPedalModel.cpp
+++ b/src/PiPedalModel.cpp
@@ -535,23 +535,17 @@ void PiPedalModel::SetPedalboard(int64_t clientId, Pedalboard &pedalboard)
void PiPedalModel::SetSnapshot(int64_t selectedSnapshot)
{
std::lock_guard lock(mutex);
- if (this->pedalboard.ApplySnapshot(selectedSnapshot))
+ if (this->pedalboard.ApplySnapshot(selectedSnapshot, pluginHost))
{
- this->pedalboard.SetCurrentSnapshotModified(false);
- this->FireSnapshotModified(selectedSnapshot,false);
- if (this->audioHost)
- {
- 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);
- FirePedalboardChanged(-1, false);
+ for (auto snapshot: this->pedalboard.snapshots())
+ {
+ if (snapshot)
+ {
+ snapshot->isModified_ = false;
+ }
+ }
+ FirePedalboardChanged(-1, true);
}
}
@@ -567,6 +561,13 @@ void PiPedalModel::SetSnapshots(std::vector> &snapshot
if (selectedSnapshot != -1)
{
this->pedalboard.selectedSnapshot(selectedSnapshot);
+ for (auto &snapshot: pedalboard.snapshots())
+ {
+ if (snapshot)
+ {
+ snapshot->isModified_ = false;
+ }
+ }
}
this->FirePedalboardChanged(-1, false); // notify clients (but don't change the running pedalboard, because it's still the same)
diff --git a/src/SplitEffect.cpp b/src/SplitEffect.cpp
index cf06c7e..2f2dcc7 100644
--- a/src/SplitEffect.cpp
+++ b/src/SplitEffect.cpp
@@ -182,6 +182,7 @@ SplitEffect::SplitEffect(
Lv2PluginInfo::ptr puginInfo = g_splitterPluginInfo;
+ defaultInputControlValues.resize(MAX_INPUT_CONTROL);
for (auto&port: puginInfo->ports())
{
if (port->is_control_port() && port->is_input())
diff --git a/src/SplitEffect.hpp b/src/SplitEffect.hpp
index e408a0e..b85fdc2 100644
--- a/src/SplitEffect.hpp
+++ b/src/SplitEffect.hpp
@@ -358,7 +358,6 @@ namespace pipedal
virtual void SetBypass(bool enabled)
{
- throw PiPedalArgumentException("Not implmented. Should not have been called.");
}
virtual float GetOutputControlValue(int index) const {
diff --git a/todo.txt b/todo.txt
index 8dc7b59..ffdaf18 100644
--- a/todo.txt
+++ b/todo.txt
@@ -1,3 +1,21 @@
+Loading shields need to be of Modal type.
+
+MOD fileTypes
+
+ - audioloop: Audio Loops, meant to be used for looper-style plugins
+ - audiorecording: Audio Recordings, triggered by plugins and stored in the unit
+ - audiosample: One-shot Audio Samples, meant to be used for sampler-style plugins
+ - audiotrack: Audio Tracks, meant to be used as full-performance/song or backtrack
+ - cabsim: Speaker Cabinets, meant as small IR audio files
+ - h2drumkit: Hydrogen Drumkits, must use h2drumkit file extension
+ - ir: Impulse Responses
+ - midiclip: MIDI Clips, to be used in sync with host tempo, must have mid or midi file extension
+ - midisong: MIDI Songs, meant to be used as full-performance/song or backtrack
+ - sf2: SF2 Instruments, must have sf2 or sf3 file extension
+ - sfz: SFZ Instruments, must have sfz file extension
+
+
+
Main menu on Pixel 5 client.
x1 bank menu (landscape pixel 5) should show current bank.