Merge branch 'dev-modui' of https://github.com/rerdavies/pipedal into dev-modui

This commit is contained in:
Robin E. R. Davies
2025-07-21 02:07:05 -04:00
68 changed files with 791 additions and 218 deletions
+2
View File
@@ -115,6 +115,7 @@
"Chowdhury",
"Chowdhury's",
"discursus",
"distro",
"distros",
"dpkg",
"flac",
@@ -134,6 +135,7 @@
"midiclip",
"midisong",
"mlmodel",
"modui",
"MOTU",
"Netplan",
"Pedalboard",
View File
+7 -3
View File
@@ -1,13 +1,13 @@
cmake_minimum_required(VERSION 3.16.0)
project(pipedal
VERSION 1.4.77
VERSION 1.4.79
DESCRIPTION "PiPedal Guitar Effect Pedal For Raspberry Pi"
HOMEPAGE_URL "https://rerdavies.github.io/pipedal"
)
EXECUTE_PROCESS( COMMAND dpkg --print-architecture COMMAND tr -d '\n' OUTPUT_VARIABLE DEBIAN_ARCHITECTURE )
set (DISPLAY_VERSION "PiPedal v1.4.77-Beta")
set (DISPLAY_VERSION "PiPedal v1.4.79-Beta")
set (PACKAGE_ARCHITECTURE ${DEBIAN_ARCHITECTURE})
set (CMAKE_INSTALL_PREFIX "/usr/")
@@ -102,7 +102,11 @@ set(CPACK_PACKAGING_INSTALL_PREFIX /usr)
set(CPACK_PROJECT_NAME ${PROJECT_NAME})
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
set(CPACK_DEBIAN_FILE_NAME DEB-DEFAULT)
set (CPACK_STRIP_FILES true)
if (CMAKE_BUILD_TYPE MATCHES Debug)
set (CPACK_STRIP_FILES false)
else()
set (CPACK_STRIP_FILES true)
endif()
set(CPACK_DEBIAN_PACKAGE_SIGN_ALGORITHM "detached")
set(CPACK_DEBIAN_PACKAGE_SIGN_TYPE "origin")
+2 -1
View File
@@ -319,6 +319,7 @@ namespace pipedal
}
if (seqHandle)
{
Lv2Log::debug("Closing ALSA Sequencer");
snd_seq_close(seqHandle);
seqHandle = nullptr;
}
@@ -608,7 +609,7 @@ namespace pipedal
#ifndef NDEBUG
#define MSG_DEBUG_LOG(x) \
case x: \
Lv2Log::debug("ALSA Sequencer Message" #x); \
Lv2Log::debug("ALSA Sequencer Message " #x); \
break;
#else
#define MSG_DEBUG_LOG(x)
+1 -1
View File
@@ -607,7 +607,7 @@ namespace pipedal
if (!obj) {
write_raw("null");
} else {
write(obj.get());
write(obj.value());
}
}
+6 -2
View File
@@ -9,11 +9,11 @@
<img src="https://img.shields.io/github/downloads/rerdavies/pipedal/total?color=%23808080&link=https%3A%2F%2Frerdavies.github.io%2Fpipedal%2Fdownload.html"/>
Download:&nbsp;<a href='https://rerdavies.github.io/pipedal/download.html'>v1.4.77</a>
Download:&nbsp;<a href='https://rerdavies.github.io/pipedal/download.html'>v1.4.79</a>
Website:&nbsp;[https://rerdavies.github.io/pipedal](https://rerdavies.github.io/pipedal).
Documentation:&nbsp;[https://rerdavies.github.io/pipedal/Documentation.html](https://rerdavies.github.io/pipedal/Documentation.html).
#### NEW version 1.4.77 Release. See the [release notes](https://rerdavies.github.io/pipedal/ReleaseNotes) for details. New Phaser and Graphic Equalizer plugins.
#### NEW version 1.4.79 Release. See the [release notes](https://rerdavies.github.io/pipedal/ReleaseNotes) for details. New Phaser and Graphic Equalizer plugins.
&nbsp;
@@ -56,8 +56,12 @@ https://github.com/user-attachments/assets/9a9fd0c6-78fc-4284-8b44-6a1929c00cc6
### [Optimizing Audio Latency](https://rerdavies.github.io/pipedal/AudioLatency.html)
### [Command-Line Configuration of PiPedal](https://rerdavies.github.io/pipedal/CommandLine.html)
### [Changing the Web Server Port](https://rerdavies.github.io/pipedal/ChangingTheWebServerPort.html)
%nbsp;
### [Using LV2 Audio Plugins](https://rerdavies.github.io/pipedal/UsingLv2Plugins.md)
### [Which LV2 Plugins does PiPedal support?](https://rerdavies.github.io/pipedal/WhichLv2PluginsAreSupported.html)
### [Support for LV2 Plugins with MOD User Interfaces](https://rerdavies.github.io/pipedal/ModUiSupport.html)
 &nbsp;
Executable
+9
View File
@@ -0,0 +1,9 @@
#!/bin/bash
# Run local jeckyl-hosted sevever for GitHub documentation page.
# See https://jekyllrb.com/docs/installation/ for instructions on how to isntall jeckyll locally.
# Then
# cd docs
# bundle install
#
cd docs
bundle exec jekyll serve --host
+3
View File
@@ -16,8 +16,11 @@
#### [Optimizing Audio Latency](AudioLatency.md)
#### [Command-Line Configuration of PiPedal](CommandLine.md)
#### [Changing the Web Server Port](ChangingTheWebServerPort.md)
&nbsp;
#### [Using LV2 Audio Plugins](UsingLv2Plugins.md)
#### [Which LV2 Plugins does PiPedal support?](WhichLv2PluginsAreSupported.md)
#### [LV2 Plugins with MOD User Interfaces](ModUiSupport.md)
&nbsp;
+2
View File
@@ -31,3 +31,5 @@ gem "wdm", "~> 0.1.1", :platforms => [:mingw, :x64_mingw, :mswin]
# Lock `http_parser.rb` gem to `v0.6.x` on JRuby builds since newer versions of the gem
# do not have a Java counterpart.
gem "http_parser.rb", "~> 0.6.0", :platforms => [:jruby]
gem "webrick", "~> 1.9"
+5 -3
View File
@@ -205,14 +205,14 @@ GEM
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
mercenary (0.3.6)
mini_portile2 (2.8.9)
minima (2.5.1)
jekyll (>= 3.5, < 5.0)
jekyll-feed (~> 0.9)
jekyll-seo-tag (~> 2.1)
minitest (5.19.0)
nokogiri (1.18.8-aarch64-linux-gnu)
racc (~> 1.4)
nokogiri (1.18.8-x86_64-linux-gnu)
nokogiri (1.18.8)
mini_portile2 (~> 2.8.2)
racc (~> 1.4)
octokit (4.25.1)
faraday (>= 1, < 3)
@@ -249,6 +249,7 @@ GEM
unf_ext
unf_ext (0.0.8.2)
unicode-display_width (1.8.0)
webrick (1.9.1)
PLATFORMS
aarch64-linux
@@ -262,6 +263,7 @@ DEPENDENCIES
tzinfo (~> 1.2)
tzinfo-data
wdm (~> 0.1.1)
webrick (~> 1.9)
BUNDLED WITH
2.4.19
+5 -5
View File
@@ -13,18 +13,18 @@ page_icon: img/Install4.jpg
Download the most recent Debian (.deb) package for your platform:
- [Raspberry Pi OS bookworm (aarch64) v1.4.77](https://github.com/rerdavies/pipedal/releases/download/v1.4.77/pipedal_1.4.77_arm64.deb)
- [Ubuntu 24.x (aarch64) v1.4.77](https://github.com/rerdavies/pipedal/releases/download/v1.4.77/pipedal_1.4.77_arm64.deb)
- [Ubuntu 24.x (amd64) v1.4.77](https://github.com/rerdavies/pipedal/releases/download/v1.4.77/pipedal_1.4.77_amd64.deb)
- [Raspberry Pi OS bookworm (aarch64) v1.4.79](https://github.com/rerdavies/pipedal/releases/download/v1.4.79/pipedal_1.4.79_arm64.deb)
- [Ubuntu 24.x (aarch64) v1.4.79](https://github.com/rerdavies/pipedal/releases/download/v1.4.79/pipedal_1.4.79_arm64.deb)
- [Ubuntu 24.x (amd64) v1.4.79](https://github.com/rerdavies/pipedal/releases/download/v1.4.79/pipedal_1.4.79_amd64.deb)
Version 1.4.77 has been tested on Raspberry Pi OS bookworm, Ubuntu 24.04 (amd64), and Ubuntu 24.10 (aarch64). Download the appropriate package for your platform, and install using the following procedure:
Version 1.4.79 has been tested on Raspberry Pi OS bookworm, Ubuntu 24.04 (amd64), and Ubuntu 24.10 (aarch64). Download the appropriate package for your platform, and install using the following procedure:
```
sudo apt update
sudo apt upgrade
cd ~/Downloads
sudo apt-get install ./pipedal_1.4.77_arm64.deb
sudo apt-get install ./pipedal_1.4.79_arm64.deb
```
You MUST use `apt-get`. `apt` will not install downloaded packages; and `dpkg -i` will not install dependencies.
+35
View File
@@ -0,0 +1,35 @@
---
page_icon: img/moduiThumb.jpg
icon_width: 120px
---
## Support for LV2 Plugins with MOD User Interfaces
{% include pageIconL.html %}
Some LV2 plugins (currently a minority of plugins) provide custom plugin user interfaces based on [MOD Audio's](https://mod.audio/desktop/)
[ModUi framework](https://wiki.mod.audio/wiki/MOD_Web_GUI_Framework). When using such a plugin, you can choose whether to use the MOD Web GUI Framework user interface (the MOD UI) or the default PiPedal user interface. For the most part, the same functionality is available in both interfaces.
Plugins that are distributed via Linux distributions usually do not implement MOD user interfaces; but all (or almost all) of the plugins that are available from the [PatchStorage website](https://patchstorage.com/platform/lv2-plugins/) do implement MOD user interfaces. Many plugins that are available from GitHub or other sources also implement MOD user interfaces. Often you can find updated versions of a plugin that is published by a distro on PatchStorage which does provide a MOD UI.
Here's an example of a MOD UI for the ZAM Eq2 plugin:
<img src="img/zam-modui.jpg" alt="ZAM Eq2 MOD UI" style="width: 100%; max-width: 400px;box-sizing: border-box;padding-left: 24px; padding-right: 24px; "/>
And the PiPedal UI for the same plugin:
<img src="img/zam-pp-ui.png" alt="ZAM Eq2 PiPedal UI" style="display: block; box-sizing: border-box; padding-left: 24px; padding-right: 24px; width: 100%; max-width: 400px; margin-left: auto; margin-right: auto"/>
Which UI you use is entirely up to you. MOD UIs tend to be a bit unfriendly for small-format devices like phones, but they do look great in a desktop browser. Sometimes the MOD UI will make better use of available screen space; sometimes the Pipedal UI will look better. It really depends on the plugin and your personal preferences. In this particular case, the MOD UI is more space efficient, but that is not always true.
To select which user interface to use, tap on the UI selection button in the toolbar for the plugin. If the plugin does not provide a MOD UI, the button will be disabled.
<img src="img/selectUi.png" alt="MOD UI selection button" style="display: block; width: 100%; padding-left: 20px; padding-right: 20px; max-width: 300px; margin-left: auto; margin-right: auto"/>
Support for MOD UIs in PiPedal is still experimental, so you may encounter some issues. PiPedal does not yet support all of the features of the MOD UI framework, not because it can't, but because we haven't been able to locate examples of plugins that use those features, which makes it difficult to test. If you encounter any issues, please report them on PiPedal's [GitHub Issues page](https://github.com/rerdavies/pipedal/issues), and we will do our best to provide quick fixes.
&nbsp;
--------
[<< Which Plugins are Supported?](WhichLv2PluginsAreSupported.md) | [Up](Documentation.md) | [BuildingPiPedal from Source >>](BuildingPiPedalFromSource.md)
+33
View File
@@ -1,4 +1,37 @@
# Release Notes
## Pipedal 1.4.79 Beta
The Big Feature:
- Support for custom MOD User Interfaces for plugins that prove a MOD UI. See the [MOD UI documentation page](https://rerdavies.github.io/pipedal/ModUiSupport.html) for details on how to use MOD User Interfaces with PiPedal. This feature is experimental. If you experience problems with plugins that have MOD user interfaces, please report them on the [PiPedal GitHub Issues page](https://github.com/rerdavies/pipedal/issues).
New in this relase:
- PiPedal remembers which plugin you were viewing when you reload a preset.
- Keep Screen On setting in the PiPedal Remote Client (requires updated Android client).
- Lock Screen Orientation setting in the PiPedal Remote Client (requires updated Android client).
If you are using the Android PiPedal remote app, you should make sure it has upgraded to the latest version. The new Remote app has been fully rolled out and is now available in the Google Play Store. It should update automatically, but you can check by opening the App Info for PiPedal Remote. If an "Update" button is displayed, click it to upgrade to the current version right away. If you have received the update already, you should notice differences in the App startup procedure (notably an animated splash screen).
The PiPedal Remote Android app has been updated to provide the following new features:
- new Keep Screen On settings.
- new Lock Screen Orientation setting.
- Edit controls are automatically repositioned above the Keyboard IME when it opens.
- The Zoomed Control feature (large controls in landscape mode on phones) has been removed. Improved scrolling provides a better solution to the problem of controls being obscured by the keyboard IME.
- Support for Android 16 Edge-to-Edge display.
- Reduced display flickering while connecting.
- Complete support for Night Mode (the Android UI now follows the PiPedal Theme setting).
- Shiny new graphics on the opening screen in support of Android 16's Edge-to-Edge display feature (but you can see it in other versions of Android as well).
Bug Fixes:
- The "Listen for Message" buttons in the MIDI Bindings dialog now ignore CC0 (Bank Select), and CC32-63 (CC LSB) MIDI message, since CC0 is used to control preset selection.
- Fixed errors loading plugins with MIDI Event ports.
- Changing volume control on low-resolution displays breaks web page.
- MIDI binding for bypass controls have been restored after having been accidentally disabled in v1.4.77.
## PiPedal 1.4.77 Beta
New TooB Player plugin; improvements to MIDI input handling; and a slew of fit-and finish
+1 -1
View File
@@ -14,4 +14,4 @@ If you install a new LV2 plugin, PiPedal will detect the change and make it avai
PiPedal does not currently allow plugins to provide custom user interfaces; it displays controls that are declared by the LV2 plugin without customization. In practice, this means that LV2 plugins with simple sets of controls work well, but those with complex sets of controls can be difficult to use. However, we would be pleased to collaborate with developers who need more than the basic set of controls. This is a feature set that Pipedal needs to address, so we would be happy to collaborate with other developers on this. Please contact rerdavies at gmail.com for further details.
--------
[<< Using LV2 Audio Plugins](UsingLv2Plugins.md) | [Up](Documentation.md) | [BuildingPiPedal from Source >>](BuildingPiPedalFromSource.md)
[<< Using LV2 Audio Plugins](UsingLv2Plugins.md) | [Up](Documentation.md) | [MOD UI Support >>](ModUiSupport.md)
-3
View File
@@ -1,7 +1,4 @@
<div style="max-width: 30%; width: {{page.icon_width}}; background: #FFF; z-index: -1; margin-right: 18px; float: left">
<img src="{{page.page_icon}}" style="width: 100%;background: #FFF; z-index: -1;
float: right" />
<div>
<p style="font-size: 10px; text-align: right; color: #888">Generated by DALL-E 2</p>
</div>
</div>
+4 -4
View File
@@ -4,9 +4,9 @@
Download the most recent Debian (.deb) package for your platform:
- [Raspberry Pi OS bookworm (aarch64) v1.4.77 Beta](https://github.com/rerdavies/pipedal/releases/download/v1.4.77/pipedal_1.4.77_arm64.deb)
- [Ubuntu 24.x (aarch64) v1.4.77 Alpha](https://github.com/rerdavies/pipedal/releases/download/v1.4.77/pipedal_1.4.77_arm64.deb)
- [Ubuntu 24.x (amd64) v1.4.77 Alpha](https://github.com/rerdavies/pipedal/releases/download/v1.4.77/pipedal_1.4.77_amd64.deb)
- [Raspberry Pi OS bookworm (aarch64) v1.4.79 Beta](https://github.com/rerdavies/pipedal/releases/download/v1.4.79/pipedal_1.4.79_arm64.deb)
- [Ubuntu 24.x (aarch64) v1.4.79 Alpha](https://github.com/rerdavies/pipedal/releases/download/v1.4.79/pipedal_1.4.79_arm64.deb)
- [Ubuntu 24.x (amd64) v1.4.79 Alpha](https://github.com/rerdavies/pipedal/releases/download/v1.4.79/pipedal_1.4.79_amd64.deb)
Install the package by running
@@ -14,7 +14,7 @@ Install the package by running
```
sudo apt update
cd ~/Downloads
sudo apt-get install ./pipedal_1.4.77_arm64.deb
sudo apt-get install ./pipedal_1.4.79_arm64.deb
```
You MUST use `apt-get` to install the package. `apt install` will NOT install the package correctly. The message about missing permissions given by `apt-get` is
expected, and can be safely ignored.
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 401 KiB

+264
View File
File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 514 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

+1 -1
View File
@@ -93,7 +93,7 @@ cabir:impulseFile3
doap:license <https://rerdavies.github.io/pipedal/LicenseToobAmp> ;
doap:maintainer <http://two-play.com/rerdavies#me> ;
lv2:minorVersion 0 ;
lv2:microVersion 63 ;
lv2:microVersion 64 ;
rdfs:comment """
TooB Cab IR is a convolution-based guitar cabinet impulse response simulator.
+1 -1
View File
@@ -50,7 +50,7 @@ toob:frequencyResponseVector
doap:license <https://rerdavies.github.io/pipedal/LicenseToobAmp> ;
doap:maintainer <http://two-play.com/rerdavies#me> ;
lv2:minorVersion 0 ;
lv2:microVersion 63 ;
lv2:microVersion 64 ;
mod:brand "TooB";
mod:label "TooB CabSim";
@@ -53,7 +53,7 @@ toobimpulse:impulseFile
doap:license <https://rerdavies.github.io/pipedal/LicenseToobAmp> ;
doap:maintainer <http://two-play.com/rerdavies#me> ;
lv2:minorVersion 0 ;
lv2:microVersion 63 ;
lv2:microVersion 64 ;
rdfs:comment """
Convolution reverb is a notoriously compute-intensive effect. If you are having performance issues, use the Max T control to constrain the length of the impulse file to
@@ -51,7 +51,7 @@ toobimpulse:impulseFile
doap:license <https://rerdavies.github.io/pipedal/LicenseToobAmp> ;
doap:maintainer <http://two-play.com/rerdavies#me> ;
lv2:minorVersion 0 ;
lv2:microVersion 63 ;
lv2:microVersion 64 ;
rdfs:comment """
+1 -1
View File
@@ -66,7 +66,7 @@ inputStage:filterGroup
doap:license <https://two-play.com/TooB/licenses/isc> ;
doap:maintainer <http://two-play.com/rerdavies#me> ;
lv2:minorVersion 0 ;
lv2:microVersion 63 ;
lv2:microVersion 64 ;
mod:brand "TooB";
mod:label "TooB Input";
+1 -1
View File
@@ -68,7 +68,7 @@ pstage:stage3
doap:license <https://rerdavies.github.io/pipedal/LicenseToobAmp> ;
doap:maintainer <http://two-play.com/rerdavies#me> ;
lv2:minorVersion 0 ;
lv2:microVersion 63 ;
lv2:microVersion 64 ;
mod:brand "TooB";
mod:label "Power Stage";
+1 -1
View File
@@ -57,7 +57,7 @@
doap:license <https://rerdavies.github.io/pipedal/LicenseToobAmp> ;
doap:maintainer <http://two-play.com/rerdavies#me> ;
lv2:minorVersion 0 ;
lv2:microVersion 63 ;
lv2:microVersion 64 ;
rdfs:comment "TooB spectrum analyzer" ;
mod:brand "TooB";
+1 -1
View File
@@ -57,7 +57,7 @@ tonestack:eqGroup
doap:license <https://rerdavies.github.io/pipedal/LicenseToobAmp> ;
doap:maintainer <http://two-play.com/rerdavies#me> ;
lv2:minorVersion 0 ;
lv2:microVersion 63 ;
lv2:microVersion 64 ;
uiext:ui <http://two-play.com/plugins/toob-tone-stack-ui>;
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -40,7 +40,7 @@
doap:license <https://rerdavies.github.io/pipedal/LicenseToobAmp> ;
doap:maintainer <http://two-play.com/rerdavies#me> ;
lv2:minorVersion 0 ;
lv2:microVersion 63 ;
lv2:microVersion 64 ;
rdfs:comment """
Emulation of a Boss CE-2 Chorus.
+1 -1
View File
@@ -41,7 +41,7 @@
doap:license <https://rerdavies.github.io/pipedal/LicenseToobAmp> ;
doap:maintainer <http://two-play.com/rerdavies#me> ;
lv2:minorVersion 0 ;
lv2:microVersion 63 ;
lv2:microVersion 64 ;
rdfs:comment """
A straightforward no-frills digital delay.
+1 -1
View File
@@ -41,7 +41,7 @@
doap:license <https://rerdavies.github.io/pipedal/LicenseToobAmp> ;
doap:maintainer <http://two-play.com/rerdavies#me> ;
lv2:minorVersion 0 ;
lv2:microVersion 63 ;
lv2:microVersion 64 ;
rdfs:comment """
Emulation of a Boss BF-2 Flanger, based on circuit analysis and simulation of the original.
@@ -41,7 +41,7 @@
doap:license <https://rerdavies.github.io/pipedal/LicenseToobAmp> ;
doap:maintainer <http://two-play.com/rerdavies#me> ;
lv2:minorVersion 0 ;
lv2:microVersion 63 ;
lv2:microVersion 64 ;
rdfs:comment """
Digital emulation of a Boss BF-2 Flanger.
+1 -1
View File
@@ -41,7 +41,7 @@
doap:license <https://rerdavies.github.io/pipedal/LicenseToobAmp> ;
doap:maintainer <http://two-play.com/rerdavies#me> ;
lv2:minorVersion 0 ;
lv2:microVersion 63 ;
lv2:microVersion 64 ;
rdfs:comment """
Toob Freeverb is an Lv2 implementation of the famous Freeverb reverb effect. FreeVerb delivers a well-balanced reverb with very little tonal coloration.
+1 -1
View File
@@ -41,7 +41,7 @@
doap:license <https://rerdavies.github.io/pipedal/LicenseToobAmp> ;
doap:maintainer <http://two-play.com/rerdavies#me> ;
lv2:minorVersion 0 ;
lv2:microVersion 63 ;
lv2:microVersion 64 ;
rdfs:comment """
A 7 octave graphic equalizer, with frequencies chosen to be useful for EQ-ing guitar signals.
""" ;
+1 -1
View File
@@ -92,7 +92,7 @@ myprefix:output_group
doap:license <https://opensource.org/license/mit/> ;
doap:maintainer <http://two-play.com/rerdavies#me> ;
lv2:minorVersion 1 ;
lv2:microVersion 63 ;
lv2:microVersion 64 ;
ui:ui <http://two-play.com/plugins/toob-looper-four-ui>;
+1 -1
View File
@@ -78,7 +78,7 @@ myprefix:output_group
doap:license <https://opensource.org/license/mit/> ;
doap:maintainer <http://two-play.com/rerdavies#me> ;
lv2:minorVersion 1 ;
lv2:microVersion 63 ;
lv2:microVersion 64 ;
ui:ui <http://two-play.com/plugins/toob-looper-one-ui>;
+1 -1
View File
@@ -67,7 +67,7 @@ toobml:sagGroup
doap:license <https://rerdavies.github.io/pipedal/LicenseToobAmp> ;
doap:maintainer <http://two-play.com/rerdavies#me> ;
lv2:minorVersion 0 ;
lv2:microVersion 63 ;
lv2:microVersion 64 ;
rdfs:comment """
The TooB ML Amplifier plugin provides emulation of a variety of amplifiers and overdrive pedals that are implemented
using neural-network-based machine learning models of real amplifiers.
+1 -1
View File
@@ -40,7 +40,7 @@
doap:license <https://rerdavies.github.io/pipedal/LicenseToobAmp> ;
doap:maintainer <http://two-play.com/rerdavies#me> ;
lv2:minorVersion 0 ;
lv2:microVersion 63 ;
lv2:microVersion 64 ;
rdfs:comment """
Remix a stereo input signal.
@@ -61,7 +61,7 @@ toobNam:eqGroup
doap:license <https://rerdavies.github.io/pipedal/LicenseToobAmp> ;
doap:maintainer <http://two-play.com/rerdavies#me> ;
lv2:minorVersion 0 ;
lv2:microVersion 63 ;
lv2:microVersion 64 ;
rdfs:comment """
A port of Steven Atkinson's Neural Amp Modeler to LV2.
+1 -1
View File
@@ -54,7 +54,7 @@ noisegate:envelope_group
doap:license <https://rerdavies.github.io/pipedal/LicenseToobAmp> ;
doap:maintainer <http://two-play.com/rerdavies#me> ;
lv2:minorVersion 0 ;
lv2:microVersion 63 ;
lv2:microVersion 64 ;
rdfs:comment """
A noise gate is an audio processing tool that controls the volume of an audio signal
by allowing it to pass through only when it exceeds a set threshold.
+1 -1
View File
@@ -40,7 +40,7 @@
doap:license <https://rerdavies.github.io/pipedal/LicenseToobAmp> ;
doap:maintainer <http://two-play.com/rerdavies#me> ;
lv2:minorVersion 0 ;
lv2:microVersion 63 ;
lv2:microVersion 64 ;
rdfs:comment """
A loose emulation of an MXR® Phase 90 Phaser.
+1 -1
View File
@@ -60,7 +60,7 @@ toobPlayer:seek
doap:license <https://rerdavies.github.io/pipedal/LicenseToobAmp> ;
doap:maintainer <http://two-play.com/rerdavies#me> ;
lv2:minorVersion 0 ;
lv2:microVersion 63 ;
lv2:microVersion 64 ;
rdfs:comment """
Play audio files. Audio files can optionally be loooped by pressing the "Set loop" button.
+1 -1
View File
@@ -51,7 +51,7 @@ recordPrefix:audioFile
doap:license <https://opensource.org/license/mit/> ;
doap:maintainer <http://two-play.com/rerdavies#me> ;
lv2:minorVersion 1 ;
lv2:microVersion 63 ;
lv2:microVersion 64 ;
ui:ui <http://two-play.com/plugins/toob-record-mono-ui>;
+1 -1
View File
@@ -88,7 +88,7 @@ myprefix:loop3_group
doap:license <https://opensource.org/license/mit/> ;
doap:maintainer <http://two-play.com/rerdavies#me> ;
lv2:minorVersion 1 ;
lv2:microVersion 63 ;
lv2:microVersion 64 ;
ui:ui <http://two-play.com/plugins/toob-record-stereo-ui>;
+1 -1
View File
@@ -40,7 +40,7 @@
doap:license <https://rerdavies.github.io/pipedal/LicenseToobAmp> ;
doap:maintainer <http://two-play.com/rerdavies#me> ;
lv2:minorVersion 0 ;
lv2:microVersion 63 ;
lv2:microVersion 64 ;
rdfs:comment """
TooB Tuner is a chromatic guitar tuner.
""" ;
+1 -1
View File
@@ -39,7 +39,7 @@
doap:license <https://rerdavies.github.io/pipedal/LicenseToobAmp> ;
doap:maintainer <http://two-play.com/rerdavies#me> ;
lv2:minorVersion 0 ;
lv2:microVersion 63 ;
lv2:microVersion 64 ;
rdfs:comment """
Volume control.
+67 -40
View File
@@ -1484,7 +1484,7 @@ namespace pipedal
#endif
}
std::jthread *audioThread = nullptr;
std::unique_ptr<std::jthread> audioThread;
bool audioRunning;
bool block = false;
@@ -1518,32 +1518,36 @@ namespace pipedal
} while (frames > 0);
return framesRead;
}
protected:
void ReadMidiData(uint32_t audioFrame)
{
AlsaMidiMessage message;
midiEventCount = 0;
while(alsaSequencer->ReadMessage(message,0))
while (alsaSequencer->ReadMessage(message, 0))
{
size_t messageSize = message.size;
if (messageSize == 0)
if (messageSize == 0)
{
continue;
}
if (midiEventMemoryIndex + messageSize >= this->midiEventMemory.size()) {
if (midiEventMemoryIndex + messageSize >= this->midiEventMemory.size())
{
continue;
}
if (midiEventCount >= this->midiEvents.size()) {
midiEvents.resize(midiEventCount*2);
if (midiEventCount >= this->midiEvents.size())
{
midiEvents.resize(midiEventCount * 2);
}
// for now, prevent META event messages from propagating.
if (message.data[0] == 0xFF && message.size > 1) {
// for now, prevent META event messages from propagating.
if (message.data[0] == 0xFF && message.size > 1)
{
continue;
}
MidiEvent *pEvent = midiEvents.data() + midiEventCount++;
pEvent->time = audioFrame;
pEvent->size = messageSize;
pEvent->size = messageSize;
pEvent->buffer = midiEventMemory.data() + midiEventMemoryIndex;
memcpy(
@@ -1551,11 +1555,10 @@ namespace pipedal
message.data,
message.size);
midiEventMemoryIndex += messageSize;
}
}
private:
private:
long WriteBuffer(snd_pcm_t *handle, uint8_t *buf, size_t frames)
{
long framesRead;
@@ -1759,7 +1762,7 @@ namespace pipedal
}
}
audioThread = new std::jthread([this]()
audioThread = std::make_unique<std::jthread>([this]()
{ AudioThread(); });
}
@@ -1773,8 +1776,7 @@ namespace pipedal
terminateAudio(true);
if (audioThread)
{
this->audioThread->join();
this->audioThread = 0;
this->audioThread = 0; // jthread joins.
}
Lv2Log::debug("Audio thread joined.");
}
@@ -1789,9 +1791,6 @@ namespace pipedal
AlsaSequencer::ptr alsaSequencer;
public:
virtual void SetAlsaSequencer(AlsaSequencer::ptr alsaSequencer) override
{
this->alsaSequencer = alsaSequencer;
@@ -1822,7 +1821,7 @@ namespace pipedal
{
for (size_t i = 0; i < buffer.size(); ++i)
{
// delete[] buffer[i];
delete[] buffer[i];
buffer[i] = 0;
}
buffer.clear();
@@ -1887,6 +1886,51 @@ namespace pipedal
snd_pcm_t *captureHandle = nullptr;
snd_pcm_hw_params_t *playbackHwParams = nullptr;
snd_pcm_hw_params_t *captureHwParams = nullptr;
Finally ff_playbackHandle{
[&playbackHandle]()
{
if (playbackHandle)
{
int rc = snd_pcm_close(playbackHandle);
if (rc < 0)
{
throw std::runtime_error("snd_pcm_close failed.");
}
playbackHandle = nullptr;
}
}};
Finally ff_captureHandle{
[&captureHandle]()
{
if (captureHandle)
{
int rc = snd_pcm_close(captureHandle);
if (rc < 0)
{
throw std::runtime_error("snd_pcm_close failed.");
}
captureHandle = nullptr;
}
}};
Finally ff_playbackHwParams{
[&playbackHwParams]()
{
if (playbackHwParams)
{
snd_pcm_hw_params_free(playbackHwParams);
}
}};
Finally ff_captureHwParams{
[&captureHwParams]()
{
if (captureHwParams)
{
snd_pcm_hw_params_free(captureHwParams);
}
}};
std::string alsaDeviceName = jackServerSettings.GetAlsaInputDevice();
bool result = false;
@@ -2001,28 +2045,6 @@ namespace pipedal
result = false;
throw;
}
if (playbackHwParams)
{
snd_pcm_hw_params_free(playbackHwParams);
playbackHwParams = nullptr;
}
if (captureHwParams)
{
snd_pcm_hw_params_free(captureHwParams);
captureHwParams = nullptr;
}
if (playbackHandle)
{
snd_pcm_close(playbackHandle);
playbackHandle = nullptr;
}
if (captureHandle)
{
snd_pcm_close(captureHandle);
captureHandle = nullptr;
}
return result;
}
@@ -2176,4 +2198,9 @@ namespace pipedal
}
#endif
}
void FreeAlsaGlobals()
{
snd_config_update_free_global(); // to get a clean Valgrind report.
}
} // namespace
+2
View File
@@ -40,5 +40,7 @@ namespace pipedal {
// test only.
void AlsaFormatEncodeDecodeTest(AudioDriverHost*driverHost);
void MidiDecoderTest();
void FreeAlsaGlobals(); // for valgrind. Free the Alsa configuration cache.
}
+4 -2
View File
@@ -1511,8 +1511,10 @@ public:
if (property != nullptr && value != nullptr && property->type == uris.atom_URID)
{
LV2_URID propertyUrid = ((LV2_Atom_URID *)property)->body;
this->pNotifyCallbacks->OnPatchSetReply(instanceId, propertyUrid, value);
// this->pNotifyCallbacks->OnNotifyMaybeLv2StateChanged(instanceId);
if (this->pNotifyCallbacks)
{
this->pNotifyCallbacks->OnPatchSetReply(instanceId, propertyUrid, value);
}
}
}
}
+1
View File
@@ -520,6 +520,7 @@ JSON_MAP_BEGIN(PedalboardItem)
JSON_MAP_REFERENCE_CONDITIONAL(PedalboardItem,topChain,IsPedalboardSplitItem)
JSON_MAP_REFERENCE_CONDITIONAL(PedalboardItem,bottomChain,&IsPedalboardSplitItem)
JSON_MAP_REFERENCE(PedalboardItem,midiBindings)
JSON_MAP_REFERENCE(PedalboardItem,midiChannelBinding)
JSON_MAP_REFERENCE(PedalboardItem,stateUpdateCount)
JSON_MAP_REFERENCE(PedalboardItem,lv2State)
JSON_MAP_REFERENCE(PedalboardItem,lilvPresetUri)
+12 -12
View File
@@ -81,7 +81,7 @@ public:
};
class PedalboardItem: public JsonMemberWritable {
class PedalboardItem {
public:
using PropertyMap = std::map<std::string,atom_object>;
int64_t instanceId_ = 0;
@@ -148,17 +148,17 @@ public:
void AddResetsForMissingProperties(Snapshot&snapshot, size_t*index) const;
virtual void write_members(json_writer&writer) const {
writer.write_member("instanceId",instanceId_);
writer.write_member("uri",uri_);
writer.write_member("pluginName",pluginName_);
writer.write_member("isEnabled",isEnabled_);
if (isSplit())
{
writer.write_member("topChain",topChain_);
writer.write_member("bottomChain",bottomChain_);
}
}
// virtual void write_members(json_writer&writer) const {
// writer.write_member("instanceId",instanceId_);
// writer.write_member("uri",uri_);
// writer.write_member("pluginName",pluginName_);
// writer.write_member("isEnabled",isEnabled_);
// if (isSplit())
// {
// writer.write_member("topChain",topChain_);
// writer.write_member("bottomChain",bottomChain_);
// }
// }
DECLARE_JSON_MAP(PedalboardItem);
};
+4 -1
View File
@@ -2239,7 +2239,10 @@ void PiPedalModel::OnPatchSetReply(uint64_t instanceId, LV2_URID patchSetPropert
}
}
}
audioHost->SetListenForAtomOutput(atomOutputListeners.size() != 0);
if (audioHost)
{
audioHost->SetListenForAtomOutput(atomOutputListeners.size() != 0);
}
}
void PiPedalModel::OnNotifyPathPatchPropertyReceived(
+6 -3
View File
@@ -828,7 +828,10 @@ Lv2PluginInfo::Lv2PluginInfo(PluginHost *lv2Host, LilvWorld *pWorld, const LilvP
std::string bundleUri = bundleUriNode.AsUri();
std::string bundlePath = lilv_file_uri_parse(bundleUri.c_str(), nullptr);
char *lilvBundlePath = lilv_file_uri_parse(bundleUri.c_str(), nullptr);
std::string bundlePath = lilvBundlePath;
lilv_free(lilvBundlePath);
if (bundlePath.length() == 0)
throw std::logic_error("Bundle uri is not a file uri.");
@@ -1655,9 +1658,9 @@ Lv2PortGroup::Lv2PortGroup(PluginHost *lv2Host, const std::string &groupUri)
this->uri_ = groupUri;
AutoLilvNode uri = lilv_new_uri(pWorld, groupUri.c_str());
LilvNode *symbolNode = lilv_world_get(pWorld, uri, lv2Host->lilvUris->lv2core__symbol, nullptr);
AutoLilvNode symbolNode = lilv_world_get(pWorld, uri, lv2Host->lilvUris->lv2core__symbol, nullptr);
symbol_ = nodeAsString(symbolNode);
LilvNode *nameNode = lilv_world_get(pWorld, uri, lv2Host->lilvUris->lv2core__name, nullptr);
AutoLilvNode nameNode = lilv_world_get(pWorld, uri, lv2Host->lilvUris->lv2core__name, nullptr);
name_ = nodeAsString(nameNode);
}
+3 -2
View File
@@ -39,6 +39,7 @@
#include "ofstream_synced.hpp"
#include "ModTemplateGenerator.hpp"
#include <mutex>
#include "WebServer.hpp"
@@ -685,7 +686,7 @@ namespace pipedal
int threads = 1;
size_t maxUploadSize = 512 * 1024 * 1024;
std::thread *pBgThread = nullptr;
std::unique_ptr<std::thread> pBgThread;
std::recursive_mutex io_mutex;
boost::asio::io_context *pIoContext = nullptr;
@@ -1417,7 +1418,7 @@ namespace pipedal
throw std::runtime_error("Bad state.");
}
this->signalOnDone = signalOnDone;
this->pBgThread = new std::thread(ThreadProc, this);
this->pBgThread = std::make_unique<std::thread>(ThreadProc, this);
}
virtual void DisplayIpAddresses() override;
+3
View File
@@ -41,6 +41,7 @@
#include "HtmlHelper.hpp"
#include <thread>
#include <atomic>
#include "AlsaDriver.hpp"
#include <signal.h>
#include <semaphore.h>
@@ -422,6 +423,8 @@ int main(int argc, char *argv[])
}
Lv2Log::info("Shutdown complete.");
FreeAlsaGlobals();
if (systemd)
{
sd_notify(0, "STOPPING=1");
+3 -8
View File
@@ -1,19 +1,12 @@
Crash-proofing: do not reload pedalboard if the previous run crashed before normal shutdown.
Persist and reconnect IP addresses in client.
Zeroconv crash assert. /var/pipedal/audio_uploads/ReverbImpulseFiles/
Investigate if ((keyCode == KeyEvent.KEYCODE_BACK))
MOD ir uses some scheme to limit the minimum buffer size, which is not implemented in Pipedal.
wa
Vu Meters, move rendering to background images, in order to reduce layout overhead.
check reload after change of LV2 plugins.
Remove FullScreenIME in PluginControlView.tsx
Exactly one underrun per seek in Toob Player
@@ -21,6 +14,7 @@ check filetime conversion in gcc 12.2! (missing c++ 20 time conversion functions
AudioFiles.cpp fileTimeToInt64
json "skip" code doesn't work with complex objects (MidiChannelBinding specifically).
- pipewire aux in?
@@ -39,3 +33,4 @@ pcm.pipedal_aux_in {
}
}
Executable
+1
View File
@@ -0,0 +1 @@
valgrind --leak-check=full --log-file=vg.output ./build/src/pipedald /etc/pipedal/config ./vite/dist -port 0.0.0.0:8080 -log-level debug
+146
View File
@@ -0,0 +1,146 @@
==5249== Memcheck, a memory error detector
==5249== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==5249== Using Valgrind-3.19.0 and LibVEX; rerun with -h for copyright info
==5249== Command: ./build/src/pipedald /etc/pipedal/config ./vite/dist -port 0.0.0.0:8080 -log-level debug
==5249== Parent PID: 5248
==5249==
==5249==
==5249== HEAP SUMMARY:
==5249== in use at exit: 88,737 bytes in 474 blocks
==5249== total heap usage: 662,523 allocs, 662,049 frees, 52,720,309 bytes allocated
==5249==
==5249== 22 bytes in 1 blocks are definitely lost in loss record 11 of 102
==5249== at 0x48850C8: malloc (vg_replace_malloc.c:381)
==5249== by 0x61DC32F: ???
==5249== by 0x61BFFC3: ???
==5249== by 0x61C01DB: ???
==5249== by 0x61BF9D7: ???
==5249== by 0x61C0267: ???
==5249== by 0x61C0677: ???
==5249== by 0x61C0C1B: ???
==5249== by 0x61C0C47: ???
==5249== by 0x5F143DB: ???
==5249== by 0x5F14613: ???
==5249== by 0x6046B87: ???
==5249==
==5249== 56 bytes in 1 blocks are definitely lost in loss record 45 of 102
==5249== at 0x48850C8: malloc (vg_replace_malloc.c:381)
==5249== by 0x6233FC7: ???
==5249== by 0x6232503: ???
==5249== by 0x6233197: ???
==5249== by 0x6233343: ???
==5249== by 0x6233AB7: ???
==5249== by 0x5F14453: ???
==5249== by 0x5F14613: ???
==5249== by 0x6046B87: ???
==5249== by 0x5EFD7B7: ???
==5249== by 0x5EFE143: ???
==5249== by 0x60467A7: ???
==5249==
==5249== 88 bytes in 1 blocks are definitely lost in loss record 52 of 102
==5249== at 0x48850C8: malloc (vg_replace_malloc.c:381)
==5249== by 0x625EF8B: ???
==5249== by 0x61CD1E7: ???
==5249== by 0x61CD3AF: ???
==5249== by 0x61CD46B: ???
==5249== by 0x5F1C0E7: ???
==5249== by 0x5F0A637: ???
==5249== by 0x5F143AB: ???
==5249== by 0x5F14613: ???
==5249== by 0x6046B87: ???
==5249== by 0x5EFD7B7: ???
==5249== by 0x5EFE143: ???
==5249==
==5249== 3,352 (80 direct, 3,272 indirect) bytes in 1 blocks are definitely lost in loss record 89 of 102
==5249== at 0x48850C8: malloc (vg_replace_malloc.c:381)
==5249== by 0x6235507: ???
==5249== by 0x61BFFEB: ???
==5249== by 0x61C01DB: ???
==5249== by 0x61BF9D7: ???
==5249== by 0x61C0267: ???
==5249== by 0x61C0677: ???
==5249== by 0x61C0C1B: ???
==5249== by 0x61C0C47: ???
==5249== by 0x5F143DB: ???
==5249== by 0x5F14613: ???
==5249== by 0x6046B87: ???
==5249==
==5249== 3,709 (80 direct, 3,629 indirect) bytes in 1 blocks are definitely lost in loss record 91 of 102
==5249== at 0x48850C8: malloc (vg_replace_malloc.c:381)
==5249== by 0x6235507: ???
==5249== by 0x626268B: ???
==5249== by 0x604751B: ???
==5249== by 0x624C53B: ???
==5249== by 0x6046AA7: ???
==5249== by 0x6046C17: ???
==5249== by 0x5EFD7B7: ???
==5249== by 0x5EFE143: ???
==5249== by 0x60467A7: ???
==5249== by 0x1B727F: CollatorImpl::CollatorImpl(std::shared_ptr<LocaleImpl>, char const*) (Locale.cpp:385)
==5249== by 0x1B7717: LocaleImpl::GetCollator() (Locale.cpp:444)
==5249==
==5249== 3,950 (56 direct, 3,894 indirect) bytes in 1 blocks are definitely lost in loss record 92 of 102
==5249== at 0x48850C8: malloc (vg_replace_malloc.c:381)
==5249== by 0x625EF8B: ???
==5249== by 0x624BE7B: ???
==5249== by 0x60460BF: ???
==5249== by 0x6046C0B: ???
==5249== by 0x5EFD7B7: ???
==5249== by 0x5EFE143: ???
==5249== by 0x60467A7: ???
==5249== by 0x1B727F: CollatorImpl::CollatorImpl(std::shared_ptr<LocaleImpl>, char const*) (Locale.cpp:385)
==5249== by 0x1B7717: LocaleImpl::GetCollator() (Locale.cpp:444)
==5249== by 0x156B67: main (main.cpp:303)
==5249==
==5249== 4,264 bytes in 1 blocks are definitely lost in loss record 99 of 102
==5249== at 0x48850C8: malloc (vg_replace_malloc.c:381)
==5249== by 0x625EFDF: ???
==5249== by 0x61C063F: ???
==5249== by 0x61C0C1B: ???
==5249== by 0x61C0C47: ???
==5249== by 0x5F143DB: ???
==5249== by 0x5F14613: ???
==5249== by 0x6046B87: ???
==5249== by 0x5EFD7B7: ???
==5249== by 0x5EFE143: ???
==5249== by 0x60467A7: ???
==5249== by 0x1B727F: CollatorImpl::CollatorImpl(std::shared_ptr<LocaleImpl>, char const*) (Locale.cpp:385)
==5249==
==5249== 5,804 (256 direct, 5,548 indirect) bytes in 1 blocks are definitely lost in loss record 100 of 102
==5249== at 0x48850C8: malloc (vg_replace_malloc.c:381)
==5249== by 0x625EF8B: ???
==5249== by 0x5F143CF: ???
==5249== by 0x5F14613: ???
==5249== by 0x6046B87: ???
==5249== by 0x5EFD7B7: ???
==5249== by 0x5EFE143: ???
==5249== by 0x60467A7: ???
==5249== by 0x1B727F: CollatorImpl::CollatorImpl(std::shared_ptr<LocaleImpl>, char const*) (Locale.cpp:385)
==5249== by 0x1B7717: LocaleImpl::GetCollator() (Locale.cpp:444)
==5249== by 0x156B67: main (main.cpp:303)
==5249==
==5249== 7,733 bytes in 276 blocks are definitely lost in loss record 101 of 102
==5249== at 0x488A1C4: realloc (vg_replace_malloc.c:1437)
==5249== by 0x5912A2B: serd_chunk_sink (in /usr/lib/aarch64-linux-gnu/libserd-0.so.0.30.16)
==5249== by 0x5912A87: serd_chunk_sink_finish (in /usr/lib/aarch64-linux-gnu/libserd-0.so.0.30.16)
==5249== by 0x590DA67: serd_file_uri_parse (in /usr/lib/aarch64-linux-gnu/libserd-0.so.0.30.16)
==5249== by 0x470DE3: pipedal::Lv2PluginInfo::Lv2PluginInfo(pipedal::PluginHost*, LilvWorldImpl*, LilvPluginImpl const*) (PluginHost.cpp:831)
==5249== by 0x49D8F7: void std::_Construct<pipedal::Lv2PluginInfo, pipedal::PluginHost*, LilvWorldImpl*&, LilvPluginImpl const*&>(pipedal::Lv2PluginInfo*, pipedal::PluginHost*&&, LilvWorldImpl*&, LilvPluginImpl const*&) (stl_construct.h:119)
==5249== by 0x49A61F: void std::allocator_traits<std::allocator<void> >::construct<pipedal::Lv2PluginInfo, pipedal::PluginHost*, LilvWorldImpl*&, LilvPluginImpl const*&>(std::allocator<void>&, pipedal::Lv2PluginInfo*, pipedal::PluginHost*&&, LilvWorldImpl*&, LilvPluginImpl const*&) (alloc_traits.h:635)
==5249== by 0x496C5F: std::_Sp_counted_ptr_inplace<pipedal::Lv2PluginInfo, std::allocator<void>, (__gnu_cxx::_Lock_policy)2>::_Sp_counted_ptr_inplace<pipedal::PluginHost*, LilvWorldImpl*&, LilvPluginImpl const*&>(std::allocator<void>, pipedal::PluginHost*&&, LilvWorldImpl*&, LilvPluginImpl const*&) (shared_ptr_base.h:604)
==5249== by 0x48F12B: std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count<pipedal::Lv2PluginInfo, std::allocator<void>, pipedal::PluginHost*, LilvWorldImpl*&, LilvPluginImpl const*&>(pipedal::Lv2PluginInfo*&, std::_Sp_alloc_shared_tag<std::allocator<void> >, pipedal::PluginHost*&&, LilvWorldImpl*&, LilvPluginImpl const*&) (shared_ptr_base.h:971)
==5249== by 0x488A3B: std::__shared_ptr<pipedal::Lv2PluginInfo, (__gnu_cxx::_Lock_policy)2>::__shared_ptr<std::allocator<void>, pipedal::PluginHost*, LilvWorldImpl*&, LilvPluginImpl const*&>(std::_Sp_alloc_shared_tag<std::allocator<void> >, pipedal::PluginHost*&&, LilvWorldImpl*&, LilvPluginImpl const*&) (shared_ptr_base.h:1712)
==5249== by 0x482803: std::shared_ptr<pipedal::Lv2PluginInfo>::shared_ptr<std::allocator<void>, pipedal::PluginHost*, LilvWorldImpl*&, LilvPluginImpl const*&>(std::_Sp_alloc_shared_tag<std::allocator<void> >, pipedal::PluginHost*&&, LilvWorldImpl*&, LilvPluginImpl const*&) (shared_ptr.h:464)
==5249== by 0x47E363: std::shared_ptr<pipedal::Lv2PluginInfo> std::make_shared<pipedal::Lv2PluginInfo, pipedal::PluginHost*, LilvWorldImpl*&, LilvPluginImpl const*&>(pipedal::PluginHost*&&, LilvWorldImpl*&, LilvPluginImpl const*&) (shared_ptr.h:1010)
==5249==
==5249== LEAK SUMMARY:
==5249== definitely lost: 12,635 bytes in 284 blocks
==5249== indirectly lost: 16,343 bytes in 30 blocks
==5249== possibly lost: 0 bytes in 0 blocks
==5249== still reachable: 59,759 bytes in 160 blocks
==5249== suppressed: 0 bytes in 0 blocks
==5249== Reachable blocks (those to which a pointer was found) are not shown.
==5249== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==5249==
==5249== For lists of detected and suppressed errors, rerun with: -s
==5249== ERROR SUMMARY: 9 errors from 9 contexts (suppressed: 0 from 0)
+5 -2
View File
@@ -255,8 +255,11 @@ export const MainPage =
// selectedItem = value.getFirstSelectableItem();
// }
let selectedItem = value.selectedPlugin;
if (selectedItem === -1 || !value.hasItem(selectedItem)) {
selectedItem = value.getFirstSelectableItem();
if (selectedItem !== -2 && selectedItem !== -3) // start and end nodes.
{
if (selectedItem === -1 || !value.hasItem(selectedItem)) {
selectedItem = value.getFirstSelectableItem();
}
}
this.setState({
pedalboard: value,
+5
View File
@@ -24,6 +24,11 @@ export enum MidiDeviceSelection {
DeviceList = 2
}
// This feature is not yet completely implemented.
export const midiChannelBindingControlFeatureEnabled: boolean = false; // set to true to enable the midi channel binding control in the plugin control view.
export default class MidiChannelBinding {
deserialize(input: any) : MidiChannelBinding {
this.deviceSelection = input.deviceSelection;
-1
View File
@@ -399,7 +399,6 @@ class CustomSelectPathControl implements ModGuiControl {
}
let valueElement = this.getValueElement();
if (valueElement) {
/// xxx: update the display value.
if (this.pathValue === null || this.pathValue === "") {
valueElement.textContent = "No file selected";
return;
+2 -1
View File
@@ -43,6 +43,7 @@ import {
} from './Pedalboard';
import MidiIcon from './svg/ic_midi.svg?react';
import { midiChannelBindingControlFeatureEnabled } from './MidiChannelBinding';
const START_CONTROL = Pedalboard.START_CONTROL;
@@ -995,7 +996,7 @@ withStyles(
const classes = withStyles.getClasses(this.props);
return (
<div className={hasBorder ? classes.iconFrame : classes.borderlessIconFrame} onContextMenu={(e) => { e.preventDefault(); }}>
{hasMidiConnector && (
{hasMidiConnector && midiChannelBindingControlFeatureEnabled && (
<div className={classes.midiConnectorDecoration} >
<MidiIcon style={{ width: 16, height: 16, fill: this.props.theme.palette.text.secondary }} />
</div>
+4 -2
View File
@@ -27,6 +27,8 @@ import AutoZoom from './AutoZoom';
import ModGuiHost from './ModGuiHost';
import {midiChannelBindingControlFeatureEnabled} from './MidiChannelBinding';
import { withStyles } from "tss-react/mui";
import { PiPedalModel, PiPedalModelFactory } from './PiPedalModel';
import { UiPlugin, UiControl, UiFileProperty, UiFrequencyPlot, ScalePoint } from './Lv2Plugin';
@@ -762,7 +764,7 @@ const PluginControlView =
makeIoPluginInfo("Output", Pedalboard.END_PEDALBOARD_ITEM_URI);
midiBindingControl(pedalboardItem: PedalboardItem): ReactNode {
if (!pedalboardItem.midiChannelBinding) {
if ((!pedalboardItem.midiChannelBinding) || (midiChannelBindingControlFeatureEnabled === false)) {
return false;
}
return (
@@ -890,7 +892,7 @@ const PluginControlView =
pedalboardItem.midiChannelBinding = MidiChannelBinding.CreateMissingValue();
}
if (pedalboardItem.midiChannelBinding) {
if (pedalboardItem.midiChannelBinding && midiChannelBindingControlFeatureEnabled) {
nodes.push(this.midiBindingControl(pedalboardItem));
}
return (
+118 -95
View File
@@ -95,7 +95,9 @@ class TelltaleState {
}
const LEFT_X = BORDER_THICKNESS;
const RIGHT_X = BORDER_THICKNESS + + CHANNEL_WIDTH + BORDER_THICKNESS;
const RIGHT_X = BORDER_THICKNESS + CHANNEL_WIDTH + BORDER_THICKNESS;
const TOP_Y = BORDER_THICKNESS;
const VU_BAR_HEIGHT = DISPLAY_HEIGHT-2*BORDER_THICKNESS;
const styles = (theme: Theme) => ({
frame: css({
@@ -119,15 +121,16 @@ const styles = (theme: Theme) => ({
overflow: "hidden",
}),
monoTextFrame: css({
display: "flex",flexFlow: "column nowrap", alignItems: "center", textAlign: "center"
display: "flex",flexFlow: "column nowrap", alignItems: "center", textAlign: "center", overflow: "clip",
}),
stereoTextFrame: css({
display: "flex",flexFlow: "column nowrap", alignItems: "center", textAlign: "center"
display: "flex",flexFlow: "column nowrap", alignItems: "center", textAlign: "center",overflow: "clip",
}),
vuTextFrame: css({
color: theme.palette.text.secondary,
display: "table-cell",
display: "div",
position: "relative",
overflow: "clip",
marginTop: 4,
textAlign: "center",
width: 20, height: 16,
@@ -135,73 +138,60 @@ const styles = (theme: Theme) => ({
justifyContent: "center",
alignItems: "center"
}),
redFrameL: css({
frameL: css({
position: "absolute",
top: "100%",
top: TOP_Y ,
left: LEFT_X,
width: CHANNEL_WIDTH,
height: DISPLAY_HEIGHT - 2,
background: "#F00"
height: VU_BAR_HEIGHT,
overflow: "clip"
}),
yellowFrameL: css({
top: "100%",
left: LEFT_X,
frameR: css({
position: "absolute",
overflow: "clip",
top: TOP_Y,
left: RIGHT_X,
width: CHANNEL_WIDTH,
position: "absolute",
height: DISPLAY_HEIGHT - 2,
background: "#CC0"
height: VU_BAR_HEIGHT,
}),
greenFrameL: css({
top: "100%",
left: LEFT_X,
yellowBar: css({
top: 0,
left: 0,
width: CHANNEL_WIDTH,
height: VU_BAR_HEIGHT,
position: "absolute",
height: DISPLAY_HEIGHT - 2,
background: "#0C2"
background: "#CC0",
transform: "translateY(" + VU_BAR_HEIGHT + "px)"
}),
indicatorL: css({
greenBar: css({
top: 0,
left: 0,
width: CHANNEL_WIDTH,
height: VU_BAR_HEIGHT,
position: "absolute",
left: LEFT_X,
background: "#0C2",
transform: "translateY(" + VU_BAR_HEIGHT + "px)"
}),
redBar: css({
top: 0,
left: 0,
width: CHANNEL_WIDTH,
height: VU_BAR_HEIGHT,
position: "absolute",
background: "#F00",
transform: "translateY(" + VU_BAR_HEIGHT + "px)"
}),
indicatorBar: css({
position: "absolute",
left: 0,
width: CHANNEL_WIDTH,
height: TELLTALE_HEIGHT + "px",
top: "100%",
background: "#F00"
top: 0,
background: "#F00",
transform: "translateY(" + VU_BAR_HEIGHT + "px)"
}),
redFrameR: css({
position: "absolute",
top: "100%",
left: RIGHT_X,
width: CHANNEL_WIDTH,
height: DISPLAY_HEIGHT - 2,
background: "#F00"
}),
yellowFrameR: css({
top: "100%",
left: RIGHT_X,
width: CHANNEL_WIDTH,
position: "absolute",
height: DISPLAY_HEIGHT - 2,
background: "#CC0"
}),
greenFrameR: css({
top: "100%",
left: RIGHT_X,
width: CHANNEL_WIDTH,
position: "absolute",
height: DISPLAY_HEIGHT - 2,
background: "#0C2"
}),
indicatorR: css({
position: "absolute",
left: RIGHT_X,
width: CHANNEL_WIDTH,
height: TELLTALE_HEIGHT + "px",
top: "100%",
background: "#F00"
})
});
@@ -261,10 +251,12 @@ export const VuMeter =
telltaleStateR: TelltaleState = new TelltaleState();
vuInfo?: VuUpdateInfo;
requesttedStereoState: boolean = false;
requestedStereoState: boolean = false;
private currentDisplayValue: string | null = null;
updateText(telltaleDb: number)
{
if (this.textRef.current) {
let displayValue: string;
if (telltaleDb <= MIN_DB)
@@ -288,16 +280,39 @@ export const VuMeter =
}
}
}
this.textRef.current.innerText = displayValue;
if (this.currentDisplayValue !== displayValue)
{
this.currentDisplayValue = displayValue;
this.textRef.current.innerText = displayValue;
}
}
}
private currentVuInfo: VuUpdateInfo | null = null;
private animationFrameHandle: number | null = null;
onVuChanged(vuInfo: VuUpdateInfo): void {
this.currentVuInfo = vuInfo;
if (this.animationFrameHandle == null)
{
this.animationFrameHandle = window.requestAnimationFrame(() => {
this.animationFrameHandle = null;
this.animateVuUpdate();
});
}
}
private animateVuUpdate() : void
{
let value: number;
let valueR: number;
this.vuInfo = vuInfo;
let vuInfo = this.currentVuInfo;
if (!vuInfo) {
return; // no vu info.
}
if (!this.divRef.current) { // unmounted?
return;
}
let isStereo: boolean;
@@ -312,34 +327,37 @@ export const VuMeter =
}
if (this.state.isStereo !== isStereo)
{
if (isStereo !== this.requesttedStereoState) // guard against overrunning the layout engine.
if (isStereo !== this.requestedStereoState) // guard against overrunning the layout engine.
{
this.requesttedStereoState = isStereo;
this.requestedStereoState = isStereo;
this.setState({
isStereo: isStereo
});
return; // we can't procede without stereo layout.
return; // we can't proceed without stereo layout.
}
}
let childNodes = this.divRef.current!.childNodes;
let leftFrameChildNodes = childNodes[0].childNodes;
let vuData: VuChannelData = {
value: value,
redDiv: childNodes[0] as HTMLDivElement,
yellowDiv: childNodes[1] as HTMLDivElement,
greenDiv: childNodes[2] as HTMLDivElement,
telltaleDiv: childNodes[3] as HTMLDivElement
redDiv: leftFrameChildNodes[0] as HTMLDivElement,
yellowDiv: leftFrameChildNodes[1] as HTMLDivElement,
greenDiv: leftFrameChildNodes[2] as HTMLDivElement,
telltaleDiv: leftFrameChildNodes[3] as HTMLDivElement
};
this.updateChannel(vuData,this.telltaleStateL);
if (this.state.isStereo) {
let rightFrameChildren = childNodes[1].childNodes;
vuData = {
value: valueR,
redDiv: childNodes[4] as HTMLDivElement,
yellowDiv: childNodes[5] as HTMLDivElement,
greenDiv: childNodes[6] as HTMLDivElement,
telltaleDiv: childNodes[7] as HTMLDivElement
redDiv: rightFrameChildren[0] as HTMLDivElement,
yellowDiv: rightFrameChildren[1] as HTMLDivElement,
greenDiv: rightFrameChildren[2] as HTMLDivElement,
telltaleDiv: rightFrameChildren[3] as HTMLDivElement
};
this.updateChannel(vuData, this.telltaleStateR);
}
@@ -367,17 +385,17 @@ export const VuMeter =
let INVISIBLE_Y = INTERIOR_DISPLAY_HEIGHT + "px";
if (y >= this.yYellow) {
// green only.
vuData.greenDiv.style.top = y + "px";
vuData.yellowDiv.style.top = INVISIBLE_Y;
vuData.redDiv.style.top = INVISIBLE_Y;
vuData.greenDiv.style.transform = `translateY(${y}px)`;
vuData.yellowDiv.style.transform = `translateY(${INVISIBLE_Y})`;
vuData.redDiv.style.transform = `translateY(${INVISIBLE_Y})`;
} else {
vuData.greenDiv.style.top = this.yYellow + "px";
vuData.greenDiv.style.transform = `translateY(${this.yYellow}px)`;
if (y >= this.yZero) {
vuData.yellowDiv.style.top = y + "px";
vuData.redDiv.style.top = INVISIBLE_Y;
vuData.yellowDiv.style.transform = `translateY(${y}px)`;
vuData.redDiv.style.transform = `translateY(${INVISIBLE_Y})`;
} else {
vuData.yellowDiv.style.top = this.yZero + "px";
vuData.redDiv.style.top = y + "px";
vuData.yellowDiv.style.transform = `translateY(${this.yZero}px)`;
vuData.redDiv.style.transform = `translateY(${y}px)`;
}
}
let dbTelltale = telltaleState.getTelltaleHoldValue(db);
@@ -399,7 +417,7 @@ export const VuMeter =
yTelltale = INTERIOR_DISPLAY_HEIGHT;
}
}
vuData.telltaleDiv.style.top = yTelltale + "px";
vuData.telltaleDiv.style.transform = `translateY(${yTelltale}px)`;
}
@@ -467,23 +485,28 @@ export const VuMeter =
if (!this.state.isStereo) {
return (<div className={classes.frame} ref={this.divRef}
>
<div className={classes.redFrameL} />
<div className={classes.yellowFrameL} />
<div className={classes.greenFrameL} />
<div className={classes.indicatorL} />
<div className={classes.frameL}>
<div className={classes.redBar} />
<div className={classes.yellowBar} />
<div className={classes.greenBar} />
<div className={classes.indicatorBar} />
</div>
</div>);
} else {
return (<div className={classes.frameStereo} ref={this.divRef}
>
<div className={classes.redFrameL} />
<div className={classes.yellowFrameL} />
<div className={classes.greenFrameL} />
<div className={classes.indicatorL} />
<div className={classes.redFrameR} />
<div className={classes.yellowFrameR} />
<div className={classes.greenFrameR} />
<div className={classes.indicatorR} />
<div className={classes.frameL}>
<div className={classes.redBar} />
<div className={classes.yellowBar} />
<div className={classes.greenBar} />
<div className={classes.indicatorBar} />
</div>
<div className={classes.frameR}>
<div className={classes.redBar} />
<div className={classes.yellowBar} />
<div className={classes.greenBar} />
<div className={classes.indicatorBar} />
</div>
</div>);