From 807dd613ac064c762894f14ea41ef8206ac2c35b Mon Sep 17 00:00:00 2001 From: Robin Davies Date: Sat, 12 Oct 2024 19:18:34 -0400 Subject: [PATCH 01/13] Enable ipv6 on hotspot. --- src/HotspotManager.cpp | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/src/HotspotManager.cpp b/src/HotspotManager.cpp index d4e76a5..8d9de21 100644 --- a/src/HotspotManager.cpp +++ b/src/HotspotManager.cpp @@ -467,7 +467,7 @@ void HotspotManagerImpl::onReload() case State::HotspotConnected: default: // force a reload. - StopHotspot(); + StopHotspot(); SetState(State::Monitoring); MaybeStartHotspot(); return; @@ -861,28 +861,32 @@ void HotspotManagerImpl::StartHotspot() settings["ipv4"]["method"] = "shared"; settings["ipv6"]["method"] = "shared"; + settings["ipv6"]["addr-gen-mode"] = 1; // "stable-privacy"; + + //////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////// - - // Create connection - settings["ipv4"]["method"] = sdbus::Variant(std::string("shared")); - //settings["ipv6"]["method"] = sdbus::Variant(std::string("ignore")); + // 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>{{{"address", sdbus::Variant("192.168.60.1")}, {"prefix", sdbus::Variant(uint32_t(24))}}}); + // settings["ipv4"]["gateway'"] = sdbus::Variant(std::string("192.168.60.1")); settings["ipv4"]["dhcp-send-hostname"] = sdbus::Variant(true); settings["ipv4"]["dhcp-hostname"] = sdbus::Variant("raspberrypi"); // settings["ipv4"]["dhcp-options"] = sdbus::Variant(std::vector{ - // "option:classless-static-route,192.168.60.0/24,0.0.0.0,0.0.0.0/0,192.168.60.1"}); + // "option:classless-static-route,192.168.60.0/23,0.0.0.0,0.0.0.0/0,192.168.60.1"}); + + // settings["ipv4"]["dhcp-options"] = sdbus::Variant(std::vector{ + // "option:classless-static-route,192.168.60.0/23,192.168.60.1"}); - settings["ipv4"]["route-data"] = sdbus::Variant(std::vector>{{ - {"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"; + settings["ipv6"]["address-data"] = sdbus::Variant(std::vector>{ + {{"address", sdbus::Variant("fdd2:e477:7b37:5b09::1")}, + {"prefix", sdbus::Variant(uint32_t(64))}}}); + + settings["ipv6"]["gateway"] = sdbus::Variant("fdd2:e477:7b37:5b09::1"); std::map options; options["persist"] = "disk"; From b05f31aa8e0bb6dda9ec8129ec35caff6bc50b8e Mon Sep 17 00:00:00 2001 From: Robin Davies Date: Sat, 12 Oct 2024 19:20:17 -0400 Subject: [PATCH 02/13] Remove vestiges of old P2P DHCP range. --- src/templates/30-pipedal-p2p-dnsmasq-nm.conf | 4 ++-- src/templates/30-pipedal-p2p.conf | 4 ++-- src/templates/dnsmasq-pipedal-nm.conf | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/templates/30-pipedal-p2p-dnsmasq-nm.conf b/src/templates/30-pipedal-p2p-dnsmasq-nm.conf index 75349b9..88e629b 100644 --- a/src/templates/30-pipedal-p2p-dnsmasq-nm.conf +++ b/src/templates/30-pipedal-p2p-dnsmasq-nm.conf @@ -3,9 +3,9 @@ interface=p2p-${WLAN}-* #disable dns, dhcp only.a" port=0 - dhcp-range=172.23.0.20,172.23.0.127,15m + dhcp-range=192.168.60.20,192.168.60.127,15m domain=local - address=/pipedal-p2p.local/172.23.0.2 + address=/pipedal-p2p.local/192.168.60.2 except-interface=eth0 except-interface=${WLAN} diff --git a/src/templates/30-pipedal-p2p.conf b/src/templates/30-pipedal-p2p.conf index a5d42ae..fe1b86f 100644 --- a/src/templates/30-pipedal-p2p.conf +++ b/src/templates/30-pipedal-p2p.conf @@ -3,9 +3,9 @@ server=8.8.4.4 interface=p2p-wlan0-0 - dhcp-range=172.23.0.3,172.23.0.127,15m + dhcp-range=192.168.60.3,192.168.60.127,15m domain=local - address=/pipedal.local/172.23.0.2 + address=/pipedal.local/192.168.60.2 except-interface=eth0 except-interface=wlan0 diff --git a/src/templates/dnsmasq-pipedal-nm.conf b/src/templates/dnsmasq-pipedal-nm.conf index e11d09f..e6d3394 100644 --- a/src/templates/dnsmasq-pipedal-nm.conf +++ b/src/templates/dnsmasq-pipedal-nm.conf @@ -1,9 +1,9 @@ # PiPedal dnsmasq settings for p2p #disable dns, dhcp only." port=0 -dhcp-range=172.23.0.3,172.23.0.127,15m +dhcp-range=192.168.60.3,192.168.60.127,15m domain=local -address=/pipedal-p2p.local/172.23.0.2 +address=/pipedal-p2p.local/192.168.60.2 # defensive. Not actually required. except-interface=eth0 From b9c3ad236752ba417de24911eb66e20e7b60a99d Mon Sep 17 00:00:00 2001 From: Robin Davies Date: Sat, 12 Oct 2024 19:22:51 -0400 Subject: [PATCH 03/13] Set pipedal_d shell to /usr/sbin/nologin --- CMakeLists.txt | 4 ++-- README.md | 4 ++-- docs/ChangingTheWebServerPort.md | 2 +- docs/Installing.md | 6 +++--- docs/download.md | 4 ++-- docs/index.md | 4 ++-- react/src/AppThemed.tsx | 2 +- src/CMakeLists.txt | 23 ++++++++++++++------ src/ConfigMain.cpp | 37 ++++++++++++++++++++++++++++++-- src/SetWifiConfig.cpp | 20 ++++++++--------- src/main.cpp | 32 +++++++++++++++++++++++++-- 11 files changed, 105 insertions(+), 33 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 94de23a..aa33e24 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,10 +1,10 @@ cmake_minimum_required(VERSION 3.16.0) project(pipedal - VERSION 1.3.56 + VERSION 1.3.57 DESCRIPTION "PiPedal Guitar Effect Pedal For Raspberry Pi" HOMEPAGE_URL "https://rerdavies.github.io/pipedal" ) -set (DISPLAY_VERSION "PiPedal v1.3.56-Release") +set (DISPLAY_VERSION "PiPedal v1.3.57-Experimental") set (PACKAGE_ARCHITECTURE "arm64") set (CMAKE_INSTALL_PREFIX "/usr/") diff --git a/README.md b/README.md index 125dc9d..1a21295 100644 --- a/README.md +++ b/README.md @@ -6,13 +6,13 @@ -Download: v1.3.56 +Download: v1.3.57 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.56 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.57 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/ChangingTheWebServerPort.md b/docs/ChangingTheWebServerPort.md index 36135bb..6b59875 100644 --- a/docs/ChangingTheWebServerPort.md +++ b/docs/ChangingTheWebServerPort.md @@ -10,7 +10,7 @@ You can optionally restrict the addresses on which PiPedal will respond by provi To configure PiPedal to only accept connections on the Wi-Fi host access point: - sudo pipedalconfig --install --port 172.23.0.2:80 + sudo pipedalconfig --install --port 192.168.60.1:80 -------- [<< Command-Line Configuration of PiPedal](CommandLine.md) | [Up](Documentation.md) | [Using LV2 Audio Plugins >>](UsingLv2Plugins.md) \ No newline at end of file diff --git a/docs/Installing.md b/docs/Installing.md index 8d88236..0ac4947 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.56](https://github.com/rerdavies/pipedal/releases/download/) +- [Raspberry Pi OS bookworm (64-bit) v1.3.57](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.56 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.57 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.56_arm64.deb + sudo apt-get install pipedal_1.3.57_arm64.deb ``` Adjust accordingly if you have downloaded v1.1.31. diff --git a/docs/download.md b/docs/download.md index 91efbd1..fcc9ca4 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.56 +- Raspberry Pi OS Bookworm (64-bit) v1.3.57 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.56_arm64.deb + sudo apt-get install ./pipedal_1.3.57_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 e849e82..67d6b02 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,7 +1,7 @@ -v1.3.56 +v1.3.57   @@ -9,7 +9,7 @@ To download PiPedal, click [here](download.md). To view PiPedal documentation, click [here](Documentation.md). -#### NEW version 1.3.56 Release. See the [release notes](https://rerdavies.github.io/pipedal/ReleaseNotes) for details. +#### NEW version 1.3.57 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 3b54b8e..2dd578e 100644 --- a/react/src/AppThemed.tsx +++ b/react/src/AppThemed.tsx @@ -103,7 +103,7 @@ const appStyles = (theme: Theme) => createStyles({ bottom: "0px", opacity: 0.8, background: - isDarkMode() ? "#222" : "#DDD", + isDarkMode() ? "#222" : "#EEE", }, loadingContent: { display: "block", diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9d7f1a1..f6c17cd 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -5,6 +5,10 @@ set (CMAKE_INSTALL_PREFIX "/usr/") set (USE_PCH 1) +set (ENABLE_BACKTRACE 1) + +set (USE_SANITIZE true) + set(CXX_STANDARD 20) include(FindPkgConfig) @@ -96,9 +100,6 @@ endif() set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED True) -set (USE_SANITIZE true) - - if (!ENABLE_VST3) set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wno-psabi -DARCHITECTURE=${CPACK_SYSTEM_NAME}") else() @@ -119,10 +120,17 @@ if (CMAKE_BUILD_TYPE MATCHES Debug) endif() elseif(CMAKE_BUILD_TYPE MATCHES RelWithDebInfo) message(STATUS "RelWithgDebInfo build") - #set (CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} "" ) + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DNDEBUG" ) else() message(STATUS "Release build") - #set (CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} "" ) + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DNDEBUG" ) +endif() + +if (ENABLE_BACKTRACE) + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -rdynamic") + if (${DEBIAN_ARCHITECTURE} MATCHES arm64) + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -funwind-tables") + endif() endif() @@ -292,6 +300,9 @@ add_executable(pipedald ) target_include_directories(pipedald PRIVATE ${PIPEDAL_INCLUDES}) +target_compile_definitions(pipedald PRIVATE "ENABLE_BACKTRACE=${ENABLE_BACKTRACE}") + + target_link_libraries(pipedald PRIVATE PiPedalCommon ${PIPEDAL_LIBS} @@ -627,7 +638,7 @@ add_executable(pipedalconfig ) -target_link_libraries(pipedalconfig PRIVATE PiPedalCommon pthread atomic uuid stdc++fs +target_link_libraries(pipedalconfig PRIVATE PiPedalCommon pthread atomic uuid stdc++fs ) add_executable(pipedal_latency_test diff --git a/src/ConfigMain.cpp b/src/ConfigMain.cpp index 6b5e159..8170388 100644 --- a/src/ConfigMain.cpp +++ b/src/ConfigMain.cpp @@ -44,6 +44,9 @@ #include #include "ofstream_synced.hpp" +#include +#include + #define P2PD_DISABLED #if JACK_HOST @@ -88,6 +91,29 @@ namespace fs = std::filesystem; #define REMOVE_OLD_SERVICE 0 // Grandfathering: whether to remove the old shutdown service (now pipedaladmind) #define OLD_SHUTDOWN_SERVICE "pipedalshutdownd" + + +void changeUserShell(const char* username, const char* newShell) { + struct passwd* pw; + struct passwd p; + char buf[1024]; + + pw = getpwnam(username); + if (pw == nullptr) { + throw std::runtime_error("User not found"); + } + if (strcmp(pw->pw_shell,newShell) == 0) { + return; + } + std::string args = SS("/usr/sbin/usermod -s " << newShell << " " << username); + + if (silentSysExec(args.c_str()) != EXIT_SUCCESS) + { + cout << "Failed to set shell for " << username << endl; + } +} + + fs::path GetServiceFileName(const std::string &serviceName) { return fs::path(SERVICE_PATH) / (serviceName + ".service"); @@ -926,7 +952,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.service"); DeployVarConfig(); @@ -994,7 +1020,7 @@ void Install(const fs::path &programPrefix, const std::string endpointAddress) if (!userExists(SERVICE_ACCOUNT_NAME)) { - if (sysExec(USERADD_BIN " " SERVICE_ACCOUNT_NAME " -g " SERVICE_GROUP_NAME " -m --home /var/pipedal/home -N -r") != EXIT_SUCCESS) + if (sysExec(USERADD_BIN " " SERVICE_ACCOUNT_NAME " -g " SERVICE_GROUP_NAME " -s /usr/sbin/nologin -m --home /var/pipedal/home -N -r") != EXIT_SUCCESS) { // throw std::runtime_error("Failed to create service account."); } @@ -1007,6 +1033,13 @@ 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); + try { + changeUserShell(SERVICE_ACCOUNT_NAME, "/usr/sbin/nologon"); + } catch (const std::exception&e) + { + cout << "Error: Can't set user shell for pipedal_d. " << e.what() << std::endl; + + } // create and configure /var directory. fs::path varDirectory("/var/pipedal"); diff --git a/src/SetWifiConfig.cpp b/src/SetWifiConfig.cpp index cc866c8..cc5a131 100644 --- a/src/SetWifiConfig.cpp +++ b/src/SetWifiConfig.cpp @@ -544,9 +544,9 @@ p2p configuration: dnsmaqsq.d/30-pipedal-p2p.conf: interface=p2p-wlan0-0 - dhcp-range=p2p-wlan0,173.24.0.3,172.23.0.127,1h + dhcp-range=p2p-wlan0,173.24.0.3,192.168.60.127,1h domain=local - address=/pipedal.local/172.23.0.2 + address=/pipedal.local/192.168.60.2 except-interface=eth0 except-interface=wlan0 @@ -556,8 +556,8 @@ except-interface=lo dhcpcd.conf: ====== interface p2p-wlan0-0 - static ip_address=172.24.0.1/16 - domain_name_servers=172.24.0.1 + static ip_address=192.168.60.1/16 + domain_name_servers=192.168.60.1 Watch resolv.conf to make sure we don't lose DNS servers. ************************************************************************************/ @@ -672,8 +672,8 @@ static void ConfigDhcpcdForP2p() // dhcpcd.conf: // ====== // interface p2p-wlan0-0 - // static ip_address=172.24.0.1/24 - // domain_name_server=172.24.0.1 + // static ip_address=192.168.60.1/24 + // domain_name_server=192.168.60.1 int line = dhcpcd.GetLineThatStartsWith("hostname"); std::string hostNameLine; @@ -691,8 +691,8 @@ static void ConfigDhcpcdForP2p() { line = dhcpcd.GetLineCount(); // interface p2p-wlan0-0 - // static ip_address=172.24.0.1/16 (trying int on .1.) - // domain_name_server=172.24.0.1 + // static ip_address=192.168.60.1/16 (trying int on .1.) + // domain_name_server=192.168.60.1 dhcpcd.InsertLine(line++, "interface p2p-wlan0-0"); dhcpcd.InsertLine(line++, " static ip_address=" P2P_INTERFACE_ADDR); @@ -705,8 +705,8 @@ static void ConfigDhcpcdForP2p() line = dhcpcd.GetLineCount(); } // interface p2p-wlan0-0 - // static ip_address=172.24.0.1/16 (trying int on .1.) - // domain_name_server=172.24.0.1 + // static ip_address=192.168.60.1/16 (trying int on .1.) + // domain_name_server=192.168.60.1 dhcpcd.InsertLine(line++, SS("allowinterfaces p2p-" << GetWifiConfigWlanAddress() << "-*").c_str()); dhcpcd.InsertLine(line++, "static ip_address=" P2P_INTERFACE_ADDR); diff --git a/src/main.cpp b/src/main.cpp index b3b4d63..8af84a4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -27,7 +27,7 @@ #include "ServiceConfiguration.hpp" #include "AvahiService.hpp" #include "WebServerConfig.hpp" - +#include #include "PiPedalSocket.hpp" #include "PluginHost.hpp" #include @@ -87,11 +87,39 @@ static void AsanCheck() exit(EXIT_FAILURE); } +#if ENABLE_BACKTRACE +void segvHandler(int sig) { + void *array[10]; + + // Get void*'s for all entries on the stack + size_t size; + size = backtrace(array, 10); + + // Print out all the frames to stderr + const char *message = "Error: SEGV signal received.\n"; + write(STDERR_FILENO,message,strlen(message)); + + backtrace_symbols_fd(array+2, size-2, STDERR_FILENO); + _exit(EXIT_FAILURE); +} + + +static void EnableBacktrace() +{ + signal(SIGSEGV, segvHandler); + +} +#endif + int main(int argc, char *argv[]) { #ifndef WIN32 - umask(002); // newly created files in /var/pipedal get 775-ish permissions, which improves debugging/live-service interaction. + umask(002); // newly created files in /var/pipedal get 7cd75-ish permissions, which improves debugging/live-service interaction. +#endif + +#if ENABLE_BACKTRACE + EnableBacktrace(); #endif // Check command line arguments. From 3c8b34cd3852c52fb3ffbabb27d755dafc14e14e Mon Sep 17 00:00:00 2001 From: Robin Davies Date: Sat, 12 Oct 2024 20:51:45 -0400 Subject: [PATCH 04/13] Esc, enter key handling in search control --- react/src/LoadPluginDialog.tsx | 8 ++++++++ react/src/SearchControl.tsx | 18 ++++++++++++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/react/src/LoadPluginDialog.tsx b/react/src/LoadPluginDialog.tsx index 2a9eeba..4429f1f 100644 --- a/react/src/LoadPluginDialog.tsx +++ b/react/src/LoadPluginDialog.tsx @@ -607,6 +607,11 @@ export const LoadPluginDialog = this.hSearchTimeout = undefined; } + handleApplyFilter() + { + this.handleSearchStringReady(); + } + cancelSearchTimeout() { if (this.hSearchTimeout) { @@ -734,6 +739,9 @@ export const LoadPluginDialog = onTextChanged={(text) => { this.handleSearchStringChanged(text); }} + onApplyFilter={() => { + this.handleApplyFilter(); + }} onClearFilterClick={() => { if (this.state.search_string !== "") { this.requestScrollTo(); diff --git a/react/src/SearchControl.tsx b/react/src/SearchControl.tsx index cfff2f1..d134b42 100644 --- a/react/src/SearchControl.tsx +++ b/react/src/SearchControl.tsx @@ -17,7 +17,7 @@ // 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 React from 'react'; +import React, { KeyboardEvent } from 'react'; import { Theme } from '@mui/material/styles'; import { WithStyles } from '@mui/styles'; import withStyles from '@mui/styles/withStyles'; @@ -39,6 +39,7 @@ interface SearchControlProps extends WithStyles { onTextChanged: (searchString: string) => void; onClick: () => void; onClearFilterClick: () => void; + onApplyFilter: () => void; inputRef?: React.RefObject; showSearchIcon?: boolean @@ -66,6 +67,17 @@ const SearchControl = withStyles(styles, { withTheme: true })( } return this.defaultInputRef; } + onKeyDown(ev: KeyboardEvent) + { + ev.stopPropagation(); // don't let the ENTER key propagate propagate the enclosing dialog Enter key handler. + if (ev.key === "Enter") + { + this.props.onApplyFilter(); + } else if (ev.key === "Escape") + { + this.props.onClearFilterClick(); + } + } componentDidUpdate(oldProps: SearchControlProps) { if (oldProps.collapsed ?? false !== this.props.collapsed ?? false) { let inputRef = this.getInputRef(); @@ -96,7 +108,9 @@ const SearchControl = withStyles(styles, { withTheme: true })( ) } - {this.onKeyDown(ev);}} + style={{ flex: "1 1", visibility: (this.props.collapsed ?? false) ? "collapse" : "visible", marginRight: 12, height: 32, }} inputRef={this.getInputRef()} From bd7cdeba22b4988ac0070d0f883b2cee5d3e5f12 Mon Sep 17 00:00:00 2001 From: Robin Davies Date: Sat, 12 Oct 2024 22:09:05 -0400 Subject: [PATCH 05/13] Add -log-level flag to pipedald. --- src/main.cpp | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/main.cpp b/src/main.cpp index 8af84a4..42e127e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -111,6 +111,17 @@ static void EnableBacktrace() } #endif +static bool TryGetLogLevel(const std::string&strLogLevel,LogLevel*result) +{ + if (strLogLevel == "debug") {*result= LogLevel::Debug; return true;} + if (strLogLevel == "info") {*result= LogLevel::Info; return true;} + if (strLogLevel == "warning") {*result= LogLevel::Warning; return true;} + if (strLogLevel == "error") { *result= LogLevel::Error; return true;} + *result = LogLevel::Info; + return false; +} + + int main(int argc, char *argv[]) { @@ -127,12 +138,14 @@ int main(int argc, char *argv[]) bool error = false; bool systemd = false; bool testExtraDevice = false; + std::string logLevel; std::string portOption; CommandLineParser parser; parser.AddOption("-h", &help); parser.AddOption("--help", &help); parser.AddOption("-systemd", &systemd); + parser.AddOption("-log-level",&logLevel); parser.AddOption("-port", &portOption); parser.AddOption("-test-extra-device", &testExtraDevice); // advertise two different devices (for testing multi-device connect) @@ -167,6 +180,7 @@ int main(int argc, char *argv[]) << "Options:\n" << " -systemd: Log to systemd journals instead of to the console.\n" << " -port: Port to listen on e.g. 80, or 0.0.0.0:80\n" + << " -log-level: (debug|info|warning|error)" << "Example:\n" << " pipedald /etc/pipedal/config /etc/pipedal/react -port 80 \n" "\n" @@ -208,6 +222,18 @@ int main(int argc, char *argv[]) } Lv2Log::log_level(configuration.GetLogLevel()); + if (logLevel.length() != 0) + { + LogLevel lv2LogLevel; + if (TryGetLogLevel(logLevel,&lv2LogLevel)) + { + Lv2Log::log_level(lv2LogLevel); + + } else { + Lv2Log::error(SS("Invalid log level: " << logLevel)); + return EXIT_SUCCESS; // indicate to systemd that we don't want a restart. + } + } if (portOption.length() != 0) { From fec62960ad0eb40a5d84bbf586782ebd693c210c Mon Sep 17 00:00:00 2001 From: Robin Davies Date: Sat, 12 Oct 2024 22:09:21 -0400 Subject: [PATCH 06/13] Bug fix: GxTuner not working. --- .vscode/launch.json | 2 +- react/src/GxTunerControl.tsx | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index d459cd3..7b833ab 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -76,7 +76,7 @@ "request": "launch", // Resolved by CMake Tools: "program": "${command:cmake.launchTargetPath}", - "args": [ "/etc/pipedal/config", "/etc/pipedal/react", "-port", "0.0.0.0:8080" ], + "args": [ "/etc/pipedal/config", "/etc/pipedal/react", "-port", "0.0.0.0:8080", "-log-level","debug" ], "stopAtEntry": false, "cwd": "${workspaceFolder}", "environment": [ diff --git a/react/src/GxTunerControl.tsx b/react/src/GxTunerControl.tsx index 566151b..9f997f2 100644 --- a/react/src/GxTunerControl.tsx +++ b/react/src/GxTunerControl.tsx @@ -176,7 +176,8 @@ const GxTunerControl = { midiNote = value; } else { - if (value < 65) + hz = value; + if (hz < 65) { hz = -1; midiNote = -1; From 1788f086331f5e6289cef07ad2568e55748cb715 Mon Sep 17 00:00:00 2001 From: Robin Davies Date: Sun, 13 Oct 2024 11:36:09 -0400 Subject: [PATCH 07/13] Control/VU updates stop when client view is hidden. --- react/src/PiPedalModel.tsx | 59 ++++++++++++++++++++++++------------ react/src/SnapshotDialog.tsx | 2 +- 2 files changed, 41 insertions(+), 20 deletions(-) diff --git a/react/src/PiPedalModel.tsx b/react/src/PiPedalModel.tsx index d54a494..196688c 100644 --- a/react/src/PiPedalModel.tsx +++ b/react/src/PiPedalModel.tsx @@ -457,13 +457,39 @@ export class PiPedalModel //implements PiPedalModel this.onSocketConnectionLost = this.onSocketConnectionLost.bind(this); } + + private expectDisconnectTimer?: NodeJS.Timeout = undefined; + + cancelExpectDisconnectTimer() + { + if (this.expectDisconnectTimer) { + clearTimeout(this.expectDisconnectTimer); + } + } + startExpectDisconnectTimer() + { + this.cancelExpectDisconnectTimer(); + // poll for access to a running pipedal server + this.expectDisconnectTimer = setTimeout( + async () => { + this.reconnectReason = ReconnectReason.Disconnected; + }, + 5 * 1000); + + } + expectDisconnect(reason: ReconnectReason) { + this.cancelExpectDisconnectTimer(); this.reconnectReason = reason; + if (this.reconnectReason !== ReconnectReason.Disconnected) + { + this.startExpectDisconnectTimer(); + } } onSocketReconnecting(retry: number, maxRetries: number): boolean { + this.cancelExpectDisconnectTimer(); if (this.isClosed) return false; - if (this.visibilityState.get() === VisibilityState.Hidden) return false; //if (retry !== 0) { switch (this.reconnectReason) { case ReconnectReason.Disconnected: @@ -515,7 +541,6 @@ export class PiPedalModel //implements PiPedalModel } onSocketMessage(header: PiPedalMessageHeader, body?: any) { - if (this.visibilityState.get() === VisibilityState.Hidden) return; let message = header.message; if (message === "onControlChanged") { @@ -1187,7 +1212,6 @@ export class PiPedalModel //implements PiPedalModel if (this.backgroundStateTimeout) { clearTimeout(this.backgroundStateTimeout); this.backgroundStateTimeout = undefined; - return; } if (this.state.get() === State.Background) { console.log("Exiting background state."); @@ -1200,17 +1224,19 @@ export class PiPedalModel //implements PiPedalModel // on Android, delay entering background state by 180 seconds, // since background management is more complicated. e.g. screen flips, and system upload dialogs. - if (this.isAndroidHosted()) { - if (this.backgroundStateTimeout) { - clearTimeout(this.backgroundStateTimeout); - } - this.backgroundStateTimeout = setTimeout(() => { - this.backgroundStateTimeout = undefined; - this.enterBackgroundState_(); - }, 180000); - } else { - this.enterBackgroundState_(); - } + // if (this.isAndroidHosted()) { + // yyyx; + // if (this.backgroundStateTimeout) { + // clearTimeout(this.backgroundStateTimeout); + // } + // this.backgroundStateTimeout = setTimeout(() => { + // this.backgroundStateTimeout = undefined; + // this.enterBackgroundState_(); + // }, 180000); + // } else { + // this.enterBackgroundState_(); + // } + this.enterBackgroundState_(); } enterBackgroundState_() { if (this.state.get() !== State.Background) { @@ -1227,11 +1253,9 @@ export class PiPedalModel //implements PiPedalModel switch (document.visibilityState) { case "visible": - this.visibilityState.set(VisibilityState.Visible); this.exitBackgroundState(); break; case "hidden": - this.visibilityState.set(VisibilityState.Hidden); this.enterBackgroundState(); break; } @@ -2424,9 +2448,6 @@ export class PiPedalModel //implements PiPedalModel } private handleNotifyPatchProperty(clientHandle: number, instanceId: number, propertyUri: string, jsonObject: any) { - // yyy this whole path is obsolete. We now get property change notifications - // always, since the entire pedalboard must track excactly. - // Review carefully. let pedalboard = this.pedalboard.get(); let pedalboardItem = pedalboard.getItem(instanceId); if (pedalboardItem) { diff --git a/react/src/SnapshotDialog.tsx b/react/src/SnapshotDialog.tsx index 3076795..8c1b973 100644 --- a/react/src/SnapshotDialog.tsx +++ b/react/src/SnapshotDialog.tsx @@ -86,7 +86,7 @@ export default class SnapshotDialog extends ResizeResponsiveComponent Date: Sun, 13 Oct 2024 21:23:25 -0400 Subject: [PATCH 08/13] Numeric values on main VUs. --- react/src/PluginControlView.tsx | 6 +-- react/src/VuMeter.tsx | 89 +++++++++++++++++++++++++++++++-- 2 files changed, 87 insertions(+), 8 deletions(-) diff --git a/react/src/PluginControlView.tsx b/react/src/PluginControlView.tsx index f0c038c..5620021 100644 --- a/react/src/PluginControlView.tsx +++ b/react/src/PluginControlView.tsx @@ -94,7 +94,7 @@ const styles = (theme: Theme) => createStyles({ }, vuMeterL: { position: "fixed", - paddingLeft: 12, + paddingLeft: 6, paddingRight: 4, paddingBottom: 24, left: 0, @@ -634,10 +634,10 @@ const PluginControlView = return (
- +
- +
{ diff --git a/react/src/VuMeter.tsx b/react/src/VuMeter.tsx index ea3cb96..c524eef 100644 --- a/react/src/VuMeter.tsx +++ b/react/src/VuMeter.tsx @@ -20,8 +20,7 @@ import React, { Component } from 'react'; import { Theme } from '@mui/material/styles'; import { WithStyles } from '@mui/styles'; -import createStyles from '@mui/styles/createStyles'; -import withStyles from '@mui/styles/withStyles'; +import {createStyles,withStyles} from '@mui/styles'; import { PiPedalModel, State,PiPedalModelFactory, VuUpdateInfo, VuSubscriptionHandle } from './PiPedalModel'; @@ -55,13 +54,15 @@ class TelltaleState { telltaleDb: number = MIN_DB; lastTelltaleTime: number = 0; telltaleHoldTime: number = 0; + telltaleHoldValue: number = MIN_DB; reset() : void { this.telltaleHoldTime = 0; this.lastTelltaleTime = 0; this.telltaleDb = MIN_DB; + this.telltaleHoldValue = MIN_DB; } - getValue(currentDb: number): number { + getTelltaleHoldValue(currentDb: number): number { let t = new Date().getTime(); let holdValue: number; @@ -78,6 +79,7 @@ class TelltaleState { } } } + this.telltaleHoldValue = holdValue; if (currentDb > holdValue) { this.telltaleDb = currentDb; @@ -93,7 +95,7 @@ class TelltaleState { const LEFT_X = BORDER_THICKNESS; const RIGHT_X = BORDER_THICKNESS + + CHANNEL_WIDTH + BORDER_THICKNESS; -const styles = ({ palette }: Theme) => createStyles({ +const styles = (theme: Theme) => createStyles({ frame: { position: "relative", width: CHANNEL_WIDTH + 2*BORDER_THICKNESS, @@ -114,6 +116,23 @@ const styles = ({ palette }: Theme) => createStyles({ background: "black", overflow: "hidden", }, + monoTextFrame: { + display: "flex",flexFlow: "column nowrap", alignItems: "center", textAlign: "center" + }, + stereoTextFrame: { + display: "flex",flexFlow: "column nowrap", alignItems: "center", textAlign: "center" + }, + vuTextFrame: { + color: theme.palette.text.secondary, + display: "table-cell", + position: "relative", + marginTop: 4, + textAlign: "center", + width: 20, height: 16, + fontSize: "11px", + justifyContent: "center", + alignItems: "center" + }, redFrameL: { position: "absolute", top: "100%", @@ -189,6 +208,7 @@ interface VuMeterProps extends WithStyles { instanceId: number; display: "input" | "output"; theme: Theme; + displayText?: boolean; } interface VuMeterState { @@ -213,6 +233,7 @@ export const VuMeter = class extends Component { divRef: React.RefObject = React.createRef(); + textRef: React.RefObject = React.createRef(); model: PiPedalModel; yZero: number; @@ -240,6 +261,35 @@ export const VuMeter = vuInfo?: VuUpdateInfo; requesttedStereoState: boolean = false; + updateText(telltaleDb: number) + { + if (this.textRef.current) { + let displayValue: string; + if (telltaleDb <= MIN_DB) + { + displayValue = "-"; + } else { + let iDb = Math.round(telltaleDb); + if (iDb > 0) + { + displayValue = "+" + Math.round(telltaleDb).toString() + "\u00A0" + } else if (iDb < 0) { + displayValue = Math.round(telltaleDb).toString() + "\u00A0"; + } else { + if (telltaleDb === 0) { + displayValue = "0"; + } else if (telltaleDb > 0) + { + displayValue = "+0\u00A0"; + } else { + displayValue = "-0\u00A0"; + } + } + } + this.textRef.current.innerText = displayValue; + } + } + onVuChanged(vuInfo: VuUpdateInfo): void { let value: number; let valueR: number; @@ -291,6 +341,15 @@ export const VuMeter = }; this.updateChannel(vuData, this.telltaleStateR); } + if (this.props.displayText) + { + if (this.state.isStereo) + { + this.updateText(Math.max(this.telltaleStateL.telltaleHoldValue,this.telltaleStateR.telltaleHoldValue)); + } else { + this.updateText(this.telltaleStateL.telltaleHoldValue); + } + } } resetTelltales() { @@ -319,7 +378,7 @@ export const VuMeter = vuData.redDiv.style.top = y + "px"; } } - let dbTelltale = telltaleState.getValue(db); + let dbTelltale = telltaleState.getTelltaleHoldValue(db); let yTelltale = dbToY(dbTelltale); if (yTelltale < this.yZero) { @@ -381,8 +440,28 @@ export const VuMeter = render() { + let displayText = this.props.displayText??false; let classes = this.props.classes; + if (displayText) + { + return ( +
+ { + this.renderVus() + } +
+
+ ); + } else { + return this.renderVus(); + } + } + + renderVus() { + + let classes = this.props.classes; if (!this.state.isStereo) { return (
From ab3b89b44ed97e5954a7a332341f2da026080c32 Mon Sep 17 00:00:00 2001 From: Robin Davies Date: Sun, 13 Oct 2024 21:24:15 -0400 Subject: [PATCH 09/13] Night Mode System Settings on Android client. --- react/public/index.html | 37 +++++++++++++++++++++++++++++-------- react/src/AndroidHost.tsx | 4 ++++ react/src/DarkMode.tsx | 32 ++++++++++++++++++++++++++++---- 3 files changed, 61 insertions(+), 12 deletions(-) diff --git a/react/public/index.html b/react/public/index.html index d0032f9..9adbd5f 100644 --- a/react/public/index.html +++ b/react/public/index.html @@ -6,7 +6,8 @@ - + + @@ -42,19 +43,39 @@