Merge pull request #283 from rerdavies/dev

Dev Merge to fix docs links.
This commit is contained in:
Robin Davies
2025-03-18 05:16:45 -04:00
committed by GitHub
67 changed files with 4411 additions and 363 deletions
+30 -10
View File
@@ -20,15 +20,15 @@ An RT_PREEMPT kernel provides slightly better realtime audio than a PREEMPT_DYNA
## Support for WIFI Auto-Hotspots on Ubuntu Server
The following information applies when installing PiPedal on Ubuntu Server 24.0x only. This information does not apply
to Unbuntu Desktop installs or Raspberry Pi OS Lite installs.
to Unbuntu Desktop installs or Raspberry Pi OS Lite installs, which use the Network Manager TCP/IP stack by default.
PiPedal's Auto-Hotspot feature only works on Linux systems that are using the Network Manager network services stack.
Ubuntu Server 24.x (and probably other server-specific installs on other Debian distros) uses the Netplan network services stack by instead. It does so because the Netplan network stack is the preferred network stack when managing
farms of cloud servers.
It's easy enough to reconfigure Ubuntu Server to run the Network Manager network stack instead. However you should be
aware that Netplan TCP/IP configuration settings will not be migrated to Network Manager. If you perform this step on a server on which changes have beeen madce to Netplan configuration files, you will need to manually migrate those
changes to Network Manager configuration files. On a clean install of Ubuntu Server, this will not be a problem.
aware that Netplan TCP/IP configuration settings will not be migrated to Network Manager. If you perform this step on a server on which changes have beeen made to Netplan configuration files, you will lose those configuration changes, and will need to reimplement them in Network Manager. If you are
a Netplan configuration (or are working with a clean install), then the default Network Manager configuration will work perfectly well too.
To reconfigure Ubuntu Server to use the Network Manager network stack (and therefore enable PiPedal's Auto-Hotspot feature), run the following command:
@@ -123,11 +123,33 @@ The following table shows measured round-trip audio latencies for a MOTU M2 exte
<tr><td>128</td><td>442/9.2ms</td><td>571/11.9ms</td><td>699/14.6ms</td></tr>
</table>
LINUX Kernel version 5.16 includes fixes to ALSA audio that are supposed to dramatically improve USB audio latency. As of July 2022, these fixes have not yet made it into Raspberry Pi OS, but are probably available on non-LTS versions of Ubuntu.
Selecting 2 buffers provides lower latency, but leaves very little CPU time for audio processing, so you may experience more underruns if
you select 2. Selecting 4 buffers provides much more time for proessing. Using a buffer size of 16 increases CPU load slightly, since there a
certain amoung of CPU overhead associated with handling of each buffer. That being said, 16x4 audio buffer configuration is a highly recommended
choice if your audio adapter can support it. It provides excellent latency with very little chance of overruns.
PiPedal uses the ALSA audio stack; so (unlike Jack Audio) there is no performance penalty for using 44100Hz sample rates. However, using a 48000Hz sampling rates does provide significant improvements in high-frequency audio quality when performing digital audio signal processing.
All things being equal, you should perfer 48000hz sample rates to 44100Hz sample rates. The higher sample rate makes it easier for plugins to implement
audio effects without high-frequency artifacts; and Nueral Amp Models are usually designed to work best at 48000Hz sample rates.
### Activating the Wi-Fi Auto-Hotspot
### Configuring Input Trim Levels on Older USB Audio Devices
For best results, you should set the input gain of your audio device so that the signal level is as high as possible without clipping. If you click on the
input node of a preset, the left VU meter will show the audio input levels as received directly from your audio adapter.
Some older USB audio devices do not provide volume knobs to control input gain of the audio signal, and the default trim settings are often less than
ideal. To configure the input gain on these devices, use the following procedure.
- ssh to the host, or launch a terminal window on the host if you have configured your Raspberry Pi to boot to a graphical desktop.
- Run `alsamixer` to configure the input gain.
- Press F6 to select the sound card.
- Press TAB to scroll across pages/channels until you reach the CAPTURE slider(s).
- Connect and play your instrument, while watch the input VU meter in the PiPedal UI. Use the UP and DOWN arrow keys to adjust the input gain.
- Press the ESC key to close alsa mixer.
- Run `sudo alsactl store` to save the settings permanantly.
## Activating the Wi-Fi Auto-Hotspot
The PiPedal <b><i>Auto-Hotspot</i></b> feature allows you to connect to your Raspberry Pi even if you don't have
access to a Wi-Fi router. For example, if you are performing at a live venue, you probably will not
@@ -188,14 +210,12 @@ automatically connect to your laptop hotspot whenever it sees it, after you have
credentials on your Raspberry Pi. After the first time, all you need to do is turn on your laptop hotspot, and Raspberry Pi OS will
connect to it.
Usually, you cannect from your laptop using the same web address: http://raspberrpi (or the hostname of your raspberry pi, if you have
changed it). Unlike Android phones (where mDNS name resolution doesn't work on Android-hosted hotspots), mDNS/Bonjour name resolution usually
Usually, you can conect from your laptop using the same web address: `http://raspberrypi` (`http://raspberrypi.local` on Ubuntu), or the hostname of your raspberry pi, if you have changed it. Unlike Android phones (where mDNS name resolution doesn't work on Android-hosted hotspots), mDNS/Bonjour name resolution usually
works on laptop-hosted hotspots when using Windows or Mac OS. If are running Linux on your laptop, you may need to install and configure the
Avahi package to get mDNS/Bonjour name resolution to work.
And if that doesn't work, you can configure PiPedal to launch an auto-hotspot, and then connect from your laptop to the PiPedal hotspot on your Raspberry Pi.
When the Raspberry Pi hosts the hotspot, mDNS discovery is definitely enabled; so you should be able to connect using http://raspberrypi. But if that doesn't work, PiPedal's IP address will always be 10.40.1, when the PiPedal Wi-Fi hotspot is running, so you can always connect using http://10.40.0.1.
When the Raspberry Pi hosts the hotspot, mDNS discovery is definitely enabled; so you should be able to connect using http://raspberrypi. But if that doesn't work, PiPedal's IP address will always be 10.40.0.1, when the PiPedal Wi-Fi hotspot is running, so you can always connect using http://10.40.0.1.
--------
+1 -1
View File
@@ -6,7 +6,7 @@
## PiPedal 1.4.71 Beta
- Resolves installation issues on Ubuntu Server.
- Resolves installation issues on Ubuntu Server./
## PiPedal 1.4.70 Beta
+2 -2
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 57 ;
lv2:microVersion 58 ;
rdfs:comment """
TooB Cab IR is a convolution-based guitar cabinet impulse response simulator.
@@ -274,7 +274,7 @@ Limitations of Liability that apply to these works.
lv2:name "Predelay";
lv2:portProperty epp:notOnGUI;
lv2:default 0 ;
lv2:default 0.0 ;
lv2:minimum 0 ;
lv2:maximum 1 ;
+3 -2
View File
@@ -22,6 +22,7 @@
@prefix urid: <http://lv2plug.in/ns/ext/urid#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix pipedal_ui: <http://github.com/rerdavies/pipedal/ui#> .
@prefix pipedal_patch: <http://github.com/rerdavies/pipedal/patch#> .
@prefix toob: <http://two-play.com/plugins/toob#> .
@prefix cabsim: <two-play.com/plugins/toob-cab-sim#> .
@@ -49,13 +50,13 @@ toob:frequencyResponseVector
doap:license <https://rerdavies.github.io/pipedal/LicenseToobAmp> ;
doap:maintainer <http://two-play.com/rerdavies#me> ;
lv2:minorVersion 0 ;
lv2:microVersion 57 ;
lv2:microVersion 58 ;
mod:brand "TooB";
mod:label "TooB CabSim";
lv2:requiredFeature urid:map ;
lv2:optionalFeature lv2:hardRTCapable;
patch:readable
pipedal_patch:readable
toob:frequencyResponseVector;
rdfs:comment """
@@ -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 57 ;
lv2:microVersion 58 ;
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 57 ;
lv2:microVersion 58 ;
rdfs:comment """
+3 -6
View File
@@ -24,6 +24,7 @@
@prefix pg: <http://lv2plug.in/ns/ext/port-groups#> .
@prefix pipedal_ui: <http://github.com/rerdavies/pipedal/ui#> .
@prefix pipedal_patch: <http://github.com/rerdavies/pipedal/patch#> .
@prefix toob: <http://two-play.com/plugins/toob#> .
@prefix inputStage: <http://two-play.com/plugins/toob-input_stage#> .
@@ -65,16 +66,14 @@ inputStage:filterGroup
doap:license <https://two-play.com/TooB/licenses/isc> ;
doap:maintainer <http://two-play.com/rerdavies#me> ;
lv2:minorVersion 0 ;
lv2:microVersion 57 ;
lv2:microVersion 58 ;
mod:brand "TooB";
mod:label "TooB Input";
lv2:requiredFeature urid:map ;
lv2:optionalFeature lv2:hardRTCapable;
patch:writable
<http://two-play.com/plugins/toob#frequencyResponseVector>;
patch:readable
pipedal_patch:readable
<http://two-play.com/plugins/toob#frequencyResponseVector>;
rdfs:comment """
@@ -282,8 +281,6 @@ The GateT control provides a noise gate. Set to minimum value to disable.
lv2:extensionData uiext:resize ;
lv2:extensionData uiext:idleInterface;
lv2:requiredFeature uiext:idleInterface ;
patch:writable
<http://two-play.com/plugins/toob#frequencyResponseVector>;
.
<http://two-play.com/plugins/toob-input_stage>
+3 -2
View File
@@ -25,6 +25,7 @@
@prefix modgui: <http://moddevices.com/ns/modgui#> .
@prefix pstage: <http://two-play.com/plugins/toob-power-stage-2#> .
@prefix pipedal_patch: <http://github.com/rerdavies/pipedal/patch#> .
pstage:stage1
a param:ControlGroup ,
@@ -67,13 +68,13 @@ pstage:stage3
doap:license <https://rerdavies.github.io/pipedal/LicenseToobAmp> ;
doap:maintainer <http://two-play.com/rerdavies#me> ;
lv2:minorVersion 0 ;
lv2:microVersion 57 ;
lv2:microVersion 58 ;
mod:brand "TooB";
mod:label "Power Stage";
lv2:requiredFeature urid:map ;
lv2:optionalFeature lv2:hardRTCapable;
patch:readable
pipedal_patch:readable
<http://two-play.com/plugins/toob-power-stage-2#uiState>;
rdfs:comment """
+3 -4
View File
@@ -13,6 +13,7 @@
@prefix mod: <http://moddevices.com/ns/mod#> .
@prefix param: <http://lv2plug.in/ns/ext/parameters#> .
@prefix work: <http://lv2plug.in/ns/ext/worker#> .
@prefix pipedal_patch: <http://github.com/rerdavies/pipedal/patch#> .
@prefix atom: <http://lv2plug.in/ns/ext/atom#> .
@prefix patch: <http://lv2plug.in/ns/ext/patch#> .
@@ -49,16 +50,14 @@
;
uiext:ui <http://two-play.com/plugins/toob-spectrum-ui>;
patch:writable
<http://two-play.com/plugins/toob#spectrumResponseVector>;
patch:readable
pipedal_patch:readable
<http://two-play.com/plugins/toob#spectrumResponseVector>;
doap:license <https://rerdavies.github.io/pipedal/LicenseToobAmp> ;
doap:maintainer <http://two-play.com/rerdavies#me> ;
lv2:minorVersion 0 ;
lv2:microVersion 57 ;
lv2:microVersion 58 ;
rdfs:comment "TooB spectrum analyzer" ;
mod:brand "TooB";
+4 -2
View File
@@ -23,6 +23,8 @@
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix pipedal_ui: <http://github.com/rerdavies/pipedal/ui#> .
@prefix pipedal_patch: <http://github.com/rerdavies/pipedal/patch#> .
@prefix toob: <http://two-play.com/plugins/toob#> .
@prefix tonestack: <two-play.com/plugins/toob-tone-stack#> .
@@ -55,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 57 ;
lv2:microVersion 58 ;
uiext:ui <http://two-play.com/plugins/toob-tone-stack-ui>;
@@ -68,7 +70,7 @@ tone stack used in Polytone and HiWatt amps.
mod:label "Tone Stack";
lv2:requiredFeature urid:map ;
lv2:optionalFeature lv2:hardRTCapable;
patch:readable
pipedal_patch:readable
toob:frequencyResponseVector;
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 57 ;
lv2:microVersion 58 ;
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 57 ;
lv2:microVersion 58 ;
rdfs:comment """
A straightforward no-frills digital delay.
+2 -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 57 ;
lv2:microVersion 58 ;
rdfs:comment """
Emulation of a Boss BF-2 Flanger, based on circuit analysis and simulation of the original.
@@ -99,6 +99,7 @@ Emulation of a Boss BF-2 Flanger, based on circuit analysis and simulation of th
lv2:symbol "lfo" ;
lv2:name "LFO";
lv2:portProperty epp:notOnGUI;
lv2:minimum -1.0 ;
lv2:maximum 1.0 ;
],
@@ -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 57 ;
lv2:microVersion 58 ;
rdfs:comment """
Digital emulation of a Boss BF-2 Flanger.
@@ -99,6 +99,7 @@ should use the monophonic version of this effect.
a lv2:OutputPort ,
lv2:ControlPort ;
lv2:portProperty epp:notOnGUI;
lv2:index 3 ;
lv2:symbol "lfo" ;
lv2:name "LFO";
+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 57 ;
lv2:microVersion 58 ;
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.
+915
View File
@@ -0,0 +1,915 @@
@prefix doap: <http://usefulinc.com/ns/doap#> .
@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix units: <http://lv2plug.in/ns/extensions/units#> .
@prefix urid: <http://lv2plug.in/ns/ext/urid#> .
@prefix atom: <http://lv2plug.in/ns/ext/atom#> .
@prefix midi: <http://lv2plug.in/ns/ext/midi#> .
@prefix uiext: <http://lv2plug.in/ns/extensions/ui#> .
@prefix idpy: <http://harrisonconsoles.com/lv2/inlinedisplay#> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix mod: <http://moddevices.com/ns/mod#> .
@prefix param: <http://lv2plug.in/ns/ext/parameters#> .
@prefix work: <http://lv2plug.in/ns/ext/worker#> .
@prefix pg: <http://lv2plug.in/ns/ext/port-groups#> .
@prefix atom: <http://lv2plug.in/ns/ext/atom#> .
@prefix patch: <http://lv2plug.in/ns/ext/patch#> .
@prefix state: <http://lv2plug.in/ns/ext/state#> .
@prefix urid: <http://lv2plug.in/ns/ext/urid#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix ui: <http://lv2plug.in/ns/extensions/ui#> .
@prefix pprop: <http://lv2plug.in/ns/ext/port-props#> .
@prefix pipedal_ui: <http://github.com/rerdavies/pipedal/ui#> .
@prefix looperPrefix: <http://two-play.com/plugins/toob-looper#> .
@prefix myprefix: <http://two-play.com/plugins/toob-looper-four#> .
myprefix:stereoInGroup
a pg:StereoGroup, pg:InputGroup ;
rdfs:label "Stereo Input" ;
lv2:symbol "in_g" .
myprefix:steroOutGroup a pg:Group ;
a pg:StereoGroup, pg:OuputGroup ;
rdfs:label "Stereo Output" ;
lv2:symbol "out_g" .
myprefix:syncGroup
a pg:ControlGroup ;
lv2:name "Clock" ;
lv2:symbol "sync_g" .
myprefix:loop_main_group
a pg:ControlGroup ;
lv2:name "Main Loop" ;
lv2:symbol "loop_main_group" .
myprefix:loop2_group
a pg:ControlGroup ;
lv2:name "Loop 2" ;
lv2:symbol "loop2_group" .
myprefix:loop3_group
a pg:ControlGroup ;
lv2:name "Loop 3" ;
lv2:symbol "loop3_group" .
myprefix:loop4_group
a pg:ControlGroup ;
lv2:name "Loop 4" ;
lv2:symbol "loop4_group" .
myprefix:options_group
a pg:ControlGroup ;
lv2:name "Record Options" ;
lv2:symbol "options_group" .
myprefix:output_group
a pg:ControlGroup ;
lv2:name "Output" ;
lv2:symbol "output_group" .
<http://two-play.com/rerdavies#me>
a foaf:Person ;
foaf:name "Robin Davies" ;
foaf:mbox <mailto:rerdavies@gmail.com> ;
foaf:homepage <https://github.com/sponsors/rerdavies> .
<http://two-play.com/plugins/toob-looper-four>
a lv2:Plugin ,
lv2:UtilityPlugin ;
doap:name "TooB 4Looper (stereo)"
;
doap:license <https://opensource.org/license/mit/> ;
doap:maintainer <http://two-play.com/rerdavies#me> ;
lv2:minorVersion 1 ;
lv2:microVersion 58 ;
ui:ui <http://two-play.com/plugins/toob-looper-four-ui>;
lv2:extensionData state:interface ;
rdfs:comment """
## Toob 4Looper
A 4-channel looper. If you are using a MIDI foot controller, you may want to consider using Toob One-Control looper, which allows control of
looping using a single footswitch. TooB 4Looper does support MIDI control using four footswitches. See the Midi Operation section below for
more information.
### Basic Operation
You must record a main loop before loops 2 through 4 are available.
To start recording the main loop, press the Main Loop record button. The red Record LED will light up to indicate that the main loop is recording.
You can configure TooB 4Looper to use a variable length main loop, or a fixed length loop. See the documentation on the Bars control for more
information on how to use a fixed-length loop. If the Bars control is set to "Free", the length of the main loop will be established when
you next press the Record or Play button after the main loop has started recording. Pressing the record button will mark the end of the
loop, and continue on in Overdub mode. Pressing the Play button will mark the end of the loop, and start playback.
Once the main loop has been established, you can toggle back and forth between Overdub and Play modes by pressing the Record and Play buttons
resepectively.
You can also mute the loop by going to Play mode, and pushing the Play button once more. Pushing the Play button while in Mute mode will
re-enable audio output from the loop.
Pressing the Main Loop stop buton will stop playback of of all loops, and return the looper to its initial state.
To record a secondary loop, press the Record button for the loop you want to record. The Record LED will light up to indicate that the loop
is recording. If the Rec Sync option is enabled, the loop will go to Cue Overdub mode, and once the main loop reaches the end of its loop,
the loop will switch to Record mode. If the Rec Sync option is disabled, the loop will start recording immediately. The length of secondary
loops will always be the same as the length of the main loop. Once the loop has started, pressing the play button will start playback.
Pressing the record button will overdub content of the loop. In Play mode, pushing the Play button again will mute the loop. Pressing
the Play button when the loop is muted will re-enable audio output from the loop. Pressing the Stop button will stop playback, and erase
the contents of the loop. There is no concept of "undoing" individual overdubs in TooB 4Looper. If you're done with a loop, just erase it.
### Clock Options
Clock options determine the tempo and number of beats in a bar. They affect the behavior of the looper when the Bars control (see below) is set to
a numeric value, and also affect the rate and pattern of the flashing LEDs when counting in.
### Record Options
Record Options control the behavior of the looper.
When Count In is enabled, The looper will Count In before starting the main loop. The Record LED will flash when counting in, and go solid
once recording starts. The pattern of blinking lights depends on the TimeSig setting, so for example, if the Time Signature is set to 4/4, the
blinking LED will signal a count-in pattern of "1 - 2 - 1 2 3 4".
When Bars is set to Free (the minimum value), the length of the main loop will be set by a second tap of the
Control button after recording of the main loop starts. If Bars is set to a numeric value, the length of the main loop will be determined by the number
of bars set in the Bars control, and the current settings of the Clock controls.
If Dub Sync is off, overdubs will start recording as soon as you tap the Control button. If enabled, the start
of the secondary loop will sync with main loop. Tapping the Control button will put the looper in "Cue Overdub" state
and the LEDs will flash until the end of the main loop is reached, at which point the new loop will start recording.
The Loop End option only has effect when the Bars control is set to a numeric value, and does nothing if Bars is set to "Free".
When set to REC-PLAY, the main loop will record exactly N bars of audio, and switch to play mode when the end of the loop is reached.
When set to REC-DUB, the main loop will record exactly N bars of audio, and then continue on in overdub mode.
### MIDI Operation
If you want to control your looper with one foot controller switch, please use Toob One-Control Looper instead. Toob 4Looper
allows you to control loops with four foot controller switches (one for each loop). In order to do this, TooB 4Looper provides
a hidden controls only visible in PiPedal's MIDI Bindings user-interface. The hidden controls are named `Midi CTL`; there's one
control for each loop. A single tap of the control will cause the loop to start
recording or playing or overdubbing, depending on the state of the loop. Long-pressing the control will erase the loop. Erasing the main loop
will stop all playback, erasing all other loops as well, and return the Toob 4Looper to its initial state.
To use the hidden controls, you must bind each of them to your MIDI controller's footswitches. It is recommended that you configure
your MIDI controller to send MIDI Note-on/Note off messages. You can bind the controls to MIDI CC messages as well, but the behavior
of your controller may not match what TooB 4Looper expects. If you must use MIDI CC messages, you should configure your MIDI
controller to set a CC value of zero when not pressed, and a value of 127 when pressed, and adjust PiPedal's MIDI bindings appropriately.
The following state table controls how the hidden controls operate. Each loop has an independent state.
### State Table for Looop Operations
The following table describes state transitions for each loop. Note that loops 2 to 4 are not available until the main loop has been recorded.
```
+-----------+--------------+----------------------------------+
| State | Action | Effect |
|-----------|--------------|----------------------------------|
| Empty | Record / | Start counting in if COUNT IN is |
| | Control Tap | enabled; otherwise start |
| | | recording immediately. |
|-----------|--------------|----------------------------------|
| Count-In | Stop / | Return to empty state |
| | Long-press | |
| | | |
| | Complete | Start recording |
|-----------|--------------|----------------------------------|
| Recording | Play | Set the loop length (main loop |
| | | only_) and go to play state . |
| | | |
| | Record | Set the loop length (main loop |
| | | only_) and go to Overdub state . |
| | | |
| | Stop/ | Discard the current loop and |
| | Long-Press | return to Empty state |
| | | |
| | Control Tap | Set the loop length (main loop |
| | | only_) and go to play or Overdub |
| | | state depending on ON REC END. |
| | | |
| | End of loop | go to play or overdub state |
| | | depending on ON REC END |
|-----------|--------------|----------------------------------|
| Playing | Record / Tap | If DUB SYNC is on, go to |
| | | Cue Ovdb state; otherwise |
| | | start overdubbing immediately. |
| | | |
| | Play | Mute the loop, and go to Mute |
| | | state. |
| | | |
| | Stop / | Discard the current loop and go |
| | Long-press | to Empty state. |
|-----------|--------------|----------------------------------|
| Mute | Play / Tap | Unmute the loop and go to Play |
| | | state. |
| | | |
| | Record | Start overdubbing. |
| | | |
| | Stop / | Discard the current loop and go |
| | Long-press | to Empty state. |
|-----------|--------------|----------------------------------|
| Cue Ovdb | End-of-loop | Start overdubbing. |
| | | |
| | Tap | Cancel the pending overdub. |
| | | |
| | Long-press | Discard the current loop and go |
| | | to Empty state. |
|-----------|--------------|----------------------------------|
| Overdub | Play / Tap | Start playing. |
| | | |
| | End of loop | (If DUB SYNC is on, and |
| | | REC->PLAY is selected) Go to |
| | | play state, otherwise, continue |
| | | in overdub state. |
+-----------|--------------|----------------------------------+
```
""" ;
mod:brand "TooB";
mod:label "4Looper";
lv2:optionalFeature lv2:hardRTCapable;
lv2:port
################# MAIN Loop
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 0;
lv2:symbol "control1" ;
lv2:name "MIDI Ctl";
rdfs:comment "Hidden control for MIDI operation. See documentation for details.";
lv2:default 0.0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
lv2:portProperty lv2:integer, lv2:toggled, mod:preferMomentaryOffByDefault, pprop:notOnGUI;
pg:group myprefix:loop_main_group ;
],
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 1;
lv2:symbol "stop1" ;
lv2:name "⏹";
rdfs:comment "Reset all loops.";
lv2:default 0.0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
lv2:portProperty lv2:toggled,pprop:trigger;
pg:group myprefix:loop_main_group ;
],
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 2;
lv2:symbol "record1" ;
lv2:name "⏺";
rdfs:comment "Recording/overdub the main loop";
lv2:default 0.0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
lv2:portProperty lv2:toggled,pprop:trigger;
pg:group myprefix:loop_main_group ;
],
[
a lv2:OutputPort ,
lv2:ControlPort ;
lv2:index 3;
lv2:symbol "record_led1" ;
lv2:name "";
lv2:portProperty lv2:toggled ;
lv2:default 0.0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
pipedal_ui:ledColor "red";
pg:group myprefix:loop_main_group ;
],
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 4;
lv2:symbol "play1" ;
lv2:name "⏵";
rdfs:comment "Play Loop 1. Click again to stop.";
lv2:default 0.0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
lv2:portProperty lv2:toggled,pprop:trigger;
pg:group myprefix:loop_main_group ;
],
[
a lv2:OutputPort ,
lv2:ControlPort ;
lv2:index 5;
lv2:symbol "play_led1" ;
lv2:name "";
lv2:portProperty lv2:toggled ;
lv2:default 0.0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
pipedal_ui:ledColor "green";
pg:group myprefix:loop_main_group ;
],
[
a lv2:OutputPort ,
lv2:ControlPort ;
lv2:index 6;
lv2:symbol "position1" ;
rdfs:comment "Time";
lv2:name "\u00A0\u00A0\u00A0\u00A0";
units:unit units:pc ;
lv2:default 0.0 ;
lv2:minimum 0.0 ;
lv2:maximum 1.0 ;
pg:group myprefix:loop_main_group ;
],
################# Loop2
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 7;
lv2:symbol "control2" ;
lv2:name "MIDI Ctl";
rdfs:comment "Hidden control for MIDI operation. See documentation for details.";
lv2:default 0.0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
lv2:portProperty lv2:integer, lv2:toggled, mod:preferMomentaryOffByDefault, pprop:notOnGUI;
pg:group myprefix:loop2_group ;
],
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 8;
lv2:symbol "stop2" ;
lv2:name "⏹";
rdfs:comment "Reset loop 2.";
lv2:default 0.0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
lv2:portProperty lv2:toggled,pprop:trigger;
pg:group myprefix:loop2_group ;
],
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 9;
lv2:symbol "record2" ;
lv2:name "⏺";
rdfs:comment "Record/Overdub loop 2";
lv2:default 0.0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
lv2:portProperty lv2:toggled,pprop:trigger;
pg:group myprefix:loop2_group ;
],
[
a lv2:OutputPort ,
lv2:ControlPort ;
lv2:index 10;
lv2:symbol "record_led2" ;
lv2:name "";
lv2:portProperty lv2:toggled ;
lv2:default 0.0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
pipedal_ui:ledColor "red";
pg:group myprefix:loop2_group ;
],
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 11;
lv2:symbol "play2" ;
lv2:name "⏵";
rdfs:comment "Play Loop 2. Click again to stop.";
lv2:default 0.0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
lv2:portProperty lv2:toggled,pprop:trigger;
pg:group myprefix:loop2_group ;
],
[
a lv2:OutputPort ,
lv2:ControlPort ;
lv2:index 12;
lv2:symbol "play_led2" ;
lv2:name "";
lv2:portProperty lv2:toggled ;
lv2:default 0.0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
pipedal_ui:ledColor "green";
pg:group myprefix:loop2_group ;
],
[
a lv2:OutputPort ,
lv2:ControlPort ;
lv2:index 13;
lv2:symbol "position2" ;
rdfs:comment "Time";
lv2:name "\u00A0\u00A0\u00A0\u00A0";
units:unit units:pc ;
lv2:default 0.0 ;
lv2:minimum 0.0 ;
lv2:maximum 1.0 ;
pg:group myprefix:loop2_group ;
],
################# Loop3
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 14;
lv2:symbol "control3" ;
lv2:name "MIDI Ctl";
rdfs:comment "Hidden control for MIDI operation. See documentation for details.";
lv2:default 0.0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
lv2:portProperty lv2:integer, lv2:toggled, mod:preferMomentaryOffByDefault, pprop:notOnGUI;
pg:group myprefix:loop3_group ;
],
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 15;
lv2:symbol "stop3" ;
lv2:name "⏹";
rdfs:comment "Reset loop 3.";
lv2:default 0.0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
lv2:portProperty lv2:toggled,pprop:trigger;
pg:group myprefix:loop3_group ;
],
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 16;
lv2:symbol "record3" ;
lv2:name "⏺";
rdfs:comment "Record/Overdub loop 3";
lv2:default 0.0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
lv2:portProperty lv2:toggled,pprop:trigger;
pg:group myprefix:loop3_group ;
],
[
a lv2:OutputPort ,
lv2:ControlPort ;
lv2:index 17;
lv2:symbol "record_led3" ;
lv2:name "";
lv2:portProperty lv2:toggled ;
lv2:default 0.0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
pipedal_ui:ledColor "red";
pg:group myprefix:loop3_group ;
],
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 18;
lv2:symbol "play3" ;
lv2:name "⏵";
rdfs:comment "Play Loop 3. Click again to stop.";
lv2:default 0.0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
lv2:portProperty lv2:toggled,pprop:trigger;
pg:group myprefix:loop3_group ;
],
[
a lv2:OutputPort ,
lv2:ControlPort ;
lv2:index 19;
lv2:symbol "play_led3" ;
lv2:name "";
lv2:portProperty lv2:toggled ;
lv2:default 0.0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
pipedal_ui:ledColor "green";
pg:group myprefix:loop3_group ;
],
[
a lv2:OutputPort ,
lv2:ControlPort ;
lv2:index 20;
lv2:symbol "position3" ;
rdfs:comment "Time";
lv2:name "\u00A0\u00A0\u00A0\u00A0";
units:unit units:pc ;
lv2:default 0.0 ;
lv2:minimum 0.0 ;
lv2:maximum 1.0 ;
pg:group myprefix:loop3_group ;
],
################# Loop4
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 21;
lv2:symbol "control4" ;
lv2:name "Midi Ctl";
rdfs:comment "Hidden control for MIDI operation. See documentation for details.";
lv2:default 0.0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
lv2:portProperty lv2:integer, lv2:toggled, mod:preferMomentaryOffByDefault, pprop:notOnGUI;
pg:group myprefix:loop4_group ;
],
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 22;
lv2:symbol "stop4" ;
lv2:name "⏹";
rdfs:comment "Reset loop 4.";
lv2:default 0.0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
lv2:portProperty lv2:toggled,pprop:trigger;
pg:group myprefix:loop4_group ;
],
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 23;
lv2:symbol "record4" ;
lv2:name "⏺";
rdfs:comment "Record/Overdub loop 4";
lv2:default 0.0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
lv2:portProperty lv2:toggled,pprop:trigger;
pg:group myprefix:loop4_group ;
],
[
a lv2:OutputPort ,
lv2:ControlPort ;
lv2:index 24;
lv2:symbol "record_led4" ;
lv2:name "";
lv2:portProperty lv2:toggled ;
lv2:default 0.0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
pipedal_ui:ledColor "red";
pg:group myprefix:loop4_group ;
],
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 25;
lv2:symbol "play4" ;
lv2:name "⏵";
rdfs:comment "Play Loop 4. Click again to stop.";
lv2:default 0.0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
lv2:portProperty lv2:toggled,pprop:trigger;
pg:group myprefix:loop4_group ;
],
[
a lv2:OutputPort ,
lv2:ControlPort ;
lv2:index 26;
lv2:symbol "play_led4" ;
lv2:name "";
lv2:portProperty lv2:toggled ;
lv2:default 0.0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
pipedal_ui:ledColor "green";
pg:group myprefix:loop4_group ;
],
[
a lv2:OutputPort ,
lv2:ControlPort ;
lv2:index 27;
lv2:symbol "position4" ;
rdfs:comment "Time";
lv2:name "\u00A0\u00A0\u00A0\u00A0";
units:unit units:pc ;
lv2:default 0.0 ;
lv2:minimum 0.0 ;
lv2:maximum 1.0 ;
pg:group myprefix:loop4_group ;
],
###### Sync
[
a lv2:OutputPort ,
lv2:ControlPort ;
lv2:index 28;
lv2:symbol "bar_led" ;
lv2:name "\u00A0\u00A0Bar\u00A0\u00A0";
lv2:portProperty lv2:toggled ;
lv2:default 0.0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
pipedal_ui:ledColor "red";
pg:group myprefix:syncGroup ;
],
[
a lv2:OutputPort ,
lv2:ControlPort ;
lv2:index 29;
lv2:symbol "beat_led" ;
lv2:name "\u00A0Beat\u00A0";
lv2:portProperty lv2:toggled ;
lv2:default 0.0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
pipedal_ui:ledColor "red";
pg:group myprefix:syncGroup ;
],
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 30;
lv2:symbol "tempo" ;
lv2:name "Tempo";
lv2:default 120.0 ;
lv2:minimum 40.0;
lv2:maximum 240.0;
units:unit units:bpm;
rdfs:comment "Tempo in quarter-notes per minute"
; pg:group myprefix:syncGroup
],
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 31 ;
lv2:symbol "timesig" ;
rdfs:comment "Time Signature";
lv2:name "TimeSig";
lv2:default 2 ;
lv2:minimum 0;
lv2:maximum 5;
lv2:portProperty lv2:enumeration ;
lv2:scalePoint [
rdfs:label "2/2" ;
rdf:value 0
] , [
rdfs:label "3/4" ;
rdf:value 1
] , [
rdfs:label "4/4" ;
rdf:value 2
] ,
[
rdfs:label "5/4" ;
rdf:value 3
] ,
[
rdfs:label "6/8" ;
rdf:value 4
] ,
[
rdfs:label "7/4" ;
rdf:value 5
];
pg:group myprefix:syncGroup
],
########## Options
[
lv2:name "Count In" ;
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 32;
lv2:symbol "rec_count_in" ;
lv2:default 1.0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
lv2:portProperty lv2:toggled;
rdfs:comment "Whether to count in when starting the main loop.";
pg:group myprefix:options_group ;
],
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 33 ;
lv2:symbol "bars" ;
lv2:name "Bars";
lv2:default 0.0 ;
lv2:minimum 0;
lv2:maximum 32;
units:unit units:bar ;
lv2:portProperty lv2:integer;
rdfs:comment "Loop length in bars. Set to minimum for arbitrary length loops.";
pg:group myprefix:options_group ;
lv2:scalePoint [
rdfs:label "Free" ;
rdf:value 0.0
]
],
[
lv2:name "Rec Sync" ;
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 34;
lv2:symbol "rec_sync_option" ;
lv2:default 0.0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
lv2:portProperty lv2:toggled;
rdfs:comment "Whether to sync the start of the loop with the main loop when recording secondary loops.";
pg:group myprefix:options_group ;
],
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 35;
lv2:symbol "loop_end_option" ;
lv2:name "On Rec End";
lv2:default 1.0 ;
lv2:minimum 1.0;
lv2:maximum 2.0;
lv2:portProperty lv2:enumeration;
rdfs:comment "(One-control MIDI operation only) Whether to go to OVERDUB or PLAY state when recording of the main loop ends.";
lv2:scalePoint [
rdfs:label "REC->PLAY" ;
rdf:value 1.0
] , [
rdfs:label "REC->DUB" ;
rdf:value 2.0
] ;
pg:group myprefix:options_group ;
],
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 36;
lv2:symbol "level" ;
lv2:name "Level";
lv2:name "Level";
pg:group myprefix:output_group ;
lv2:default 0.0 ;
lv2:minimum -60.0;
lv2:maximum 30.0;
lv2:scalePoint [
rdfs:label "-INF" ;
rdf:value -60.0
];
units:unit units:db
],
################# Audio/Control Busses
[
a lv2:AudioPort ,
lv2:InputPort ;
lv2:index 37 ;
lv2:symbol "in" ;
lv2:name "In";
pg:group myprefix:stereoInGroup ;
lv2:designation pg:left
],
[
a lv2:AudioPort ,
lv2:OutputPort ;
lv2:index 38 ;
lv2:symbol "out" ;
lv2:name "Out" ;
pg:group myprefix:stereoOutGroup ;
lv2:designation pg:left
],
[
a atom:AtomPort ,
lv2:InputPort ;
lv2:index 39 ;
atom:bufferType atom:Sequence ;
atom:supports patch:Message;
lv2:symbol "controlIn" ;
lv2:name "ControlIn"
],
[
a atom:AtomPort ,
lv2:OutputPort ;
lv2:index 40 ;
atom:bufferType atom:Sequence ;
atom:supports patch:Message;
lv2:symbol "controlOut" ;
lv2:name "ControlOut"
],
[
a lv2:AudioPort ,
lv2:InputPort ;
lv2:index 41;
lv2:symbol "inR" ;
lv2:name "InR" ;
pg:group myprefix:stereoInGroup ;
lv2:designation pg:right
],
[
a lv2:AudioPort ,
lv2:OutputPort ;
lv2:index 42 ;
lv2:symbol "outR" ;
lv2:name "OutR" ;
pg:group myprefix:stereoOutGroup ;
lv2:designation pg:right
]
;
.
<http://two-play.com/plugins/toob-looper-four-ui>
a ui:X11UI ;
lv2:binary <ToobAmpUI.so>;
lv2:extensionData ui:resize ;
lv2:extensionData ui:idleInterface ;
lv2:requiredFeature ui:idleInterface ;
.
+606
View File
@@ -0,0 +1,606 @@
@prefix doap: <http://usefulinc.com/ns/doap#> .
@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix units: <http://lv2plug.in/ns/extensions/units#> .
@prefix urid: <http://lv2plug.in/ns/ext/urid#> .
@prefix atom: <http://lv2plug.in/ns/ext/atom#> .
@prefix midi: <http://lv2plug.in/ns/ext/midi#> .
@prefix epp: <http://lv2plug.in/ns/ext/port-props#> .
@prefix idpy: <http://harrisonconsoles.com/lv2/inlinedisplay#> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix mod: <http://moddevices.com/ns/mod#> .
@prefix param: <http://lv2plug.in/ns/ext/parameters#> .
@prefix work: <http://lv2plug.in/ns/ext/worker#> .
@prefix pg: <http://lv2plug.in/ns/ext/port-groups#> .
@prefix atom: <http://lv2plug.in/ns/ext/atom#> .
@prefix patch: <http://lv2plug.in/ns/ext/patch#> .
@prefix state: <http://lv2plug.in/ns/ext/state#> .
@prefix urid: <http://lv2plug.in/ns/ext/urid#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix ui: <http://lv2plug.in/ns/extensions/ui#> .
@prefix uiext: <http://lv2plug.in/ns/extensions/ui#> .
@prefix pprop: <http://lv2plug.in/ns/ext/port-props#> .
@prefix pipedal_ui: <http://github.com/rerdavies/pipedal/ui#> .
@prefix myprefix: <http://two-play.com/plugins/toob-looper-one#> .
myprefix:stereoInGroup
a pg:StereoGroup, pg:InputGroup ;
rdfs:label "Stereo Input" ;
lv2:symbol "in_g" .
myprefix:steroOutGroup a pg:Group ;
a pg:StereoGroup, pg:OuputGroup ;
rdfs:label "Stereo Output" ;
lv2:symbol "out_g" .
myprefix:syncGroup
a pg:ControlGroup ;
lv2:name "Clock" ;
lv2:symbol "sync_g" .
myprefix:loop_main_group
a pg:ControlGroup ;
lv2:name "Control" ;
lv2:symbol "loop_main_group" .
myprefix:options_group
a pg:ControlGroup ;
lv2:name "Record Options" ;
lv2:symbol "options_group" .
myprefix:output_group
a pg:ControlGroup ;
lv2:name "Output" ;
lv2:symbol "output_group" .
<http://two-play.com/rerdavies#me>
a foaf:Person ;
foaf:name "Robin Davies" ;
foaf:mbox <mailto:rerdavies@gmail.com> ;
foaf:homepage <https://github.com/sponsors/rerdavies> .
<http://two-play.com/plugins/toob-looper-one>
a lv2:Plugin ,
lv2:UtilityPlugin ;
doap:name "TooB One-Button Looper (stereo)"
;
doap:license <https://opensource.org/license/mit/> ;
doap:maintainer <http://two-play.com/rerdavies#me> ;
lv2:minorVersion 1 ;
lv2:microVersion 58 ;
ui:ui <http://two-play.com/plugins/toob-looper-one-ui>;
lv2:extensionData state:interface ;
rdfs:comment """
## TooB One-Button Looper.
TooB One-Button Looper is designed to be controlled by a single MIDI foot controller. If you will be controlling your looper from a screen user-interface, use Toob 4Looper instead.
### Basic Operation
To use the One-Button Looper with PiPedal, bind a MIDI foot switch to the control port using the PiPedal MIDI Bindings user-interface. It's easiest to configure
the MIDI foot controller to send Note-On/Note-Off midi messages, since the control values that a MIDI foot controller sends may not be consistent with what the
One-Button Looper expects. However, if you must use a MIDI foot controller that sends Control Change messages, then you must configure the MIDI foot controller
to send a CC value of zero when not pressed, and a non-zero value when pressed.
Loop overdubs are stored in a stack, so that they can be erased one at a time. To erase the most recent overdub, and return to the previous state of the loop,
long-press the MIDI controller (or the Control button if you are using the PiPedal user interface). A long-press is a press of at least 1/2 second, but
less than two seconds. The current loop will be undone when you release the control. To stop looping altogether, press the MIDI foot controller (or the Control button) for at least two seconds. The looper will stop when you
release the control.
### Clock Options
Clock options determine the tempo and number of beats in a bar. They affect the behavior of the looper when the Bars control (see below) is set to
a numeric value, and also affect the rate of the flashing LEDs when counting in.
### Record Options
Record Options control the behavior of the looper.
When Count In is enabled, The looper will Count In before starting the main loop. The Record LED will flash when counting in, and go solid
once recording starts. The pattern of blinking lights depends on the TimeSig setting, so for example, if the Time Signature is set to 4/4, the
blinking LED will signal a count-in pattern of "1 - 2 - 1 2 3 4".
When Bars is set to Free (the minimum value), the length of the main loop will be set by the second tap of the
Control button after recording of the main loop starts. If Bars is set to a numeric value, the length of the main loop will be determined by the number
of bars set in the Bars control, and the current settings of the Clock controls.
If Dub Sync is off, overdubs will start recording as soon as you tap the Control button. If enabled, the start
of the secondary loop will sync with main loop. Tapping the Control button will put the looper in "Cue Overdub" state
and the LEDs will flash until the end of the main loop is reached, at which point the new loop will start recording.
The Loop End option only has effect when the Bars control is set to a numeric value, and does nothing if Bars is set to "Free".
When set to REC-PLAY, the main loop will record exactly N bars of audio, and switch to play mode when the end of the loop is reached.
When set to REC-DUB, the main loop will record exactly N bars of audio, and then continue on in overdub mode.
### Looper State Table
```
+-----------+--------------+----------------------------------+
| State | Action | Effect |
|-----------|--------------|----------------------------------|
| Empty | Tap | Start counting in if COUNT IN is |
| | | enabled; otherwise start |
| | | recording immediately. |
|-----------|--------------|----------------------------------|
| Count-In | Tap/ | Return to empty state |
| | Long-press | |
| | | |
| | Complete | Start recording |
|-----------|--------------|----------------------------------|
| Recording | Tap | Set the loop length and go to |
| | | play state. |
| | | |
| | Long-press | Discard the current loop and |
| | | return to Empty state |
| | | |
| | End of loop | go to play or overdub state |
| | | depending on ON REC END |
|-----------|--------------|----------------------------------|
| Playing | Tap | If DUB SYNC is on, go to |
| | | Cue Ovdb state; otherwise |
| | | start overdubbing immediately. |
| | | |
| | Long-press | Undo the most recent |
| | | overdub and go to play |
| | | state. |
|-----------|--------------|----------------------------------|
| Cue Ovdb | End-of-loop | Start overdubbing. |
| | | |
| | Tap | Cancel the pending overdub. |
| | | |
| | Long-press | Cancel the pending overdub. |
|-----------|--------------|----------------------------------|
| Overdub | Tap | Start playing. |
| | | |
| | End of loop | (If DUB SYNC is on, and |
| | | REC->PLAY is selected) Go to |
| | | play state, otherwise, continue |
| | | in overdub state. |
+-----------|--------------|----------------------------------+
```
""" ;
mod:brand "TooB";
mod:label "One-Looper";
lv2:optionalFeature lv2:hardRTCapable;
lv2:port
################# MAIN Loop
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 0;
lv2:symbol "control" ;
lv2:name "";
rdfs:comment "Looper control. See the plugin documentation for details.";
lv2:default 0.0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
lv2:portProperty lv2:integer, lv2:toggled, mod:preferMomentaryOffByDefault;
pg:group myprefix:loop_main_group ;
],
[
a lv2:OutputPort ,
lv2:ControlPort ;
lv2:index 1;
lv2:symbol "record_led" ;
lv2:name "";
lv2:portProperty lv2:toggled ;
lv2:default 0.0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
pipedal_ui:ledColor "red";
pg:group myprefix:loop_main_group ;
],
[
a lv2:OutputPort ,
lv2:ControlPort ;
lv2:index 2 ;
lv2:symbol "play_led" ;
lv2:name "";
lv2:portProperty lv2:toggled ;
lv2:default 0.0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
pg:group myprefix:loop_main_group ;
pipedal_ui:ledColor "green";
],
[
a lv2:OutputPort ,
lv2:ControlPort ;
lv2:index 3;
lv2:symbol "position" ;
rdfs:comment "Loop position";
lv2:name "\u00A0\u00A0\u00A0\u00A0";
units:unit units:pc ;
lv2:default 0.0 ;
lv2:minimum 0.0 ;
lv2:maximum 1.0 ;
pg:group myprefix:loop_main_group ;
],
[
a lv2:OutputPort ,
lv2:ControlPort ;
lv2:index 4;
lv2:symbol "loop_level" ;
rdfs:comment "Loop Level";
lv2:name "\u00A0\u00A0\u00A0\u00A0";
lv2:default 0.0 ;
lv2:minimum 0.0 ;
lv2:maximum 21.0 ;
pg:group myprefix:loop_main_group ;
lv2:portProperty lv2:enumeration ;
lv2:scalePoint [
rdfs:label "-" ;
rdf:value 0.0
] ,
[
rdfs:label "1" ;
rdf:value 1.0
],
[
rdfs:label "2" ;
rdf:value 2.0
],
[
rdfs:label "3" ;
rdf:value 3.0
],
[
rdfs:label "4" ;
rdf:value 4.0
],
[
rdfs:label "5" ;
rdf:value 5.0
],
[
rdfs:label "6" ;
rdf:value 6.0
],
[
rdfs:label "7" ;
rdf:value 7.0
],
[
rdfs:label "8" ;
rdf:value 8.0
],
[
rdfs:label "9" ;
rdf:value 9.0
],
[
rdfs:label "10" ;
rdf:value 10.0
],
[
rdfs:label "11" ;
rdf:value 11.0
],
[
rdfs:label "12" ;
rdf:value 12.0
],
[
rdfs:label "13" ;
rdf:value 13.0
],
[
rdfs:label "14" ;
rdf:value 14.0
],
[
rdfs:label "15" ;
rdf:value 15.0
],
[
rdfs:label "16" ;
rdf:value 16.0
],
[
rdfs:label "17" ;
rdf:value 17.0
],
[
rdfs:label "18" ;
rdf:value 18.0
],
[
rdfs:label "19" ;
rdf:value 19.0
],
[
rdfs:label "20" ;
rdf:value 20.0
],
[
rdfs:label "+" ;
rdf:value 21.0
]
;
],
###### Sync
[
a lv2:OutputPort ,
lv2:ControlPort ;
lv2:index 5;
lv2:symbol "bar_led" ;
lv2:name "\u00A0\u00A0Bar\u00A0\u00A0";
lv2:portProperty lv2:toggled ;
lv2:default 0.0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
pipedal_ui:ledColor "red";
pg:group myprefix:syncGroup ;
],
[
a lv2:OutputPort ,
lv2:ControlPort ;
lv2:index 6;
lv2:symbol "beat_led" ;
lv2:name "\u00A0Beat\u00A0";
lv2:portProperty lv2:toggled ;
lv2:default 0.0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
pipedal_ui:ledColor "red";
pg:group myprefix:syncGroup ;
],
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 7;
lv2:symbol "tempo" ;
lv2:name "Tempo";
lv2:default 120.0 ;
lv2:minimum 40.0;
lv2:maximum 240.0;
units:unit units:bpm;
rdfs:comment "Tempo in quarter-notes per minute"
; pg:group myprefix:syncGroup
],
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 8;
lv2:symbol "timesig" ;
rdfs:comment "Time Signature";
lv2:name "TimeSig";
lv2:default 2 ;
lv2:minimum 0;
lv2:maximum 5;
lv2:portProperty lv2:enumeration ;
lv2:scalePoint [
rdfs:label "2/2" ;
rdf:value 0
] , [
rdfs:label "3/4" ;
rdf:value 1
] , [
rdfs:label "4/4" ;
rdf:value 2
] ,
[
rdfs:label "5/4" ;
rdf:value 3
] ,
[
rdfs:label "6/8" ;
rdf:value 4
] ,
[
rdfs:label "7/4" ;
rdf:value 5
];
pg:group myprefix:syncGroup
],
########## Options
[
lv2:name "Count In" ;
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 9;
lv2:symbol "rec_count_in" ;
lv2:default 0.0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
lv2:portProperty lv2:toggled;
rdfs:comment "Whether to count in when starting the main loop.";
pg:group myprefix:options_group ;
],
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 10;
lv2:symbol "bars" ;
lv2:name "Bars";
lv2:default 0.0 ;
lv2:minimum 0.0 ;
lv2:maximum 32.0 ;
units:unit units:bar ;
lv2:portProperty lv2:integer;
rdfs:comment "Loop length in bars. Set to minimum for arbitrary length loops.";
pg:group myprefix:options_group ;
lv2:scalePoint [
rdfs:label "Free" ;
rdf:value 0.0 ;
] ;
],
[
lv2:name "Dub Sync" ;
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 11;
lv2:symbol "rec_sync_option" ;
lv2:default 0.0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
lv2:portProperty lv2:toggled;
rdfs:comment "Whether to sync the start of the loop with the main loop when recording secondary loops.";
pg:group myprefix:options_group ;
],
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 12;
lv2:symbol "loop_end_option" ;
lv2:name "On Rec End";
lv2:default 1.0 ;
lv2:minimum 1.0;
lv2:maximum 2.0;
lv2:portProperty lv2:enumeration;
rdfs:comment "Whether to go to OVERDUB or PLAY state a loop ends.";
lv2:scalePoint [
rdfs:label "REC->PLAY" ;
rdf:value 1.0
] , [
rdfs:label "REC->DUB" ;
rdf:value 2.0
] ;
pg:group myprefix:options_group ;
],
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 13;
lv2:symbol "level" ;
lv2:name "Level";
lv2:name "Level";
pg:group myprefix:output_group ;
lv2:default 0.0 ;
lv2:minimum -60.0;
lv2:maximum 30.0;
lv2:scalePoint [
rdfs:label "-INF" ;
rdf:value -60.0
];
units:unit units:db
],
################# Audio/Control Busses
[
a lv2:AudioPort ,
lv2:InputPort ;
lv2:index 14 ;
lv2:symbol "in" ;
lv2:name "In";
pg:group myprefix:stereoInGroup ;
lv2:designation pg:left
],
[
a lv2:AudioPort ,
lv2:OutputPort ;
lv2:index 15 ;
lv2:symbol "out" ;
lv2:name "Out" ;
pg:group myprefix:stereoOutGroup ;
lv2:designation pg:left
],
[
a atom:AtomPort ,
lv2:InputPort ;
atom:bufferType atom:Sequence ;
atom:supports patch:Message;
lv2:index 16 ;
lv2:symbol "controlIn" ;
lv2:name "ControlIn"
],
[
a atom:AtomPort ,
lv2:OutputPort ;
atom:bufferType atom:Sequence ;
atom:supports patch:Message;
lv2:index 17 ;
lv2:symbol "controlOut" ;
lv2:name "ControlOut"
],
[
a lv2:AudioPort ,
lv2:InputPort ;
lv2:index 18;
lv2:symbol "inR" ;
lv2:name "InR" ;
pg:group myprefix:stereoInGroup ;
lv2:designation pg:right
],
[
a lv2:AudioPort ,
lv2:OutputPort ;
lv2:index 19 ;
lv2:symbol "outR" ;
lv2:name "OutR" ;
pg:group myprefix:stereoOutGroup ;
lv2:designation pg:right
]
;
.
<http://two-play.com/plugins/toob-looper-one-ui>
a ui:X11UI ;
lv2:binary <ToobAmpUI.so>;
lv2:extensionData ui:resize ;
lv2:extensionData ui:idleInterface ;
lv2:requiredFeature ui:idleInterface ;
.
@@ -0,0 +1,726 @@
@prefix doap: <http://usefulinc.com/ns/doap#> .
@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix units: <http://lv2plug.in/ns/extensions/units#> .
@prefix urid: <http://lv2plug.in/ns/ext/urid#> .
@prefix atom: <http://lv2plug.in/ns/ext/atom#> .
@prefix midi: <http://lv2plug.in/ns/ext/midi#> .
@prefix epp: <http://lv2plug.in/ns/ext/port-props#> .
@prefix uiext: <http://lv2plug.in/ns/extensions/ui#> .
@prefix idpy: <http://harrisonconsoles.com/lv2/inlinedisplay#> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix mod: <http://moddevices.com/ns/mod#> .
@prefix param: <http://lv2plug.in/ns/ext/parameters#> .
@prefix work: <http://lv2plug.in/ns/ext/worker#> .
@prefix pg: <http://lv2plug.in/ns/ext/port-groups#> .
@prefix atom: <http://lv2plug.in/ns/ext/atom#> .
@prefix patch: <http://lv2plug.in/ns/ext/patch#> .
@prefix state: <http://lv2plug.in/ns/ext/state#> .
@prefix urid: <http://lv2plug.in/ns/ext/urid#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix ui: <http://lv2plug.in/ns/extensions/ui#> .
@prefix pprop: <http://lv2plug.in/ns/ext/port-props#> .
@prefix pipedal_ui: <http://github.com/rerdavies/pipedal/ui#> .
@prefix looperPrefix: <http://two-play.com/plugins/toob-looper#> .
@prefix myprefix: <http://two-play.com/plugins/toob-looper-stereo#> .
myprefix:stereoInGroup
a pg:StereoGroup, pg:InputGroup ;
rdfs:label "Stereo Input" ;
lv2:symbol "in_g" .
myprefix:steroOutGroup a pg:Group ;
a pg:StereoGroup, pg:OuputGroup ;
rdfs:label "Stereo Output" ;
lv2:symbol "out_g" .
myprefix:syncGroup
a pg:ControlGroup ;
lv2:name "Clock" ;
lv2:symbol "sync_g" .
myprefix:loop_main_group
a pg:ControlGroup ;
lv2:name "Main Loop" ;
lv2:symbol "loop_main_group" .
myprefix:loop2_group
a pg:ControlGroup ;
lv2:name "Loop 2" ;
lv2:symbol "loop2_group" .
myprefix:loop3_group
a pg:ControlGroup ;
lv2:name "Loop 3" ;
lv2:symbol "loop3_group" .
myprefix:loop4_group
a pg:ControlGroup ;
lv2:name "Loop 4" ;
lv2:symbol "loop4_group" .
myprefix:options_group
a pg:ControlGroup ;
lv2:name "Options" ;
lv2:symbol "options_group" .
myprefix:output_group
a pg:ControlGroup ;
lv2:name "Output" ;
lv2:symbol "output_group" .
<http://two-play.com/rerdavies#me>
a foaf:Person ;
foaf:name "Robin Davies" ;
foaf:mbox <mailto:rerdavies@gmail.com> ;
foaf:homepage <https://github.com/sponsors/rerdavies> .
<http://two-play.com/plugins/toob-looper-stereo>
a lv2:Plugin ,
lv2:UtilityPlugin ;
doap:name "TooB 4Looper (stereo)"
;
doap:license <https://opensource.org/license/mit/> ;
doap:maintainer <http://two-play.com/rerdavies#me> ;
lv2:minorVersion 1 ;
lv2:microVersion 57 ;
ui:ui <http://two-play.com/plugins/toob-looper-stereo-ui>;
patch:readable
looperPrefix:audioFile;
patch:writable
looperPrefix:audioFile;
lv2:extensionData state:interface ;
rdfs:comment """
A Stereo Looper.
- A single tap on the bound midi controller will start recording.
- A second tap with mark the end of the loop, and start playback.
- Subsequent taps will toggle overdub mode. When overdubbing, new audio input will be blended with the existing loop.
- A touble tap will stop playback.
- To erase an overdub, long press the MIDI controller. The loop will return to the state that it was in before the overdub was made.
""" ;
mod:brand "TooB";
mod:label "4Looper";
lv2:optionalFeature lv2:hardRTCapable;
lv2:port
################# MAIN Loop
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 0;
lv2:symbol "stop1" ;
lv2:name "⏹";
rdfs:comment "Reset loop 1.";
lv2:default 0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
lv2:portProperty lv2:toggled,pprop:trigger;
pg:group myprefix:loop_main_group ;
],
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 1;
lv2:symbol "record1" ;
lv2:name "⏺";
rdfs:comment "Record/Overdub loop 1";
lv2:default 0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
lv2:portProperty lv2:toggled,pprop:trigger;
pg:group myprefix:loop_main_group ;
],
[
a lv2:OutputPort ,
lv2:ControlPort ;
lv2:index 2;
lv2:symbol "record_led1" ;
lv2:name "";
lv2:portProperty lv2:toggled ;
lv2:default 0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
pipedal_ui:ledColor "red";
pg:group myprefix:loop_main_group ;
],
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 3;
lv2:symbol "play1" ;
lv2:name "⏵";
rdfs:comment "Play Loop 1. Click again to stop.";
lv2:default 0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
lv2:portProperty lv2:toggled,pprop:trigger;
pg:group myprefix:loop_main_group ;
],
[
a lv2:OutputPort ,
lv2:ControlPort ;
lv2:index 4;
lv2:symbol "play_led1" ;
lv2:name "";
lv2:portProperty lv2:toggled ;
lv2:default 0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
pipedal_ui:ledColor "green";
pg:group myprefix:loop_main_group ;
],
[
a lv2:OutputPort ,
lv2:ControlPort ;
lv2:index 5;
lv2:symbol "position1" ;
rdfs:comment "Time";
lv2:name "\u00A0\u00A0\u00A0\u00A0";
units:unit units:pc ;
lv2:default 0.0 ;
lv2:minimum 0.0 ;
lv2:maximum 100.0 ;
pg:group myprefix:loop_main_group ;
],
################# Loop2
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 6;
lv2:symbol "stop2" ;
lv2:name "⏹";
rdfs:comment "Reset loop 2.";
lv2:default 0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
lv2:portProperty lv2:toggled,pprop:trigger;
pg:group myprefix:loop2_group ;
],
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 7;
lv2:symbol "record2" ;
lv2:name "⏺";
rdfs:comment "Record/Overdub loop 2";
lv2:default 0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
lv2:portProperty lv2:toggled,pprop:trigger;
pg:group myprefix:loop2_group ;
],
[
a lv2:OutputPort ,
lv2:ControlPort ;
lv2:index 8;
lv2:symbol "record_led2" ;
lv2:name "";
lv2:portProperty lv2:toggled ;
lv2:default 0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
pipedal_ui:ledColor "red";
pg:group myprefix:loop2_group ;
],
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 9;
lv2:symbol "play2" ;
lv2:name "⏵";
rdfs:comment "Play Loop 2. Click again to stop.";
lv2:default 0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
lv2:portProperty lv2:toggled,pprop:trigger;
pg:group myprefix:loop2_group ;
],
[
a lv2:OutputPort ,
lv2:ControlPort ;
lv2:index 10;
lv2:symbol "play_led2" ;
lv2:name "";
lv2:portProperty lv2:toggled ;
lv2:default 0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
pipedal_ui:ledColor "green";
pg:group myprefix:loop2_group ;
],
[
a lv2:OutputPort ,
lv2:ControlPort ;
lv2:index 11;
lv2:symbol "position2" ;
rdfs:comment "Time";
lv2:name "\u00A0\u00A0\u00A0\u00A0";
units:unit units:pc ;
lv2:default 0.0 ;
lv2:minimum 0.0 ;
lv2:maximum 100.0 ;
pg:group myprefix:loop2_group ;
],
################# Loop3
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 12;
lv2:symbol "stop3" ;
lv2:name "⏹";
rdfs:comment "Reset loop 3.";
lv2:default 0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
lv2:portProperty lv2:toggled,pprop:trigger;
pg:group myprefix:loop3_group ;
],
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 13;
lv2:symbol "record3" ;
lv2:name "⏺";
rdfs:comment "Record/Overdub loop 3";
lv2:default 0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
lv2:portProperty lv2:toggled,pprop:trigger;
pg:group myprefix:loop3_group ;
],
[
a lv2:OutputPort ,
lv2:ControlPort ;
lv2:index 14;
lv2:symbol "record_led3" ;
lv2:name "";
lv2:portProperty lv2:toggled ;
lv2:default 0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
pipedal_ui:ledColor "red";
pg:group myprefix:loop3_group ;
],
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 15;
lv2:symbol "play3" ;
lv2:name "⏵";
rdfs:comment "Play Loop 3. Click again to stop.";
lv2:default 0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
lv2:portProperty lv2:toggled,pprop:trigger;
pg:group myprefix:loop3_group ;
],
[
a lv2:OutputPort ,
lv2:ControlPort ;
lv2:index 16;
lv2:symbol "play_led3" ;
lv2:name "";
lv2:portProperty lv2:toggled ;
lv2:default 0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
pipedal_ui:ledColor "green";
pg:group myprefix:loop3_group ;
],
[
a lv2:OutputPort ,
lv2:ControlPort ;
lv2:index 17;
lv2:symbol "position3" ;
rdfs:comment "Time";
lv2:name "\u00A0\u00A0\u00A0\u00A0";
units:unit units:pc ;
lv2:default 0.0 ;
lv2:minimum 0.0 ;
lv2:maximum 100.0 ;
pg:group myprefix:loop3_group ;
],
################# Loop4
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 18;
lv2:symbol "stop4" ;
lv2:name "⏹";
rdfs:comment "Reset loop 4.";
lv2:default 0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
lv2:portProperty lv2:toggled,pprop:trigger;
pg:group myprefix:loop4_group ;
],
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 19;
lv2:symbol "record4" ;
lv2:name "⏺";
rdfs:comment "Record/Overdub loop 4";
lv2:default 0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
lv2:portProperty lv2:toggled,pprop:trigger;
pg:group myprefix:loop4_group ;
],
[
a lv2:OutputPort ,
lv2:ControlPort ;
lv2:index 20;
lv2:symbol "record_led4" ;
lv2:name "";
lv2:portProperty lv2:toggled ;
lv2:default 0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
pipedal_ui:ledColor "red";
pg:group myprefix:loop4_group ;
],
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 21;
lv2:symbol "play4" ;
lv2:name "⏵";
rdfs:comment "Play Loop 4. Click again to stop.";
lv2:default 0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
lv2:portProperty lv2:toggled,pprop:trigger;
pg:group myprefix:loop4_group ;
],
[
a lv2:OutputPort ,
lv2:ControlPort ;
lv2:index 22;
lv2:symbol "play_led4" ;
lv2:name "";
lv2:portProperty lv2:toggled ;
lv2:default 0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
pipedal_ui:ledColor "green";
pg:group myprefix:loop4_group ;
],
[
a lv2:OutputPort ,
lv2:ControlPort ;
lv2:index 23;
lv2:symbol "position4" ;
rdfs:comment "Time";
lv2:name "\u00A0\u00A0\u00A0\u00A0";
units:unit units:pc ;
lv2:default 0.0 ;
lv2:minimum 0.0 ;
lv2:maximum 100.0 ;
pg:group myprefix:loop4_group ;
],
###### Sync
[
a lv2:OutputPort ,
lv2:ControlPort ;
lv2:index 24;
lv2:symbol "bar_led" ;
lv2:name "\u00A0\u00A0Bar\u00A0\u00A0";
lv2:portProperty lv2:toggled ;
lv2:default 0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
pipedal_ui:ledColor "red";
pg:group myprefix:syncGroup ;
],
[
a lv2:OutputPort ,
lv2:ControlPort ;
lv2:index 25;
lv2:symbol "beat_led" ;
lv2:name "\u00A0Beat\u00A0";
lv2:portProperty lv2:toggled ;
lv2:default 0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
pipedal_ui:ledColor "red";
pg:group myprefix:syncGroup ;
],
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 26;
lv2:symbol "tempo" ;
lv2:name "Tempo";
lv2:default 120.0 ;
lv2:minimum 40.0;
lv2:maximum 240.0;
units:unit units:bpm;
rdfs:comment "Tempo in quarter-notes per minute"
; pg:group myprefix:syncGroup
],
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 27;
lv2:symbol "timesig" ;
rdfs:comment "Time Signature";
lv2:name "TimeSig";
lv2:default 2 ;
lv2:minimum 0;
lv2:maximum 5;
lv2:portProperty lv2:enumeration ;
lv2:scalePoint [
rdfs:label "2/2" ;
rdf:value 0
] , [
rdfs:label "3/4" ;
rdf:value 1
] , [
rdfs:label "4/4" ;
rdf:value 2
] ,
[
rdfs:label "5/4" ;
rdf:value 3
] ,
[
rdfs:label "6/8" ;
rdf:value 4
] ,
[
rdfs:label "7/4" ;
rdf:value 5
];
pg:group myprefix:syncGroup
],
########## Options
[
lv2:name "Count In" ;
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 28;
lv2:symbol "rec_count_in" ;
lv2:default 1.0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
lv2:portProperty lv2:toggled;
rdfs:comment "Whether to count in when starting the main loop.";
pg:group myprefix:options_group ;
],
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 29;
lv2:symbol "bars" ;
lv2:name "Bars";
lv2:default 0 ;
lv2:minimum 0;
lv2:maximum 32;
units:unit units:bar ;
lv2:portProperty lv2:integer;
rdfs:comment "Loop length in bars. Set to minimum for arbitrary length loops.";
pg:group myprefix:options_group ;
lv2:scalePoint [
rdfs:label "Free" ;
rdf:value 0.0
]
],
[
lv2:name "Rec Sync" ;
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 30;
lv2:symbol "rec_sync_option" ;
lv2:default 1.0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
lv2:portProperty lv2:toggled;
rdfs:comment "Whether to sync the start of the loop with the main loop when recording secondary loops.";
pg:group myprefix:options_group ;
],
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 31;
lv2:symbol "loop_end_option" ;
lv2:name "On Rec End";
lv2:default 1.0 ;
lv2:minimum 1.0;
lv2:maximum 2.0;
lv2:portProperty lv2:enumeration;
rdfs:comment "(One-control MIDI operation only) Whether to go to OVERDUB or PLAY state when recording of the main loop ends.";
lv2:scalePoint [
rdfs:label "REC->PLAY" ;
rdf:value 1.0
] , [
rdfs:label "REC->DUB" ;
rdf:value 2.0
] ;
pg:group myprefix:options_group ;
],
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 32;
lv2:symbol "level" ;
lv2:name "Level";
lv2:name "Level";
pg:group myprefix:output_group ;
lv2:default 0 ;
lv2:minimum -60.0;
lv2:maximum 30.0;
lv2:scalePoint [
rdfs:label "-INF" ;
rdf:value -60.0
];
units:unit units:db
],
################# Audio/Control Busses
[
a lv2:AudioPort ,
lv2:InputPort ;
lv2:index 33 ;
lv2:symbol "in" ;
lv2:name "In";
pg:group myprefix:stereoInGroup ;
lv2:designation pg:left
],
[
a lv2:AudioPort ,
lv2:OutputPort ;
lv2:index 34 ;
lv2:symbol "out" ;
lv2:name "Out" ;
pg:group myprefix:stereoOutGroup ;
lv2:designation pg:left
],
[
a atom:AtomPort ,
lv2:InputPort ;
lv2:index 35 ;
lv2:symbol "controlIn" ;
lv2:name "ControlIn"
],
[
a atom:AtomPort ,
lv2:OutputPort ;
lv2:index 36 ;
lv2:symbol "controlOut" ;
lv2:name "ControlOut"
],
[
a lv2:AudioPort ,
lv2:InputPort ;
lv2:index 37;
lv2:symbol "inR" ;
lv2:name "InR" ;
pg:group myprefix:stereoInGroup ;
lv2:designation pg:right
],
[
a lv2:AudioPort ,
lv2:OutputPort ;
lv2:index 38 ;
lv2:symbol "outR" ;
lv2:name "OutR" ;
pg:group myprefix:stereoOutGroup ;
lv2:designation pg:right
]
;
.
<http://two-play.com/plugins/toob-record-stereo-ui>
a ui:X11UI ;
lv2:binary <.so>;
lv2:extensionData ui:resize ;
lv2:extensionData ui:idleInterface ;
lv2:requiredFeature ui:idleInterface ;
.
+4 -2
View File
@@ -15,6 +15,8 @@
@prefix work: <http://lv2plug.in/ns/ext/worker#> .
@prefix pg: <http://lv2plug.in/ns/ext/port-groups#> .
@prefix pipedal_ui: <http://github.com/rerdavies/pipedal/ui#> .
@prefix pipedal_patch: <http://github.com/rerdavies/pipedal/patch#> .
@prefix toob: <http://two-play.com/plugins/toob#> .
@prefix atom: <http://lv2plug.in/ns/ext/atom#> .
@@ -65,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 57 ;
lv2:microVersion 58 ;
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.
@@ -127,7 +129,7 @@ and uses model files from the GuitarML Neural Pi project (https://github.com/Gui
patch:writable
toobml:modelFile;
patch:readable
pipedal_patch:readable
<http://two-play.com/plugins/toob#frequencyResponseVector>
;
@@ -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 57 ;
lv2:microVersion 58 ;
rdfs:comment """
A port of Steven Atkinson's Neural Amp Modeler to LV2.
+266
View File
@@ -0,0 +1,266 @@
@prefix doap: <http://usefulinc.com/ns/doap#> .
@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix units: <http://lv2plug.in/ns/extensions/units#> .
@prefix urid: <http://lv2plug.in/ns/ext/urid#> .
@prefix atom: <http://lv2plug.in/ns/ext/atom#> .
@prefix midi: <http://lv2plug.in/ns/ext/midi#> .
@prefix epp: <http://lv2plug.in/ns/ext/port-props#> .
@prefix uiext: <http://lv2plug.in/ns/extensions/ui#> .
@prefix idpy: <http://harrisonconsoles.com/lv2/inlinedisplay#> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix mod: <http://moddevices.com/ns/mod#> .
@prefix param: <http://lv2plug.in/ns/ext/parameters#> .
@prefix work: <http://lv2plug.in/ns/ext/worker#> .
@prefix pg: <http://lv2plug.in/ns/ext/port-groups#> .
@prefix atom: <http://lv2plug.in/ns/ext/atom#> .
@prefix patch: <http://lv2plug.in/ns/ext/patch#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix state: <http://lv2plug.in/ns/ext/state#> .
@prefix urid: <http://lv2plug.in/ns/ext/urid#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix ui: <http://lv2plug.in/ns/extensions/ui#> .
@prefix pprop: <http://lv2plug.in/ns/ext/port-props#> .
@prefix pipedal_ui: <http://github.com/rerdavies/pipedal/ui#> .
@prefix recordPrefix: <http://two-play.com/plugins/toob-record#> .
@prefix myprefix: <http://two-play.com/plugins/toob-record-mono#> .
<http://two-play.com/rerdavies#me>
a foaf:Person ;
foaf:name "Robin Davies" ;
foaf:mbox <mailto:rerdavies@gmail.com> ;
foaf:homepage <https://github.com/sponsors/rerdavies> .
recordPrefix:audioFile
a lv2:Parameter;
rdfs:label "File";
mod:fileTypes "audiorecording,audio";
rdfs:range atom:Path;
lv2:index 6
.
<http://two-play.com/plugins/toob-record-mono>
a lv2:Plugin ,
lv2:UtilityPlugin ;
doap:name "TooB Record Input (mono)"
;
doap:license <https://opensource.org/license/mit/> ;
doap:maintainer <http://two-play.com/rerdavies#me> ;
lv2:minorVersion 1 ;
lv2:microVersion 58 ;
ui:ui <http://two-play.com/plugins/toob-record-mono-ui>;
patch:readable
recordPrefix:audioFile;
patch:writable
recordPrefix:audioFile;
lv2:extensionData state:interface ;
rdfs:comment """
Record the plugin's audio input signal to a monophonic file. See also: TooB Record Input (stereo), which records a stereo file.
""" ;
mod:brand "TooB";
mod:label "Record Input";
lv2:optionalFeature lv2:hardRTCapable;
lv2:port
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 0;
lv2:symbol "stop" ;
lv2:name "⏹";
rdfs:comment "Stop.";
lv2:default 0.0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
lv2:portProperty lv2:toggled,pprop:trigger;
],
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 1;
lv2:symbol "record" ;
lv2:name "⏺";
rdfs:comment "Start recording. Click again to stop.";
lv2:default 0.0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
lv2:portProperty lv2:toggled,pprop:trigger;
],
[
a lv2:OutputPort ,
lv2:ControlPort ;
lv2:index 2;
lv2:symbol "record_led" ;
lv2:name "";
lv2:portProperty lv2:toggled ;
lv2:minimum 0.0;
lv2:maximum 1.0;
pipedal_ui:ledColor "red";
],
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 3;
lv2:symbol "play" ;
lv2:name "⏵";
rdfs:comment "Preview recorded file. Click again to stop.";
lv2:default 0.0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
lv2:portProperty lv2:toggled,pprop:trigger;
],
[
a lv2:OutputPort ,
lv2:ControlPort ;
lv2:index 4;
lv2:symbol "play_led" ;
lv2:name "";
lv2:portProperty lv2:toggled ;
lv2:minimum 0.0;
lv2:maximum 1.0;
pipedal_ui:ledColor "green";
],
[
a lv2:OutputPort ,
lv2:ControlPort ;
lv2:index 5;
lv2:symbol "record_time" ;
rdfs:comment "Time";
lv2:name "";
units:unit units:s ;
lv2:minimum 0.0;
lv2:maximum 1000000.0;
],
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 6;
lv2:symbol "fformat" ;
lv2:name "Format";
rdfs:comment "Recording File Format";
lv2:portProperty lv2:integer, lv2:enumeration ;
lv2:default 0.0 ;
lv2:minimum 0 ;
lv2:maximum 3 ;
lv2:scalePoint [
rdfs:label "WAV" ;
rdf:value 0
],
[
rdfs:label "WAV (float32)" ;
rdf:value 1
],
[
rdfs:label "FLAC" ;
rdf:value 2;
],
[
rdfs:label "MP3" ;
rdf:value 3
]
;
],
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 7;
lv2:symbol "level" ;
lv2:name "Level";
rdfs:comment "Input trim level for recording";
lv2:default 0.0 ;
lv2:minimum -60.0;
lv2:maximum 30.0;
lv2:scalePoint [
rdfs:label "-INF" ;
rdf:value -60.0
];
units:unit units:db
],
[
a lv2:OutputPort ,
lv2:ControlPort ;
lv2:index 8 ;
lv2:symbol "level_vu" ;
lv2:name "";
rdfs:comment "Recording level";
lv2:default -60 ;
lv2:minimum -60 ;
lv2:maximum 20 ;
units:unit units:db
],
[
a lv2:AudioPort ,
lv2:InputPort ;
lv2:index 9 ;
lv2:symbol "in" ;
lv2:name "In"
],
[
a lv2:AudioPort ,
lv2:OutputPort ;
lv2:index 10 ;
lv2:symbol "out" ;
lv2:name "Out"
],
[
a atom:AtomPort ,
lv2:InputPort ;
lv2:index 11 ;
atom:bufferType atom:Sequence ;
atom:supports patch:Message;
lv2:designation lv2:control ;
lv2:symbol "controlIn" ;
lv2:name "ControlIn"
],
[
a atom:AtomPort ,
lv2:OutputPort ;
lv2:index 12 ;
atom:bufferType atom:Sequence ;
atom:supports patch:Message;
lv2:designation lv2:control ;
lv2:symbol "controlOut" ;
lv2:name "ControlOut"
]
.
<http://two-play.com/plugins/toob-record-mono-ui>
a ui:X11UI ;
lv2:binary <ToobAmpUI.so>;
lv2:extensionData ui:resize ;
lv2:extensionData ui:idleInterface ;
lv2:requiredFeature ui:idleInterface ;
ui:portNotification [
ui:plugin <http://two-play.com/plugins/toob-record-mono> ;
lv2:symbol "controlOut" ;
];
.
@@ -0,0 +1,325 @@
@prefix doap: <http://usefulinc.com/ns/doap#> .
@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix units: <http://lv2plug.in/ns/extensions/units#> .
@prefix urid: <http://lv2plug.in/ns/ext/urid#> .
@prefix atom: <http://lv2plug.in/ns/ext/atom#> .
@prefix midi: <http://lv2plug.in/ns/ext/midi#> .
@prefix epp: <http://lv2plug.in/ns/ext/port-props#> .
@prefix uiext: <http://lv2plug.in/ns/extensions/ui#> .
@prefix idpy: <http://harrisonconsoles.com/lv2/inlinedisplay#> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix mod: <http://moddevices.com/ns/mod#> .
@prefix param: <http://lv2plug.in/ns/ext/parameters#> .
@prefix work: <http://lv2plug.in/ns/ext/worker#> .
@prefix pg: <http://lv2plug.in/ns/ext/port-groups#> .
@prefix atom: <http://lv2plug.in/ns/ext/atom#> .
@prefix patch: <http://lv2plug.in/ns/ext/patch#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix state: <http://lv2plug.in/ns/ext/state#> .
@prefix urid: <http://lv2plug.in/ns/ext/urid#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix ui: <http://lv2plug.in/ns/extensions/ui#> .
@prefix pprop: <http://lv2plug.in/ns/ext/port-props#> .
@prefix pipedal_ui: <http://github.com/rerdavies/pipedal/ui#> .
@prefix recordPrefix: <http://two-play.com/plugins/toob-record#> .
@prefix myprefix: <http://two-play.com/plugins/toob-record-stereo#> .
<http://two-play.com/rerdavies#me>
a foaf:Person ;
foaf:name "Robin Davies" ;
foaf:mbox <mailto:rerdavies@gmail.com> ;
foaf:homepage <https://github.com/sponsors/rerdavies> .
recordPrefix:audioFile
a lv2:Parameter;
rdfs:label "File";
mod:fileTypes "audiorecording,audio";
rdfs:range atom:Path;
lv2:index 6
.
myprefix:stereoInGroup
a pg:StereoGroup, pg:InputGroup ;
rdfs:label "Stereo Input" ;
lv2:symbol "in_g" .
myprefix:steroOutGroup a pg:Group ;
a pg:StereoGroup, pg:OuputGroup ;
rdfs:label "Stereo Output" ;
lv2:symbol "out_g" .
myprefix:loop0_group
a param:ControlGroup ,
pg:InputGroup ;
lv2:name "Master" ;
lv2:symbol "loop0_group" .
myprefix:loop1_group
a param:ControlGroup ,
pg:InputGroup ;
lv2:name "1" ;
lv2:symbol "loop1_group" .
myprefix:loop2_group
a param:ControlGroup ,
pg:InputGroup ;
lv2:name "2" ;
lv2:symbol "loop2_group" .
myprefix:loop3_group
a param:ControlGroup ,
pg:InputGroup ;
lv2:name "3" ;
lv2:symbol "loop3_group" .
<http://two-play.com/plugins/toob-record-stereo>
a lv2:Plugin ,
lv2:UtilityPlugin ;
doap:name "TooB Record Input (stereo)"
;
doap:license <https://opensource.org/license/mit/> ;
doap:maintainer <http://two-play.com/rerdavies#me> ;
lv2:minorVersion 1 ;
lv2:microVersion 58 ;
ui:ui <http://two-play.com/plugins/toob-record-stereo-ui>;
patch:readable
recordPrefix:audioFile;
patch:writable
recordPrefix:audioFile;
lv2:extensionData state:interface ;
rdfs:comment """
Record the plugin's audio input signal to a stereophonic file. See also: TooB Record Input (mono), which records a monophonic file.
""" ;
mod:brand "TooB";
mod:label "Record Input";
lv2:optionalFeature lv2:hardRTCapable;
lv2:port
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 0;
lv2:symbol "stop" ;
lv2:name "⏹";
rdfs:comment "Stop.";
lv2:default 0.0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
lv2:portProperty lv2:toggled,pprop:trigger;
],
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 1;
lv2:symbol "record" ;
lv2:name "⏺";
rdfs:comment "Start recording. Click again to stop.";
lv2:default 0.0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
lv2:portProperty lv2:toggled,pprop:trigger;
],
[
a lv2:OutputPort ,
lv2:ControlPort ;
lv2:index 2;
lv2:symbol "record_led" ;
lv2:name "";
lv2:portProperty lv2:toggled ;
lv2:minimum 0.0;
lv2:maximum 1.0;
pipedal_ui:ledColor "red";
],
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 3;
lv2:symbol "play" ;
lv2:name "⏵";
rdfs:comment "Preview the recorded file. Click again to stop.";
lv2:default 0.0 ;
lv2:minimum 0.0;
lv2:maximum 1.0;
lv2:portProperty lv2:toggled,pprop:trigger;
],
[
a lv2:OutputPort ,
lv2:ControlPort ;
lv2:index 4;
lv2:symbol "play_led" ;
lv2:name "";
lv2:portProperty lv2:toggled ;
lv2:minimum 0.0;
lv2:maximum 1.0;
pipedal_ui:ledColor "green";
],
[
a lv2:OutputPort ,
lv2:ControlPort ;
lv2:index 5;
lv2:symbol "record_time" ;
rdfs:comment "Time";
lv2:name "";
units:unit units:s ;
lv2:minimum 0.0;
lv2:maximum 1000000.0;
],
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 6;
lv2:symbol "fformat" ;
lv2:name "Format";
rdfs:comment "Recording File Format";
lv2:portProperty lv2:integer, lv2:enumeration ;
lv2:default 0.0 ;
lv2:minimum 0 ;
lv2:maximum 3 ;
lv2:scalePoint [
rdfs:label "WAV" ;
rdf:value 0
],
[
rdfs:label "WAV (float32)" ;
rdf:value 1
],
[
rdfs:label "FLAC" ;
rdf:value 2;
],
[
rdfs:label "MP3" ;
rdf:value 3
]
;
],
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 7;
lv2:symbol "level" ;
lv2:name "Level";
lv2:name "Input trim level for recording";
lv2:default 0.0 ;
lv2:minimum -60.0;
lv2:maximum 30.0;
lv2:scalePoint [
rdfs:label "-INF" ;
rdf:value -60.0
];
units:unit units:db
],
[
a lv2:OutputPort ,
lv2:ControlPort ;
lv2:index 8 ;
lv2:symbol "level_vu" ;
lv2:name "";
rdfs:comment "Recording level";
lv2:default -60 ;
lv2:minimum -60 ;
lv2:maximum 20 ;
units:unit units:db
],
[
a lv2:AudioPort ,
lv2:InputPort ;
lv2:index 9 ;
lv2:symbol "in" ;
lv2:name "In";
pg:group myprefix:stereoInGroup ;
lv2:designation pg:left
],
[
a lv2:AudioPort ,
lv2:OutputPort ;
lv2:index 10 ;
lv2:symbol "out" ;
lv2:name "Out";
pg:group myprefix:stereoOutGroup ;
lv2:designation pg:left
],
[
a atom:AtomPort ,
lv2:InputPort ;
lv2:index 11 ;
atom:bufferType atom:Sequence ;
atom:supports patch:Message;
lv2:symbol "controlIn" ;
lv2:name "ControlIn"
],
[
a atom:AtomPort ,
lv2:OutputPort ;
lv2:index 12 ;
atom:bufferType atom:Sequence ;
atom:supports patch:Message;
lv2:symbol "controlOut" ;
lv2:name "ControlOut"
],
[
a lv2:AudioPort ,
lv2:InputPort ;
lv2:index 13 ;
lv2:symbol "inR" ;
lv2:name "InR" ;
pg:group myprefix:stereoInGroup ;
lv2:designation pg:right
],
[
a lv2:AudioPort ,
lv2:OutputPort ;
lv2:index 14 ;
lv2:symbol "outR" ;
lv2:name "OutR" ;
pg:group myprefix:stereoOutGroup ;
lv2:designation pg:right
]
.
<http://two-play.com/plugins/toob-record-stereo-ui>
a ui:X11UI ;
lv2:binary <ToobAmpUI.so>;
lv2:extensionData ui:resize ;
lv2:extensionData ui:idleInterface ;
lv2:requiredFeature ui:idleInterface ;
.
+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 57 ;
lv2:microVersion 58 ;
rdfs:comment """
TooB Tuner is a chromatic guitar tuner.
""" ;
+19
View File
@@ -71,6 +71,25 @@
lv2:binary <ToobAmp.so> ;
rdfs:seeAlso <ToobFlangerStereo.ttl> .
<http://two-play.com/plugins/toob-record-mono> a lv2:Plugin ;
lv2:binary <ToobAmp.so> ;
rdfs:seeAlso <ToobRecordMono.ttl> .
<http://two-play.com/plugins/toob-record-stereo> a lv2:Plugin ;
lv2:binary <ToobAmp.so> ;
rdfs:seeAlso <ToobRecordStereo.ttl> .
<http://two-play.com/plugins/toob-looper-four> a lv2:Plugin ;
lv2:binary <ToobAmp.so> ;
rdfs:seeAlso <ToobLooperFour.ttl> .
<http://two-play.com/plugins/toob-looper-one> a lv2:Plugin ;
lv2:binary <ToobAmp.so> ;
rdfs:seeAlso <ToobLooperOne.ttl> .
tpset:toob-flanger-preset-0
a pset:Preset ;
@@ -0,0 +1,108 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="256"
height="36"
viewBox="0 0 67.73333 9.525"
version="1.1"
id="svg5"
inkscape:version="1.2.2 (732a01da63, 2022-12-09, custom)"
sodipodi:docname="ToobCabSimLogo_master.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview7"
pagecolor="#2e2e2e"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
showgrid="false"
inkscape:zoom="1.414909"
inkscape:cx="195.77231"
inkscape:cy="90.465182"
inkscape:window-width="1920"
inkscape:window-height="1008"
inkscape:window-x="1440"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" />
<defs
id="defs2" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<g
aria-label="TooB 4Looper"
id="text236"
style="font-style:italic;font-weight:bold;font-size:5.64444px;line-height:0;font-family:Timana;-inkscape-font-specification:'Timana Bold Italic';fill:#686868;stroke:#7f7f7f;stroke-width:0.285001;stop-color:#000000">
<path
d="m 10.655146,7.1034565 0.654755,-3.1383087 h -0.874888 l 0.191911,-0.8918216 h 2.833509 L 13.262878,3.9651478 H 12.38799 l -0.654756,3.1383087 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path631" />
<path
d="m 14.160346,7.1599009 q -0.575733,0 -0.891822,-0.3104442 Q 12.95808,6.533368 12.95808,5.9576351 q 0,-0.4007552 0.112889,-0.7619994 0.112889,-0.3668886 0.333022,-0.6491106 0.220133,-0.2878665 0.54751,-0.4515552 0.333022,-0.1693332 0.767644,-0.1693332 0.575733,0 0.886177,0.3160886 0.316089,0.3104442 0.316089,0.8861771 0,0.4007553 -0.112889,0.7676439 -0.112889,0.3612442 -0.333022,0.6491106 -0.220133,0.282222 -0.553155,0.4515552 -0.327377,0.1636888 -0.761999,0.1636888 z m 0.118533,-0.8015105 q 0.158044,0 0.282222,-0.1862665 0.124178,-0.191911 0.197555,-0.4797774 0.07338,-0.2935109 0.07338,-0.5983107 0,-0.3668886 -0.237066,-0.3668886 -0.158045,0 -0.282222,0.1919109 -0.124178,0.1862666 -0.197556,0.474133 -0.06773,0.2878665 -0.06773,0.5983107 0,0.3668886 0.231422,0.3668886 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path633" />
<path
d="m 17.586523,7.1599009 q -0.575733,0 -0.891822,-0.3104442 -0.310444,-0.3160887 -0.310444,-0.8918216 0,-0.4007552 0.112889,-0.7619994 0.112889,-0.3668886 0.333022,-0.6491106 0.220133,-0.2878665 0.54751,-0.4515552 0.333022,-0.1693332 0.767644,-0.1693332 0.575733,0 0.886177,0.3160886 0.316089,0.3104442 0.316089,0.8861771 0,0.4007553 -0.112889,0.7676439 -0.112889,0.3612442 -0.333022,0.6491106 -0.220133,0.282222 -0.553155,0.4515552 -0.327377,0.1636888 -0.761999,0.1636888 z m 0.118533,-0.8015105 q 0.158044,0 0.282222,-0.1862665 0.124178,-0.191911 0.197555,-0.4797774 0.07338,-0.2935109 0.07338,-0.5983107 0,-0.3668886 -0.237066,-0.3668886 -0.158045,0 -0.282222,0.1919109 -0.124178,0.1862666 -0.197556,0.474133 -0.06773,0.2878665 -0.06773,0.5983107 0,0.3668886 0.231422,0.3668886 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path635" />
<path
d="m 19.669324,7.1034565 0.85231,-4.0301303 h 1.343377 q 0.649111,0 0.931333,0.2483554 0.282222,0.2483553 0.282222,0.6321773 0,0.4120441 -0.214489,0.6660439 -0.208844,0.2539998 -0.603955,0.3725331 v 0.022578 q 0.242711,0.079022 0.383822,0.282222 0.146755,0.1975554 0.146755,0.4854219 0,0.4684885 -0.220133,0.7619994 -0.214489,0.2935109 -0.581377,0.4289775 -0.361244,0.1298221 -0.8128,0.1298221 z M 21.4699,4.6199028 q 0.282222,0 0.383822,-0.1241777 0.107245,-0.1241776 0.107245,-0.3160886 0,-0.282222 -0.349956,-0.282222 h -0.174977 l -0.163689,0.7224883 z m -0.316088,1.6425321 q 0.248355,0 0.400755,-0.1354666 0.1524,-0.141111 0.1524,-0.3330219 0,-0.191911 -0.09031,-0.282222 -0.09031,-0.095956 -0.321733,-0.095956 h -0.186267 l -0.180622,0.846666 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path637" />
<path
d="m 25.945947,7.1034565 0.163689,-0.7789327 h -1.51271 L 24.738037,5.6189687 26.837768,3.0733262 H 27.83119 L 27.317546,5.5117244 H 27.72959 L 27.560257,6.3245238 H 27.148213 L 26.984524,7.1034565 Z M 25.703236,5.5117244 h 0.575733 l 0.135466,-0.5362218 q 0.02822,-0.095956 0.06209,-0.2144888 0.03387,-0.1241777 0.06209,-0.2257776 0.02822,-0.1072443 0.03951,-0.141111 h -0.02258 q -0.0508,0.090311 -0.141111,0.2370665 -0.09031,0.141111 -0.174977,0.2370665 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path639" />
<path
d="m 27.989234,7.1034565 0.85231,-4.0301303 h 1.078089 l -0.666044,3.1495976 h 1.315154 l -0.186266,0.8805327 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path641" />
<path
d="m 32.307233,7.1599009 q -0.575732,0 -0.891821,-0.3104442 -0.310444,-0.3160887 -0.310444,-0.8918216 0,-0.4007552 0.112888,-0.7619994 0.112889,-0.3668886 0.333022,-0.6491106 0.220134,-0.2878665 0.547511,-0.4515552 0.333022,-0.1693332 0.767644,-0.1693332 0.575733,0 0.886177,0.3160886 0.316089,0.3104442 0.316089,0.8861771 0,0.4007553 -0.112889,0.7676439 -0.112889,0.3612442 -0.333022,0.6491106 -0.220133,0.282222 -0.553155,0.4515552 -0.327378,0.1636888 -0.762,0.1636888 z m 0.118534,-0.8015105 q 0.158044,0 0.282222,-0.1862665 0.124177,-0.191911 0.197555,-0.4797774 0.07338,-0.2935109 0.07338,-0.5983107 0,-0.3668886 -0.237067,-0.3668886 -0.158044,0 -0.282222,0.1919109 -0.124177,0.1862666 -0.197555,0.474133 -0.06773,0.2878665 -0.06773,0.5983107 0,0.3668886 0.231422,0.3668886 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path643" />
<path
d="m 35.73341,7.1599009 q -0.575733,0 -0.891822,-0.3104442 -0.310444,-0.3160887 -0.310444,-0.8918216 0,-0.4007552 0.112889,-0.7619994 0.112888,-0.3668886 0.333022,-0.6491106 0.220133,-0.2878665 0.54751,-0.4515552 0.333022,-0.1693332 0.767644,-0.1693332 0.575733,0 0.886177,0.3160886 0.316089,0.3104442 0.316089,0.8861771 0,0.4007553 -0.112889,0.7676439 -0.112889,0.3612442 -0.333022,0.6491106 -0.220133,0.282222 -0.553155,0.4515552 -0.327378,0.1636888 -0.761999,0.1636888 z m 0.118533,-0.8015105 q 0.158044,0 0.282222,-0.1862665 0.124177,-0.191911 0.197555,-0.4797774 0.07338,-0.2935109 0.07338,-0.5983107 0,-0.3668886 -0.237067,-0.3668886 -0.158044,0 -0.282222,0.1919109 -0.124177,0.1862666 -0.197555,0.474133 -0.06773,0.2878665 -0.06773,0.5983107 0,0.3668886 0.231422,0.3668886 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path645" />
<path
d="m 37.500122,8.4581221 0.948266,-4.476041 h 0.852311 l -0.03387,0.3499553 h 0.02258 q 0.129822,-0.1975554 0.299155,-0.2991554 0.174978,-0.1072443 0.412044,-0.1072443 0.417689,0 0.666044,0.2991553 0.254,0.2991553 0.254,0.8523105 0,0.3894663 -0.1016,0.7619994 -0.09596,0.3668886 -0.276578,0.6660439 -0.180622,0.2991554 -0.440266,0.4797775 -0.259644,0.1749776 -0.581377,0.1749776 -0.208845,0 -0.366889,-0.1072444 Q 38.995899,6.9397677 38.88301,6.7591456 H 38.86043 Q 38.8435,6.9792788 38.81527,7.1937675 38.78705,7.4139007 38.708025,7.7807893 L 38.566921,8.4581221 Z M 39.306343,6.301946 q 0.146755,0 0.265289,-0.1693332 0.118533,-0.1693332 0.186266,-0.4289775 0.07338,-0.2596442 0.07338,-0.5249329 0,-0.3951108 -0.237067,-0.3951108 -0.124177,0 -0.220133,0.1072443 -0.09596,0.1072444 -0.169333,0.2765776 -0.06773,0.1693332 -0.107244,0.3668886 -0.03387,0.191911 -0.03387,0.3725331 0,0.1749776 0.06209,0.2878664 0.06773,0.1072444 0.180622,0.1072444 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path647" />
<path
d="m 42.619632,7.1599009 q -0.592666,0 -0.914399,-0.3273775 Q 41.3835,6.4995014 41.3835,5.9237685 q 0,-0.3838219 0.107244,-0.7394217 0.112889,-0.3612441 0.333022,-0.6434661 0.220133,-0.2822221 0.553155,-0.4459108 0.338667,-0.1693332 0.795866,-0.1693332 0.524933,0 0.824089,0.2370665 0.299155,0.2370665 0.299155,0.6321773 0,0.513644 -0.400755,0.8297327 -0.400756,0.3160886 -1.275644,0.3160886 h -0.163689 v 0.045155 q 0,0.4063997 0.451556,0.4063997 0.237066,0 0.44591,-0.073378 0.214489,-0.073378 0.4572,-0.1975554 v 0.756355 q -0.248355,0.1241777 -0.519288,0.2031998 -0.265289,0.079022 -0.671689,0.079022 z m 0.02258,-1.885243 q 0.361244,0 0.502355,-0.1354666 0.141111,-0.141111 0.141111,-0.282222 0,-0.090311 -0.05644,-0.1467554 -0.05645,-0.062089 -0.174978,-0.062089 -0.124178,0 -0.231422,0.095955 -0.1016,0.095955 -0.169333,0.2427109 -0.06773,0.141111 -0.09031,0.2878665 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path649" />
<path
d="m 44.482298,7.1034565 0.660399,-3.1213754 h 0.852311 l -0.0508,0.5192885 h 0.02258 q 0.197555,-0.333022 0.406399,-0.4515552 0.214489,-0.1241777 0.530578,-0.1241777 0.06209,0 0.129822,0.00564 0.06773,0.00564 0.09031,0.016933 l -0.231422,1.0555104 q -0.05644,-0.028222 -0.146756,-0.045156 -0.09031,-0.016933 -0.191911,-0.016933 -0.248355,0 -0.434622,0.1693332 -0.180622,0.1693332 -0.276577,0.6208884 l -0.293511,1.371599 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path651" />
</g>
<path
id="path1348"
style="color:#000000;fill:#e0e0e0;fill-opacity:0.752941;stroke-width:0.714406;-inkscape-stroke:none"
d="M 5.4193109,1.6360535 C 4.0746261,1.6465667 2.9804856,2.7485866 2.9805103,4.0933129 v 1.5080987 0.00443 0.00406 0.00702 c 0.00324,0.6351315 0.1709081,1.2397841 0.5330952,1.705241 0.091293,0.1173226 0.1960748,0.2241342 0.3126952,0.3186015 V 5.3666133 h 0.00259 V 4.0933129 C 3.8288705,3.2043172 4.5362516,2.4899017 5.4252198,2.4829515 6.3176074,2.4761075 7.0387059,3.1839609 7.0477631,4.0763306 v 0.016982 1.6742295 c 0,0.3851813 -0.1170262,0.6035969 -0.3182329,0.7675243 C 6.5283236,6.6989941 6.2034026,6.8056753 5.769664,6.8056753 H 5.437754 V 8.3957797 H 6.193851 V 7.5229912 C 6.5799202,7.4642455 6.9804539,7.4245038 7.2655789,7.1922063 7.6635843,6.8679419 7.8946602,6.354867 7.8946602,5.7675423 V 4.0933128 4.0693159 4.0682086 C 7.8809586,2.7185401 6.7690097,1.6257071 5.4193109,1.6360535 Z"
sodipodi:nodetypes="ccccccscccccccsssccccsscccc" />
<g
aria-label="B"
id="text1054"
style="font-style:italic;font-weight:900;font-size:6.35px;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke-width:0.285001;stop-color:#000000"
transform="matrix(0.71440613,0,0,0.71440613,-2.144828,0.00813001)">
<path
id="path1085"
style="font-style:normal;-inkscape-font-specification:'Roboto, Heavy';stroke-width:0.285"
d="M 8.865092,5.8580404 V 8.9958333 11.74073 H 9.9533976 V 8.9958333 h 0.7441404 c 0.549837,-0.00413 0.964283,-0.116789 1.243335,-0.3379638 0.281119,-0.223242 0.42168,-0.5560389 0.42168,-0.9983887 0,-0.2439125 -0.06305,-0.4506186 -0.189136,-0.6201172 -0.12609,-0.1694982 -0.306958,-0.2852537 -0.542602,-0.3472656 0.208772,-0.078548 0.366902,-0.2005048 0.474389,-0.3658692 0.107487,-0.1653644 0.161231,-0.3648358 0.161231,-0.598413 0,-0.4051429 -0.151929,-0.7141686 -0.455786,-0.9270752 C 11.508859,4.5878339 11.18123,4.4813802 10.486698,4.4813802 H 9.9533976 c -1.0883054,0 -1.0883056,1.029605 -1.0883056,1.3766602 z m 1.0883056,-0.022757 c 0,-0.3308701 0.1341694,-0.4768142 0.3334184,-0.4952 l 0.199882,-0.018444 c 0.203885,-0.018814 0.420647,0.042375 0.530201,0.127124 0.109553,0.082682 0.164331,0.2191083 0.164331,0.4092774 0,0.1653644 -0.05064,0.2904216 -0.151929,0.3751709 -0.101285,0.08475 -0.270784,0.1281579 -0.508496,0.1302246 H 9.9533976 Z m 0,1.2412875 h 0.7627444 c 0.374137,0.00207 0.561206,0.1912032 0.561206,0.5674073 0,0.1632973 -0.05271,0.2904217 -0.15813,0.381372 -0.105419,0.088883 -0.256315,0.1333252 -0.452686,0.1333252 H 9.9533976 Z"
sodipodi:nodetypes="cccccccsscssczccssscssccsccscscc" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 13 KiB

@@ -0,0 +1,144 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="306"
height="36"
viewBox="0 0 80.962496 9.525"
version="1.1"
id="svg5"
inkscape:version="1.2.2 (732a01da63, 2022-12-09, custom)"
sodipodi:docname="ToobCabSimLogo_master.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview7"
pagecolor="#2e2e2e"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
showgrid="false"
inkscape:zoom="1.414909"
inkscape:cx="195.77231"
inkscape:cy="90.465182"
inkscape:window-width="1920"
inkscape:window-height="1008"
inkscape:window-x="1440"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" />
<defs
id="defs2" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<g
aria-label="TooB One-Button Looper"
id="text236"
style="font-style:italic;font-weight:bold;font-size:5.64444px;line-height:0;font-family:Timana;-inkscape-font-specification:'Timana Bold Italic';fill:#686868;stroke:#7f7f7f;stroke-width:0.285001;stop-color:#000000">
<path
d="m 10.655146,7.1034565 0.654755,-3.1383087 h -0.874888 l 0.191911,-0.8918216 h 2.833509 L 13.262878,3.9651478 H 12.38799 l -0.654756,3.1383087 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path460" />
<path
d="m 14.160346,7.1599009 q -0.575733,0 -0.891822,-0.3104442 Q 12.95808,6.533368 12.95808,5.9576351 q 0,-0.4007552 0.112889,-0.7619994 0.112889,-0.3668886 0.333022,-0.6491106 0.220133,-0.2878665 0.54751,-0.4515552 0.333022,-0.1693332 0.767644,-0.1693332 0.575733,0 0.886177,0.3160886 0.316089,0.3104442 0.316089,0.8861771 0,0.4007553 -0.112889,0.7676439 -0.112889,0.3612442 -0.333022,0.6491106 -0.220133,0.282222 -0.553155,0.4515552 -0.327377,0.1636888 -0.761999,0.1636888 z m 0.118533,-0.8015105 q 0.158044,0 0.282222,-0.1862665 0.124178,-0.191911 0.197555,-0.4797774 0.07338,-0.2935109 0.07338,-0.5983107 0,-0.3668886 -0.237066,-0.3668886 -0.158045,0 -0.282222,0.1919109 -0.124178,0.1862666 -0.197556,0.474133 -0.06773,0.2878665 -0.06773,0.5983107 0,0.3668886 0.231422,0.3668886 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path462" />
<path
d="m 17.586523,7.1599009 q -0.575733,0 -0.891822,-0.3104442 -0.310444,-0.3160887 -0.310444,-0.8918216 0,-0.4007552 0.112889,-0.7619994 0.112889,-0.3668886 0.333022,-0.6491106 0.220133,-0.2878665 0.54751,-0.4515552 0.333022,-0.1693332 0.767644,-0.1693332 0.575733,0 0.886177,0.3160886 0.316089,0.3104442 0.316089,0.8861771 0,0.4007553 -0.112889,0.7676439 -0.112889,0.3612442 -0.333022,0.6491106 -0.220133,0.282222 -0.553155,0.4515552 -0.327377,0.1636888 -0.761999,0.1636888 z m 0.118533,-0.8015105 q 0.158044,0 0.282222,-0.1862665 0.124178,-0.191911 0.197555,-0.4797774 0.07338,-0.2935109 0.07338,-0.5983107 0,-0.3668886 -0.237066,-0.3668886 -0.158045,0 -0.282222,0.1919109 -0.124178,0.1862666 -0.197556,0.474133 -0.06773,0.2878665 -0.06773,0.5983107 0,0.3668886 0.231422,0.3668886 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path464" />
<path
d="m 19.669324,7.1034565 0.85231,-4.0301303 h 1.343377 q 0.649111,0 0.931333,0.2483554 0.282222,0.2483553 0.282222,0.6321773 0,0.4120441 -0.214489,0.6660439 -0.208844,0.2539998 -0.603955,0.3725331 v 0.022578 q 0.242711,0.079022 0.383822,0.282222 0.146755,0.1975554 0.146755,0.4854219 0,0.4684885 -0.220133,0.7619994 -0.214489,0.2935109 -0.581377,0.4289775 -0.361244,0.1298221 -0.8128,0.1298221 z M 21.4699,4.6199028 q 0.282222,0 0.383822,-0.1241777 0.107245,-0.1241776 0.107245,-0.3160886 0,-0.282222 -0.349956,-0.282222 h -0.174977 l -0.163689,0.7224883 z m -0.316088,1.6425321 q 0.248355,0 0.400755,-0.1354666 0.1524,-0.141111 0.1524,-0.3330219 0,-0.191911 -0.09031,-0.282222 -0.09031,-0.095956 -0.321733,-0.095956 h -0.186267 l -0.180622,0.846666 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path466" />
<path
d="m 26.459591,7.1599009 q -0.767644,0 -1.15711,-0.423333 -0.389467,-0.4289775 -0.389467,-1.128888 0,-0.4684886 0.129822,-0.9256882 0.135467,-0.4628441 0.400756,-0.8410216 0.270933,-0.3781775 0.682977,-0.6039551 0.412044,-0.2257776 0.970844,-0.2257776 0.745066,0 1.128888,0.423333 0.383822,0.423333 0.383822,1.128888 0,0.4684886 -0.129823,0.9313326 -0.124177,0.4571997 -0.389466,0.8353772 -0.265289,0.3781775 -0.671688,0.6039551 -0.400756,0.2257776 -0.959555,0.2257776 z m 0.09596,-0.8918215 q 0.270933,0 0.491067,-0.2314221 0.220133,-0.231422 0.344311,-0.615244 0.129822,-0.3838219 0.129822,-0.846666 0,-0.3160887 -0.135467,-0.4910663 -0.129822,-0.1806221 -0.378177,-0.1806221 -0.225778,0 -0.412045,0.1523999 -0.186266,0.1467554 -0.321733,0.3951108 -0.129822,0.2427109 -0.203199,0.5475107 -0.06773,0.2991553 -0.06773,0.6039551 0,0.666044 0.553155,0.666044 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path468" />
<path
d="m 28.847187,7.1034565 0.660399,-3.1213754 h 0.852311 L 30.32603,4.416703 h 0.02258 q 0.1524,-0.2652887 0.3556,-0.3781775 0.208844,-0.1128888 0.502355,-0.1128888 0.293511,0 0.474133,0.1241777 0.180622,0.1185332 0.265289,0.3217331 0.08467,0.1975554 0.08467,0.4402663 0,0.1580443 -0.02258,0.3217331 -0.01693,0.1636887 -0.04516,0.3104442 l -0.349955,1.6594654 h -1.0668 l 0.3556,-1.7046209 q 0.01693,-0.073378 0.03387,-0.1806221 0.01693,-0.1128888 0.01693,-0.2088443 0,-0.1185333 -0.06209,-0.1749777 -0.06209,-0.062089 -0.146755,-0.062089 -0.158045,0 -0.293511,0.1975554 -0.129822,0.191911 -0.214489,0.6095996 l -0.321733,1.5239988 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path470" />
<path
d="m 33.763492,7.1599009 q -0.592666,0 -0.914399,-0.3273775 -0.321733,-0.333022 -0.321733,-0.9087549 0,-0.3838219 0.107244,-0.7394217 0.112889,-0.3612441 0.333022,-0.6434661 0.220133,-0.2822221 0.553155,-0.4459108 0.338666,-0.1693332 0.795866,-0.1693332 0.524933,0 0.824088,0.2370665 0.299156,0.2370665 0.299156,0.6321773 0,0.513644 -0.400756,0.8297327 -0.400755,0.3160886 -1.275643,0.3160886 h -0.163689 v 0.045155 q 0,0.4063997 0.451555,0.4063997 0.237067,0 0.445911,-0.073378 0.214489,-0.073378 0.4572,-0.1975554 v 0.756355 q -0.248356,0.1241777 -0.519289,0.2031998 -0.265288,0.079022 -0.671688,0.079022 z m 0.02258,-1.885243 q 0.361244,0 0.502355,-0.1354666 0.141111,-0.141111 0.141111,-0.282222 0,-0.090311 -0.05644,-0.1467554 -0.05644,-0.062089 -0.174978,-0.062089 -0.124178,0 -0.231422,0.095955 -0.1016,0.095955 -0.169333,0.2427109 -0.06773,0.141111 -0.09031,0.2878665 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path472" />
<path
d="m 35.62616,6.019724 0.174977,-0.8579549 h 1.523999 L 37.150158,6.019724 Z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path474" />
<path
d="m 37.511405,7.1034565 0.85231,-4.0301303 h 1.343377 q 0.649111,0 0.931333,0.2483554 0.282222,0.2483553 0.282222,0.6321773 0,0.4120441 -0.214489,0.6660439 -0.208844,0.2539998 -0.603955,0.3725331 v 0.022578 q 0.242711,0.079022 0.383822,0.282222 0.146755,0.1975554 0.146755,0.4854219 0,0.4684885 -0.220133,0.7619994 -0.214488,0.2935109 -0.581377,0.4289775 -0.361244,0.1298221 -0.812799,0.1298221 z m 1.800576,-2.4835537 q 0.282222,0 0.383822,-0.1241777 0.107245,-0.1241776 0.107245,-0.3160886 0,-0.282222 -0.349956,-0.282222 h -0.174977 l -0.163689,0.7224883 z m -0.316088,1.6425321 q 0.248355,0 0.400755,-0.1354666 0.1524,-0.141111 0.1524,-0.3330219 0,-0.191911 -0.09031,-0.282222 -0.09031,-0.095956 -0.321733,-0.095956 h -0.186267 l -0.180622,0.846666 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path476" />
<path
d="m 42.089052,7.1599009 q -0.287867,0 -0.474133,-0.1185332 Q 41.434297,6.91719 41.34963,6.7139901 41.26496,6.5107903 41.26496,6.2737238 q 0,-0.1580443 0.01693,-0.3217331 0.02258,-0.1636888 0.0508,-0.3104442 l 0.349955,-1.6594654 h 1.066799 l -0.355599,1.6989765 q -0.01693,0.073378 -0.03387,0.1862665 -0.01693,0.1072444 -0.01693,0.2031998 0,0.1185333 0.06209,0.1806221 0.06209,0.056444 0.146756,0.056444 0.141111,0 0.276577,-0.1919109 0.141111,-0.1975554 0.231422,-0.615244 l 0.321734,-1.5183544 h 1.066799 l -0.6604,3.1213754 h -0.85231 l 0.03387,-0.4346219 h -0.02258 q -0.1524,0.2596443 -0.3556,0.3781775 -0.2032,0.1128888 -0.502355,0.1128888 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path478" />
<path
d="m 45.639402,7.1599009 q -0.406399,0 -0.620888,-0.1749776 -0.208844,-0.1806221 -0.208844,-0.5757329 0,-0.1128888 0.02258,-0.2596443 0.02258,-0.1467554 0.04516,-0.2596442 l 0.231422,-1.1063103 h -0.423333 l 0.112889,-0.524933 0.59831,-0.2427109 0.378178,-0.6603995 h 0.711199 l -0.135466,0.6265329 h 0.795866 L 46.97149,4.7835916 h -0.795866 l -0.231422,1.0555103 q -0.01693,0.079022 -0.03387,0.1636888 -0.01129,0.079022 -0.01129,0.1241776 0,0.090311 0.0508,0.1354666 0.0508,0.039511 0.124177,0.039511 0.107245,0 0.237067,-0.033867 0.129822,-0.039511 0.265288,-0.095956 v 0.8015105 q -0.174977,0.084667 -0.406399,0.1354665 -0.225778,0.0508 -0.530578,0.0508 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path480" />
<path
d="m 48.218916,7.1599009 q -0.4064,0 -0.620889,-0.1749776 -0.208844,-0.1806221 -0.208844,-0.5757329 0,-0.1128888 0.02258,-0.2596443 0.02258,-0.1467554 0.04516,-0.2596442 l 0.231422,-1.1063103 h -0.423333 l 0.112889,-0.524933 0.598311,-0.2427109 0.378177,-0.6603995 h 0.7112 l -0.135467,0.6265329 h 0.795866 l -0.174977,0.8015105 h -0.795866 l -0.231422,1.0555103 q -0.01693,0.079022 -0.03387,0.1636888 -0.01129,0.079022 -0.01129,0.1241776 0,0.090311 0.0508,0.1354666 0.0508,0.039511 0.124178,0.039511 0.107244,0 0.237066,-0.033867 0.129822,-0.039511 0.265289,-0.095956 v 0.8015105 q -0.174978,0.084667 -0.4064,0.1354665 -0.225777,0.0508 -0.530577,0.0508 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path482" />
<path
d="m 51.103229,7.1599009 q -0.575733,0 -0.891821,-0.3104442 -0.310445,-0.3160887 -0.310445,-0.8918216 0,-0.4007552 0.112889,-0.7619994 0.112889,-0.3668886 0.333022,-0.6491106 0.220133,-0.2878665 0.547511,-0.4515552 0.333022,-0.1693332 0.767644,-0.1693332 0.575733,0 0.886177,0.3160886 0.316088,0.3104442 0.316088,0.8861771 0,0.4007553 -0.112888,0.7676439 -0.112889,0.3612442 -0.333022,0.6491106 -0.220133,0.282222 -0.553155,0.4515552 -0.327378,0.1636888 -0.762,0.1636888 z m 0.118533,-0.8015105 q 0.158045,0 0.282222,-0.1862665 0.124178,-0.191911 0.197556,-0.4797774 0.07338,-0.2935109 0.07338,-0.5983107 0,-0.3668886 -0.237067,-0.3668886 -0.158044,0 -0.282222,0.1919109 -0.124178,0.1862666 -0.197555,0.474133 -0.06773,0.2878665 -0.06773,0.5983107 0,0.3668886 0.231422,0.3668886 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path484" />
<path
d="m 53.157808,7.1034565 0.6604,-3.1213754 h 0.85231 l -0.03387,0.4346219 h 0.02258 q 0.1524,-0.2652887 0.3556,-0.3781775 0.208844,-0.1128888 0.502355,-0.1128888 0.293511,0 0.474133,0.1241777 0.180622,0.1185332 0.265289,0.3217331 0.08467,0.1975554 0.08467,0.4402663 0,0.1580443 -0.02258,0.3217331 -0.01693,0.1636887 -0.04516,0.3104442 L 55.92358,7.1034565 H 54.856781 L 55.21238,5.3988356 q 0.01693,-0.073378 0.03387,-0.1806221 0.01693,-0.1128888 0.01693,-0.2088443 0,-0.1185333 -0.06209,-0.1749777 -0.06209,-0.062089 -0.146756,-0.062089 -0.158044,0 -0.293511,0.1975554 -0.129822,0.191911 -0.214489,0.6095996 l -0.321733,1.5239988 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path486" />
<path
d="m 58.164424,7.1034565 0.85231,-4.0301303 h 1.078088 l -0.666043,3.1495976 h 1.315154 l -0.186266,0.8805327 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path488" />
<path
d="m 62.482425,7.1599009 q -0.575733,0 -0.891821,-0.3104442 Q 61.28016,6.533368 61.28016,5.9576351 q 0,-0.4007552 0.112888,-0.7619994 0.112889,-0.3668886 0.333022,-0.6491106 0.220134,-0.2878665 0.547511,-0.4515552 0.333022,-0.1693332 0.767644,-0.1693332 0.575733,0 0.886177,0.3160886 0.316089,0.3104442 0.316089,0.8861771 0,0.4007553 -0.112889,0.7676439 -0.112889,0.3612442 -0.333022,0.6491106 -0.220133,0.282222 -0.553155,0.4515552 -0.327378,0.1636888 -0.762,0.1636888 z m 0.118534,-0.8015105 q 0.158044,0 0.282222,-0.1862665 0.124177,-0.191911 0.197555,-0.4797774 0.07338,-0.2935109 0.07338,-0.5983107 0,-0.3668886 -0.237067,-0.3668886 -0.158044,0 -0.282222,0.1919109 -0.124177,0.1862666 -0.197555,0.474133 -0.06773,0.2878665 -0.06773,0.5983107 0,0.3668886 0.231422,0.3668886 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path490" />
<path
d="m 65.908603,7.1599009 q -0.575733,0 -0.891821,-0.3104442 -0.310444,-0.3160887 -0.310444,-0.8918216 0,-0.4007552 0.112888,-0.7619994 0.112889,-0.3668886 0.333022,-0.6491106 0.220133,-0.2878665 0.547511,-0.4515552 0.333022,-0.1693332 0.767644,-0.1693332 0.575733,0 0.886177,0.3160886 0.316089,0.3104442 0.316089,0.8861771 0,0.4007553 -0.112889,0.7676439 -0.112889,0.3612442 -0.333022,0.6491106 -0.220133,0.282222 -0.553155,0.4515552 -0.327378,0.1636888 -0.762,0.1636888 z m 0.118534,-0.8015105 q 0.158044,0 0.282222,-0.1862665 0.124177,-0.191911 0.197555,-0.4797774 0.07338,-0.2935109 0.07338,-0.5983107 0,-0.3668886 -0.237067,-0.3668886 -0.158044,0 -0.282222,0.1919109 -0.124177,0.1862666 -0.197555,0.474133 -0.06773,0.2878665 -0.06773,0.5983107 0,0.3668886 0.231422,0.3668886 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path492" />
<path
d="m 67.675316,8.4581221 0.948266,-4.476041 h 0.85231 l -0.03387,0.3499553 h 0.02258 q 0.129823,-0.1975554 0.299156,-0.2991554 0.174977,-0.1072443 0.412044,-0.1072443 0.417688,0 0.666044,0.2991553 0.254,0.2991553 0.254,0.8523105 0,0.3894663 -0.1016,0.7619994 -0.09596,0.3668886 -0.276578,0.6660439 -0.180622,0.2991554 -0.440266,0.4797775 -0.259644,0.1749776 -0.581378,0.1749776 -0.208844,0 -0.366888,-0.1072444 -0.158044,-0.1128888 -0.270933,-0.2935109 h -0.02258 q -0.01693,0.2201332 -0.04516,0.4346219 -0.02822,0.2201332 -0.107244,0.5870218 L 68.742115,8.4581221 Z M 69.481537,6.301946 q 0.146755,0 0.265288,-0.1693332 0.118534,-0.1693332 0.186267,-0.4289775 0.07338,-0.2596442 0.07338,-0.5249329 0,-0.3951108 -0.237067,-0.3951108 -0.124178,0 -0.220133,0.1072443 -0.09596,0.1072444 -0.169333,0.2765776 -0.06773,0.1693332 -0.107245,0.3668886 -0.03387,0.191911 -0.03387,0.3725331 0,0.1749776 0.06209,0.2878664 0.06773,0.1072444 0.180623,0.1072444 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path494" />
<path
d="m 72.794822,7.1599009 q -0.592666,0 -0.914399,-0.3273775 -0.321733,-0.333022 -0.321733,-0.9087549 0,-0.3838219 0.107244,-0.7394217 0.112889,-0.3612441 0.333022,-0.6434661 0.220133,-0.2822221 0.553155,-0.4459108 0.338667,-0.1693332 0.795866,-0.1693332 0.524933,0 0.824088,0.2370665 0.299156,0.2370665 0.299156,0.6321773 0,0.513644 -0.400755,0.8297327 -0.400756,0.3160886 -1.275644,0.3160886 h -0.163689 v 0.045155 q 0,0.4063997 0.451556,0.4063997 0.237066,0 0.44591,-0.073378 0.214489,-0.073378 0.4572,-0.1975554 v 0.756355 q -0.248355,0.1241777 -0.519289,0.2031998 -0.265288,0.079022 -0.671688,0.079022 z m 0.02258,-1.885243 q 0.361244,0 0.502355,-0.1354666 0.141111,-0.141111 0.141111,-0.282222 0,-0.090311 -0.05644,-0.1467554 -0.05644,-0.062089 -0.174978,-0.062089 -0.124178,0 -0.231422,0.095955 -0.1016,0.095955 -0.169333,0.2427109 -0.06773,0.141111 -0.09031,0.2878665 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path496" />
<path
d="m 74.657495,7.1034565 0.6604,-3.1213754 h 0.85231 l -0.0508,0.5192885 h 0.02258 q 0.197556,-0.333022 0.4064,-0.4515552 0.214489,-0.1241777 0.530577,-0.1241777 0.06209,0 0.129822,0.00564 0.06773,0.00564 0.09031,0.016933 l -0.231422,1.0555104 q -0.05644,-0.028222 -0.146755,-0.045156 -0.09031,-0.016933 -0.191911,-0.016933 -0.248355,0 -0.434622,0.1693332 -0.180622,0.1693332 -0.276578,0.6208884 l -0.29351,1.371599 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path498" />
</g>
<path
id="path1348"
style="color:#000000;fill:#e0e0e0;fill-opacity:0.752941;stroke-width:0.714406;-inkscape-stroke:none"
d="M 5.4193109,1.6360535 C 4.0746261,1.6465667 2.9804856,2.7485866 2.9805103,4.0933129 v 1.5080987 0.00443 0.00406 0.00702 c 0.00324,0.6351315 0.1709081,1.2397841 0.5330952,1.705241 0.091293,0.1173226 0.1960748,0.2241342 0.3126952,0.3186015 V 5.3666133 h 0.00259 V 4.0933129 C 3.8288705,3.2043172 4.5362516,2.4899017 5.4252198,2.4829515 6.3176074,2.4761075 7.0387059,3.1839609 7.0477631,4.0763306 v 0.016982 1.6742295 c 0,0.3851813 -0.1170262,0.6035969 -0.3182329,0.7675243 C 6.5283236,6.6989941 6.2034026,6.8056753 5.769664,6.8056753 H 5.437754 V 8.3957797 H 6.193851 V 7.5229912 C 6.5799202,7.4642455 6.9804539,7.4245038 7.2655789,7.1922063 7.6635843,6.8679419 7.8946602,6.354867 7.8946602,5.7675423 V 4.0933128 4.0693159 4.0682086 C 7.8809586,2.7185401 6.7690097,1.6257071 5.4193109,1.6360535 Z"
sodipodi:nodetypes="ccccccscccccccsssccccsscccc" />
<g
aria-label="B"
id="text1054"
style="font-style:italic;font-weight:900;font-size:6.35px;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke-width:0.285001;stop-color:#000000"
transform="matrix(0.71440613,0,0,0.71440613,-2.144828,0.00813001)">
<path
id="path1085"
style="font-style:normal;-inkscape-font-specification:'Roboto, Heavy';stroke-width:0.285"
d="M 8.865092,5.8580404 V 8.9958333 11.74073 H 9.9533976 V 8.9958333 h 0.7441404 c 0.549837,-0.00413 0.964283,-0.116789 1.243335,-0.3379638 0.281119,-0.223242 0.42168,-0.5560389 0.42168,-0.9983887 0,-0.2439125 -0.06305,-0.4506186 -0.189136,-0.6201172 -0.12609,-0.1694982 -0.306958,-0.2852537 -0.542602,-0.3472656 0.208772,-0.078548 0.366902,-0.2005048 0.474389,-0.3658692 0.107487,-0.1653644 0.161231,-0.3648358 0.161231,-0.598413 0,-0.4051429 -0.151929,-0.7141686 -0.455786,-0.9270752 C 11.508859,4.5878339 11.18123,4.4813802 10.486698,4.4813802 H 9.9533976 c -1.0883054,0 -1.0883056,1.029605 -1.0883056,1.3766602 z m 1.0883056,-0.022757 c 0,-0.3308701 0.1341694,-0.4768142 0.3334184,-0.4952 l 0.199882,-0.018444 c 0.203885,-0.018814 0.420647,0.042375 0.530201,0.127124 0.109553,0.082682 0.164331,0.2191083 0.164331,0.4092774 0,0.1653644 -0.05064,0.2904216 -0.151929,0.3751709 -0.101285,0.08475 -0.270784,0.1281579 -0.508496,0.1302246 H 9.9533976 Z m 0,1.2412875 h 0.7627444 c 0.374137,0.00207 0.561206,0.1912032 0.561206,0.5674073 0,0.1632973 -0.05271,0.2904217 -0.15813,0.381372 -0.105419,0.088883 -0.256315,0.1333252 -0.452686,0.1333252 H 9.9533976 Z"
sodipodi:nodetypes="cccccccsscssczccssscssccsccscscc" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 21 KiB

@@ -0,0 +1,148 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="350"
height="36"
viewBox="0 0 92.604162 9.525"
version="1.1"
id="svg5"
inkscape:version="1.2.2 (732a01da63, 2022-12-09, custom)"
sodipodi:docname="ToobCabSimLogo_master.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview7"
pagecolor="#2e2e2e"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
showgrid="false"
inkscape:zoom="1.414909"
inkscape:cx="195.77231"
inkscape:cy="90.465182"
inkscape:window-width="1920"
inkscape:window-height="1008"
inkscape:window-x="1440"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" />
<defs
id="defs2" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<g
aria-label="TooB Record Input (mono)"
id="text236"
style="font-style:italic;font-weight:bold;font-size:5.64444px;line-height:0;font-family:Timana;-inkscape-font-specification:'Timana Bold Italic';fill:#686868;stroke:#7f7f7f;stroke-width:0.285001;stop-color:#000000">
<path
d="m 10.655146,7.1034565 0.654755,-3.1383087 h -0.874888 l 0.191911,-0.8918216 h 2.833509 L 13.262878,3.9651478 H 12.38799 l -0.654756,3.1383087 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path737" />
<path
d="m 14.160346,7.1599009 q -0.575733,0 -0.891822,-0.3104442 Q 12.95808,6.533368 12.95808,5.9576351 q 0,-0.4007552 0.112889,-0.7619994 0.112889,-0.3668886 0.333022,-0.6491106 0.220133,-0.2878665 0.54751,-0.4515552 0.333022,-0.1693332 0.767644,-0.1693332 0.575733,0 0.886177,0.3160886 0.316089,0.3104442 0.316089,0.8861771 0,0.4007553 -0.112889,0.7676439 -0.112889,0.3612442 -0.333022,0.6491106 -0.220133,0.282222 -0.553155,0.4515552 -0.327377,0.1636888 -0.761999,0.1636888 z m 0.118533,-0.8015105 q 0.158044,0 0.282222,-0.1862665 0.124178,-0.191911 0.197555,-0.4797774 0.07338,-0.2935109 0.07338,-0.5983107 0,-0.3668886 -0.237066,-0.3668886 -0.158045,0 -0.282222,0.1919109 -0.124178,0.1862666 -0.197556,0.474133 -0.06773,0.2878665 -0.06773,0.5983107 0,0.3668886 0.231422,0.3668886 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path739" />
<path
d="m 17.586523,7.1599009 q -0.575733,0 -0.891822,-0.3104442 -0.310444,-0.3160887 -0.310444,-0.8918216 0,-0.4007552 0.112889,-0.7619994 0.112889,-0.3668886 0.333022,-0.6491106 0.220133,-0.2878665 0.54751,-0.4515552 0.333022,-0.1693332 0.767644,-0.1693332 0.575733,0 0.886177,0.3160886 0.316089,0.3104442 0.316089,0.8861771 0,0.4007553 -0.112889,0.7676439 -0.112889,0.3612442 -0.333022,0.6491106 -0.220133,0.282222 -0.553155,0.4515552 -0.327377,0.1636888 -0.761999,0.1636888 z m 0.118533,-0.8015105 q 0.158044,0 0.282222,-0.1862665 0.124178,-0.191911 0.197555,-0.4797774 0.07338,-0.2935109 0.07338,-0.5983107 0,-0.3668886 -0.237066,-0.3668886 -0.158045,0 -0.282222,0.1919109 -0.124178,0.1862666 -0.197556,0.474133 -0.06773,0.2878665 -0.06773,0.5983107 0,0.3668886 0.231422,0.3668886 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path741" />
<path
d="m 19.669324,7.1034565 0.85231,-4.0301303 h 1.343377 q 0.649111,0 0.931333,0.2483554 0.282222,0.2483553 0.282222,0.6321773 0,0.4120441 -0.214489,0.6660439 -0.208844,0.2539998 -0.603955,0.3725331 v 0.022578 q 0.242711,0.079022 0.383822,0.282222 0.146755,0.1975554 0.146755,0.4854219 0,0.4684885 -0.220133,0.7619994 -0.214489,0.2935109 -0.581377,0.4289775 -0.361244,0.1298221 -0.8128,0.1298221 z M 21.4699,4.6199028 q 0.282222,0 0.383822,-0.1241777 0.107245,-0.1241776 0.107245,-0.3160886 0,-0.282222 -0.349956,-0.282222 h -0.174977 l -0.163689,0.7224883 z m -0.316088,1.6425321 q 0.248355,0 0.400755,-0.1354666 0.1524,-0.141111 0.1524,-0.3330219 0,-0.191911 -0.09031,-0.282222 -0.09031,-0.095956 -0.321733,-0.095956 h -0.186267 l -0.180622,0.846666 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path743" />
<path
d="m 24.715459,7.1034565 0.85231,-4.0301303 h 1.0668 q 0.694266,0 1.061154,0.2765776 0.372533,0.2765775 0.372533,0.8297327 0,0.3668886 -0.124177,0.615244 -0.118534,0.2483553 -0.299156,0.3951108 -0.180622,0.1467554 -0.355599,0.2257776 l 0.728132,1.6876876 H 26.843413 L 26.307191,5.6359021 h -0.2032 L 25.793547,7.1034565 Z M 26.42008,4.8174582 q 0.214489,0 0.389466,-0.1298221 0.180622,-0.1298221 0.180622,-0.4402663 0,-0.1467555 -0.08467,-0.2483554 -0.07902,-0.1015999 -0.287867,-0.1015999 H 26.47088 l -0.191911,0.9200437 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path745" />
<path
d="m 29.761587,7.1599009 q -0.592667,0 -0.9144,-0.3273775 -0.321733,-0.333022 -0.321733,-0.9087549 0,-0.3838219 0.107245,-0.7394217 0.112888,-0.3612441 0.333021,-0.6434661 0.220134,-0.2822221 0.553156,-0.4459108 0.338666,-0.1693332 0.795866,-0.1693332 0.524933,0 0.824088,0.2370665 0.299155,0.2370665 0.299155,0.6321773 0,0.513644 -0.400755,0.8297327 -0.400755,0.3160886 -1.275643,0.3160886 h -0.163689 v 0.045155 q 0,0.4063997 0.451555,0.4063997 0.237066,0 0.445911,-0.073378 0.214488,-0.073378 0.457199,-0.1975554 v 0.756355 q -0.248355,0.1241777 -0.519288,0.2031998 -0.265289,0.079022 -0.671688,0.079022 z m 0.02258,-1.885243 q 0.361244,0 0.502355,-0.1354666 0.141111,-0.141111 0.141111,-0.282222 0,-0.090311 -0.05644,-0.1467554 -0.05644,-0.062089 -0.174978,-0.062089 -0.124177,0 -0.231422,0.095955 -0.1016,0.095955 -0.169333,0.2427109 -0.06773,0.141111 -0.09031,0.2878665 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path747" />
<path
d="m 32.956342,7.1599009 q -0.316089,0 -0.581377,-0.1298221 -0.265289,-0.1298221 -0.423333,-0.4120442 -0.158045,-0.282222 -0.158045,-0.7337772 0,-0.5531551 0.2032,-0.9934215 0.208844,-0.4459107 0.581377,-0.705555 0.378178,-0.2596442 0.886178,-0.2596442 0.29351,0 0.530577,0.056444 0.242711,0.0508 0.479777,0.1636887 L 34.13603,4.9359915 q -0.141111,-0.062089 -0.3048,-0.1128888 -0.163689,-0.0508 -0.316088,-0.0508 -0.163689,0 -0.287867,0.1072444 -0.124178,0.1015999 -0.2032,0.2652887 -0.07902,0.1580443 -0.118533,0.3386664 -0.03951,0.1806221 -0.03951,0.3330219 0,0.2765776 0.09031,0.383822 0.09596,0.1015999 0.254,0.1015999 0.197555,0 0.383822,-0.062089 0.186266,-0.067733 0.395111,-0.1749777 v 0.846666 q -0.220134,0.1185333 -0.462845,0.1862666 -0.24271,0.062089 -0.570088,0.062089 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path749" />
<path
d="m 35.840648,7.1599009 q -0.575733,0 -0.891821,-0.3104442 -0.310444,-0.3160887 -0.310444,-0.8918216 0,-0.4007552 0.112888,-0.7619994 0.112889,-0.3668886 0.333022,-0.6491106 0.220133,-0.2878665 0.547511,-0.4515552 0.333022,-0.1693332 0.767644,-0.1693332 0.575733,0 0.886177,0.3160886 0.316089,0.3104442 0.316089,0.8861771 0,0.4007553 -0.112889,0.7676439 -0.112889,0.3612442 -0.333022,0.6491106 -0.220133,0.282222 -0.553155,0.4515552 -0.327378,0.1636888 -0.762,0.1636888 z m 0.118534,-0.8015105 q 0.158044,0 0.282222,-0.1862665 0.124177,-0.191911 0.197555,-0.4797774 0.07338,-0.2935109 0.07338,-0.5983107 0,-0.3668886 -0.237067,-0.3668886 -0.158044,0 -0.282222,0.1919109 -0.124178,0.1862666 -0.197555,0.474133 -0.06773,0.2878665 -0.06773,0.5983107 0,0.3668886 0.231423,0.3668886 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path751" />
<path
d="m 37.895227,7.1034565 0.6604,-3.1213754 h 0.85231 l -0.0508,0.5192885 h 0.02258 q 0.197555,-0.333022 0.4064,-0.4515552 0.214488,-0.1241777 0.530577,-0.1241777 0.06209,0 0.129822,0.00564 0.06773,0.00564 0.09031,0.016933 l -0.231422,1.0555104 q -0.05644,-0.028222 -0.146755,-0.045156 -0.09031,-0.016933 -0.191911,-0.016933 -0.248356,0 -0.434622,0.1693332 -0.180622,0.1693332 -0.276578,0.6208884 l -0.29351,1.371599 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path753" />
<path
d="m 41.304469,7.1599009 q -0.237067,0 -0.440267,-0.1128888 Q 40.661003,6.9341233 40.536825,6.674479 40.418292,6.4148348 40.418292,5.968924 q 0,-0.2257776 0.0508,-0.5023552 0.05644,-0.2765775 0.163688,-0.5475107 0.107245,-0.2709331 0.270934,-0.4967107 0.163688,-0.2257776 0.389466,-0.3612442 0.225778,-0.1354665 0.508,-0.1354665 0.253999,0 0.389466,0.1128888 0.141111,0.1128888 0.265289,0.3047998 h 0.02258 q 0,-0.033867 0.0056,-0.1523999 0.0056,-0.1185333 0.02258,-0.2652887 0.01693,-0.1523999 0.04516,-0.282222 L 42.721223,2.813682 h 1.078088 l -0.908755,4.2897745 h -0.85231 l 0.02822,-0.3386664 H 42.04389 Q 41.931002,6.9228344 41.767313,7.0413677 41.603624,7.1599009 41.304469,7.1599009 Z M 41.744735,6.301946 q 0.124178,0 0.220133,-0.1072444 0.1016,-0.1128888 0.169333,-0.282222 0.07338,-0.1749776 0.107245,-0.3668886 0.03951,-0.1975554 0.03951,-0.3668886 0,-0.1806221 -0.05644,-0.2878665 -0.0508,-0.1072443 -0.163689,-0.1072443 -0.146756,0 -0.276578,0.1693332 -0.124177,0.1693332 -0.2032,0.4289774 -0.07338,0.2539999 -0.07338,0.524933 0,0.3951108 0.237066,0.3951108 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path755" />
<path
d="m 44.860468,7.1034565 0.129823,-0.615244 0.530577,-0.2201331 0.496711,-2.3367983 -0.440267,-0.2370665 0.129822,-0.6208884 h 2.07151 l -0.129822,0.6208884 -0.553155,0.2370665 -0.496711,2.3367983 0.445911,0.2201331 -0.129822,0.615244 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path757" />
<path
d="m 47.53029,7.1034565 0.6604,-3.1213754 H 49.043 L 49.00913,4.416703 h 0.02258 q 0.152399,-0.2652887 0.355599,-0.3781775 0.208845,-0.1128888 0.502355,-0.1128888 0.293511,0 0.474133,0.1241777 0.180623,0.1185332 0.265289,0.3217331 0.08467,0.1975554 0.08467,0.4402663 0,0.1580443 -0.02258,0.3217331 -0.01693,0.1636887 -0.04516,0.3104442 l -0.349955,1.6594654 h -1.066799 l 0.3556,-1.7046209 q 0.01693,-0.073378 0.03387,-0.1806221 0.01693,-0.1128888 0.01693,-0.2088443 0,-0.1185333 -0.06209,-0.1749777 -0.06209,-0.062089 -0.146756,-0.062089 -0.158044,0 -0.293511,0.1975554 -0.129822,0.191911 -0.214488,0.6095996 l -0.321727,1.523999 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path759" />
<path
d="m 50.753265,8.4581221 0.948266,-4.476041 h 0.852311 l -0.03387,0.3499553 h 0.02258 q 0.129822,-0.1975554 0.299155,-0.2991554 0.174978,-0.1072443 0.412044,-0.1072443 0.417689,0 0.666044,0.2991553 0.254,0.2991553 0.254,0.8523105 0,0.3894663 -0.1016,0.7619994 -0.09595,0.3668886 -0.276577,0.6660439 -0.180622,0.2991554 -0.440267,0.4797775 -0.259644,0.1749776 -0.581377,0.1749776 -0.208844,0 -0.366889,-0.1072444 -0.158044,-0.1128888 -0.270933,-0.2935109 h -0.02258 q -0.01693,0.2201332 -0.04515,0.4346219 -0.02822,0.2201332 -0.107244,0.5870218 L 51.820065,8.4581221 Z M 52.559486,6.301946 q 0.146756,0 0.265289,-0.1693332 0.118533,-0.1693332 0.186266,-0.4289775 0.07338,-0.2596442 0.07338,-0.5249329 0,-0.3951108 -0.237066,-0.3951108 -0.124178,0 -0.220133,0.1072443 -0.09596,0.1072444 -0.169334,0.2765776 -0.06773,0.1693332 -0.107244,0.3668886 -0.03387,0.191911 -0.03387,0.3725331 0,0.1749776 0.06209,0.2878664 0.06773,0.1072444 0.180622,0.1072444 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path761" />
<path
d="m 55.494598,7.1599009 q -0.287867,0 -0.474133,-0.1185332 Q 54.839843,6.91719 54.755176,6.7139901 54.67051,6.5107903 54.67051,6.2737238 q 0,-0.1580443 0.01693,-0.3217331 0.02258,-0.1636888 0.0508,-0.3104442 l 0.349955,-1.6594654 h 1.066799 l -0.355599,1.6989765 q -0.01693,0.073378 -0.03387,0.1862665 -0.01693,0.1072444 -0.01693,0.2031998 0,0.1185333 0.06209,0.1806221 0.06209,0.056444 0.146755,0.056444 0.141111,0 0.276578,-0.1919109 0.141111,-0.1975554 0.231422,-0.615244 l 0.321733,-1.5183544 h 1.066799 l -0.6604,3.1213754 h -0.85231 l 0.03387,-0.4346219 h -0.02258 q -0.1524,0.2596443 -0.3556,0.3781775 -0.2032,0.1128888 -0.502355,0.1128888 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path763" />
<path
d="m 59.044947,7.1599009 q -0.4064,0 -0.620889,-0.1749776 -0.208844,-0.1806221 -0.208844,-0.5757329 0,-0.1128888 0.02258,-0.2596443 0.02258,-0.1467554 0.04516,-0.2596442 l 0.231422,-1.1063103 h -0.423333 l 0.112889,-0.524933 0.598311,-0.2427109 0.378177,-0.6603995 h 0.7112 l -0.135467,0.6265329 h 0.795866 l -0.174978,0.8015105 h -0.795866 l -0.231422,1.0555103 q -0.01693,0.079022 -0.03387,0.1636888 -0.01129,0.079022 -0.01129,0.1241776 0,0.090311 0.0508,0.1354666 0.0508,0.039511 0.124177,0.039511 0.107245,0 0.237067,-0.033867 0.129822,-0.039511 0.265289,-0.095956 v 0.8015105 q -0.174978,0.084667 -0.4064,0.1354665 -0.225778,0.0508 -0.530577,0.0508 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path765" />
<path
d="M 62.567083,7.995278 Q 62.437261,7.763856 62.341306,7.4534118 62.24535,7.148612 62.19455,6.8268789 62.14939,6.4995014 62.14939,6.2059905 q 0,-0.9595548 0.361244,-1.7497764 0.366888,-0.7902217 1.049866,-1.4957767 h 0.891821 Q 64.051566,3.3950593 63.735477,3.8974145 63.419389,4.3941252 63.233122,4.981147 63.0525,5.5625243 63.0525,6.251146 q 0,0.2596443 0.03951,0.5700885 0.03951,0.3047998 0.107244,0.6095995 0.07338,0.3047998 0.174978,0.564444 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path767" />
<path
d="m 64.13624,7.1034565 0.660399,-3.1213754 h 0.852311 l -0.04516,0.513644 h 0.02258 q 0.163689,-0.3104442 0.372533,-0.4402663 0.208844,-0.1298221 0.530578,-0.1298221 0.321733,0 0.49671,0.1467554 0.174978,0.1467555 0.248356,0.423333 h 0.02258 q 0.344311,-0.5700884 0.948266,-0.5700884 0.383822,0 0.587022,0.2370665 0.2032,0.231422 0.2032,0.6829772 0,0.2539998 -0.06209,0.564444 l -0.344311,1.6933321 h -1.066799 l 0.3556,-1.7384876 q 0.01129,-0.056444 0.02258,-0.1523999 0.01693,-0.095955 0.01693,-0.2144887 0,-0.2257776 -0.191911,-0.2257776 -0.2032,0 -0.333022,0.2088443 -0.124178,0.2088443 -0.208844,0.6265329 l -0.3048,1.4957766 H 65.85215 l 0.361244,-1.7384876 q 0.01129,-0.062089 0.02258,-0.1636887 0.01693,-0.1016 0.01693,-0.1693332 0,-0.1411111 -0.05644,-0.1975555 -0.05644,-0.062089 -0.141111,-0.062089 -0.158045,0 -0.287867,0.1636888 Q 65.637664,5.09968 65.53042,5.5851019 l -0.327378,1.5183544 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path769" />
<path
d="m 70.734596,7.1599009 q -0.575733,0 -0.891822,-0.3104442 Q 69.53233,6.533368 69.53233,5.9576351 q 0,-0.4007552 0.112889,-0.7619994 0.112889,-0.3668886 0.333022,-0.6491106 0.220133,-0.2878665 0.547511,-0.4515552 0.333022,-0.1693332 0.767643,-0.1693332 0.575733,0 0.886178,0.3160886 0.316088,0.3104442 0.316088,0.8861771 0,0.4007553 -0.112889,0.7676439 -0.112888,0.3612442 -0.333022,0.6491106 -0.220133,0.282222 -0.553155,0.4515552 -0.327377,0.1636888 -0.761999,0.1636888 z m 0.118533,-0.8015105 q 0.158044,0 0.282222,-0.1862665 0.124178,-0.191911 0.197556,-0.4797774 0.07338,-0.2935109 0.07338,-0.5983107 0,-0.3668886 -0.237066,-0.3668886 -0.158045,0 -0.282222,0.1919109 -0.124178,0.1862666 -0.197556,0.474133 -0.06773,0.2878665 -0.06773,0.5983107 0,0.3668886 0.231422,0.3668886 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path771" />
<path
d="m 72.789175,7.1034565 0.660399,-3.1213754 h 0.852311 l -0.03387,0.4346219 h 0.02258 q 0.1524,-0.2652887 0.3556,-0.3781775 0.208844,-0.1128888 0.502355,-0.1128888 0.293511,0 0.474133,0.1241777 0.180622,0.1185332 0.265289,0.3217331 0.08467,0.1975554 0.08467,0.4402663 0,0.1580443 -0.02258,0.3217331 -0.01693,0.1636887 -0.04516,0.3104442 l -0.349955,1.6594654 h -1.0668 l 0.3556,-1.7046209 q 0.01693,-0.073378 0.03387,-0.1806221 0.01693,-0.1128888 0.01693,-0.2088443 0,-0.1185333 -0.06209,-0.1749777 -0.06209,-0.062089 -0.146755,-0.062089 -0.158045,0 -0.293511,0.1975554 -0.129822,0.191911 -0.214489,0.6095996 l -0.321733,1.5239988 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path773" />
<path
d="m 77.671611,7.1599009 q -0.575732,0 -0.891821,-0.3104442 -0.310444,-0.3160887 -0.310444,-0.8918216 0,-0.4007552 0.112888,-0.7619994 0.112889,-0.3668886 0.333022,-0.6491106 0.220134,-0.2878665 0.547511,-0.4515552 0.333022,-0.1693332 0.767644,-0.1693332 0.575733,0 0.886177,0.3160886 0.316089,0.3104442 0.316089,0.8861771 0,0.4007553 -0.112889,0.7676439 -0.112889,0.3612442 -0.333022,0.6491106 -0.220133,0.282222 -0.553155,0.4515552 -0.327378,0.1636888 -0.762,0.1636888 z m 0.118534,-0.8015105 q 0.158044,0 0.282222,-0.1862665 0.124177,-0.191911 0.197555,-0.4797774 0.07338,-0.2935109 0.07338,-0.5983107 0,-0.3668886 -0.237067,-0.3668886 -0.158044,0 -0.282222,0.1919109 -0.124177,0.1862666 -0.197555,0.474133 -0.06773,0.2878665 -0.06773,0.5983107 0,0.3668886 0.231422,0.3668886 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path775" />
<path
d="m 79.297213,7.995278 q 0.400755,-0.4346218 0.711199,-0.9313326 0.310445,-0.5023552 0.485422,-1.0893769 0.180622,-0.5870218 0.180622,-1.2699991 0,-0.2652887 -0.03951,-0.5700884 -0.03951,-0.3047998 -0.112888,-0.6095996 -0.07338,-0.3047997 -0.174978,-0.564444 h 0.812799 q 0.146756,0.2483554 0.237067,0.5531551 0.09031,0.3047998 0.135466,0.6265329 0.04516,0.3160887 0.04516,0.6095995 0,0.9595549 -0.349955,1.7497765 -0.344311,0.7902216 -1.032933,1.4957766 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path777" />
</g>
<path
id="path1348"
style="color:#000000;fill:#e0e0e0;fill-opacity:0.752941;stroke-width:0.714406;-inkscape-stroke:none"
d="M 5.4193109,1.6360535 C 4.0746261,1.6465667 2.9804856,2.7485866 2.9805103,4.0933129 v 1.5080987 0.00443 0.00406 0.00702 c 0.00324,0.6351315 0.1709081,1.2397841 0.5330952,1.705241 0.091293,0.1173226 0.1960748,0.2241342 0.3126952,0.3186015 V 5.3666133 h 0.00259 V 4.0933129 C 3.8288705,3.2043172 4.5362516,2.4899017 5.4252198,2.4829515 6.3176074,2.4761075 7.0387059,3.1839609 7.0477631,4.0763306 v 0.016982 1.6742295 c 0,0.3851813 -0.1170262,0.6035969 -0.3182329,0.7675243 C 6.5283236,6.6989941 6.2034026,6.8056753 5.769664,6.8056753 H 5.437754 V 8.3957797 H 6.193851 V 7.5229912 C 6.5799202,7.4642455 6.9804539,7.4245038 7.2655789,7.1922063 7.6635843,6.8679419 7.8946602,6.354867 7.8946602,5.7675423 V 4.0933128 4.0693159 4.0682086 C 7.8809586,2.7185401 6.7690097,1.6257071 5.4193109,1.6360535 Z"
sodipodi:nodetypes="ccccccscccccccsssccccsscccc" />
<g
aria-label="B"
id="text1054"
style="font-style:italic;font-weight:900;font-size:6.35px;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke-width:0.285001;stop-color:#000000"
transform="matrix(0.71440613,0,0,0.71440613,-2.144828,0.00813001)">
<path
id="path1085"
style="font-style:normal;-inkscape-font-specification:'Roboto, Heavy';stroke-width:0.285"
d="M 8.865092,5.8580404 V 8.9958333 11.74073 H 9.9533976 V 8.9958333 h 0.7441404 c 0.549837,-0.00413 0.964283,-0.116789 1.243335,-0.3379638 0.281119,-0.223242 0.42168,-0.5560389 0.42168,-0.9983887 0,-0.2439125 -0.06305,-0.4506186 -0.189136,-0.6201172 -0.12609,-0.1694982 -0.306958,-0.2852537 -0.542602,-0.3472656 0.208772,-0.078548 0.366902,-0.2005048 0.474389,-0.3658692 0.107487,-0.1653644 0.161231,-0.3648358 0.161231,-0.598413 0,-0.4051429 -0.151929,-0.7141686 -0.455786,-0.9270752 C 11.508859,4.5878339 11.18123,4.4813802 10.486698,4.4813802 H 9.9533976 c -1.0883054,0 -1.0883056,1.029605 -1.0883056,1.3766602 z m 1.0883056,-0.022757 c 0,-0.3308701 0.1341694,-0.4768142 0.3334184,-0.4952 l 0.199882,-0.018444 c 0.203885,-0.018814 0.420647,0.042375 0.530201,0.127124 0.109553,0.082682 0.164331,0.2191083 0.164331,0.4092774 0,0.1653644 -0.05064,0.2904216 -0.151929,0.3751709 -0.101285,0.08475 -0.270784,0.1281579 -0.508496,0.1302246 H 9.9533976 Z m 0,1.2412875 h 0.7627444 c 0.374137,0.00207 0.561206,0.1912032 0.561206,0.5674073 0,0.1632973 -0.05271,0.2904217 -0.15813,0.381372 -0.105419,0.088883 -0.256315,0.1333252 -0.452686,0.1333252 H 9.9533976 Z"
sodipodi:nodetypes="cccccccsscssczccssscssccsccscscc" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 22 KiB

@@ -0,0 +1,156 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="350"
height="36"
viewBox="0 0 92.604162 9.525"
version="1.1"
id="svg5"
inkscape:version="1.2.2 (732a01da63, 2022-12-09, custom)"
sodipodi:docname="ToobCabSimLogo_master.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview7"
pagecolor="#2e2e2e"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
showgrid="false"
inkscape:zoom="1.414909"
inkscape:cx="195.77231"
inkscape:cy="90.465182"
inkscape:window-width="1920"
inkscape:window-height="1008"
inkscape:window-x="1440"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" />
<defs
id="defs2" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<g
aria-label="TooB Record Input (stereo)"
id="text236"
style="font-style:italic;font-weight:bold;font-size:5.64444px;line-height:0;font-family:Timana;-inkscape-font-specification:'Timana Bold Italic';fill:#686868;stroke:#7f7f7f;stroke-width:0.285001;stop-color:#000000">
<path
d="m 10.655146,7.1034565 0.654755,-3.1383087 h -0.874888 l 0.191911,-0.8918216 h 2.833509 L 13.262878,3.9651478 H 12.38799 l -0.654756,3.1383087 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path893" />
<path
d="m 14.160346,7.1599009 q -0.575733,0 -0.891822,-0.3104442 Q 12.95808,6.533368 12.95808,5.9576351 q 0,-0.4007552 0.112889,-0.7619994 0.112889,-0.3668886 0.333022,-0.6491106 0.220133,-0.2878665 0.54751,-0.4515552 0.333022,-0.1693332 0.767644,-0.1693332 0.575733,0 0.886177,0.3160886 0.316089,0.3104442 0.316089,0.8861771 0,0.4007553 -0.112889,0.7676439 -0.112889,0.3612442 -0.333022,0.6491106 -0.220133,0.282222 -0.553155,0.4515552 -0.327377,0.1636888 -0.761999,0.1636888 z m 0.118533,-0.8015105 q 0.158044,0 0.282222,-0.1862665 0.124178,-0.191911 0.197555,-0.4797774 0.07338,-0.2935109 0.07338,-0.5983107 0,-0.3668886 -0.237066,-0.3668886 -0.158045,0 -0.282222,0.1919109 -0.124178,0.1862666 -0.197556,0.474133 -0.06773,0.2878665 -0.06773,0.5983107 0,0.3668886 0.231422,0.3668886 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path895" />
<path
d="m 17.586523,7.1599009 q -0.575733,0 -0.891822,-0.3104442 -0.310444,-0.3160887 -0.310444,-0.8918216 0,-0.4007552 0.112889,-0.7619994 0.112889,-0.3668886 0.333022,-0.6491106 0.220133,-0.2878665 0.54751,-0.4515552 0.333022,-0.1693332 0.767644,-0.1693332 0.575733,0 0.886177,0.3160886 0.316089,0.3104442 0.316089,0.8861771 0,0.4007553 -0.112889,0.7676439 -0.112889,0.3612442 -0.333022,0.6491106 -0.220133,0.282222 -0.553155,0.4515552 -0.327377,0.1636888 -0.761999,0.1636888 z m 0.118533,-0.8015105 q 0.158044,0 0.282222,-0.1862665 0.124178,-0.191911 0.197555,-0.4797774 0.07338,-0.2935109 0.07338,-0.5983107 0,-0.3668886 -0.237066,-0.3668886 -0.158045,0 -0.282222,0.1919109 -0.124178,0.1862666 -0.197556,0.474133 -0.06773,0.2878665 -0.06773,0.5983107 0,0.3668886 0.231422,0.3668886 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path897" />
<path
d="m 19.669324,7.1034565 0.85231,-4.0301303 h 1.343377 q 0.649111,0 0.931333,0.2483554 0.282222,0.2483553 0.282222,0.6321773 0,0.4120441 -0.214489,0.6660439 -0.208844,0.2539998 -0.603955,0.3725331 v 0.022578 q 0.242711,0.079022 0.383822,0.282222 0.146755,0.1975554 0.146755,0.4854219 0,0.4684885 -0.220133,0.7619994 -0.214489,0.2935109 -0.581377,0.4289775 -0.361244,0.1298221 -0.8128,0.1298221 z M 21.4699,4.6199028 q 0.282222,0 0.383822,-0.1241777 0.107245,-0.1241776 0.107245,-0.3160886 0,-0.282222 -0.349956,-0.282222 h -0.174977 l -0.163689,0.7224883 z m -0.316088,1.6425321 q 0.248355,0 0.400755,-0.1354666 0.1524,-0.141111 0.1524,-0.3330219 0,-0.191911 -0.09031,-0.282222 -0.09031,-0.095956 -0.321733,-0.095956 h -0.186267 l -0.180622,0.846666 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path899" />
<path
d="m 24.715459,7.1034565 0.85231,-4.0301303 h 1.0668 q 0.694266,0 1.061154,0.2765776 0.372533,0.2765775 0.372533,0.8297327 0,0.3668886 -0.124177,0.615244 -0.118534,0.2483553 -0.299156,0.3951108 -0.180622,0.1467554 -0.355599,0.2257776 l 0.728132,1.6876876 H 26.843413 L 26.307191,5.6359021 h -0.2032 L 25.793547,7.1034565 Z M 26.42008,4.8174582 q 0.214489,0 0.389466,-0.1298221 0.180622,-0.1298221 0.180622,-0.4402663 0,-0.1467555 -0.08467,-0.2483554 -0.07902,-0.1015999 -0.287867,-0.1015999 H 26.47088 l -0.191911,0.9200437 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path901" />
<path
d="m 29.761587,7.1599009 q -0.592667,0 -0.9144,-0.3273775 -0.321733,-0.333022 -0.321733,-0.9087549 0,-0.3838219 0.107245,-0.7394217 0.112888,-0.3612441 0.333021,-0.6434661 0.220134,-0.2822221 0.553156,-0.4459108 0.338666,-0.1693332 0.795866,-0.1693332 0.524933,0 0.824088,0.2370665 0.299155,0.2370665 0.299155,0.6321773 0,0.513644 -0.400755,0.8297327 -0.400755,0.3160886 -1.275643,0.3160886 h -0.163689 v 0.045155 q 0,0.4063997 0.451555,0.4063997 0.237066,0 0.445911,-0.073378 0.214488,-0.073378 0.457199,-0.1975554 v 0.756355 q -0.248355,0.1241777 -0.519288,0.2031998 -0.265289,0.079022 -0.671688,0.079022 z m 0.02258,-1.885243 q 0.361244,0 0.502355,-0.1354666 0.141111,-0.141111 0.141111,-0.282222 0,-0.090311 -0.05644,-0.1467554 -0.05644,-0.062089 -0.174978,-0.062089 -0.124177,0 -0.231422,0.095955 -0.1016,0.095955 -0.169333,0.2427109 -0.06773,0.141111 -0.09031,0.2878665 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path903" />
<path
d="m 32.956342,7.1599009 q -0.316089,0 -0.581377,-0.1298221 -0.265289,-0.1298221 -0.423333,-0.4120442 -0.158045,-0.282222 -0.158045,-0.7337772 0,-0.5531551 0.2032,-0.9934215 0.208844,-0.4459107 0.581377,-0.705555 0.378178,-0.2596442 0.886178,-0.2596442 0.29351,0 0.530577,0.056444 0.242711,0.0508 0.479777,0.1636887 L 34.13603,4.9359915 q -0.141111,-0.062089 -0.3048,-0.1128888 -0.163689,-0.0508 -0.316088,-0.0508 -0.163689,0 -0.287867,0.1072444 -0.124178,0.1015999 -0.2032,0.2652887 -0.07902,0.1580443 -0.118533,0.3386664 -0.03951,0.1806221 -0.03951,0.3330219 0,0.2765776 0.09031,0.383822 0.09596,0.1015999 0.254,0.1015999 0.197555,0 0.383822,-0.062089 0.186266,-0.067733 0.395111,-0.1749777 v 0.846666 q -0.220134,0.1185333 -0.462845,0.1862666 -0.24271,0.062089 -0.570088,0.062089 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path905" />
<path
d="m 35.840648,7.1599009 q -0.575733,0 -0.891821,-0.3104442 -0.310444,-0.3160887 -0.310444,-0.8918216 0,-0.4007552 0.112888,-0.7619994 0.112889,-0.3668886 0.333022,-0.6491106 0.220133,-0.2878665 0.547511,-0.4515552 0.333022,-0.1693332 0.767644,-0.1693332 0.575733,0 0.886177,0.3160886 0.316089,0.3104442 0.316089,0.8861771 0,0.4007553 -0.112889,0.7676439 -0.112889,0.3612442 -0.333022,0.6491106 -0.220133,0.282222 -0.553155,0.4515552 -0.327378,0.1636888 -0.762,0.1636888 z m 0.118534,-0.8015105 q 0.158044,0 0.282222,-0.1862665 0.124177,-0.191911 0.197555,-0.4797774 0.07338,-0.2935109 0.07338,-0.5983107 0,-0.3668886 -0.237067,-0.3668886 -0.158044,0 -0.282222,0.1919109 -0.124178,0.1862666 -0.197555,0.474133 -0.06773,0.2878665 -0.06773,0.5983107 0,0.3668886 0.231423,0.3668886 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path907" />
<path
d="m 37.895227,7.1034565 0.6604,-3.1213754 h 0.85231 l -0.0508,0.5192885 h 0.02258 q 0.197555,-0.333022 0.4064,-0.4515552 0.214488,-0.1241777 0.530577,-0.1241777 0.06209,0 0.129822,0.00564 0.06773,0.00564 0.09031,0.016933 l -0.231422,1.0555104 q -0.05644,-0.028222 -0.146755,-0.045156 -0.09031,-0.016933 -0.191911,-0.016933 -0.248356,0 -0.434622,0.1693332 -0.180622,0.1693332 -0.276578,0.6208884 l -0.29351,1.371599 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path909" />
<path
d="m 41.304469,7.1599009 q -0.237067,0 -0.440267,-0.1128888 Q 40.661003,6.9341233 40.536825,6.674479 40.418292,6.4148348 40.418292,5.968924 q 0,-0.2257776 0.0508,-0.5023552 0.05644,-0.2765775 0.163688,-0.5475107 0.107245,-0.2709331 0.270934,-0.4967107 0.163688,-0.2257776 0.389466,-0.3612442 0.225778,-0.1354665 0.508,-0.1354665 0.253999,0 0.389466,0.1128888 0.141111,0.1128888 0.265289,0.3047998 h 0.02258 q 0,-0.033867 0.0056,-0.1523999 0.0056,-0.1185333 0.02258,-0.2652887 0.01693,-0.1523999 0.04516,-0.282222 L 42.721223,2.813682 h 1.078088 l -0.908755,4.2897745 h -0.85231 l 0.02822,-0.3386664 H 42.04389 Q 41.931002,6.9228344 41.767313,7.0413677 41.603624,7.1599009 41.304469,7.1599009 Z M 41.744735,6.301946 q 0.124178,0 0.220133,-0.1072444 0.1016,-0.1128888 0.169333,-0.282222 0.07338,-0.1749776 0.107245,-0.3668886 0.03951,-0.1975554 0.03951,-0.3668886 0,-0.1806221 -0.05644,-0.2878665 -0.0508,-0.1072443 -0.163689,-0.1072443 -0.146756,0 -0.276578,0.1693332 -0.124177,0.1693332 -0.2032,0.4289774 -0.07338,0.2539999 -0.07338,0.524933 0,0.3951108 0.237066,0.3951108 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path911" />
<path
d="m 44.860468,7.1034565 0.129823,-0.615244 0.530577,-0.2201331 0.496711,-2.3367983 -0.440267,-0.2370665 0.129822,-0.6208884 h 2.07151 l -0.129822,0.6208884 -0.553155,0.2370665 -0.496711,2.3367983 0.445911,0.2201331 -0.129822,0.615244 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path913" />
<path
d="m 47.53029,7.1034565 0.6604,-3.1213754 H 49.043 L 49.00913,4.416703 h 0.02258 q 0.152399,-0.2652887 0.355599,-0.3781775 0.208845,-0.1128888 0.502355,-0.1128888 0.293511,0 0.474133,0.1241777 0.180623,0.1185332 0.265289,0.3217331 0.08467,0.1975554 0.08467,0.4402663 0,0.1580443 -0.02258,0.3217331 -0.01693,0.1636887 -0.04516,0.3104442 l -0.349955,1.6594654 h -1.066799 l 0.3556,-1.7046209 q 0.01693,-0.073378 0.03387,-0.1806221 0.01693,-0.1128888 0.01693,-0.2088443 0,-0.1185333 -0.06209,-0.1749777 -0.06209,-0.062089 -0.146756,-0.062089 -0.158044,0 -0.293511,0.1975554 -0.129822,0.191911 -0.214488,0.6095996 l -0.321727,1.523999 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path915" />
<path
d="m 50.753265,8.4581221 0.948266,-4.476041 h 0.852311 l -0.03387,0.3499553 h 0.02258 q 0.129822,-0.1975554 0.299155,-0.2991554 0.174978,-0.1072443 0.412044,-0.1072443 0.417689,0 0.666044,0.2991553 0.254,0.2991553 0.254,0.8523105 0,0.3894663 -0.1016,0.7619994 -0.09595,0.3668886 -0.276577,0.6660439 -0.180622,0.2991554 -0.440267,0.4797775 -0.259644,0.1749776 -0.581377,0.1749776 -0.208844,0 -0.366889,-0.1072444 -0.158044,-0.1128888 -0.270933,-0.2935109 h -0.02258 q -0.01693,0.2201332 -0.04515,0.4346219 -0.02822,0.2201332 -0.107244,0.5870218 L 51.820065,8.4581221 Z M 52.559486,6.301946 q 0.146756,0 0.265289,-0.1693332 0.118533,-0.1693332 0.186266,-0.4289775 0.07338,-0.2596442 0.07338,-0.5249329 0,-0.3951108 -0.237066,-0.3951108 -0.124178,0 -0.220133,0.1072443 -0.09596,0.1072444 -0.169334,0.2765776 -0.06773,0.1693332 -0.107244,0.3668886 -0.03387,0.191911 -0.03387,0.3725331 0,0.1749776 0.06209,0.2878664 0.06773,0.1072444 0.180622,0.1072444 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path917" />
<path
d="m 55.494598,7.1599009 q -0.287867,0 -0.474133,-0.1185332 Q 54.839843,6.91719 54.755176,6.7139901 54.67051,6.5107903 54.67051,6.2737238 q 0,-0.1580443 0.01693,-0.3217331 0.02258,-0.1636888 0.0508,-0.3104442 l 0.349955,-1.6594654 h 1.066799 l -0.355599,1.6989765 q -0.01693,0.073378 -0.03387,0.1862665 -0.01693,0.1072444 -0.01693,0.2031998 0,0.1185333 0.06209,0.1806221 0.06209,0.056444 0.146755,0.056444 0.141111,0 0.276578,-0.1919109 0.141111,-0.1975554 0.231422,-0.615244 l 0.321733,-1.5183544 h 1.066799 l -0.6604,3.1213754 h -0.85231 l 0.03387,-0.4346219 h -0.02258 q -0.1524,0.2596443 -0.3556,0.3781775 -0.2032,0.1128888 -0.502355,0.1128888 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path919" />
<path
d="m 59.044947,7.1599009 q -0.4064,0 -0.620889,-0.1749776 -0.208844,-0.1806221 -0.208844,-0.5757329 0,-0.1128888 0.02258,-0.2596443 0.02258,-0.1467554 0.04516,-0.2596442 l 0.231422,-1.1063103 h -0.423333 l 0.112889,-0.524933 0.598311,-0.2427109 0.378177,-0.6603995 h 0.7112 l -0.135467,0.6265329 h 0.795866 l -0.174978,0.8015105 h -0.795866 l -0.231422,1.0555103 q -0.01693,0.079022 -0.03387,0.1636888 -0.01129,0.079022 -0.01129,0.1241776 0,0.090311 0.0508,0.1354666 0.0508,0.039511 0.124177,0.039511 0.107245,0 0.237067,-0.033867 0.129822,-0.039511 0.265289,-0.095956 v 0.8015105 q -0.174978,0.084667 -0.4064,0.1354665 -0.225778,0.0508 -0.530577,0.0508 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path921" />
<path
d="M 62.567083,7.995278 Q 62.437261,7.763856 62.341306,7.4534118 62.24535,7.148612 62.19455,6.8268789 62.14939,6.4995014 62.14939,6.2059905 q 0,-0.9595548 0.361244,-1.7497764 0.366888,-0.7902217 1.049866,-1.4957767 h 0.891821 Q 64.051566,3.3950593 63.735477,3.8974145 63.419389,4.3941252 63.233122,4.981147 63.0525,5.5625243 63.0525,6.251146 q 0,0.2596443 0.03951,0.5700885 0.03951,0.3047998 0.107244,0.6095995 0.07338,0.3047998 0.174978,0.564444 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path923" />
<path
d="m 65.14095,7.1599009 q -0.310444,0 -0.558799,-0.045155 -0.242711,-0.045155 -0.423333,-0.1298221 v -0.857955 q 0.253999,0.1411111 0.468488,0.1975555 0.220133,0.0508 0.445911,0.0508 0.06773,0 0.1524,-0.011289 0.09031,-0.016933 0.1524,-0.056444 0.06773,-0.039511 0.06773,-0.1241777 0,-0.062089 -0.02822,-0.1128888 -0.02822,-0.0508 -0.118533,-0.1185332 -0.09031,-0.067733 -0.282222,-0.1693332 -0.293511,-0.1636888 -0.428978,-0.3668886 -0.129822,-0.2088443 -0.129822,-0.5023552 0,-0.4402663 0.310444,-0.7111995 0.316089,-0.2765775 0.970844,-0.2765775 0.3048,0 0.558799,0.073378 0.259645,0.073378 0.496711,0.2201332 L 66.461749,4.9134137 Q 66.303705,4.8118138 66.10615,4.7327916 q -0.191911,-0.079022 -0.3556,-0.079022 -0.208845,0 -0.208845,0.1862665 0,0.079022 0.08467,0.141111 0.09031,0.062089 0.282222,0.1580443 0.620889,0.3047998 0.620889,0.8805327 0,0.5813773 -0.378178,0.8635993 -0.372533,0.2765776 -1.010355,0.2765776 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path925" />
<path
d="m 68.036554,7.1599009 q -0.406399,0 -0.620888,-0.1749776 -0.208844,-0.1806221 -0.208844,-0.5757329 0,-0.1128888 0.02258,-0.2596443 0.02258,-0.1467554 0.04516,-0.2596442 l 0.231422,-1.1063103 h -0.423333 l 0.112889,-0.524933 0.59831,-0.2427109 0.378178,-0.6603995 h 0.711199 l -0.135466,0.6265329 h 0.795866 l -0.174978,0.8015105 h -0.795866 l -0.231422,1.0555103 q -0.01693,0.079022 -0.03387,0.1636888 -0.01129,0.079022 -0.01129,0.1241776 0,0.090311 0.0508,0.1354666 0.0508,0.039511 0.124178,0.039511 0.107244,0 0.237067,-0.033867 0.129822,-0.039511 0.265288,-0.095956 v 0.8015105 q -0.174977,0.084667 -0.406399,0.1354665 -0.225778,0.0508 -0.530578,0.0508 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path927" />
<path
d="m 70.954734,7.1599009 q -0.592666,0 -0.914399,-0.3273775 -0.321733,-0.333022 -0.321733,-0.9087549 0,-0.3838219 0.107244,-0.7394217 0.112889,-0.3612441 0.333022,-0.6434661 0.220133,-0.2822221 0.553155,-0.4459108 0.338667,-0.1693332 0.795866,-0.1693332 0.524933,0 0.824089,0.2370665 0.299155,0.2370665 0.299155,0.6321773 0,0.513644 -0.400755,0.8297327 -0.400756,0.3160886 -1.275644,0.3160886 h -0.163689 v 0.045155 q 0,0.4063997 0.451556,0.4063997 0.237066,0 0.44591,-0.073378 0.214489,-0.073378 0.4572,-0.1975554 v 0.756355 q -0.248355,0.1241777 -0.519288,0.2031998 -0.265289,0.079022 -0.671689,0.079022 z m 0.02258,-1.885243 q 0.361244,0 0.502355,-0.1354666 0.141111,-0.141111 0.141111,-0.282222 0,-0.090311 -0.05644,-0.1467554 -0.05644,-0.062089 -0.174978,-0.062089 -0.124178,0 -0.231422,0.095955 -0.1016,0.095955 -0.169333,0.2427109 -0.06773,0.141111 -0.09031,0.2878665 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path929" />
<path
d="m 72.817404,7.1034565 0.660399,-3.1213754 h 0.852311 l -0.0508,0.5192885 h 0.02258 q 0.197556,-0.333022 0.4064,-0.4515552 0.214489,-0.1241777 0.530578,-0.1241777 0.06209,0 0.129822,0.00564 0.06773,0.00564 0.09031,0.016933 L 75.22758,5.0037248 q -0.05644,-0.028222 -0.146756,-0.045156 -0.09031,-0.016933 -0.191911,-0.016933 -0.248355,0 -0.434622,0.1693332 -0.180622,0.1693332 -0.276577,0.6208884 l -0.293511,1.371599 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path931" />
<path
d="m 76.576595,7.1599009 q -0.592667,0 -0.9144,-0.3273775 -0.321733,-0.333022 -0.321733,-0.9087549 0,-0.3838219 0.107245,-0.7394217 0.112888,-0.3612441 0.333022,-0.6434661 0.220133,-0.2822221 0.553155,-0.4459108 0.338666,-0.1693332 0.795866,-0.1693332 0.524933,0 0.824088,0.2370665 0.299155,0.2370665 0.299155,0.6321773 0,0.513644 -0.400755,0.8297327 -0.400755,0.3160886 -1.275643,0.3160886 h -0.163689 v 0.045155 q 0,0.4063997 0.451555,0.4063997 0.237067,0 0.445911,-0.073378 0.214489,-0.073378 0.4572,-0.1975554 v 0.756355 q -0.248356,0.1241777 -0.519289,0.2031998 -0.265289,0.079022 -0.671688,0.079022 z m 0.02258,-1.885243 q 0.361245,0 0.502356,-0.1354666 0.141111,-0.141111 0.141111,-0.282222 0,-0.090311 -0.05644,-0.1467554 -0.05644,-0.062089 -0.174977,-0.062089 -0.124178,0 -0.231422,0.095955 -0.1016,0.095955 -0.169334,0.2427109 -0.06773,0.141111 -0.09031,0.2878665 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path933" />
<path
d="m 79.810863,7.1599009 q -0.575733,0 -0.891821,-0.3104442 -0.310445,-0.3160887 -0.310445,-0.8918216 0,-0.4007552 0.112889,-0.7619994 0.112889,-0.3668886 0.333022,-0.6491106 0.220133,-0.2878665 0.547511,-0.4515552 0.333022,-0.1693332 0.767644,-0.1693332 0.575733,0 0.886177,0.3160886 0.316088,0.3104442 0.316088,0.8861771 0,0.4007553 -0.112888,0.7676439 -0.112889,0.3612442 -0.333022,0.6491106 -0.220133,0.282222 -0.553155,0.4515552 -0.327378,0.1636888 -0.762,0.1636888 z m 0.118533,-0.8015105 q 0.158045,0 0.282222,-0.1862665 0.124178,-0.191911 0.197556,-0.4797774 0.07338,-0.2935109 0.07338,-0.5983107 0,-0.3668886 -0.237067,-0.3668886 -0.158044,0 -0.282222,0.1919109 -0.124178,0.1862666 -0.197555,0.474133 -0.06773,0.2878665 -0.06773,0.5983107 0,0.3668886 0.231422,0.3668886 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path935" />
<path
d="m 81.436465,7.995278 q 0.400755,-0.4346218 0.711199,-0.9313326 0.310444,-0.5023552 0.485422,-1.0893769 0.180622,-0.5870218 0.180622,-1.2699991 0,-0.2652887 -0.03951,-0.5700884 -0.03951,-0.3047998 -0.112889,-0.6095996 -0.07338,-0.3047997 -0.174977,-0.564444 h 0.812799 q 0.146755,0.2483554 0.237066,0.5531551 0.09031,0.3047998 0.135467,0.6265329 0.04516,0.3160887 0.04516,0.6095995 0,0.9595549 -0.349956,1.7497765 -0.344311,0.7902216 -1.032932,1.4957766 z"
style="font-weight:900;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke:none;stroke-width:0.285"
id="path937" />
</g>
<path
id="path1348"
style="color:#000000;fill:#e0e0e0;fill-opacity:0.752941;stroke-width:0.714406;-inkscape-stroke:none"
d="M 5.4193109,1.6360535 C 4.0746261,1.6465667 2.9804856,2.7485866 2.9805103,4.0933129 v 1.5080987 0.00443 0.00406 0.00702 c 0.00324,0.6351315 0.1709081,1.2397841 0.5330952,1.705241 0.091293,0.1173226 0.1960748,0.2241342 0.3126952,0.3186015 V 5.3666133 h 0.00259 V 4.0933129 C 3.8288705,3.2043172 4.5362516,2.4899017 5.4252198,2.4829515 6.3176074,2.4761075 7.0387059,3.1839609 7.0477631,4.0763306 v 0.016982 1.6742295 c 0,0.3851813 -0.1170262,0.6035969 -0.3182329,0.7675243 C 6.5283236,6.6989941 6.2034026,6.8056753 5.769664,6.8056753 H 5.437754 V 8.3957797 H 6.193851 V 7.5229912 C 6.5799202,7.4642455 6.9804539,7.4245038 7.2655789,7.1922063 7.6635843,6.8679419 7.8946602,6.354867 7.8946602,5.7675423 V 4.0933128 4.0693159 4.0682086 C 7.8809586,2.7185401 6.7690097,1.6257071 5.4193109,1.6360535 Z"
sodipodi:nodetypes="ccccccscccccccsssccccsscccc" />
<g
aria-label="B"
id="text1054"
style="font-style:italic;font-weight:900;font-size:6.35px;font-family:Roboto;-inkscape-font-specification:'Roboto, Heavy Italic';fill:#e0e0e0;fill-opacity:0.752941;stroke-width:0.285001;stop-color:#000000"
transform="matrix(0.71440613,0,0,0.71440613,-2.144828,0.00813001)">
<path
id="path1085"
style="font-style:normal;-inkscape-font-specification:'Roboto, Heavy';stroke-width:0.285"
d="M 8.865092,5.8580404 V 8.9958333 11.74073 H 9.9533976 V 8.9958333 h 0.7441404 c 0.549837,-0.00413 0.964283,-0.116789 1.243335,-0.3379638 0.281119,-0.223242 0.42168,-0.5560389 0.42168,-0.9983887 0,-0.2439125 -0.06305,-0.4506186 -0.189136,-0.6201172 -0.12609,-0.1694982 -0.306958,-0.2852537 -0.542602,-0.3472656 0.208772,-0.078548 0.366902,-0.2005048 0.474389,-0.3658692 0.107487,-0.1653644 0.161231,-0.3648358 0.161231,-0.598413 0,-0.4051429 -0.151929,-0.7141686 -0.455786,-0.9270752 C 11.508859,4.5878339 11.18123,4.4813802 10.486698,4.4813802 H 9.9533976 c -1.0883054,0 -1.0883056,1.029605 -1.0883056,1.3766602 z m 1.0883056,-0.022757 c 0,-0.3308701 0.1341694,-0.4768142 0.3334184,-0.4952 l 0.199882,-0.018444 c 0.203885,-0.018814 0.420647,0.042375 0.530201,0.127124 0.109553,0.082682 0.164331,0.2191083 0.164331,0.4092774 0,0.1653644 -0.05064,0.2904216 -0.151929,0.3751709 -0.101285,0.08475 -0.270784,0.1281579 -0.508496,0.1302246 H 9.9533976 Z m 0,1.2412875 h 0.7627444 c 0.374137,0.00207 0.561206,0.1912032 0.561206,0.5674073 0,0.1632973 -0.05271,0.2904217 -0.15813,0.381372 -0.105419,0.088883 -0.256315,0.1333252 -0.452686,0.1333252 H 9.9533976 Z"
sodipodi:nodetypes="cccccccsscssczccssscssccsccscscc" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.
Binary file not shown.
+7 -7
View File
@@ -720,7 +720,7 @@ namespace pipedal
std::vector<float *> &buffers = this->captureBuffers;
int channels = this->captureChannels;
constexpr float scale = 1.0f / (std::numeric_limits<int16_t>::max() + 1L);
constexpr double scale = 1.0f / (std::numeric_limits<int16_t>::max() + 1L);
for (size_t frame = 0; frame < frames; ++frame)
{
for (int channel = 0; channel < channels; ++channel)
@@ -891,7 +891,7 @@ namespace pipedal
std::vector<float *> &buffers = this->playbackBuffers;
int channels = this->playbackChannels;
constexpr float scale = std::numeric_limits<int32_t>::max();
constexpr double scale = std::numeric_limits<int32_t>::max();
for (size_t frame = 0; frame < frames; ++frame)
{
for (int channel = 0; channel < channels; ++channel)
@@ -913,7 +913,7 @@ namespace pipedal
std::vector<float *> &buffers = this->playbackBuffers;
int channels = this->playbackChannels;
constexpr float scale = 0x00FFFFFF;
constexpr double scale = 0x00FFFFFF;
for (size_t frame = 0; frame < frames; ++frame)
{
for (int channel = 0; channel < channels; ++channel)
@@ -935,7 +935,7 @@ namespace pipedal
std::vector<float *> &buffers = this->playbackBuffers;
int channels = this->playbackChannels;
constexpr float scale = 0x00FFFFFF;
constexpr double scale = 0x00FFFFFF;
for (size_t frame = 0; frame < frames; ++frame)
{
for (int channel = 0; channel < channels; ++channel)
@@ -955,7 +955,7 @@ namespace pipedal
std::vector<float *> &buffers = this->playbackBuffers;
int channels = this->playbackChannels;
constexpr float scale = std::numeric_limits<int32_t>::max();
constexpr double scale = std::numeric_limits<int32_t>::max();
for (size_t frame = 0; frame < frames; ++frame)
{
for (int channel = 0; channel < channels; ++channel)
@@ -975,7 +975,7 @@ namespace pipedal
std::vector<float *> &buffers = this->playbackBuffers;
int channels = this->playbackChannels;
constexpr float scale = std::numeric_limits<int32_t>::max();
constexpr double scale = std::numeric_limits<int32_t>::max();
for (size_t frame = 0; frame < frames; ++frame)
{
for (int channel = 0; channel < channels; ++channel)
@@ -1000,7 +1000,7 @@ namespace pipedal
std::vector<float *> &buffers = this->playbackBuffers;
int channels = this->playbackChannels;
constexpr float scale = std::numeric_limits<int32_t>::max();
constexpr double scale = std::numeric_limits<int32_t>::max();
for (size_t frame = 0; frame < frames; ++frame)
{
for (int channel = 0; channel < channels; ++channel)
+1 -1
View File
@@ -867,6 +867,7 @@ private:
pEffect->RequestAllPathPatchProperties();
}
}
realtimeActivePedalboard->UpdateAudioPorts();
}
reEntered = false;
@@ -1696,7 +1697,6 @@ public:
{
if (pPedalboard)
{
pPedalboard->Deactivate();
std::lock_guard guard(mutex);
for (auto it = activePedalboards.begin(); it != activePedalboards.end(); ++it)
+1 -1
View File
@@ -5,7 +5,7 @@ set (CMAKE_INSTALL_PREFIX "/usr/")
set (USE_PCH 1)
set (ENABLE_BACKTRACE 1)
set (ENABLE_BACKTRACE 0)
set (USE_SANITIZE OFF) # seems to be broken on Ubuntu 24.10
+4 -2
View File
@@ -724,7 +724,8 @@ void SetVarPermissions(
if (chown(entry.path().c_str(), uid, gid) != 0)
{
std::cout << "Error: failed to set ownership of file " << entry.path() << std::endl;
// Expect spurious pulse config files to be un-chown-able.
// std::cout << "Error: failed to set ownership of file " << entry.path() << std::endl;
}
try
@@ -740,7 +741,8 @@ void SetVarPermissions(
}
catch (const std::exception &e)
{
std::cout << "Error: failed to set permissions on file " << entry.path() << std::endl;
// spurious errors on pulse config files.
// std::cout << "Error: failed to set permissions on file " << entry.path() << std::endl;
}
}
}
+68 -12
View File
@@ -353,7 +353,6 @@ void Lv2Effect::PreparePortIndices()
{
this->isInputTriggerControlPort[portIndex] = true;
}
}
}
}
@@ -402,6 +401,13 @@ void Lv2Effect::SetAudioInputBuffer(int index, float *buffer)
{
this->inputAudioBuffers[index] = buffer;
if (borrowedEffect)
{
// Already running on the realtime thread,
// so don't update the audio ports until the effect gets placed on the realtime thread.
return;
}
if (inputAudioPortIndices.size() == inputAudioBuffers.size())
{
int pluginIndex = this->inputAudioPortIndices[index];
@@ -409,12 +415,13 @@ void Lv2Effect::SetAudioInputBuffer(int index, float *buffer)
}
else
{
// cases: 1->0, 1->1, 2->0, 2->1
if (index < inputAudioPortIndices.size())
{
int pluginIndex = this->inputAudioPortIndices[index];
lilv_instance_connect_port(this->pInstance, pluginIndex, buffer);
}
throw std::runtime_error("Invalid input buffer index.");
// // cases: 1->0, 1->1, 2->0, 2->1
// if (index < inputAudioPortIndices.size())
// {
// int pluginIndex = this->inputAudioPortIndices[index];
// lilv_instance_connect_port(this->pInstance, pluginIndex, buffer);
// }
}
}
@@ -425,7 +432,7 @@ void Lv2Effect::SetAudioInputBuffer(float *left)
SetAudioInputBuffer(0, left);
SetAudioInputBuffer(1, left);
}
else if (GetNumberOfInputAudioBuffers() != 0)
else if (GetNumberOfInputAudioBuffers() != 0)
{
SetAudioInputBuffer(0, left);
}
@@ -448,9 +455,16 @@ void Lv2Effect::SetAudioOutputBuffer(int index, float *buffer)
{
this->outputAudioBuffers[index] = buffer;
if (borrowedEffect)
{
// Effect is already running on the realtime thread,
// so don't update the audio ports until the updated pedalboard gets placed on the realtime thread.
return;
}
if (this->inputAudioPortIndices.size() != 0) // i.e. we're not mixing a zero-input control
{
if ((size_t)index < this->inputAudioPortIndices.size())
if ((size_t)index < this->outputAudioPortIndices.size())
{
int pluginIndex = this->outputAudioPortIndices[index];
lilv_instance_connect_port(pInstance, pluginIndex, buffer);
@@ -470,6 +484,10 @@ int Lv2Effect::GetControlIndex(const std::string &key) const
Lv2Effect::~Lv2Effect()
{
if (activated)
{
Deactivate();
}
if (worker)
{
worker->Close();
@@ -489,11 +507,40 @@ Lv2Effect::~Lv2Effect()
void Lv2Effect::Activate()
{
if (this->activated)
{
return;
}
this->activated = true;
this->AssignUnconnectedPorts();
lilv_instance_activate(pInstance);
this->BypassTo(this->bypass ? 1.0f : 0.0f);
}
void Lv2Effect::UpdateAudioPorts()
{
// called on realtime thread to switch borrowed effects to the new buffer pointers.
if (borrowedEffect)
{
for (size_t i = 0; i < this->inputAudioPortIndices.size(); ++i)
{
int portIndex = this->inputAudioPortIndices[i];
if (GetAudioInputBuffer(i) != nullptr)
{
lilv_instance_connect_port(pInstance, portIndex, GetAudioInputBuffer(i));
}
}
for (size_t i = 0; i < this->outputAudioPortIndices.size(); ++i)
{
int portIndex = this->outputAudioPortIndices[i];
if (GetAudioOutputBuffer(i) != nullptr)
{
lilv_instance_connect_port(pInstance, portIndex, GetAudioOutputBuffer(i));
}
}
}
}
void Lv2Effect::AssignUnconnectedPorts()
{
for (size_t i = 0; i < this->inputAudioPortIndices.size(); ++i)
@@ -515,6 +562,7 @@ void Lv2Effect::AssignUnconnectedPorts()
{
float *buffer = bufferPool.AllocateBuffer<float>(pHost->GetMaxAudioBufferSize());
int pluginIndex = this->outputAudioPortIndices[i];
lilv_instance_connect_port(pInstance, pluginIndex, buffer);
}
}
}
@@ -545,6 +593,11 @@ void Lv2Effect::AssignUnconnectedPorts()
}
void Lv2Effect::Deactivate()
{
if (!activated)
{
return;
}
activated = false;
if (worker)
{
worker->Close();
@@ -591,15 +644,18 @@ void Lv2Effect::Run(uint32_t samples, RealtimeRingBufferWriter *realtimeRingBuff
for (size_t i = 0; i < this->outputMixBuffers.size(); ++i)
{
float *__restrict input;
if (i >= this->inputAudioBuffers.size()) {
if (i >= this->inputAudioBuffers.size())
{
if (this->inputAudioBuffers.size() == 0)
{
break;
}
input = this->inputAudioBuffers[0];
} else {
}
else
{
input = this->inputAudioBuffers[i];
}
}
float *__restrict pluginOutput = this->outputMixBuffers[i].data();
float *__restrict finalOutput = this->outputAudioBuffers[i];
+6 -1
View File
@@ -199,9 +199,14 @@ namespace pipedal
int actualAudioOutputs = 0;
std::vector<std::vector<float>> outputMixBuffers;
void BypassTo(float value);
bool borrowedEffect = false;
bool activated = false;
public:
bool IsBorrowedEffect() const { return borrowedEffect; }
void SetBorrowedEffect(bool value) { borrowedEffect = value; }
void UpdateAudioPorts();
// non RT-thread use only.
std::string GetPathPatchProperty(const std::string&propertyUri);
// non RT-thread use only.
+103 -62
View File
@@ -60,18 +60,20 @@ int Lv2Pedalboard::GetControlIndex(uint64_t instanceId, const std::string &symbo
std::vector<float *> Lv2Pedalboard::PrepareItems(
std::vector<PedalboardItem> &items,
std::vector<float *> inputBuffers,
Lv2PedalboardErrorList &errorList)
Lv2PedalboardErrorList &errorList,
ExistingEffectMap *existingEffects)
{
for (int i = 0; i < items.size(); ++i)
{
auto &item = items[i];
if (!item.isEmpty())
{
IEffect *pEffect = nullptr;
std::shared_ptr<IEffect> pEffect = nullptr;
if (item.isSplit())
{
auto pSplit = new SplitEffect(item.instanceId(), pHost->GetSampleRate(), inputBuffers);
pEffect = pSplit;
pEffect = std::shared_ptr<IEffect>(pSplit);
int topInputChannels = inputBuffers.size();
int bottomInputChannels = inputBuffers.size();
@@ -84,8 +86,8 @@ std::vector<float *> Lv2Pedalboard::PrepareItems(
this->processActions.push_back(preMixAction);
std::vector<float *> topResult = PrepareItems(item.topChain(), topInputs, errorList);
std::vector<float *> bottomResult = PrepareItems(item.bottomChain(), bottomInputs, errorList);
std::vector<float *> topResult = PrepareItems(item.topChain(), topInputs, errorList,existingEffects);
std::vector<float *> bottomResult = PrepareItems(item.bottomChain(), bottomInputs, errorList,existingEffects);
this->processActions.push_back(
[pSplit](uint32_t frames)
@@ -94,7 +96,7 @@ std::vector<float *> Lv2Pedalboard::PrepareItems(
// if split is L/R, always output stereo.
bool forceStereo = (controlValue != nullptr && controlValue->value() == 2);
pSplit->SetChainBuffers(topInputs, bottomInputs, topResult, bottomResult,forceStereo);
pSplit->SetChainBuffers(topInputs, bottomInputs, topResult, bottomResult, forceStereo);
for (int i = 0; i < item.controlValues().size(); ++i)
{
@@ -108,31 +110,40 @@ std::vector<float *> Lv2Pedalboard::PrepareItems(
}
else
{
std::shared_ptr<IEffect> pLv2Effect;
IEffect *pLv2Effect = nullptr;
try
if (existingEffects && existingEffects->contains(item.instanceId())
)
{
pLv2Effect = this->pHost->CreateEffect(item);
pLv2Effect = existingEffects->at(item.instanceId());
((Lv2Effect*)pLv2Effect.get())->SetBorrowedEffect(true);
}
catch (const std::exception &e)
else
{
Lv2Log::warning(SS(e.what()));
}
try
{
pLv2Effect = std::shared_ptr<IEffect>(this->pHost->CreateEffect(item));
}
catch (const std::exception &e)
{
Lv2Log::warning(SS(e.what()));
}
if (pLv2Effect)
{
if (pLv2Effect->HasErrorMessage())
if (pLv2Effect && pLv2Effect->HasErrorMessage())
{
std::string error = pLv2Effect->TakeErrorMessage();
Lv2Log::error(error);
errorList.push_back({item.instanceId(), error});
}
}
if (pLv2Effect)
{
pEffect = pLv2Effect;
uint64_t instanceId = pEffect->GetInstanceId();
pLv2Effect->PrepareNoInputEffect(inputBuffers.size(),pHost->GetMaxAudioBufferSize());
pLv2Effect->PrepareNoInputEffect(inputBuffers.size(), pHost->GetMaxAudioBufferSize());
if (inputBuffers.size() == 1)
{
@@ -173,35 +184,34 @@ std::vector<float *> Lv2Pedalboard::PrepareItems(
// Reset any trigger controls to default state after processing
if (pLv2Effect->IsLv2Effect())
{
Lv2Effect*lv2Effect = (Lv2Effect*)pLv2Effect;
Lv2Effect *lv2Effect = (Lv2Effect *)pLv2Effect.get();
auto pluginInfo = pHost->GetPluginInfo(item.uri());
if (pluginInfo) {
for (auto control: pluginInfo->ports())
if (pluginInfo)
{
for (auto control : pluginInfo->ports())
{
if (control->trigger_property() && control->is_input() && control->is_control_port())
{
int controlIndex = lv2Effect->GetControlIndex(control->symbol());
if (controlIndex >= 0)
if (controlIndex >= 0)
{
float defaultValue = control->default_value();
this->processActions.push_back(
[pLv2Effect,controlIndex,defaultValue](int32_t frames) {
pLv2Effect->SetControl(controlIndex,defaultValue);
}
);
[pLv2Effect, controlIndex, defaultValue](int32_t frames)
{
pLv2Effect->SetControl(controlIndex, defaultValue);
});
}
}
}
}
}
}
}
if (pEffect)
{
this->effects.push_back(std::shared_ptr<IEffect>(pEffect)); // for ownership.
this->realtimeEffects.push_back(pEffect); // because std::shared_ptr is not threadsafe.
this->effects.push_back(pEffect); // for ownership.
this->realtimeEffects.push_back(pEffect.get()); // because std::shared_ptr is not threadsafe.
std::vector<float *> effectOutput;
@@ -214,7 +224,7 @@ std::vector<float *> Lv2Pedalboard::PrepareItems(
effectOutput.push_back(CreateNewAudioBuffer());
effectOutput.push_back(CreateNewAudioBuffer());
}
for (size_t i = 0; i < effectOutput.size(); ++i)
for (size_t i = 0; i < effectOutput.size(); ++i)
{
pEffect->SetAudioOutputBuffer(i, effectOutput[i]);
}
@@ -225,7 +235,7 @@ std::vector<float *> Lv2Pedalboard::PrepareItems(
return inputBuffers;
}
void Lv2Pedalboard::Prepare(IHost *pHost, Pedalboard &pedalboard, Lv2PedalboardErrorList &errorList)
void Lv2Pedalboard::Prepare(IHost *pHost, Pedalboard &pedalboard, Lv2PedalboardErrorList &errorList, ExistingEffectMap *existingEffects)
{
this->pHost = pHost;
@@ -242,7 +252,7 @@ void Lv2Pedalboard::Prepare(IHost *pHost, Pedalboard &pedalboard, Lv2PedalboardE
this->pedalboardInputBuffers.push_back(bufferPool.AllocateBuffer<float>(pHost->GetMaxAudioBufferSize()));
}
auto outputs = PrepareItems(pedalboard.items(), this->pedalboardInputBuffers, errorList);
auto outputs = PrepareItems(pedalboard.items(), this->pedalboardInputBuffers, errorList, existingEffects);
int nOutputs = pHost->GetNumberOfOutputAudioChannels();
if (nOutputs == 1)
{
@@ -276,7 +286,6 @@ void Lv2Pedalboard::PrepareMidiMap(const PedalboardItem &pedalboardItem)
else
{
pluginInfo = pHost->GetPluginInfo(pedalboardItem.uri());
}
int effectIndex = this->GetIndexOfInstanceId(pedalboardItem.instanceId());
@@ -315,10 +324,15 @@ void Lv2Pedalboard::PrepareMidiMap(const PedalboardItem &pedalboardItem)
mapping.midiBinding = binding;
mapping.instanceId = pedalboardItem.instanceId();
if (pPortInfo->trigger_property())
if (pPortInfo->mod_momentaryOffByDefault() || pPortInfo->mod_momentaryOnByDefault())
{
mapping.mappingType = MidiControlType::MomentarySwitch;
}
else if (pPortInfo->trigger_property())
{
mapping.mappingType = MidiControlType::Trigger;
} else if (pPortInfo->IsSwitch())
}
else if (pPortInfo->IsSwitch())
{
mapping.mappingType = MidiControlType::Toggle;
}
@@ -326,7 +340,7 @@ void Lv2Pedalboard::PrepareMidiMap(const PedalboardItem &pedalboardItem)
{
mapping.mappingType = MidiControlType::Select;
}
else
else
{
mapping.mappingType = MidiControlType::Dial;
}
@@ -365,12 +379,25 @@ void Lv2Pedalboard::PrepareMidiMap(const Pedalboard &pedalboard)
{
auto &item = pedalboard.items()[i];
PrepareMidiMap(item);
}
std::sort(this->midiMappings.begin(), this->midiMappings.end(),
[](const MidiMapping &left, const MidiMapping &right)
{ return left.key < right.key; });
[](const MidiMapping &left, const MidiMapping &right)
{ return left.key < right.key; });
}
void Lv2Pedalboard::UpdateAudioPorts()
{
for (int i = 0; i < this->effects.size(); ++i)
{
IEffect *effect = this->realtimeEffects[i];
if (effect->IsLv2Effect())
{
Lv2Effect *lv2Effect = (Lv2Effect *)effect;
lv2Effect->UpdateAudioPorts();
}
}
}
void Lv2Pedalboard::Activate()
{
for (int i = 0; i < this->effects.size(); ++i)
@@ -522,19 +549,18 @@ void Lv2Pedalboard::ResetAtomBuffers()
}
}
void Lv2Pedalboard::GatherPathPatchProperties(IPatchWriterCallback*cbPatchWriter)
void Lv2Pedalboard::GatherPathPatchProperties(IPatchWriterCallback *cbPatchWriter)
{
for (auto& pEffect : this->effects) {
for (auto &pEffect : this->effects)
{
if (pEffect->IsLv2Effect())
{
Lv2Effect *pLv2Effect = (Lv2Effect*)pEffect.get();
Lv2Effect *pLv2Effect = (Lv2Effect *)pEffect.get();
pLv2Effect->GatherPathPatchProperties(cbPatchWriter);
}
}
}
void Lv2Pedalboard::ProcessParameterRequests(RealtimePatchPropertyRequest *pParameterRequests)
{
while (pParameterRequests != nullptr)
@@ -572,7 +598,6 @@ void Lv2Pedalboard::ProcessParameterRequests(RealtimePatchPropertyRequest *pPara
}
}
void Lv2Pedalboard::GatherPatchProperties(RealtimePatchPropertyRequest *pParameterRequests)
{
while (pParameterRequests != nullptr)
@@ -630,7 +655,7 @@ void Lv2Pedalboard::OnMidiMessage(size_t size, uint8_t *message,
if (size < 3)
return;
index = message[1];
value = message[2] == 0? 0: 127; // zero velocity = note off.
value = message[2] == 0 ? 0 : 127; // zero velocity = note off.
}
else if (cmd == 0xB0) // midi control.
{
@@ -689,22 +714,25 @@ void Lv2Pedalboard::OnMidiMessage(size_t size, uint8_t *message,
case MidiControlType::Trigger:
{
bool triggered = false;
if (mapping.midiBinding.switchControlType() == SwitchControlTypeT::TRIGGER_ON_RISING_EDGE
|| mapping.midiBinding.bindingType() == BINDING_TYPE_NOTE
)
if (mapping.midiBinding.switchControlType() == SwitchControlTypeT::TRIGGER_ON_RISING_EDGE || mapping.midiBinding.bindingType() == BINDING_TYPE_NOTE)
{
if (mapping.lastValue < range)
{
if (!mapping.lastValueIncreasing) {
if (!mapping.lastValueIncreasing)
{
triggered = true;
}
mapping.lastValueIncreasing = true;
mapping.lastValue = range;
} else {
}
else
{
mapping.lastValueIncreasing = false;
mapping.lastValue = range;
}
} else {
}
else
{
triggered = true;
}
if (triggered)
@@ -730,12 +758,15 @@ void Lv2Pedalboard::OnMidiMessage(size_t size, uint8_t *message,
{
if (range > mapping.lastValue)
{
if (!mapping.lastValueIncreasing) {
if (!mapping.lastValueIncreasing)
{
triggered = true;
}
mapping.lastValueIncreasing = true;
mapping.lastValue = range;
} else {
}
else
{
mapping.lastValueIncreasing = false;
mapping.lastValue = range;
}
@@ -748,30 +779,40 @@ void Lv2Pedalboard::OnMidiMessage(size_t size, uint8_t *message,
pEffect->SetControl(mapping.controlIndex, currentValue);
pfnCallback(callbackHandle, mapping.instanceId, mapping.pPortInfo->index(), currentValue);
}
} else if (mapping.midiBinding.switchControlType() == SwitchControlTypeT::TOGGLE_ON_VALUE)
}
else if (mapping.midiBinding.switchControlType() == SwitchControlTypeT::TOGGLE_ON_VALUE)
{
triggered = true;
mapping.lastValue = range;
IEffect *pEffect = this->realtimeEffects[mapping.effectIndex];
IEffect *pEffect = this->realtimeEffects[mapping.effectIndex];
float currentValue = pEffect->GetControlValue(mapping.controlIndex);
if (currentValue != range)
{
pEffect->SetControl(mapping.controlIndex, range);
pfnCallback(callbackHandle, mapping.instanceId, mapping.pPortInfo->index(), range);
}
} else {
}
else
{
// any control value toggles.
triggered = true;
mapping.lastValue = range;
IEffect *pEffect = this->realtimeEffects[mapping.effectIndex];
IEffect *pEffect = this->realtimeEffects[mapping.effectIndex];
float currentValue = pEffect->GetControlValue(mapping.controlIndex);
currentValue = currentValue == 0 ? 1: 0;
currentValue = currentValue == 0 ? 1 : 0;
pEffect->SetControl(mapping.controlIndex, currentValue);
pfnCallback(callbackHandle, mapping.instanceId, mapping.pPortInfo->index(), currentValue);
}
break;
}
case MidiControlType::MomentarySwitch:
{
IEffect *pEffect = this->realtimeEffects[mapping.effectIndex];
pEffect->SetControl(mapping.controlIndex, range != 0 ? mapping.pPortInfo->max_value() : mapping.pPortInfo->min_value());
// do NOT notify anyone!
}
break;
case MidiControlType::Select:
case MidiControlType::Dial:
{
@@ -780,12 +821,12 @@ void Lv2Pedalboard::OnMidiMessage(size_t size, uint8_t *message,
float currentValue = mapping.pPortInfo->rangeToValue(range);
if (pEffect->GetControlValue(mapping.controlIndex) != currentValue)
{
this->SetControlValue(mapping.effectIndex, mapping.controlIndex,currentValue);
this->SetControlValue(mapping.effectIndex, mapping.controlIndex, currentValue);
pfnCallback(callbackHandle, mapping.instanceId, mapping.pPortInfo->index(), currentValue);
}
break;
}
case MidiControlType::None:
case MidiControlType::None:
default:
break;
}
+12 -3
View File
@@ -35,6 +35,8 @@ namespace pipedal
class RealtimePatchPropertyRequest;
class RealtimeRingBufferWriter;
using ExistingEffectMap = std::map<uint64_t, std::shared_ptr<IEffect>>;
struct Lv2PedalboardError
{
int64_t intanceId;
@@ -78,7 +80,8 @@ namespace pipedal
Select,
Dial,
Toggle,
Trigger
Trigger,
MomentarySwitch
};
class MidiMapping
{
@@ -101,7 +104,8 @@ namespace pipedal
std::vector<float *> PrepareItems(
std::vector<PedalboardItem> &items,
std::vector<float *> inputBuffers,
Lv2PedalboardErrorList &errorList);
Lv2PedalboardErrorList &errorList,
ExistingEffectMap *existingEffects);
void PrepareMidiMap(const Pedalboard &pedalboard);
void PrepareMidiMap(const PedalboardItem &pedalboardItem);
@@ -114,9 +118,12 @@ namespace pipedal
Lv2Pedalboard() {}
~Lv2Pedalboard() {}
void Prepare(IHost *pHost, Pedalboard &pedalboard, Lv2PedalboardErrorList &errorList);
void Prepare(IHost *pHost, Pedalboard &pedalboard, Lv2PedalboardErrorList &errorList, ExistingEffectMap *existingEffects = nullptr);
std::vector<IEffect *> &GetEffects() { return realtimeEffects; }
std::vector<std::shared_ptr<IEffect>> &GetSharedEffectList() { return effects; }
int GetIndexOfInstanceId(uint64_t instanceId)
{
@@ -140,6 +147,8 @@ namespace pipedal
}
void Activate();
void Deactivate();
void UpdateAudioPorts();
bool Run(float **inputBuffers, float **outputBuffers, uint32_t samples, RealtimeRingBufferWriter *realtimeWriter);
void ResetAtomBuffers();
+4
View File
@@ -167,6 +167,10 @@ MimeTypes::MimeTypes()
AddMimeType("MPG", "video/mp2p");
AddMimeType("MPEG", "video/mp2p");
// custom.
AddMimeType("NAM", "application/x-nam+json");
}
const MimeTypes&MimeTypes::instance()
+31 -7
View File
@@ -508,6 +508,7 @@ void PiPedalModel::FireBanksChanged(int64_t clientId)
}
}
void PiPedalModel::FirePedalboardChanged(int64_t clientId, bool loadAudioThread)
{
if (loadAudioThread)
@@ -593,10 +594,28 @@ void PiPedalModel::UpdateCurrentPedalboard(int64_t clientId, Pedalboard &pedalbo
UpdateVst3Settings(pedalboard);
this->pedalboard = pedalboard;
UpdateDefaults(&this->pedalboard);
this->FirePedalboardChanged(clientId);
Lv2PedalboardErrorList errorMessages;
std::shared_ptr<Lv2Pedalboard> lv2Pedalboard{
this->pluginHost.UpdateLv2PedalboardStructure(pedalboard, this->lv2Pedalboard.get(), errorMessages)
};
this->lv2Pedalboard = lv2Pedalboard;
// apply the error messages to the lv2Pedalboard.
// return true if the error messages have changed
audioHost->SetPedalboard(lv2Pedalboard);
this->pedalboard = pedalboard;
previousPedalboard = this->pedalboard;
previousPedalboardLoaded = true;
this->pedalboard = pedalboard;
UpdateRealtimeVuSubscriptions();
UpdateRealtimeMonitorPortSubscriptions();
this->FirePedalboardChanged(clientId,false);
this->SetPresetChanged(clientId, true);
}
}
@@ -2159,10 +2178,10 @@ void PiPedalModel::OnNotifyMidiListen(bool isNote, uint8_t noteOrControl)
{
std::lock_guard<std::recursive_mutex> lock(mutex);
for (int i = 0; i < midiEventListeners.size(); ++i)
for (int i = 0; i < midiEventListeners.size(); ++i)
{
auto &listener = midiEventListeners[i];
if ((!isNote) || (!listener.listenForControlsOnly))
if ((!isNote) == (listener.listenForControls))
{
auto subscriber = this->GetNotificationSubscriber(listener.clientId);
if (subscriber)
@@ -2179,10 +2198,10 @@ void PiPedalModel::OnNotifyMidiListen(bool isNote, uint8_t noteOrControl)
audioHost->SetListenForMidiEvent(midiEventListeners.size() != 0);
}
void PiPedalModel::ListenForMidiEvent(int64_t clientId, int64_t clientHandle, bool listenForControlsOnly)
void PiPedalModel::ListenForMidiEvent(int64_t clientId, int64_t clientHandle, bool listenForControls)
{
std::lock_guard<std::recursive_mutex> lock(mutex);
MidiListener listener{clientId, clientHandle, listenForControlsOnly};
MidiListener listener{clientId, clientHandle, listenForControls};
midiEventListeners.push_back(listener);
audioHost->SetListenForMidiEvent(true);
}
@@ -2879,3 +2898,8 @@ void PiPedalModel::OnAlsaDriverTerminatedAbnormally() {
}
});
}
bool PiPedalModel::IsInUploadsDirectory(const std::string &path)
{
return storage.IsInUploadsDirectory(path);
}
+4 -2
View File
@@ -145,7 +145,7 @@ namespace pipedal
public:
int64_t clientId;
int64_t clientHandle;
bool listenForControlsOnly;
bool listenForControls;
};
class AtomOutputListener
{
@@ -436,7 +436,7 @@ namespace pipedal
JackServerSettings GetJackServerSettings();
void SetJackServerSettings(const JackServerSettings &jackServerSettings);
void ListenForMidiEvent(int64_t clientId, int64_t clientHandle, bool listenForControlsOnly);
void ListenForMidiEvent(int64_t clientId, int64_t clientHandle, bool listenForControls);
void CancelListenForMidiEvent(int64_t clientId, int64_t clientHandle);
void MonitorPatchProperty(int64_t clientId, int64_t clientHandle, uint64_t instanceId, const std::string &propertyUri);
@@ -456,6 +456,8 @@ namespace pipedal
std::string RenameFilePropertyFile(const std::string &oldRelativePath, const std::string &newRelativePath, const UiFileProperty &uiFileProperty);
FilePropertyDirectoryTree::ptr GetFilePropertydirectoryTree(const UiFileProperty &uiFileProperty,const std::string&selectedPath);
bool IsInUploadsDirectory(const std::string &path);
std::string UploadUserFile(const std::string &directory, int64_t instanceId, const std::string &patchProperty, const std::string &filename, std::istream &inputStream, size_t streamLength);
uint64_t CreateNewPreset();
+3 -3
View File
@@ -181,13 +181,13 @@ JSON_MAP_END()
class ListenForMidiEventBody
{
public:
bool listenForControlsOnly_;
bool listenForControls_;
int64_t handle_;
DECLARE_JSON_MAP(ListenForMidiEventBody);
};
JSON_MAP_BEGIN(ListenForMidiEventBody)
JSON_MAP_REFERENCE(ListenForMidiEventBody, listenForControlsOnly)
JSON_MAP_REFERENCE(ListenForMidiEventBody, listenForControls)
JSON_MAP_REFERENCE(ListenForMidiEventBody, handle)
JSON_MAP_END()
@@ -1072,7 +1072,7 @@ public:
{
ListenForMidiEventBody body;
pReader->read(&body);
this->model.ListenForMidiEvent(this->clientId, body.handle_, body.listenForControlsOnly_);
this->model.ListenForMidiEvent(this->clientId, body.handle_, body.listenForControls_);
}
else if (message == "cancelListenForMidiEvent")
{
+4
View File
@@ -33,6 +33,10 @@
#include "ModFileTypes.hpp"
#define PIPEDAL_PATCH "http://github.com/rerdavies/pipedal/patch"
#define PIPEDAL_PATCH_PREFIX PIPEDAL_PATCH "#"
#define PIPEDAL_PATCH__readable (PIPEDAL_PATCH_PREFIX "readable")
#define PIPEDAL_UI "http://github.com/rerdavies/pipedal/ui"
#define PIPEDAL_UI_PREFIX PIPEDAL_UI "#"
+36 -1
View File
@@ -172,6 +172,8 @@ void PluginHost::LilvUris::Initialize(LilvWorld *pWorld)
#define MOD_PREFIX "http://moddevices.com/ns/mod#"
mod__label = lilv_new_uri(pWorld, MOD_PREFIX "label");
mod__brand = lilv_new_uri(pWorld, MOD_PREFIX "brand");
mod__preferMomentaryOffByDefault = lilv_new_uri(pWorld, MOD_PREFIX "preferMomentaryOffByDefault");
mod__preferMomentaryOnByDefault = lilv_new_uri(pWorld, MOD_PREFIX "preferMomentaryOnByDefault");
// ui:portNotification
// [
// ui:portIndex 3;
@@ -191,6 +193,7 @@ void PluginHost::LilvUris::Initialize(LilvWorld *pWorld)
patch__writable = lilv_new_uri(pWorld, LV2_PATCH__writable);
patch__readable = lilv_new_uri(pWorld, LV2_PATCH__readable);
pipedal_patch__readable = lilv_new_uri(pWorld, PIPEDAL_PATCH__readable);
dc__format = lilv_new_uri(pWorld, "http://purl.org/dc/terms/format");
@@ -1000,7 +1003,8 @@ Lv2PortInfo::Lv2PortInfo(PluginHost *host, const LilvPlugin *plugin, const LilvP
}
}
this->integer_property_ = lilv_port_has_property(plugin, pPort, host->lilvUris->integer_property_uri);
this->mod_momentaryOffByDefault_ = lilv_port_has_property(plugin, pPort, host->lilvUris->mod__preferMomentaryOffByDefault);
this->mod_momentaryOnByDefault_ = lilv_port_has_property(plugin, pPort, host->lilvUris->mod__preferMomentaryOnByDefault);
this->enumeration_property_ = lilv_port_has_property(plugin, pPort, host->lilvUris->enumeration_property_uri);
this->toggled_property_ = lilv_port_has_property(plugin, pPort, host->lilvUris->core__toggled);
@@ -1238,6 +1242,32 @@ std::shared_ptr<Lv2PluginInfo> PluginHost::GetPluginInfo(const std::string &uri)
return ff->second;
}
Lv2Pedalboard *PluginHost::UpdateLv2PedalboardStructure(Pedalboard &pedalboard,Lv2Pedalboard *existingPedalboard,Lv2PedalboardErrorList &errorList)
{
ExistingEffectMap existingEffects;
if (existingPedalboard)
{
for (auto &effect : existingPedalboard->GetSharedEffectList())
{
if (effect->IsLv2Effect()) {
existingEffects[effect->GetInstanceId()] = effect;
}
}
}
Lv2Pedalboard *pPedalboard = new Lv2Pedalboard();
try
{
pPedalboard->Prepare(this, pedalboard, errorList,&existingEffects);
return pPedalboard;
}
catch (const std::exception &e)
{
delete pPedalboard;
throw;
}
}
Lv2Pedalboard *PluginHost::CreateLv2Pedalboard(Pedalboard &pedalboard, Lv2PedalboardErrorList &errorMessages)
{
Lv2Pedalboard *pPedalboard = new Lv2Pedalboard();
@@ -1697,6 +1727,8 @@ json_map::storage_type<Lv2PortInfo> Lv2PortInfo::jmap{
MAP_REF(Lv2PortInfo, integer_property),
MAP_REF(Lv2PortInfo, enumeration_property),
MAP_REF(Lv2PortInfo, toggled_property),
MAP_REF(Lv2PortInfo, mod_momentaryOffByDefault),
MAP_REF(Lv2PortInfo, mod_momentaryOnByDefault),
MAP_REF(Lv2PortInfo, not_on_gui),
MAP_REF(Lv2PortInfo, buffer_type),
MAP_REF(Lv2PortInfo, port_group),
@@ -1761,6 +1793,9 @@ json_map::storage_type<Lv2PluginUiPort> Lv2PluginUiPort::jmap{{
MAP_REF(Lv2PluginUiPort, range_steps),
MAP_REF(Lv2PluginUiPort, integer_property),
MAP_REF(Lv2PluginUiPort, mod_momentaryOffByDefault),
MAP_REF(Lv2PluginUiPort, mod_momentaryOnByDefault),
MAP_REF(Lv2PluginUiPort, enumeration_property),
MAP_REF(Lv2PluginUiPort, not_on_gui),
MAP_REF(Lv2PluginUiPort, toggled_property),
+20 -2
View File
@@ -218,6 +218,10 @@ namespace pipedal
bool integer_property_ = false;
bool enumeration_property_ = false;
bool toggled_property_ = false;
bool mod_momentaryOffByDefault_ = false;
bool mod_momentaryOnByDefault_ = false;
bool not_on_gui_ = false;
std::string buffer_type_;
std::string port_group_;
@@ -288,6 +292,8 @@ namespace pipedal
LV2_PROPERTY_GETSET_SCALAR(range_steps);
LV2_PROPERTY_GETSET_SCALAR(trigger_property);
LV2_PROPERTY_GETSET_SCALAR(integer_property);
LV2_PROPERTY_GETSET_SCALAR(mod_momentaryOffByDefault);
LV2_PROPERTY_GETSET_SCALAR(mod_momentaryOnByDefault);
LV2_PROPERTY_GETSET_SCALAR(enumeration_property);
LV2_PROPERTY_GETSET_SCALAR(toggled_property);
LV2_PROPERTY_GETSET_SCALAR(not_on_gui);
@@ -503,7 +509,12 @@ namespace pipedal
: symbol_(pPort->symbol()), index_(pPort->index()),
is_input_(pPort->is_input()), name_(pPort->name()), min_value_(pPort->min_value()), max_value_(pPort->max_value()),
default_value_(pPort->default_value()), range_steps_(pPort->range_steps()), display_priority_(pPort->display_priority()),
is_logarithmic_(pPort->is_logarithmic()), integer_property_(pPort->integer_property()), enumeration_property_(pPort->enumeration_property()),
is_logarithmic_(pPort->is_logarithmic()),
integer_property_(pPort->integer_property()),
mod_momentaryOffByDefault_(pPort->mod_momentaryOffByDefault()),
mod_momentaryOnByDefault_(pPort->mod_momentaryOnByDefault()),
enumeration_property_(pPort->enumeration_property()),
toggled_property_(pPort->toggled_property()), not_on_gui_(pPort->not_on_gui()), scale_points_(pPort->scale_points()),
trigger_property_(pPort->trigger_property()),
pipedal_ledColor_(pPort->pipedal_ledColor()),
@@ -544,6 +555,9 @@ namespace pipedal
int range_steps_ = 0;
bool integer_property_ = false;
bool mod_momentaryOffByDefault_ = false;
bool mod_momentaryOnByDefault_ = false;
bool enumeration_property_ = false;
bool not_on_gui_ = false;
bool toggled_property_ = false;
@@ -743,10 +757,12 @@ namespace pipedal
AutoLilvNode patch__writable;
AutoLilvNode patch__readable;
AutoLilvNode pipedal_patch__readable;
AutoLilvNode mod__brand;
AutoLilvNode mod__label;
AutoLilvNode mod__preferMomentaryOffByDefault;
AutoLilvNode mod__preferMomentaryOnByDefault;
AutoLilvNode dc__format;
AutoLilvNode mod__fileTypes;
@@ -885,6 +901,8 @@ namespace pipedal
virtual Lv2Pedalboard *CreateLv2Pedalboard(Pedalboard &pedalboard,Lv2PedalboardErrorList &errorList);
virtual Lv2Pedalboard *UpdateLv2PedalboardStructure(Pedalboard &pedalboard,Lv2Pedalboard *existingPedalboard,Lv2PedalboardErrorList &errorList);
void setSampleRate(double sampleRate)
{
this->sampleRate = sampleRate;
+32 -14
View File
@@ -153,7 +153,7 @@ namespace pipedal
}
}
template <class Clock, class Duration>
RingBufferStatus readWait_until(size_t size,const std::chrono::time_point<Clock, Duration> &time_point)
RingBufferStatus readWait_until(size_t size, const std::chrono::time_point<Clock, Duration> &time_point)
{
while (true)
{
@@ -161,7 +161,7 @@ namespace pipedal
{
std::unique_lock lock(mutex);
size_t available = readSpace_();
if (available >= size)
if (available >= size)
{
return RingBufferStatus::Ready;
}
@@ -215,12 +215,13 @@ namespace pipedal
return (size_t)size;
}
size_t readSpace()
{
std::unique_lock lock(mutex);
return readSpace_();
}
bool write(size_t bytes, uint8_t *data)
{
if (MULTI_WRITER)
@@ -273,7 +274,7 @@ namespace pipedal
if (MULTI_WRITER)
{
std::lock_guard guard(writeMutex);
if (writeSpace() <= sizeof(bytes) + bytes +bytes2)
if (writeSpace() <= sizeof(bytes) + bytes + bytes2)
{
return false;
}
@@ -340,6 +341,23 @@ namespace pipedal
}
}
size_t read_packet(size_t maxSize, void*data) {
size_t packet_size;
if (!read(sizeof(packet_size), (uint8_t*)&packet_size))
{
throw std::runtime_error("RingBuffer::read_packet: failed to read packet size.");
}
if (packet_size > maxSize)
{
throw std::runtime_error("RingBuffer::read_packet: packet size too large.");
}
if (!read(packet_size, (uint8_t*)data))
{
throw std::runtime_error("RingBuffer::read_packet: failed to read packet data.");
}
return packet_size;
}
bool read(size_t bytes, uint8_t *data)
{
if (readSpace() < bytes)
@@ -366,18 +384,20 @@ namespace pipedal
delete[] buffer;
}
bool isReadReady() {
bool isReadReady()
{
std::lock_guard lock(mutex);
if (isReadReady_()) return true;
if (isReadReady_())
return true;
return !this->is_open;
}
bool isReadReady(size_t size) {
bool isReadReady(size_t size)
{
size_t available = readSpace();
return available >= size;
}
private:
size_t readSpace_()
{
int64_t size = writePosition - readPosition;
@@ -389,7 +409,7 @@ namespace pipedal
uint32_t peekSize()
{
volatile uint32_t result;
uint8_t *p = (uint8_t*)&result;
uint8_t *p = (uint8_t *)&result;
size_t ix = this->readPosition;
for (size_t i = 0; i < sizeof(result); ++i)
{
@@ -400,14 +420,12 @@ namespace pipedal
bool isReadReady_()
{
size_t available = readSpace_();
if (available < sizeof(uint32_t)) return false;
if (available < sizeof(uint32_t))
return false;
// peak to get the size!
uint32_t packetSize = peekSize();
return packetSize+sizeof(uint32_t) <= available;
return packetSize + sizeof(uint32_t) <= available;
}
};
};
+1
View File
@@ -327,6 +327,7 @@ namespace pipedal
return;
}
}
template <typename T>
void write(RingBufferCommand command, const T &value, size_t dataLength, uint8_t *variableData)
{
+73 -2
View File
@@ -34,6 +34,7 @@
#include "PresetBundle.hpp"
#include "json.hpp"
#include "HotspotManager.hpp"
#include "MimeTypes.hpp"
#define OLD_PRESET_EXTENSION ".piPreset"
#define PRESET_EXTENSION ".piPreset"
@@ -51,6 +52,22 @@ using namespace pipedal;
using namespace boost::system;
namespace fs = std::filesystem;
static bool HasDotDot(const std::filesystem::path &path) {
for (auto &part : path)
{
if (part == "..") {
return true;
}
if (part == ".")
{
return true;
}
}
return false;
}
class UserUploadResponse
{
public:
@@ -63,6 +80,13 @@ JSON_MAP_REFERENCE(UserUploadResponse, errorMessage)
JSON_MAP_REFERENCE(UserUploadResponse, path)
JSON_MAP_END()
static std::string GetMimeType(const std::filesystem::path&path) {
std::string extension = path.extension();
const MimeTypes&mimeTypes = MimeTypes::instance();
auto result = mimeTypes.MimeTypeFromExtension(extension);
return result;
}
static bool IsZipFile(const std::filesystem::path &path)
{
std::ifstream f(path);
@@ -119,6 +143,10 @@ public:
return false;
}
std::string segment = request_uri.segment(1);
if (segment == "downloadMediaFile")
{
return true;
}
if (segment == "uploadPluginPresets")
{
return true;
@@ -154,7 +182,7 @@ public:
return false;
}
std::string GetContentDispositionHeader(const std::string &name, const std::string &extension)
static std::string GetContentDispositionHeader(const std::string &name, const std::string &extension)
{
std::string fileName = name.substr(0, 64) + extension;
std::stringstream s;
@@ -218,6 +246,26 @@ public:
try
{
std::string segment = request_uri.segment(1);
if (segment == "downloadMediaFile") {
fs::path path = request_uri.query("path");
if (!fs::exists(path) || !this->model->IsInUploadsDirectory(path) || HasDotDot(path))
{
throw PiPedalException("File not found.");
}
auto mimeType = GetMimeType(path);
if (mimeType.empty()) {
throw PiPedalException("Can't download files of this type.");
}
res.set(HttpField::content_type, mimeType);
res.set(HttpField::cache_control, "no-cache");
std::string disposition = GetContentDispositionHeader(path.stem().string(), path.extension().string());
res.set(HttpField::content_disposition, disposition);
size_t contentLength = std::filesystem::file_size(path);
res.setContentLength(contentLength);
return;
}
if (segment == "downloadPluginPresets")
{
std::string name;
@@ -235,6 +283,7 @@ public:
res.set(HttpField::content_disposition, GetContentDispositionHeader(name, PLUGIN_PRESETS_EXTENSION));
return;
}
if (segment == "downloadPreset")
{
std::string name;
@@ -294,7 +343,29 @@ public:
{
std::string segment = request_uri.segment(1);
if (segment == "downloadPluginPresets")
if (segment == "downloadMediaFile") {
fs::path path = request_uri.query("path");
bool t = this->model->IsInUploadsDirectory(path);
std::cout << (t? "true": "false") << std::endl;
(void)t;
if (!fs::exists(path) || !this->model->IsInUploadsDirectory(path) || HasDotDot(path))
{
throw PiPedalException("File not found.");
}
auto mimeType = GetMimeType(path);
if (mimeType.empty()) {
throw PiPedalException("Can't download files of this type.");
}
res.set(HttpField::content_type, mimeType);
res.set(HttpField::cache_control, "no-cache");
std::string disposition = GetContentDispositionHeader(path.stem().string(), path.extension().string());
res.set(HttpField::content_disposition, disposition);
size_t contentLength = std::filesystem::file_size(path);
res.setContentLength(contentLength);
res.setBodyFile(path,false);
return;
} else if (segment == "downloadPluginPresets")
{
std::string name;
std::string content;
Executable
+2
View File
@@ -0,0 +1,2 @@
#!/bin/bash
npm run dev -- --host 0.0.0.0
+1 -1
View File
@@ -29,7 +29,7 @@
"@vitejs/plugin-react": "^4.3.4",
"eslint": "^9.19.0",
"eslint-plugin-react-hooks": "^5.0.0",
"eslint-plugin-react-refresh": "^0.4.18",
"eslint-plugin-react-refresh": "^0.4.19",
"globals": "^15.14.0",
"typescript": "~5.7.2",
"typescript-eslint": "^8.22.0",
+1 -1
View File
@@ -31,7 +31,7 @@
"@vitejs/plugin-react": "^4.3.4",
"eslint": "^9.19.0",
"eslint-plugin-react-hooks": "^5.0.0",
"eslint-plugin-react-refresh": "^0.4.18",
"eslint-plugin-react-refresh": "^0.4.19",
"globals": "^15.14.0",
"typescript": "~5.7.2",
"typescript-eslint": "^8.22.0",
+1 -1
View File
@@ -44,7 +44,7 @@ import ListItemIcon from '@mui/material/ListItemIcon';
import ListItemText from '@mui/material/ListItemText';
import CircularProgress from '@mui/material/CircularProgress';
import { type OnChangedHandler } from './ObservableProperty';
import ErrorOutlineIcon from '@mui/icons-material/Error';
import ErrorOutlineIcon from '@mui/icons-material/ErrorOutline';
import ResizeResponsiveComponent from './ResizeResponsiveComponent';
import Button from '@mui/material/Button';
import PresetSelector from './PresetSelector';
+115 -42
View File
@@ -19,7 +19,7 @@
import React from 'react';
import {createStyles} from './WithStyles';
import { createStyles } from './WithStyles';
import { Theme } from '@mui/material/styles';
@@ -33,6 +33,7 @@ import { PiPedalModel, PiPedalModelFactory, FileEntry, BreadcrumbEntry, FileRequ
import { isDarkMode } from './DarkMode';
import Button from '@mui/material/Button';
import FileUploadIcon from '@mui/icons-material/FileUpload';
import FileDownloadIcon from '@mui/icons-material/FileDownload';
import AudioFileIcon from '@mui/icons-material/AudioFile';
import ArrowBackIcon from '@mui/icons-material/ArrowBack';
import FolderIcon from '@mui/icons-material/Folder';
@@ -100,6 +101,7 @@ export interface FilePropertyDialogProps extends WithStyles<typeof styles> {
instanceId: number,
selectedFile: string,
onOk: (fileProperty: UiFileProperty, selectedItem: string) => void,
onApply: (fileProperty: UiFileProperty, selectedItem: string) => void,
onCancel: () => void
};
export interface FilePropertyDialogState {
@@ -108,9 +110,11 @@ export interface FilePropertyDialogState {
selectedFileIsDirectory: boolean;
selectedFileProtected: boolean;
hasSelection: boolean;
hasFileSelection: boolean;
canDelete: boolean;
fileResult: FileRequestResult;
navDirectory: string;
windowWidth: number;
uploadDirectory: string;
isProtectedDirectory: boolean;
columns: number;
@@ -121,6 +125,7 @@ export interface FilePropertyDialogState {
newFolderDialogOpen: boolean;
renameDialogOpen: boolean;
moveDialogOpen: boolean;
initialSelection: string;
};
function pathExtension(path: string) {
@@ -199,10 +204,12 @@ export default withStyles(
fullScreen: this.getFullScreen(),
selectedFile: selectedFile,
selectedFileProtected: true,
windowWidth: this.windowSize.width,
selectedFileIsDirectory: false,
navDirectory: this.getNavDirectoryFromFile(selectedFile, props.fileProperty),
uploadDirectory: "",
hasSelection: false,
hasFileSelection: false,
canDelete: false,
columns: 0,
columnWidth: 1,
@@ -213,7 +220,8 @@ export default withStyles(
menuAnchorEl: null,
newFolderDialogOpen: false,
renameDialogOpen: false,
moveDialogOpen: false
moveDialogOpen: false,
initialSelection: this.props.selectedFile
};
this.requestScroll = true;
}
@@ -259,12 +267,13 @@ export default withStyles(
// }
filesResult.files.splice(0, 0, { pathname: "", displayName: "<none>", isDirectory: false, isProtected: true });
let fileEntry = this.getFileEntry(filesResult.files, this.state.selectedFile);
let fileEntry = this.getFileEntry(filesResult.files, this.state.selectedFile);
this.setState({
isProtectedDirectory: filesResult.isProtected,
fileResult: filesResult,
hasSelection: !!fileEntry,
selectedFileProtected: fileEntry ? fileEntry.isProtected: true,
hasFileSelection: !!fileEntry && (!fileEntry.isDirectory) && (!fileEntry.isProtected),
selectedFileProtected: fileEntry ? fileEntry.isProtected : true,
navDirectory: navPath,
uploadDirectory: filesResult.currentDirectory
});
@@ -297,7 +306,8 @@ export default withStyles(
onWindowSizeChanged(width: number, height: number): void {
this.setState({
fullScreen: this.getFullScreen()
fullScreen: this.getFullScreen(),
windowWidth: width
})
if (this.lastDivRef !== null) {
this.onMeasureRef(this.lastDivRef);
@@ -373,11 +383,16 @@ export default withStyles(
onSelectValue(fileEntry: FileEntry) {
this.requestScroll = true;
if (!fileEntry.isDirectory)
{
this.props.onApply(this.props.fileProperty,fileEntry.pathname);
}
this.setState({
selectedFile: fileEntry.pathname,
selectedFileIsDirectory: fileEntry.isDirectory,
selectedFileProtected: fileEntry.isProtected,
hasSelection: this.isFileInList(this.state.fileResult.files, fileEntry.pathname)
hasSelection: this.isFileInList(this.state.fileResult.files, fileEntry.pathname),
hasFileSelection: !fileEntry.isDirectory && !fileEntry.isDirectory && !fileEntry.isProtected
})
}
onDoubleClickValue(selectedFile: string) {
@@ -392,14 +407,21 @@ export default withStyles(
this.setState({ menuAnchorEl: null });
}
handleDelete() {
if (this.state.selectedFileProtected) {
return;
if (this.state.selectedFileProtected) {
return;
}
this.setState({ openConfirmDeleteDialog: true });
}
handleDownloadFile() {
if (this.state.selectedFileProtected || !this.state.hasFileSelection) {
return;
}
let file = this.state.selectedFile;
this.model.downloadAudioFile(file);
}
handleConfirmDelete() {
if (this.state.selectedFileProtected) {
return;
if (this.state.selectedFileProtected) {
return;
}
this.setState({ openConfirmDeleteDialog: false });
if (this.state.hasSelection) {
@@ -424,20 +446,21 @@ export default withStyles(
this.model.deleteUserFile(this.state.selectedFile)
.then(
() => {
if (newSelection)
{
this.setState({
if (newSelection) {
this.setState({
selectedFile: newSelection.pathname,
selectedFileIsDirectory: newSelection.isDirectory,
selectedFileProtected: newSelection.isProtected,
hasSelection: true
hasSelection: true,
hasFileSelection: !newSelection.isDirectory && !newSelection.isProtected
});
} else {
this.setState({
selectedFile: "",
selectedFileIsDirectory: false,
selectedFileProtected: true,
hasSelection: false
hasSelection: false,
hasFileSelection: false
});
}
@@ -580,8 +603,7 @@ export default withStyles(
}
let protectedDirectory = this.state.fileResult.isProtected;
let protectedItem = true;
if (this.state.hasSelection)
{
if (this.state.hasSelection) {
protectedItem = this.state.selectedFileProtected;
}
let canMoveOrRename = this.hasSelectedFileOrFolder() && !protectedItem;
@@ -719,31 +741,82 @@ export default withStyles(
</DialogContent>
<Divider />
<DialogActions style={{ justifyContent: "stretch" }}>
<div style={{ display: "flex", width: "100%", alignItems: "center", flexFlow: "row nowrap" }}>
<IconButton style={{ visibility: (this.state.hasSelection ? "visible" : "hidden") }} aria-label="delete" component="label" color="primary"
disabled={!this.state.hasSelection || this.state.selectedFile === "" || protectedItem}
onClick={() => this.handleDelete()} >
<OldDeleteIcon fontSize='small' />
</IconButton>
{this.state.windowWidth > 500 ? (
<div style={{ display: "flex", width: "100%", alignItems: "center", flexFlow: "row nowrap" }}>
<IconButton style={{ visibility: (this.state.hasSelection ? "visible" : "hidden") }} aria-label="delete" component="label" color="primary"
disabled={!this.state.hasSelection || this.state.selectedFile === "" || protectedItem}
onClick={() => this.handleDelete()} >
<OldDeleteIcon fontSize='small' />
</IconButton>
<Button style={{ flex: "0 0 auto" }} aria-label="upload" variant="text" startIcon={<FileUploadIcon />}
onClick={() => { this.setState({ openUploadFileDialog: true }) }} disabled={protectedDirectory}
>
<div>Upload</div>
</Button>
<div style={{ flex: "1 1 auto" }}>&nbsp;</div>
<Button style={{ flex: "0 0 auto" }} aria-label="upload" variant="text" startIcon={<FileUploadIcon />}
onClick={() => { this.setState({ openUploadFileDialog: true }) }} disabled={protectedDirectory}
>
<div>Upload</div>
</Button>
<Button variant="dialogSecondary" onClick={() => { this.props.onCancel(); }} aria-label="cancel">
Cancel
</Button>
<Button variant="dialogPrimary" style={{ flex: "0 0 auto" }}
onClick={() => { this.openSelectedFile(); }}
<Button style={{ flex: "0 0 auto" }} aria-label="upload" variant="text" startIcon={<FileDownloadIcon />}
onClick={() => { this.handleDownloadFile(); }} disabled={protectedDirectory || !this.state.hasFileSelection}
>
<div>Download</div>
</Button>
disabled={(!this.state.hasSelection) && this.state.selectedFile !== ""} aria-label="select"
>
{okButtonText}
</Button>
</div>
<div style={{ flex: "1 1 auto" }}>&nbsp;</div>
<Button variant="dialogSecondary" onClick={() => {
this.props.onApply(this.props.fileProperty,this.state.initialSelection);
this.props.onCancel();
}} aria-label="cancel">
Cancel
</Button>
<Button variant="dialogPrimary" style={{ flex: "0 0 auto" }}
onClick={() => { this.openSelectedFile(); }}
disabled={(!this.state.hasSelection) && this.state.selectedFile !== ""} aria-label="select"
>
{okButtonText}
</Button>
</div>
) : (
<div style={{width: "100%"}}>
<div style={{ display: "flex", width: "100%", alignItems: "center", flexFlow: "row nowrap" }}>
<IconButton style={{ visibility: (this.state.hasSelection ? "visible" : "hidden") }} aria-label="delete" component="label" color="primary"
disabled={!this.state.hasSelection || this.state.selectedFile === "" || protectedItem}
onClick={() => this.handleDelete()} >
<OldDeleteIcon fontSize='small' />
</IconButton>
<Button style={{ flex: "0 0 auto" }} aria-label="upload" variant="text" startIcon={<FileUploadIcon />}
onClick={() => { this.setState({ openUploadFileDialog: true }) }} disabled={protectedDirectory}
>
<div>Upload</div>
</Button>
<Button style={{ flex: "0 0 auto" }} aria-label="upload" variant="text" startIcon={<FileDownloadIcon />}
onClick={() => { this.handleDownloadFile(); }} disabled={protectedDirectory || !this.state.hasFileSelection}
>
<div>Download</div>
</Button>
<div style={{ flex: "1 1 auto" }}>&nbsp;</div>
</div>
<div style={{ display: "flex", width: "100%", alignItems: "center", flexFlow: "row nowrap" }}>
<div style={{ flex: "1 1 auto" }}>&nbsp;</div>
<Button variant="dialogSecondary" onClick={() => { this.props.onCancel(); }} aria-label="cancel">
Cancel
</Button>
<Button variant="dialogPrimary" style={{ flex: "0 0 auto" }}
onClick={() => { this.openSelectedFile(); }}
disabled={(!this.state.hasSelection) && this.state.selectedFile !== ""} aria-label="select"
>
{okButtonText}
</Button>
</div>
</div>
)}
</DialogActions>
<UploadFileDialog
open={this.state.openUploadFileDialog}
@@ -897,10 +970,10 @@ export default withStyles(
private onExecuteNewFolder(newName: string) {
this.model.createNewSampleDirectory(pathConcat(this.state.navDirectory, newName), this.props.fileProperty)
.then((newPath) => {
this.setState({
this.setState({
selectedFile: newPath,
selectedFileIsDirectory:
true,selectedFileProtected: false
selectedFileIsDirectory:
true, selectedFileProtected: false
});
this.requestFiles(this.state.navDirectory);
this.requestScroll = true
+1 -1
View File
@@ -197,7 +197,7 @@ const GxTunerControl =
let nameIndex = noteNumber -octave* tet;
if (nameIndex < 0) nameIndex += tet;
name = names[ nameIndex ] + (octave-2);
name = names[ nameIndex ] + (octave-1);
valid = true;
fraction = note-noteNumber;
if (fraction >= 0) {
+29 -3
View File
@@ -451,9 +451,12 @@ export enum ControlType {
ABSwitch,
Select,
Trigger,
Momentary,
MomentaryOnByDefault,
Tuner,
Vu,
Progress,
DbVu,
OutputText
}
@@ -494,6 +497,8 @@ deserialize(input: any): UiControl {
this.display_priority = input.display_priority;
this.range_steps = input.range_steps;
this.integer_property = input.integer_property;
this.mod_momentaryOffByDefault = input.mod_momentaryOffByDefault;
this.mod_momentaryOnByDefault = input.mod_momentaryOnByDefault;
this.enumeration_property = input.enumeration_property;
this.toggled_property = input.toggled_property;
this.trigger_property = input.trigger_property;
@@ -522,6 +527,8 @@ deserialize(input: any): UiControl {
} else if (this.units === Units.db) {
this.controlType = ControlType.DbVu;
} else if (this.units === Units.pc) {
this.controlType = ControlType.Progress;
} else if (this.enumeration_property) {
this.controlType = ControlType.OutputText;
} else if (displayUnitAsText(this.units))
@@ -533,7 +540,7 @@ deserialize(input: any): UiControl {
}
if (this.isValidEnumeration()) {
this.controlType = ControlType.Select;
if (this.scale_points.length === 2) {
if (this.scale_points.length === 2 && this.min_value === 0 && this.max_value === 1) {
this.controlType = ControlType.ABSwitch;
}
} else {
@@ -541,9 +548,15 @@ deserialize(input: any): UiControl {
this.controlType = ControlType.OnOffSwitch;
}
}
if (this.is_input && this.trigger_property)
if (this.is_input)
{
this.controlType = ControlType.Trigger;
if (this.mod_momentaryOnByDefault) {
this.controlType = ControlType.MomentaryOnByDefault;
} else if (this.mod_momentaryOffByDefault) {
this.controlType = ControlType.Momentary;
} else if (this.trigger_property) {
this.controlType = ControlType.Trigger;
}
}
return this;
}
@@ -591,6 +604,8 @@ deserialize(input: any): UiControl {
display_priority: number = -1;
range_steps: number = 0;
integer_property: boolean = false;
mod_momentaryOffByDefault: boolean = false;
mod_momentaryOnByDefault: boolean = false;
enumeration_property: boolean = false;
trigger_property: boolean = false;
not_on_gui: boolean = false;
@@ -640,6 +655,14 @@ deserialize(input: any): UiControl {
isTrigger(): boolean {
return this.controlType === ControlType.Trigger;
}
isMomentary(): boolean {
return this.controlType === ControlType.Momentary;
}
isMomentaryOnByDefault(): boolean {
return this.controlType === ControlType.MomentaryOnByDefault;
}
isOutputText(): boolean {
return !this.is_input && this.controlType === ControlType.OutputText;
}
@@ -662,6 +685,9 @@ deserialize(input: any): UiControl {
isDbVu(): boolean {
return this.controlType === ControlType.DbVu;
}
isProgress(): boolean {
return this.controlType === ControlType.Progress;
}
valueToRange(value: number): number {
if (this.toggled_property) return value === 0 ? 0 : 1;
+13 -4
View File
@@ -48,10 +48,11 @@ const styles = (theme: Theme) => createStyles({
enum MidiControlType {
None,
Select,
Dial,
Toggle,
Trigger,
Dial,
Select,
MomentarySwitch
}
interface MidiBindingViewProps extends WithStyles<typeof styles> {
@@ -149,7 +150,7 @@ const MidiBindingView =
for (let i = 0; i < 127; ++i) {
result.push(
<MenuItem value={i}>{Utility.midiNoteName(i)}</MenuItem>
<MenuItem key={"k" + i} value={i}>{Utility.midiNoteName(i)}</MenuItem>
)
}
@@ -188,6 +189,12 @@ const MidiBindingView =
let port = this.props.uiPlugin.getControl(this.props.midiBinding.symbol);
if (!port) return MidiControlType.None;
if (port.mod_momentaryOffByDefault || port.mod_momentaryOnByDefault) {
return MidiControlType.MomentarySwitch;
}
if (port.trigger_property) {
return MidiControlType.Trigger;
}
if (port.trigger_property) {
return MidiControlType.Trigger;
}
@@ -230,7 +237,9 @@ const MidiBindingView =
value={midiBinding.bindingType}
>
<MenuItem value={0}>None</MenuItem>
{(controlType === MidiControlType.Toggle || controlType === MidiControlType.Trigger) && (
{(controlType === MidiControlType.Toggle
|| controlType === MidiControlType.Trigger
|| controlType === MidiControlType.MomentarySwitch) && (
<MenuItem value={1}>Note</MenuItem>
)}
<MenuItem value={2}>Control</MenuItem>
+114 -100
View File
@@ -24,7 +24,7 @@ import { PiPedalModel, PiPedalModelFactory, ListenHandle } from './PiPedalModel'
import Typography from '@mui/material/Typography';
import { Theme } from '@mui/material/styles';
import WithStyles from './WithStyles';
import {createStyles} from './WithStyles';
import { createStyles } from './WithStyles';
import { withStyles } from "tss-react/mui";
import AppBar from '@mui/material/AppBar';
@@ -34,7 +34,7 @@ import IconButton from '@mui/material/IconButton';
import MidiBinding from './MidiBinding';
import MidiBindingView from './MidiBindingView';
import Snackbar from '@mui/material/Snackbar';
import { UiPlugin,makeSplitUiPlugin } from './Lv2Plugin';
import { PortGroup, UiPlugin, makeSplitUiPlugin } from './Lv2Plugin';
import { css } from '@emotion/react';
const styles = (theme: Theme) => createStyles({
@@ -54,6 +54,11 @@ const styles = (theme: Theme) => createStyles({
pluginHead: css({
borderTop: "1pt #DDD solid", paddingLeft: 22, paddingRight: 22
}),
groupHead: css({
borderBottom: "1px solid " + theme.palette.divider,
marginLeft: 0,
marginBottom: 0
}),
bindingTd: css({
verticalAlign: "top",
paddingLeft: 12, paddingBottom: 8
@@ -65,7 +70,7 @@ const styles = (theme: Theme) => createStyles({
}),
});
function not_null<T>(value: T | null) {
function not_null<T>(value: T | null) {
if (!value) throw Error("Unexpected null value");
return value;
}
@@ -116,8 +121,7 @@ export const MidiBindingDialog =
clearTimeout(this.listenTimeoutHandle);
this.listenTimeoutHandle = undefined;
}
if (this.listenHandle)
{
if (this.listenHandle) {
this.model.cancelListenForMidiEvent(this.listenHandle)
this.listenHandle = undefined;
}
@@ -126,10 +130,9 @@ export const MidiBindingDialog =
}
handleListenSucceeded(instanceId: number, symbol: string, isNote: boolean, noteOrControl: number)
{
handleListenSucceeded(instanceId: number, symbol: string, isNote: boolean, noteOrControl: number) {
this.cancelListenForControl();
let pedalboard = this.model.pedalboard.get();
let item = pedalboard.getItem(instanceId);
if (!item) return;
@@ -144,7 +147,7 @@ export const MidiBindingDialog =
newBinding.control = noteOrControl;
}
this.model.setMidiBinding(instanceId,newBinding);
this.model.setMidiBinding(instanceId, newBinding);
}
@@ -157,9 +160,9 @@ export const MidiBindingDialog =
this.listenHandle = this.model.listenForMidiEvent(listenForControl,
(isNote: boolean, noteOrControl: number) => {
this.handleListenSucceeded(instanceId,symbol,isNote, noteOrControl);
this.handleListenSucceeded(instanceId, symbol, isNote, noteOrControl);
});
}
@@ -190,6 +193,7 @@ export const MidiBindingDialog =
let pedalboard = this.model.pedalboard.get();
let iter = pedalboard.itemsGenerator();
let keyIx = 1;
while (true) {
let v = iter.next();
if (v.done) break;
@@ -197,45 +201,43 @@ export const MidiBindingDialog =
let isSplit = item.uri === "uri://two-play/pipedal/pedalboard#Split";
let plugin : UiPlugin | null = this.model.getUiPlugin(item.uri);
if (plugin === null && isSplit)
{
let plugin: UiPlugin | null = this.model.getUiPlugin(item.uri);
if (plugin === null && isSplit) {
plugin = makeSplitUiPlugin();
let splitType = item.getControlValue("splitType");
not_null(plugin.getControl("splitType")).not_on_gui = true;
switch (splitType)
{
case 0: // A/B
not_null(plugin.getControl("select")).not_on_gui = false;
not_null(plugin.getControl("mix")).not_on_gui = true;
not_null(plugin.getControl("volL")).not_on_gui = true;
not_null(plugin.getControl("panL")).not_on_gui = true;
not_null(plugin.getControl("volR")).not_on_gui = true;
not_null(plugin.getControl("panR")).not_on_gui = true;
break;
case 1: //mixer
not_null(plugin.getControl("select")).not_on_gui = true;
not_null(plugin.getControl("mix")).not_on_gui = false;
not_null(plugin.getControl("volL")).not_on_gui = true;
not_null(plugin.getControl("panL")).not_on_gui = true;
not_null(plugin.getControl("volR")).not_on_gui = true;
not_null(plugin.getControl("panR")).not_on_gui = true;
break;
case 2: // L/R
not_null(plugin.getControl("select")).not_on_gui = true;
not_null(plugin.getControl("mix")).not_on_gui = true;
not_null(plugin.getControl("volL")).not_on_gui = false;
not_null(plugin.getControl("panL")).not_on_gui = false;
not_null(plugin.getControl("volR")).not_on_gui = false;
not_null(plugin.getControl("panR")).not_on_gui = false;
break;
switch (splitType) {
case 0: // A/B
not_null(plugin.getControl("select")).not_on_gui = false;
not_null(plugin.getControl("mix")).not_on_gui = true;
not_null(plugin.getControl("volL")).not_on_gui = true;
not_null(plugin.getControl("panL")).not_on_gui = true;
not_null(plugin.getControl("volR")).not_on_gui = true;
not_null(plugin.getControl("panR")).not_on_gui = true;
break;
case 1: //mixer
not_null(plugin.getControl("select")).not_on_gui = true;
not_null(plugin.getControl("mix")).not_on_gui = false;
not_null(plugin.getControl("volL")).not_on_gui = true;
not_null(plugin.getControl("panL")).not_on_gui = true;
not_null(plugin.getControl("volR")).not_on_gui = true;
not_null(plugin.getControl("panR")).not_on_gui = true;
break;
case 2: // L/R
not_null(plugin.getControl("select")).not_on_gui = true;
not_null(plugin.getControl("mix")).not_on_gui = true;
not_null(plugin.getControl("volL")).not_on_gui = false;
not_null(plugin.getControl("panL")).not_on_gui = false;
not_null(plugin.getControl("volR")).not_on_gui = false;
not_null(plugin.getControl("panR")).not_on_gui = false;
break;
}
// xxx
}
if (plugin) {
result.push(
<tr>
<tr key={"k" + keyIx++}>
<td colSpan={2} className={classes.pluginHead}>
<Typography variant="caption" color="textSecondary" noWrap>
{plugin.name}
@@ -243,10 +245,9 @@ export const MidiBindingDialog =
</td>
</tr>
);
if (!isSplit)
{
if (!isSplit) {
result.push(
<tr>
<tr key={"k" + keyIx++}>
<td className={classes.nameTd}>
<Typography noWrap style={{ verticalAlign: "center", height: 48 }}>
Bypass
@@ -256,8 +257,7 @@ export const MidiBindingDialog =
<MidiBindingView instanceId={item.instanceId} midiBinding={item.getMidiBinding("__bypass")}
uiPlugin={plugin}
onListen={(instanceId: number, symbol: string, listenForControl: boolean) => {
if (instanceId === -2)
{
if (instanceId === -2) {
this.cancelListenForControl();
} else {
this.handleListenForControl(instanceId, symbol, listenForControl);
@@ -271,21 +271,35 @@ export const MidiBindingDialog =
);
}
let lastPortGroup: PortGroup | null = null;
for (let i = 0; i < plugin.controls.length; ++i) {
let control = plugin.controls[i];
if (control.isHidden())
{
if (!control.is_input) {
continue;
}
if (!control.is_input)
{
continue;
let portGroup = plugin.getPortGroupBySymbol(control.port_group);
if (portGroup != lastPortGroup) {
lastPortGroup = portGroup;
if (portGroup != null) {
result.push(
<tr key={"k" + keyIx++}>
<td colSpan={2} className={classes.nameTd} >
<div className={classes.groupHead}>
<Typography variant="caption" color="textSecondary" noWrap>
{portGroup?.name}
</Typography>
</div>
</td>
</tr>
);
}
}
let symbol = control.symbol;
result.push(
<tr>
<tr key={"k" + keyIx++}>
<td className={classes.nameTd}>
<Typography noWrap style={{ verticalAlign: "middle", maxWidth: 120 }} >
<Typography noWrap style={{ verticalAlign: "middle", maxWidth: 120, marginLeft: portGroup ? 24:0 }} >
{control.name}
</Typography>
</td>
@@ -319,66 +333,66 @@ export const MidiBindingDialog =
render() {
let props = this.props;
let { open} = props;
let { open } = props;
const classes = withStyles.getClasses(props);
if (!open) {
return (<div />);
}
return (
<DialogEx tag="midiBindings" open={open} fullWidth onClose={this.handleClose} aria-labelledby="Rename-dialog-title"
fullScreen={true}
style={{userSelect: "none"}}
onEnterKey={()=>{}}
<DialogEx tag="midiBindings" open={open} fullWidth onClose={this.handleClose} aria-labelledby="Rename-dialog-title"
fullScreen={true}
style={{ userSelect: "none" }}
onEnterKey={() => { }}
>
<div style={{ display: "flex", flexDirection: "column", flexWrap: "nowrap", width: "100%", height: "100%", overflow: "hidden" }}>
<div style={{ flex: "0 0 auto" }}>
<AppBar className={classes.dialogAppBar} >
<Toolbar>
<IconButton
edge="start"
color="inherit"
onClick={this.handleClose}
aria-label="back"
size="large">
<ArrowBackIcon />
</IconButton>
<Typography noWrap variant="h6" className={classes.dialogTitle}>
Preset MIDI Bindings
</Typography>
</Toolbar>
</AppBar>
</div>
<div style={{ overflow: "auto", flex: "1 1 auto", width: "100%" }}>
<table className={classes.pluginTable} >
<colgroup>
<col style={{ width: "auto" }} />
<col style={{ width: "100%" }} />
</colgroup>
<tbody>
{this.generateTable()}
</tbody>
</table>
</div>
<div style={{ display: "flex", flexDirection: "column", flexWrap: "nowrap", width: "100%", height: "100%", overflow: "hidden" }}>
<div style={{ flex: "0 0 auto" }}>
<AppBar className={classes.dialogAppBar} >
<Toolbar>
<IconButton
edge="start"
color="inherit"
onClick={this.handleClose}
aria-label="back"
size="large">
<ArrowBackIcon />
</IconButton>
<Typography noWrap variant="h6" className={classes.dialogTitle}>
Preset MIDI Bindings
</Typography>
</Toolbar>
</AppBar>
</div>
<Snackbar
anchorOrigin={{
vertical: 'bottom',
horizontal: 'left',
}}
open={this.state.listenSnackbarOpen}
autoHideDuration={1500}
onClose={() => this.setState({ listenSnackbarOpen: false })}
message="Listening for MIDI input"
/>
<div style={{ overflow: "auto", flex: "1 1 auto", width: "100%" }}>
<table className={classes.pluginTable} >
<colgroup>
<col style={{ width: "auto" }} />
<col style={{ width: "100%" }} />
</colgroup>
<tbody>
{this.generateTable()}
</tbody>
</table>
</div>
</div>
<Snackbar
anchorOrigin={{
vertical: 'bottom',
horizontal: 'left',
}}
open={this.state.listenSnackbarOpen}
autoHideDuration={1500}
onClose={() => this.setState({ listenSnackbarOpen: false })}
message="Listening for MIDI input"
/>
</DialogEx >
);
}
},
styles);
styles);
export default MidiBindingDialog;
+12 -2
View File
@@ -2297,12 +2297,12 @@ export class PiPedalModel //implements PiPedalModel
private monitorPatchPropertyListeners: PatchPropertyListenerItem[] = [];
nextListenHandle = 1;
listenForMidiEvent(listenForControlsOnly: boolean, onComplete: (isNote: boolean, noteOrControl: number) => void): ListenHandle {
listenForMidiEvent(listenForControl: boolean, onComplete: (isNote: boolean, noteOrControl: number) => void): ListenHandle {
let handle = this.nextListenHandle++;
this.midiListeners.push(new MidiEventListener(handle, onComplete));
this.webSocket?.send("listenForMidiEvent", { listenForControlsOnly: listenForControlsOnly, handle: handle });
this.webSocket?.send("listenForMidiEvent", { listenForControls: listenForControl, handle: handle });
return {
_handle: handle
};
@@ -2388,6 +2388,16 @@ export class PiPedalModel //implements PiPedalModel
this.webSocket?.send("cancelListenForMidiEvent", listenHandle._handle);
}
downloadAudioFile(filePath: string) {
let downloadUrl = this.varServerUrl + "downloadMediaFile?path=" + encodeURIComponent(filePath);
// download with no flashing temporary tab.
let link = window.document.createElement("A") as HTMLLinkElement;
link.href = downloadUrl;
link.setAttribute("download", "");
link.click();
}
download(targetType: string, instanceId: number | string): void {
if (instanceId === -1) return;
let url = this.varServerUrl + targetType + "?id=" + instanceId;
+123 -32
View File
@@ -21,8 +21,8 @@ import React, { TouchEvent, PointerEvent, ReactNode, Component, SyntheticEvent }
import { css } from '@emotion/react';
import Button from '@mui/material/Button';
import { Theme } from '@mui/material/styles';
import WithStyles, {withTheme} from './WithStyles';
import {createStyles} from './WithStyles';
import WithStyles, { withTheme } from './WithStyles';
import { createStyles } from './WithStyles';
import { withStyles } from "tss-react/mui";
import { UiControl, ScalePoint } from './Lv2Plugin';
@@ -37,11 +37,17 @@ import DialIcon from './svg/fx_dial.svg?react';
import { isDarkMode } from './DarkMode';
import ControlTooltip from './ControlTooltip';
import PlayArrowIcon from '@mui/icons-material/PlayArrow';
import StopIcon from '@mui/icons-material/Stop';
import FiberManualRecordIcon from '@mui/icons-material/FiberManualRecord';
const MIN_ANGLE = -135;
const MAX_ANGLE = 135;
const FONT_SIZE = "0.8em";
enum ButtonStyle { None, Trigger, Momentary, MomentaryOnByDefault }
const SELECTED_OPACITY = 0.8;
const DEFAULT_OPACITY = 0.6;
@@ -53,6 +59,20 @@ const ULTRA_FINE_RANGE_SCALE = RANGE_SCALE * 50; // 12000 pixels to move from 0
export const StandardItemSize = { width: 80, height: 140 }
function androidEmoji(text: string) {
// android chrome doesn't support these characters properly.
if (text === "⏹") {
return (<StopIcon fontSize={"medium"} />);
}
if (text === "⏺") {
return (<FiberManualRecordIcon fontSize={"medium"} />)
}
if (text === "⏵")
{
return (<PlayArrowIcon fontSize={"medium"}/>);
}
return text;
}
export const pluginControlStyles = (theme: Theme) => createStyles({
frame: css({
@@ -115,12 +135,12 @@ const PluginControl =
withTheme(withStyles(
class extends Component<PluginControlProps, PluginControlState> {
frameRef: React.RefObject<HTMLDivElement|null>;
imgRef: React.RefObject<SVGSVGElement|null>;
inputRef: React.RefObject<HTMLInputElement|null>;
selectRef: React.RefObject<HTMLSelectElement|null>;
frameRef: React.RefObject<HTMLDivElement | null>;
imgRef: React.RefObject<SVGSVGElement | null>;
inputRef: React.RefObject<HTMLInputElement | null>;
selectRef: React.RefObject<HTMLSelectElement | null>;
displayValueRef: React.RefObject<HTMLDivElement|null>;
displayValueRef: React.RefObject<HTMLDivElement | null>;
model: PiPedalModel;
@@ -498,19 +518,50 @@ const PluginControl =
this.isTap = false;
}
}
}
handleTriggerMouseDown() {
handleButtonMouseLeave(buttonStyle: ButtonStyle) {
}
handleButtonMouseDown(buttonStyle: ButtonStyle) {
let uiControl = this.props.uiControl;
if (uiControl) {
let value = uiControl.max_value;
if (uiControl.max_value === uiControl.default_value) {
value = uiControl.min_value;
switch (buttonStyle) {
case ButtonStyle.Momentary:
this.model.setPedalboardControl(this.props.instanceId, uiControl.symbol,uiControl.max_value);
break;
case ButtonStyle.MomentaryOnByDefault:
this.model.setPedalboardControl(this.props.instanceId, uiControl.symbol,uiControl.min_value);
break;
case ButtonStyle.Trigger:
{
let value = uiControl.max_value;
if (uiControl.max_value === uiControl.default_value) {
value = uiControl.min_value;
}
this.model.sendPedalboardControlTrigger(this.props.instanceId, uiControl.symbol, value);
}
break;
}
this.model.sendPedalboardControlTrigger(this.props.instanceId, uiControl.symbol, value);
}
}
handleTriggerMouseUp() {
// triggers are reset on the audio thread.
handleButtonMouseUp(buttonStyle: ButtonStyle) {
let uiControl = this.props.uiControl;
if (uiControl) {
switch (buttonStyle) {
case ButtonStyle.Momentary:
this.model.setPedalboardControl(this.props.instanceId, uiControl.symbol,uiControl.min_value);
break;
case ButtonStyle.MomentaryOnByDefault:
this.model.setPedalboardControl(this.props.instanceId, uiControl.symbol,uiControl.max_value);
break;
case ButtonStyle.Trigger:
{
// trigger values are reset automatically.
}
break;
}
}
}
previewInputValue(value: number, commitValue: boolean) {
let range = this.valueToRange(value);
@@ -657,8 +708,7 @@ const PluginControl =
}
range = Math.log(value / minValue) / Math.log(uiControl.max_value / minValue);
if (!isFinite(range)) {
if (range < 0)
{
if (range < 0) {
range = 0;
} else {
range = 1.0;
@@ -672,8 +722,7 @@ const PluginControl =
} else {
range = (value - uiControl.min_value) / (uiControl.max_value - uiControl.min_value);
if (!isFinite(range)) {
if (range < 0)
{
if (range < 0) {
range = 0;
} else {
range = 1.0;
@@ -760,14 +809,28 @@ const PluginControl =
let isSelect = control.isSelect();
let isAbSwitch = control.isAbToggle();
let isOnOffSwitch = control.isOnOffSwitch();
let isTrigger = control.isTrigger();
let isButton = false;
let buttonStyle: ButtonStyle = ButtonStyle.None;
if (control.isTrigger()) {
isButton = true;
buttonStyle = ButtonStyle.Trigger;
}
if (control.isMomentary()) {
isButton = true;
buttonStyle = ButtonStyle.Momentary;
}
if (control.isMomentaryOnByDefault()) {
isButton = true;
buttonStyle = ButtonStyle.MomentaryOnByDefault;
}
if (isAbSwitch) {
switchText = control.scale_points[0].value === value ? control.scale_points[0].label : control.scale_points[1].label;
}
let item_width: number | undefined = isSelect ? 160 : 80;
if (isTrigger) {
if (isButton) {
item_width = undefined;
}
@@ -788,24 +851,38 @@ const PluginControl =
<Typography variant="caption" display="block" noWrap style={{
width: "100%",
textAlign: isSelect ? "left" : "center"
}}> {isTrigger ? "\u00A0" : control.name}</Typography>
}}> {isButton ? "\u00A0" : control.name}</Typography>
</ControlTooltip>
</div>
{/* CONTROL SECTION */}
<div className={classes.midSection}>
{isTrigger ?
{isButton ?
(
control.name.length !== 1 ? (
<Button variant="contained" color="primary" size="small"
onMouseDown={
(evt) => { this.handleTriggerMouseDown(); }
onMouseDown={
(evt) => { this.handleButtonMouseDown(buttonStyle); }
}
onMouseUp={
(evt) => { this.handleButtonMouseUp(buttonStyle); }
}
onTouchStart={
(evt) => { evt.preventDefault();
this.handleButtonMouseDown(buttonStyle); }
}
onTouchEnd={
(evt) => {
evt.preventDefault();
this.handleButtonMouseUp(buttonStyle);
}
onMouseUp={
(evt) => { this.handleTriggerMouseUp(); }
}
style={{
}
onMouseLeave={(
(evet) => { this.handleButtonMouseLeave(buttonStyle); }
)}
style={{
textTransform: "none",
background: (isDarkMode() ? "#6750A4" : undefined),
marginLeft: 8, marginRight: 8, minWidth: 60,
@@ -820,11 +897,25 @@ const PluginControl =
) : (
<Button variant="contained" color="primary" size="small"
onMouseDown={
(evt) => { this.handleTriggerMouseDown(); }
(evt) => { this.handleButtonMouseDown(buttonStyle); }
}
onMouseUp={
(evt) => { this.handleTriggerMouseUp(); }
(evt) => { this.handleButtonMouseUp(buttonStyle); }
}
onTouchStart={
(evt) => { evt.preventDefault();
this.handleButtonMouseDown(buttonStyle); }
}
onTouchEnd={
(evt) => {
evt.preventDefault();
this.handleButtonMouseUp(buttonStyle);
}
}
onMouseLeave={(
(evet) => { this.handleButtonMouseLeave(buttonStyle); }
)}
style={{
textTransform: "none",
background: (isDarkMode() ? "#6750A4" : undefined),
@@ -839,7 +930,7 @@ const PluginControl =
}}
>
{control.name}
{androidEmoji(control.name)}
</Button>
)
)
@@ -865,7 +956,7 @@ const PluginControl =
{/* LABEL/EDIT SECTION*/}
<div className={classes.editSection} >
{(!(isSelect || isOnOffSwitch || isTrigger)) &&
{(!(isSelect || isOnOffSwitch || isButton)) &&
(
(isAbSwitch) ? (
<Typography variant="caption" display="block" textAlign="center" noWrap style={{
+22 -2
View File
@@ -155,6 +155,7 @@ const styles = (theme: Theme) => createStyles({
paddingLeft: 30,
paddingRight: 30,
paddingTop: 8,
flex: "1 1 auto",
display: "flex", flexDirection: "row", flexWrap: "wrap",
justifyContent: "flex-start", alignItems: "flex_start",
@@ -170,6 +171,7 @@ const styles = (theme: Theme) => createStyles({
// See the spacer div added after all controls in render() with provides the same effect.
display: "flex", flexDirection: "row", flexWrap: "nowrap",
justifyContent: "flex-start", alignItems: "flex-start",
overflowX: "hidden",
overflowY: "hidden",
flex: "0 0 auto",
@@ -208,7 +210,7 @@ const styles = (theme: Theme) => createStyles({
marginBottom: 12,
position: "relative",
paddingLeft: 3,
paddingRight: 0,
paddingRight: 8,
paddingTop: 0,
paddingBottom: 0,
border: "2pt #AAA solid",
@@ -216,6 +218,7 @@ const styles = (theme: Theme) => createStyles({
elevation: 12,
display: "flex",
flexDirection: "row", flexWrap: "wrap",
flex: "0 1 auto",
}),
portGroupLandscape: css({
@@ -226,6 +229,7 @@ const styles = (theme: Theme) => createStyles({
position: "relative",
paddingLeft: 0,
paddingRight: 0,
paddingTop: 0,
paddingBottom: 0,
border: "2pt #AAA solid",
@@ -253,6 +257,7 @@ const styles = (theme: Theme) => createStyles({
display: "flex",
flexDirection: "row", flexWrap: "wrap",
paddingTop: 6,
rowGap: 16,
paddingBottom: 8
}),
portGroupControlsLandscape: css({
@@ -260,6 +265,7 @@ const styles = (theme: Theme) => createStyles({
flexFlow: "row nowrap",
width: "fit-content",
paddingTop: 6,
rowGap: 16,
paddingBottom: 8
})
@@ -779,6 +785,20 @@ const PluginControlView =
onCancel={() => {
this.setState({ showFileDialog: false });
}}
onApply={(fileProperty,selectedFile) => {
this.model.setPatchProperty(
this.props.instanceId,
fileProperty.patchProperty,
JsonAtom.Path(selectedFile)
)
.then(() => {
})
.catch((error) => {
this.model.showAlert("Unable to complete the operation. " + error);
});
}}
onOk={(fileProperty, selectedFile) => {
this.model.setPatchProperty(
@@ -790,7 +810,7 @@ const PluginControlView =
})
.catch((error) => {
this.model.showAlert("Unable to complete the operation. Audio is not running." + error);
this.model.showAlert("Unable to complete the operation. " + error);
});
this.setState({ showFileDialog: false });
}
+33 -12
View File
@@ -20,8 +20,7 @@
import React from 'react';
import { Theme } from '@mui/material/styles';
import WithStyles from './WithStyles';
import {createStyles} from './WithStyles';
import { createStyles } from './WithStyles';
import { withStyles } from "tss-react/mui";
import Button from '@mui/material/Button';
import DialogEx from './DialogEx';
@@ -34,7 +33,7 @@ import Typography from '@mui/material/Typography';
import Grid from '@mui/material/Grid';
import { PiPedalModelFactory } from "./PiPedalModel";
import InfoOutlinedIcon from '@mui/icons-material/InfoOutlined';
import { UiPlugin, UiControl } from './Lv2Plugin';
import { UiPlugin, PortGroup } from './Lv2Plugin';
import PluginIcon from './PluginIcon';
import { Remark } from 'react-remark';
import { css } from '@emotion/react';
@@ -56,6 +55,9 @@ const styles = (theme: Theme) => {
icon: {
fill: theme.palette.text.primary,
opacity: 0.6
},
controlHeader: {
borderBottom: "1px solid " + theme.palette.divider,
}
});
};
@@ -88,7 +90,7 @@ const PluginInfoDialogContent = withStyles(
(theme: Theme) => ({
root: {
padding: theme.spacing(2),
}
}
})
);
@@ -146,7 +148,8 @@ function ioDescription(plugin: UiPlugin): string {
// );
// }
function makeControls(controls: UiControl[]) {
function makeControls(plugin: UiPlugin, controlHeadeClass: string) {
let controls = plugin.controls;
let hasComments = false;
for (let i = 0; i < controls.length; ++i) {
@@ -156,14 +159,32 @@ function makeControls(controls: UiControl[]) {
}
}
hasComments = true;
let lastPortGroup: PortGroup | null = null;
if (hasComments) {
let trs: React.ReactElement[] = [];
for (let i = 0; i < controls.length; ++i) {
let control = controls[i];
if (!(control.not_on_gui) && control.is_input)
if (!(control.not_on_gui) && control.is_input) {
let portGroup = plugin.getPortGroupBySymbol(control.port_group);
if (portGroup !== lastPortGroup) {
if (portGroup !== null)
{
trs.push((
<tr>
<td className={controlHeadeClass} style={{ verticalAlign: "top", paddingTop: 8 }} colSpan={2}>
<Typography variant="body2" style={{ whiteSpace: "nowrap" }}>
{portGroup?.name ?? ""}
</Typography>
</td>
</tr >
));
}
lastPortGroup = portGroup;
}
trs.push((
<tr>
<td style={{ verticalAlign: "top" }}>
<td style={{ verticalAlign: "top", paddingLeft: portGroup ? 24 : 0 }}>
<Typography variant="body2" style={{ whiteSpace: "nowrap" }}>
{control.name}
</Typography>
@@ -175,14 +196,14 @@ function makeControls(controls: UiControl[]) {
</td>
</tr >
));
}
}
return (
<table style={{ paddingLeft: "24px", verticalAlign: "top" }}>
<table style={{ paddingLeft: "24px", verticalAlign: "top" }}><tbody>
{
trs
}
</table>
</tbody></table>
);
} else {
@@ -290,7 +311,7 @@ const PluginInfoDialog = withStyles((props: PluginInfoProps) => {
Controls:
</Typography>
{
makeControls(plugin.controls)
makeControls(plugin, classes.controlHeader)
}
{plugin.description.length > 0 && (
<div>
@@ -338,6 +359,6 @@ const PluginInfoDialog = withStyles((props: PluginInfoProps) => {
</div >
);
},
styles);
styles);
export default PluginInfoDialog;
+57 -2
View File
@@ -130,6 +130,7 @@ const PluginOutputControl =
private model: PiPedalModel;
private vuRef: React.RefObject<HTMLDivElement|null>;
private progressRef: React.RefObject<HTMLDivElement|null>;
private dbVuRef: React.RefObject<HTMLDivElement|null>;
private dbVuTelltaleRef: React.RefObject<HTMLDivElement|null>;
private lampRef: React.RefObject<HTMLDivElement|null>;
@@ -138,6 +139,7 @@ const PluginOutputControl =
constructor(props: PluginOutputControlProps) {
super(props);
this.vuRef = React.createRef<HTMLDivElement>();
this.progressRef = React.createRef<HTMLDivElement>();
this.dbVuRef = React.createRef<HTMLDivElement>();
this.dbVuTelltaleRef = React.createRef<HTMLDivElement>();
this.lampRef = React.createRef<HTMLDivElement>();
@@ -182,6 +184,7 @@ const PluginOutputControl =
}
}
private PROGRESS_WIDTH = 40-4;
private VU_HEIGHT = 60 - 4;
private DB_VU_HEIGHT = 60 - 4;
private animationHandle: number | undefined = undefined;
@@ -257,7 +260,23 @@ const PluginOutputControl =
} else if (this.dbVuRef.current) {
this.dbVuValue = value;
this.requestDbVuAnimation();
}
} else if (this.progressRef.current) {
let control = this.props.uiControl;
let range = (value - control.min_value) / (control.max_value - control.min_value);
let w = this.PROGRESS_WIDTH * range;
if (!this.animationHandle) {
this.animationHandle = requestAnimationFrame(
() => {
if (this.progressRef.current) {
this.progressRef.current.style.width = w + "px";
}
this.animationHandle = undefined;
}
)
}
}
else if (this.vuRef.current) {
let control = this.props.uiControl;
let range = (value - control.min_value) / (control.max_value - control.min_value);
@@ -364,6 +383,43 @@ const PluginOutputControl =
</div >
);
} else if (control.isProgress()) {
item_width = undefined;
return (
<div className={classes.controlFrame}
style={{ width: item_width }}>
{/* TITLE SECTION */}
<div className={classes.titleSection}
style={{ width: "100%" }}>
<ControlTooltip uiControl={control}>
<Typography variant="caption" display="block" style={{
width: "100%",
textAlign: "center"
}}> {control.name === "" ? "\u00A0" : control.name}</Typography>
</ControlTooltip>
</div>
{/* CONTROL SECTION */}
<div className={classes.midSection}
style={{ flex: "1 1 1", display: "flex", justifyContent: "center", alignItems: "start", flexFlow: "row nowrap" }}>
<div style={{ width: this.PROGRESS_WIDTH+2, height: 12, marginLeft: 8, marginRight: 8, background: "#181818", }}>
<div style={{ height: 8, width: this.PROGRESS_WIDTH, overflow: "hidden", position: "absolute",
margin: "1px 1px 1px 1px", background: "#282828" }}>
<div ref={this.progressRef} style={{ height: 10, width: this.PROGRESS_WIDTH, position: "absolute", marginTop: 0, background: "#0C0" }} />
<div style={{ height: 10, width: this.PROGRESS_WIDTH, position: "absolute",
boxShadow: "inset 0px 2px 4px #000D", background: "transparent"
}} />
</div>
</div>
</div>
<div className={classes.editSectionNoContent}>
</div>
</div >
);
} else if (control.isDbVu()) {
item_width = undefined;
@@ -407,7 +463,6 @@ const PluginOutputControl =
);
}
else if (control.isVu()) {
// yyx: convert this to a horizontal progress bar.
item_width = undefined;
return (
<div className={classes.controlFrame} style={{ width: item_width}}>