v1.1.20 Release

This commit is contained in:
Robin Davies
2023-04-20 15:27:18 -04:00
parent e2b62da073
commit 37426d9047
117 changed files with 2147 additions and 711 deletions
+2 -1
View File
@@ -72,7 +72,8 @@
"args": [
//"[Dev]" -- all dev-machine tests.
"[json_variants]" // subtest of your choice, or none to run all of the tests.
//"[json_variants]" // subtest of your choice, or none to run all of the tests.
"[inverting_mutex_test]"
],
"stopAtEntry": false,
+2 -2
View File
@@ -1,10 +1,10 @@
cmake_minimum_required(VERSION 3.16.0)
project(pipedal
VERSION 1.0.19
VERSION 1.1.20
DESCRIPTION "PiPedal Guitar Effect Pedal For Raspberry Pi"
HOMEPAGE_URL "https://rerdavies.github.io/pipedal"
)
set (DISPLAY_VERSION "v1.0.19")
set (DISPLAY_VERSION "v1.1.20")
set (CMAKE_INSTALL_PREFIX "/usr/")
+4 -1
View File
@@ -1,10 +1,13 @@
<img src='docs/GithubBanner.png' width="100%" /><br/>
Download: <a href='https://rerdavies.github.io/pipedal/download.html'>v1.0.19</a>
Download: <a href='https://rerdavies.github.io/pipedal/download.html'>v1.1.20</a>
Website: [https://rerdavies.github.io/pipedal](https://rerdavies.github.io/pipedal).
<quote>
NEW version 1.1 release. See the [release notes](https://rerdavies.github.io/pipedal/ReleaseNotes) for details.
</quote>
Use your Raspberry Pi as a guitar effects pedal. Configure and control PiPedal with your phone or tablet.
PiPedal running on a Raspberry Pi 4 provides stable super-low-latency audio via external USB audio devices, or internal Raspberry Pi audio hats.
+8
View File
@@ -0,0 +1,8 @@
#!/usr/bin/bash
# Copy current pipedal presets to provisioning directories.
rm -rf default_presets/plugin_presets
rm -rf default_presets/presets
mkdir default_presets/plugin_presets
mkdir default_presets/presets
cp -r /var/pipedal/plugin_presets default_presets/plugin_presets/
cp -r /var/pipedal/presets default_presets/presets/
+3 -3
View File
@@ -1,14 +1,14 @@
Architecture: arm64
Depends: libstdc++6 (>= 9), libasound2 (>= 1.0.17), libc6 (>= 2.34), libgcc-s1 (>= 4.0), libjack-jackd2-0 (>= 1.9.10+20150825) | libjack-0.125, liblilv-0-0 (>= 0.22.0~dfsg0), libnl-3-200 (>= 3.2.7), libnl-genl-3-200 (>= 3.2.7), libstdc++6 (>= 11), libsystemd0
Depends: libstdc++6 (>= 9), libasound2 (>= 1.0.17), libc6 (>= 2.34), libgcc-s1 (>= 4.0), libjack-jackd2-0 (>= 1.9.10+20150825) | libjack-0.125, liblilv-0-0 (>= 0.22.0~dfsg0), libnl-3-200 (>= 3.2.7), libnl-genl-3-200 (>= 3.2.7), libstdc++6 (>= 11), libsystemd0, dnsmasq(>= 2.85)
Description: IoT guitar effect for Raspberry Pi
IoT guitar effect pedal for Raspberry Pi, with phone-friendly web interface.
Homepage: https://github.com/rerdavies/pipedal
Maintainer: Robin E. R. Davies<rerdavies@gmail.com>
Source: pipedal
Package: pipedal
Pre-Depends: hostapd;authbind
Pre-Depends: hostapd;authbind;dnsmasq
Priority: optional
Section: sound
Version: 1.0.19
Version: 1.1.20
Installed-Size: 15147
@@ -0,0 +1 @@
{"pluginUri": "urn:zamaudio:ZaMaximX2","presets": [{"instanceId": 1,"label": "Zero","controlValues": {"ceil": 0,"rel": 25,"thresh": 0}}],"nextInstanceId": 2}
@@ -0,0 +1 @@
{"pluginUri": "urn:zamaudio:ZamGate","presets": [{"instanceId": 1,"label": "Default","controlValues": {"att": 50,"close": -50,"mak": 0,"mode": 0,"rel": 100,"sidechain": 0,"thr": -60}}],"nextInstanceId": 2}
@@ -0,0 +1 @@
{"pluginUri": "urn:zamaudio:ZamGateX2","presets": [{"instanceId": 1,"label": "Default","controlValues": {"att": 50,"close": -50,"mak": 0,"mode": 0,"rel": 100,"sidechain": 0,"thr": -60}}],"nextInstanceId": 2}
@@ -0,0 +1 @@
{"pluginUri": "urn:zamaudio:ZamGrains","presets": [ ],"nextInstanceId": 1}
@@ -0,0 +1 @@
{"pluginUri": "urn:zamaudio:ZamHeadX2","presets": [{"instanceId": 1,"label": "Zero","controlValues": {"az": 0,"elev": 0,"width": 1}}],"nextInstanceId": 2}
@@ -0,0 +1 @@
{"pluginUri": "urn:zamaudio:ZamPhono","presets": [ ],"nextInstanceId": 1}
@@ -0,0 +1 @@
{"pluginUri": "urn:zamaudio:ZamTube","presets": [ ],"nextInstanceId": 1}
@@ -0,0 +1 @@
{"pluginUri": "urn:zamaudio:ZamVerb","presets": [ ],"nextInstanceId": 1}
@@ -0,0 +1 @@
{"pluginUri": "http://two-play.com/plugins/toob-delay","presets": [{"instanceId": 1,"label": "Classic","controlValues": {"delay": 340,"feedback": 39.1666679,"level": 27}},{"instanceId": 2,"label": "Slapback","controlValues": {"delay": 94.6446991,"feedback": 39.1666679,"level": 42}}],"nextInstanceId": 3}
@@ -0,0 +1 @@
{"pluginUri": "http://two-play.com/plugins/toob-ml","presets": [{"instanceId": 1,"label": "Fender Clean","controlValues": {"bass": 0.783333361,"gain": 0,"master": 1.5,"mid": 0.5,"model": 8,"treble": 0.550000012,"trim": -3}},{"instanceId": 2,"label": "Mesa Crunch","controlValues": {"bass": 0.650000036,"gain": 0,"master": 1.5,"mid": 0.5,"model": 17,"treble": 0.550000012,"trim": -3}},{"instanceId": 3,"label": "Sparkling Clean","controlValues": {"bass": 0.650000036,"gain": 0,"master": 1.5,"mid": 0.5,"model": 19,"treble": 0.550000012,"trim": -3}}],"nextInstanceId": 4}
@@ -0,0 +1 @@
{"pluginUri": "urn:zamaudio:ZaMultiComp","presets": [{"instanceId": 1,"label": "Presence","controlValues": {"att1": 10,"att2": 10,"att3": 10,"globalgain": 0,"kn1": 3,"kn2": 3,"kn3": 3,"listen1": 0,"listen2": 0,"listen3": 0,"mak1": 9,"mak2": 6,"mak3": 6,"rat1": 5,"rat2": 5,"rat3": 5,"rel1": 200,"rel2": 200,"rel3": 200,"thr1": -20,"thr2": -18,"thr3": -16,"toggle1": 1,"toggle2": 1,"toggle3": 1,"xover1": 160,"xover2": 1400}},{"instanceId": 2,"label": "Zero","controlValues": {"att1": 10,"att2": 10,"att3": 10,"globalgain": 0,"kn1": 0,"kn2": 0,"kn3": 0,"listen1": 0,"listen2": 0,"listen3": 0,"mak1": 0,"mak2": 0,"mak3": 0,"rat1": 4,"rat2": 4,"rat3": 4,"rel1": 80,"rel2": 80,"rel3": 80,"thr1": -20,"thr2": -18,"thr3": -16,"toggle1": 0,"toggle2": 0,"toggle3": 0,"xover1": 160,"xover2": 1400}}],"nextInstanceId": 3}
@@ -0,0 +1 @@
{"pluginUri": "urn:zamaudio:ZaMultiCompX2","presets": [{"instanceId": 1,"label": "Zero","controlValues": {"att1": 10,"att2": 10,"att3": 10,"globalgain": 0,"kn1": 0,"kn2": 0,"kn3": 0,"listen1": 0,"listen2": 0,"listen3": 0,"mak1": 0,"mak2": 0,"mak3": 0,"rat1": 4,"rat2": 4,"rat3": 4,"rel1": 80,"rel2": 80,"rel3": 80,"stereodet": 1,"thr1": -20,"thr2": -18,"thr3": -16,"toggle1": 0,"toggle2": 0,"toggle3": 0,"xover1": 160,"xover2": 1400}},{"instanceId": 2,"label": "Presence","controlValues": {"att1": 10,"att2": 10,"att3": 10,"globalgain": 0,"kn1": 3,"kn2": 3,"kn3": 3,"listen1": 0,"listen2": 0,"listen3": 0,"mak1": 9,"mak2": 6,"mak3": 6,"rat1": 5,"rat2": 5,"rat3": 5,"rel1": 200,"rel2": 200,"rel3": 200,"stereodet": 1,"thr1": -20,"thr2": -18,"thr3": -16,"toggle1": 1,"toggle2": 1,"toggle3": 1,"xover1": 160,"xover2": 1400}}],"nextInstanceId": 3}
@@ -0,0 +1 @@
{"pluginUri": "urn:zamaudio:ZamComp","presets": [{"instanceId": 1,"label": "Zero","controlValues": {"att": 10,"kn": 0,"mak": 0,"rat": 4,"rel": 80,"sidech": 0,"slew": 1,"thr": 0}},{"instanceId": 2,"label": "VocalLeveller","controlValues": {"att": 50,"kn": 8,"mak": 9,"rat": 5,"rel": 400,"sidech": 0,"slew": 1,"thr": -16}},{"instanceId": 3,"label": "PoppySnare","controlValues": {"att": 10,"kn": 1,"mak": 6,"rat": 5,"rel": 10,"sidech": 0,"slew": 20,"thr": -18}}],"nextInstanceId": 4}
@@ -0,0 +1 @@
{"pluginUri": "urn:zamaudio:ZamCompX2","presets": [{"instanceId": 1,"label": "PoppySnare","controlValues": {"att": 10,"kn": 1,"mak": 6,"rat": 5,"rel": 10,"sidechain": 0,"slew": 20,"stereodet": 1,"thr": -18}},{"instanceId": 2,"label": "VocalLeveller","controlValues": {"att": 50,"kn": 8,"mak": 9,"rat": 5,"rel": 400,"sidechain": 0,"slew": 1,"stereodet": 1,"thr": -16}},{"instanceId": 3,"label": "Zero","controlValues": {"att": 10,"kn": 0,"mak": 0,"rat": 4,"rel": 80,"sidechain": 0,"slew": 1,"stereodet": 0,"thr": 0}}],"nextInstanceId": 4}
@@ -0,0 +1 @@
{"pluginUri": "urn:zamaudio:ZamDelay","presets": [ ],"nextInstanceId": 1}
@@ -0,0 +1 @@
{"pluginUri": "urn:zamaudio:ZamDynamicEQ","presets": [{"instanceId": 1,"label": "Zero","controlValues": {"att": 10,"boostcut": 0,"detectfreq": 1000,"kn": 0,"max": 10,"rat": 1.5,"rel": 80,"sidech": 0,"slew": 1,"targetfreq": 1000,"targetwidth": 1,"thr": 0,"togglehigh": 0,"togglelow": 0,"togglepeak": 1}},{"instanceId": 2,"label": "PoppySnare","controlValues": {"att": 10,"boostcut": 0,"detectfreq": 1000,"kn": 1,"max": 10,"rat": 1.5,"rel": 10,"sidech": 0,"slew": 20,"targetfreq": 1000,"targetwidth": 1,"thr": -18,"togglehigh": 0,"togglelow": 0,"togglepeak": 1}}],"nextInstanceId": 3}
@@ -0,0 +1 @@
{"pluginUri": "urn:zamaudio:ZamEQ2","presets": [{"instanceId": 1,"label": "Zero","controlValues": {"boost1": 0,"boost2": 0,"boosth": 0,"boostl": 0,"bw1": 1,"bw2": 1,"f1": 500,"f2": 3000,"fh": 8000,"fl": 250,"master": 0,"peaks": 0}},{"instanceId": 2,"label": "CarvedBass","controlValues": {"boost1": 0,"boost2": 0,"boosth": 0,"boostl": 6,"bw1": 1,"bw2": 1,"f1": 500,"f2": 3000,"fh": 8000,"fl": 60,"master": -6,"peaks": 0}},{"instanceId": 3,"label": "CarvedVox","controlValues": {"boost1": 0,"boost2": 0,"boosth": 6,"boostl": 6,"bw1": 1,"bw2": 1,"f1": 500,"f2": 3000,"fh": 330,"fl": 6600,"master": -12,"peaks": 0}},{"instanceId": 4,"label": "CarvedGuitar","controlValues": {"boost1": 5.5999999,"boost2": 0.699999988,"boosth": 0,"boostl": -1.04999995,"bw1": 1.46000004,"bw2": 1.33000004,"f1": 175,"f2": 500,"fh": 8000,"fl": 30,"master": -6,"peaks": 0}}],"nextInstanceId": 5}
@@ -0,0 +1 @@
{"pluginUri": "urn:zamaudio:ZamGEQ31","presets": [{"instanceId": 1,"label": "Default","controlValues": {"band1": 0,"band10": 0,"band11": 0,"band12": 0,"band13": 0,"band14": 0,"band15": 0,"band16": 0,"band17": 0,"band18": 0,"band19": 0,"band2": 0,"band20": 0,"band21": 0,"band22": 0,"band23": 0,"band24": 0,"band25": 0,"band26": 0,"band27": 0,"band28": 0,"band29": 0,"band3": 0,"band4": 0,"band5": 0,"band6": 0,"band7": 0,"band8": 0,"band9": 0,"master": 0}}],"nextInstanceId": 2}
@@ -0,0 +1 @@
{"entries": [{"pluginUri": "urn:zamaudio:ZaMaximX2","fileName": "1.json"},{"pluginUri": "urn:zamaudio:ZaMultiComp","fileName": "2.json"},{"pluginUri": "urn:zamaudio:ZaMultiCompX2","fileName": "3.json"},{"pluginUri": "urn:zamaudio:ZamComp","fileName": "4.json"},{"pluginUri": "urn:zamaudio:ZamCompX2","fileName": "5.json"},{"pluginUri": "urn:zamaudio:ZamDelay","fileName": "6.json"},{"pluginUri": "urn:zamaudio:ZamDynamicEQ","fileName": "7.json"},{"pluginUri": "urn:zamaudio:ZamEQ2","fileName": "8.json"},{"pluginUri": "urn:zamaudio:ZamGEQ31","fileName": "9.json"},{"pluginUri": "urn:zamaudio:ZamGate","fileName": "10.json"},{"pluginUri": "urn:zamaudio:ZamGateX2","fileName": "11.json"},{"pluginUri": "urn:zamaudio:ZamGrains","fileName": "12.json"},{"pluginUri": "urn:zamaudio:ZamHeadX2","fileName": "13.json"},{"pluginUri": "urn:zamaudio:ZamPhono","fileName": "14.json"},{"pluginUri": "urn:zamaudio:ZamTube","fileName": "15.json"},{"pluginUri": "urn:zamaudio:ZamVerb","fileName": "16.json"},{"pluginUri": "http://two-play.com/plugins/toob-delay","fileName": "17.json"},{"pluginUri": "http://two-play.com/plugins/toob-ml","fileName": "18.json"}],"nextInstanceId": 19}
File diff suppressed because one or more lines are too long
+1
View File
@@ -0,0 +1 @@
{"selectedBank": 1,"nextInstanceId": 1,"entries": [{"instanceId": 1,"name": "Default Bank"}]}
+1
View File
@@ -0,0 +1 @@
{"pluginUri": "http://calf.sourceforge.net/plugins/Filter","presets": [{"instanceId": 1,"label": "Distant Headphones","controlValues": {"freq": 305.817993,"inertia": 74,"mode": 3,"res": 0.707000017},"state": [false,{}]},{"instanceId": 2,"label": "Totally muted","controlValues": {"freq": 10,"inertia": 20,"mode": 2,"res": 0.707000017},"state": [false,{}]},{"instanceId": 3,"label": "Disco","controlValues": {"freq": 193.820999,"inertia": 74,"mode": 0,"res": 1.37955999},"state": [false,{}]}],"nextInstanceId": 4}
+1
View File
@@ -0,0 +1 @@
{"pluginUri": "http://calf.sourceforge.net/plugins/Flanger","presets": [{"instanceId": 1,"label": "Allpass filter","controlValues": {"amount": 1.85318005,"dry": 1,"feedback": -0.446399987,"min_delay": 2.63027,"mod_depth": 0.5,"mod_rate": 2.56892991,"reset": 0,"stereo": 0},"state": [false,{}]},{"instanceId": 2,"label": "Tooth Killer","controlValues": {"amount": 0.318639994,"feedback": 0.99000001,"min_delay": 0.363077998,"mod_depth": 0.181538999,"mod_rate": 0.100419},"state": [false,{}]},{"instanceId": 3,"label": "Waterlike","controlValues": {"amount": 0.926587999,"feedback": -0.169200003,"min_delay": 0.478630006,"mod_depth": 0.722720027,"mod_rate": 1.67184997},"state": [false,{}]},{"instanceId": 4,"label": "Chorus Lite","controlValues": {"amount": 0.632878006,"feedback": 0.0683998987,"min_delay": 10,"mod_depth": 2.08435011,"mod_rate": 0.910154998},"state": [false,{}]},{"instanceId": 5,"label": "Fast Sweep","controlValues": {"amount": 0.926587999,"feedback": 0.761399984,"min_delay": 0.100000001,"mod_depth": 4.35481977,"mod_rate": 5.22819996},"state": [false,{}]},{"instanceId": 6,"label": "Slow Resonant","controlValues": {"amount": 1,"feedback": -0.882000029,"min_delay": 0.125892997,"mod_depth": 0.362217993,"mod_rate": 0.146847993},"state": [false,{}]},{"instanceId": 7,"label": "Warble","controlValues": {"amount": 0.318639994,"feedback": -0.99000001,"min_delay": 0.218776003,"mod_depth": 0.181538999,"mod_rate": 20},"state": [false,{}]}],"nextInstanceId": 8}
+1
View File
@@ -0,0 +1 @@
{"pluginUri": "http://calf.sourceforge.net/plugins/MonoCompressor","presets": [{"instanceId": 1,"label": "Vocal Leveller","controlValues": {"attack": 3.10086989,"bypass": 0,"clip_in": 0,"clip_out": 1,"compression": 0.176127002,"detection": 0,"knee": 8,"level_in": 1,"makeup": 4.85678005,"meter_in": 0.847831011,"meter_out": 0.908609986,"ratio": 4.25008011,"release": 25.0011997,"stereo_link": 0,"threshold": 0.0883883983},"state": [false,{}]},{"instanceId": 2,"label": "Vocal Leveller 2","controlValues": {"attack": 10.5095997,"bypass": 0,"clip_in": 0,"clip_out": 1,"compression": 0.247421995,"detection": 0,"knee": 8,"level_in": 1,"makeup": 4.85678005,"meter_in": 0.533456981,"meter_out": 0.740245998,"ratio": 4.25008011,"release": 106.851997,"stereo_link": 0,"threshold": 0.0883883983},"state": [false,{}]},{"instanceId": 3,"label": "Snare Mic","controlValues": {"attack": 3.5034399,"bypass": 0,"clip_in": 0,"clip_out": 0,"compression": 1,"detection": 0,"knee": 1,"level_in": 1.05701995,"makeup": 2.94853997,"meter_in": 0,"meter_out": 0,"ratio": 3.00696993,"release": 21.8598995,"stereo_link": 0,"threshold": 0.164939001},"state": [false,{}]},{"instanceId": 4,"label": "Snare Mic 2","controlValues": {"attack": 10.5095997,"bypass": 0,"clip_in": 0,"clip_out": 0,"compression": 1,"detection": 0,"knee": 1,"level_in": 1.05701995,"makeup": 2.94853997,"meter_in": 0,"meter_out": 0,"ratio": 3.00696993,"release": 80.6973038,"stereo_link": 0,"threshold": 0.164939001},"state": [false,{}]}],"nextInstanceId": 5}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
View File
@@ -0,0 +1 @@
{"pluginUri": "http://calf.sourceforge.net/plugins/Reverb","presets": [{"instanceId": 1,"label": "Ambience","controlValues": {"amount": 0.291182995,"bass_cut": 514.078979,"decay_time": 1.10353994,"diffusion": 0.689999998,"dry": 1,"hf_damp": 2182.58008,"predelay": 6.5,"room_size": 4,"treble_cut": 4064.1499},"state": [false,{}]},{"instanceId": 2,"label": "Large Occupied Hall","controlValues": {"amount": 0.184284002,"decay_time": 1.45396996,"hf_damp": 9795.58008},"state": [false,{}]},{"instanceId": 3,"label": "Room","controlValues": {"amount": 0.469761014,"bass_cut": 257.649994,"decay_time": 0.445944995,"diffusion": 0.540000021,"dry": 1,"hf_damp": 5508.45996,"predelay": 25,"room_size": 4,"treble_cut": 20000},"state": [false,{}]},{"instanceId": 4,"label": "Large Empty Hall","controlValues": {"amount": 0.366021991,"decay_time": 2.00689006,"hf_damp": 20000},"state": [false,{}]},{"instanceId": 5,"label": "DiscoVerb","controlValues": {"amount": 0.269807011,"decay_time": 1,"hf_damp": 3396.48999},"state": [false,{}]},{"instanceId": 6,"label": "Empty walls","controlValues": {"amount": 0.198883995,"bass_cut": 240.453003,"decay_time": 0.505686998,"diffusion": 0.170000002,"dry": 1,"hf_damp": 3971.63989,"predelay": 13,"room_size": 4,"treble_cut": 3303.46997},"state": [false,{}]}],"nextInstanceId": 7}
+1
View File
@@ -0,0 +1 @@
{"pluginUri": "http://calf.sourceforge.net/plugins/Wavetable","presets": [{"instanceId": 1,"label": "Jazz Guitar","controlValues": {"adsr2_a": 1,"adsr2_d": 350,"adsr2_r": 50,"adsr2_s": 0.5,"adsr2_v": 1,"adsr3_a": 1,"adsr3_d": 350,"adsr3_r": 50,"adsr3_s": 0.5,"adsr3_v": 0,"adsr_a": 1,"adsr_d": 1863.34998,"adsr_r": 50,"adsr_s": 0.0299999993,"adsr_v": 0.5,"o1detune": 1,"o1level": 0.133972004,"o1offset": 0.0399999991,"o1trans": 0,"o1wave": 20,"o2detune": -1,"o2level": 0,"o2offset": 0.140000001,"o2trans": 0,"o2wave": 16},"state": [false,{}]},{"instanceId": 2,"label": "Reed","controlValues": {"adsr2_a": 1,"adsr2_d": 350,"adsr2_r": 50,"adsr2_s": 0.5,"adsr2_v": 1,"adsr3_a": 1,"adsr3_d": 350,"adsr3_r": 50,"adsr3_s": 0.5,"adsr3_v": 0,"adsr_a": 78.0643997,"adsr_d": 350,"adsr_r": 50,"adsr_s": 0.5,"adsr_v": 1,"o1detune": 6,"o1level": 0.100000001,"o1offset": -0.280000001,"o1trans": 0,"o1wave": 23,"o2detune": -6,"o2level": 0.0669858009,"o2offset": 0.400000006,"o2trans": 0,"o2wave": 24},"state": [false,{}]},{"instanceId": 3,"label": "AmbiDeXtrous","controlValues": {"adsr2_a": 1,"adsr2_d": 60.9300003,"adsr2_r": 50,"adsr2_s": 0,"adsr2_v": 1,"adsr3_a": 1,"adsr3_d": 350,"adsr3_r": 50,"adsr3_s": 0.5,"adsr3_v": 0,"adsr_a": 1,"adsr_d": 1274.21997,"adsr_r": 50,"adsr_s": 0.389999986,"adsr_v": 1,"o1detune": 6,"o1level": 0.03125,"o1offset": -0.0199999996,"o1trans": 0,"o1wave": 13,"o2detune": -6,"o2level": 0.0412346013,"o2offset": 0.0199999996,"o2trans": 0,"o2wave": 15},"state": [false,{}]},{"instanceId": 4,"label": "Double Reed","controlValues": {"adsr2_a": 1,"adsr2_d": 350,"adsr2_r": 50,"adsr2_s": 0.5,"adsr2_v": 1,"adsr3_a": 1,"adsr3_d": 350,"adsr3_r": 50,"adsr3_s": 0.5,"adsr3_v": 0,"adsr_a": 78.0643997,"adsr_d": 350,"adsr_r": 50,"adsr_s": 0.5,"adsr_v": 1,"o1detune": 6,"o1level": 0.100000001,"o1offset": 0.0199999996,"o1trans": 0,"o1wave": 24,"o2detune": -6,"o2level": 0.0669858009,"o2offset": 0.239999995,"o2trans": -12,"o2wave": 23},"state": [false,{}]},{"instanceId": 5,"label": "Sharp Sync","controlValues": {"adsr2_a": 1,"adsr2_d": 350,"adsr2_r": 50,"adsr2_s": 0.5,"adsr2_v": 0,"adsr3_a": 1,"adsr3_d": 350,"adsr3_r": 50,"adsr3_s": 0.5,"adsr3_v": 0,"adsr_a": 1,"adsr_d": 350,"adsr_r": 50,"adsr_s": 0.5,"adsr_v": 0,"o1detune": 6,"o1level": 0.03125,"o1offset": -0.0599999987,"o1trans": 0,"o1wave": 0,"o2detune": -5,"o2level": 0.0441941991,"o2offset": -0.519999981,"o2trans": 0,"o2wave": 11},"state": [false,{}]},{"instanceId": 6,"label": "Swish","controlValues": {"adsr2_a": 1,"adsr2_d": 350,"adsr2_r": 50,"adsr2_s": 0.5,"adsr2_v": 1,"adsr3_a": 1,"adsr3_d": 350,"adsr3_r": 50,"adsr3_s": 0.5,"adsr3_v": 0,"adsr_a": 47.5774994,"adsr_d": 350,"adsr_r": 50,"adsr_s": 0.5,"adsr_v": 1,"o1detune": 6,"o1level": 0.100000001,"o1offset": -0.319999993,"o1trans": 0,"o1wave": 1,"o2detune": -6,"o2level": 0,"o2offset": 0.400000006,"o2trans": 0,"o2wave": 0},"state": [false,{}]}],"nextInstanceId": 7}
File diff suppressed because one or more lines are too long
+1
View File
@@ -0,0 +1 @@
{"pluginUri": "http://drobilla.net/plugins/mda/Detune","presets": [{"instanceId": 1,"label": "Stereo Detune","controlValues": {"detune": 0.200000003,"latency": 0.5,"mix": 0.899999976,"output": 0.5},"state": [false,{}]},{"instanceId": 2,"label": "Symphonic","controlValues": {"detune": 0.200000003,"latency": 0.5,"mix": 0.899999976,"output": 0.5},"state": [false,{}]},{"instanceId": 3,"label": "Out Of Tune","controlValues": {"detune": 0.800000012,"latency": 0.5,"mix": 0.699999988,"output": 0.5},"state": [false,{}]}],"nextInstanceId": 4}
File diff suppressed because one or more lines are too long
+1
View File
@@ -0,0 +1 @@
{"pluginUri": "http://drobilla.net/plugins/mda/Leslie","presets": [{"instanceId": 1,"label": "Default","controlValues": {"hi_depth": 0.600000024,"hi_throb": 0.699999988,"hi_width": 0.699999988,"lo_throb": 0.600000024,"lo_width": 0.5,"mode": 0.5,"output": 0.5,"speed": 0.5,"x_over": 0.479999989},"state": [false,{}]},{"instanceId": 2,"label": "Slow","controlValues": {"hi_depth": 0.75,"hi_throb": 0.569999993,"hi_width": 0.699999988,"lo_throb": 0.600000024,"lo_width": 0.5,"mode": 0.5,"output": 0.5,"speed": 0.5,"x_over": 0.479999989},"state": [false,{}]},{"instanceId": 3,"label": "Fast","controlValues": {"hi_depth": 0.600000024,"hi_throb": 0.699999988,"hi_width": 0.699999988,"lo_throb": 0.600000024,"lo_width": 0.5,"mode": 1,"output": 0.5,"speed": 0.5,"x_over": 0.479999989},"state": [false,{}]}],"nextInstanceId": 4}
+1
View File
@@ -0,0 +1 @@
{"pluginUri": "http://drobilla.net/plugins/mda/Piano","presets": [{"instanceId": 1,"label": "Broken Piano","controlValues": {"env_decay": 0.0500000007,"env_release": 0.957000017,"fine_tuning": 0.449999988,"hardness_offset": 0.5,"muffling_filter": 0.298999995,"polyphony": 0.330000013,"random_detuning": 0.717999995,"stereo_width": 0.5,"stretch_tuning": 0,"vel_sensitivity": 0,"vel_to_hardness": 0.5,"vel_to_muffling": 1},"state": [false,{}]},{"instanceId": 2,"label": "Plain Piano","controlValues": {"env_decay": 0.5,"env_release": 0.5,"fine_tuning": 0.5,"hardness_offset": 0.5,"muffling_filter": 0.750999987,"polyphony": 0,"random_detuning": 0,"stereo_width": 0,"stretch_tuning": 0.5,"vel_sensitivity": 0.451999992,"vel_to_hardness": 0.5,"vel_to_muffling": 0},"state": [false,{}]},{"instanceId": 3,"label": "MDA Piano","controlValues": {"env_decay": 0.5,"env_release": 0.5,"fine_tuning": 0.5,"hardness_offset": 0.5,"muffling_filter": 0.802999973,"polyphony": 0.330000013,"random_detuning": 0.246000007,"stereo_width": 0.5,"stretch_tuning": 0.5,"vel_sensitivity": 0.375999987,"vel_to_hardness": 0.5,"vel_to_muffling": 0.250999987},"state": [false,{}]},{"instanceId": 4,"label": "Compressed Piano","controlValues": {"env_decay": 0.90200001,"env_release": 0.398999989,"fine_tuning": 0.5,"hardness_offset": 0.623000026,"muffling_filter": 1,"polyphony": 0.330000013,"random_detuning": 0,"stereo_width": 0.499000013,"stretch_tuning": 0.5,"vel_sensitivity": 0.298999995,"vel_to_hardness": 0.5,"vel_to_muffling": 0.331},"state": [false,{}]},{"instanceId": 5,"label": "Dark Piano","controlValues": {"env_decay": 0.5,"env_release": 0.601999998,"fine_tuning": 0.5,"hardness_offset": 0,"muffling_filter": 0.30399999,"polyphony": 0.330000013,"random_detuning": 0.317000002,"stereo_width": 0.651000023,"stretch_tuning": 0.5,"vel_sensitivity": 0.335999995,"vel_to_hardness": 0.5,"vel_to_muffling": 0.200000003},"state": [false,{}]},{"instanceId": 6,"label": "Concert Piano","controlValues": {"env_decay": 0.648000002,"env_release": 0.5,"fine_tuning": 0.5,"hardness_offset": 0.5,"muffling_filter": 0.298000008,"polyphony": 0.356000006,"random_detuning": 0.338999987,"stereo_width": 0.850000024,"stretch_tuning": 0.660000026,"vel_sensitivity": 0.550000012,"vel_to_hardness": 0.5,"vel_to_muffling": 0.601999998},"state": [false,{}]},{"instanceId": 7,"label": "School Piano","controlValues": {"env_decay": 0.449999988,"env_release": 0.59799999,"fine_tuning": 0.5,"hardness_offset": 0.625999987,"muffling_filter": 0.602999985,"polyphony": 0.330000013,"random_detuning": 0.421000004,"stereo_width": 0.331,"stretch_tuning": 0.800999999,"vel_sensitivity": 0.173999995,"vel_to_hardness": 0.5,"vel_to_muffling": 0.5},"state": [false,{}]},{"instanceId": 8,"label": "Dance Piano","controlValues": {"env_decay": 0.398999989,"env_release": 0.250999987,"fine_tuning": 0.5,"hardness_offset": 1,"muffling_filter": 0.671999991,"polyphony": 0.330000013,"random_detuning": 0.282999992,"stereo_width": 0.248999998,"stretch_tuning": 0.666999996,"vel_sensitivity": 0.127000004,"vel_to_hardness": 0.5,"vel_to_muffling": 0.123999998},"state": [false,{}]}],"nextInstanceId": 9}
+1
View File
@@ -0,0 +1 @@
{"pluginUri": "http://drobilla.net/plugins/mda/Splitter","presets": [{"instanceId": 1,"label": "Frequency/Level Splitter","controlValues": {"envelope": 0.5,"freq": 0.5,"freq_sw": 0.25,"level": 0.5,"level_sw": 0.5,"mode": 0,"output": 0.5},"state": [false,{}]},{"instanceId": 2,"label": "Pass Peaks Only","controlValues": {"envelope": 0.5,"freq": 0.5,"freq_sw": 0.5,"level": 0.5,"level_sw": 0,"mode": 0,"output": 0.5},"state": [false,{}]},{"instanceId": 3,"label": "Stereo Crossover","controlValues": {"envelope": 0.5,"freq": 0.5,"freq_sw": 0.25,"level": 0.5,"level_sw": 0.5,"mode": 0.666666985,"output": 0.5},"state": [false,{}]}],"nextInstanceId": 4}
+1
View File
@@ -0,0 +1 @@
{"pluginUri": "http://drobilla.net/plugins/mda/ThruZero","presets": [{"instanceId": 1,"label": "Phase Canceller","controlValues": {"depth": 0.200000003,"depth_mod": 1,"feedback": 0.300000012,"mix": 0.469999999,"rate": 0.5},"state": [false,{}]},{"instanceId": 2,"label": "Mad Modulator","controlValues": {"depth": 1,"depth_mod": 1,"feedback": 0.75,"mix": 0.5,"rate": 0.75},"state": [false,{}]},{"instanceId": 3,"label": "Chorus Doubler","controlValues": {"depth": 0.600000024,"depth_mod": 0.699999988,"feedback": 0.300000012,"mix": 0.349999994,"rate": 0.600000024},"state": [false,{}]},{"instanceId": 4,"label": "Thru-Zero Flanger","controlValues": {"depth": 0.430000007,"depth_mod": 1,"feedback": 0.300000012,"mix": 0.469999999,"rate": 0.300000012},"state": [false,{}]}],"nextInstanceId": 5}
+1
View File
@@ -0,0 +1 @@
{"pluginUri": "http://drobilla.net/plugins/mda/Vocoder","presets": [{"instanceId": 1,"label": "Default","controlValues": {"envelope": 0.159999996,"filter_q": 0.550000012,"hi_band": 0.400000006,"hi_thru": 0.400000006,"mid_freq": 0.666700006,"mod_in": 0,"output": 0.5,"quality": 0},"state": [false,{}]},{"instanceId": 2,"label": "Old Vocoder","controlValues": {"envelope": 0.159999996,"filter_q": 0.550000012,"hi_band": 0,"hi_thru": 0,"mid_freq": 0.5,"mod_in": 0,"output": 0.5,"quality": 0},"state": [false,{}]},{"instanceId": 3,"label": "Pad Vocoder","controlValues": {"envelope": 0.779999971,"filter_q": 0.550000012,"hi_band": 0.400000006,"hi_thru": 0.400000006,"mid_freq": 0.300000012,"mod_in": 0,"output": 0.5,"quality": 0},"state": [false,{}]},{"instanceId": 4,"label": "16 Band Vocoder","controlValues": {"envelope": 0.159999996,"filter_q": 0.550000012,"hi_band": 0.400000006,"hi_thru": 0.400000006,"mid_freq": 0.666700006,"mod_in": 0,"output": 0.5,"quality": 1},"state": [false,{}]},{"instanceId": 5,"label": "Choral Vocoder","controlValues": {"envelope": 0.159999996,"filter_q": 0.699999988,"hi_band": 0,"hi_thru": 0.400000006,"mid_freq": 0.5,"mod_in": 0,"output": 0.5,"quality": 0},"state": [false,{}]}],"nextInstanceId": 6}
+1
View File
@@ -0,0 +1 @@
{"pluginUri": "http://drobilla.net/plugins/mda/EPiano","presets": [{"instanceId": 1,"label": "Bright","controlValues": {"env_decay": 0.5,"env_release": 0.5,"fine_tuning": 0.5,"hardness": 1,"lfo_rate": 0.649999976,"modulation": 0.5,"overdrive": 0.5,"polyphonic": 1,"random_tuning": 0.145999998,"stereo_width": 0.5,"treble_boost": 0.800000012,"vel_sense": 0.25},"state": [false,{}]},{"instanceId": 2,"label": "Default","controlValues": {"env_decay": 0.5,"env_release": 0.5,"fine_tuning": 0.5,"hardness": 0.5,"lfo_rate": 0.649999976,"modulation": 0.5,"overdrive": 0,"polyphonic": 1,"random_tuning": 0.145999998,"stereo_width": 0.5,"treble_boost": 0.5,"vel_sense": 0.25},"state": [false,{}]},{"instanceId": 3,"label": "Tremolo","controlValues": {"env_decay": 0.5,"env_release": 0.5,"fine_tuning": 0.5,"hardness": 0.5,"lfo_rate": 0.649999976,"modulation": 0.75,"overdrive": 0,"polyphonic": 1,"random_tuning": 0.246000007,"stereo_width": 0.5,"treble_boost": 0.5,"vel_sense": 0.25},"state": [false,{}]},{"instanceId": 4,"label": "Mellow","controlValues": {"env_decay": 0.5,"env_release": 0.5,"fine_tuning": 0.5,"hardness": 0,"lfo_rate": 0.649999976,"modulation": 0.5,"overdrive": 0,"polyphonic": 1,"random_tuning": 0.246000007,"stereo_width": 0.5,"treble_boost": 0,"vel_sense": 0.25},"state": [false,{}]},{"instanceId": 5,"label": "Autopan","controlValues": {"env_decay": 0.5,"env_release": 0.5,"fine_tuning": 0.5,"hardness": 0.5,"lfo_rate": 0.649999976,"modulation": 0.25,"overdrive": 0,"polyphonic": 1,"random_tuning": 0.246000007,"stereo_width": 0.5,"treble_boost": 0.5,"vel_sense": 0.25},"state": [false,{}]}],"nextInstanceId": 6}
+1 -1
View File
@@ -1 +1 @@
{"entries": [{"pluginUri": "urn:zamaudio:ZaMaximX2","fileName": "1.json"},{"pluginUri": "urn:zamaudio:ZaMultiComp","fileName": "2.json"},{"pluginUri": "urn:zamaudio:ZaMultiCompX2","fileName": "3.json"},{"pluginUri": "urn:zamaudio:ZamComp","fileName": "4.json"},{"pluginUri": "urn:zamaudio:ZamCompX2","fileName": "5.json"},{"pluginUri": "urn:zamaudio:ZamDelay","fileName": "6.json"},{"pluginUri": "urn:zamaudio:ZamDynamicEQ","fileName": "7.json"},{"pluginUri": "urn:zamaudio:ZamEQ2","fileName": "8.json"},{"pluginUri": "urn:zamaudio:ZamGEQ31","fileName": "9.json"},{"pluginUri": "urn:zamaudio:ZamGate","fileName": "10.json"},{"pluginUri": "urn:zamaudio:ZamGateX2","fileName": "11.json"},{"pluginUri": "urn:zamaudio:ZamGrains","fileName": "12.json"},{"pluginUri": "urn:zamaudio:ZamHeadX2","fileName": "13.json"},{"pluginUri": "urn:zamaudio:ZamPhono","fileName": "14.json"},{"pluginUri": "urn:zamaudio:ZamTube","fileName": "15.json"},{"pluginUri": "urn:zamaudio:ZamVerb","fileName": "16.json"},{"pluginUri": "http://two-play.com/plugins/toob-delay","fileName": "17.json"},{"pluginUri": "http://two-play.com/plugins/toob-ml","fileName": "18.json"}],"nextInstanceId": 19}
{"entries": [{"pluginUri": "urn:zamaudio:ZaMaximX2","fileName": "1.json"},{"pluginUri": "urn:zamaudio:ZaMultiComp","fileName": "2.json"},{"pluginUri": "urn:zamaudio:ZaMultiCompX2","fileName": "3.json"},{"pluginUri": "urn:zamaudio:ZamComp","fileName": "4.json"},{"pluginUri": "urn:zamaudio:ZamCompX2","fileName": "5.json"},{"pluginUri": "urn:zamaudio:ZamDelay","fileName": "6.json"},{"pluginUri": "urn:zamaudio:ZamDynamicEQ","fileName": "7.json"},{"pluginUri": "urn:zamaudio:ZamEQ2","fileName": "8.json"},{"pluginUri": "urn:zamaudio:ZamGEQ31","fileName": "9.json"},{"pluginUri": "urn:zamaudio:ZamGate","fileName": "10.json"},{"pluginUri": "urn:zamaudio:ZamGateX2","fileName": "11.json"},{"pluginUri": "urn:zamaudio:ZamGrains","fileName": "12.json"},{"pluginUri": "urn:zamaudio:ZamHeadX2","fileName": "13.json"},{"pluginUri": "urn:zamaudio:ZamPhono","fileName": "14.json"},{"pluginUri": "urn:zamaudio:ZamTube","fileName": "15.json"},{"pluginUri": "urn:zamaudio:ZamVerb","fileName": "16.json"},{"pluginUri": "http://two-play.com/plugins/toob-delay","fileName": "17.json"},{"pluginUri": "http://two-play.com/plugins/toob-ml","fileName": "18.json"},{"pluginUri": "http://calf.sourceforge.net/plugins/Filter","fileName": "19.json"},{"pluginUri": "http://calf.sourceforge.net/plugins/Flanger","fileName": "20.json"},{"pluginUri": "http://calf.sourceforge.net/plugins/MonoCompressor","fileName": "21.json"},{"pluginUri": "http://calf.sourceforge.net/plugins/Monosynth","fileName": "22.json"},{"pluginUri": "http://calf.sourceforge.net/plugins/Organ","fileName": "23.json"},{"pluginUri": "http://calf.sourceforge.net/plugins/Reverb","fileName": "24.json"},{"pluginUri": "http://calf.sourceforge.net/plugins/Wavetable","fileName": "25.json"},{"pluginUri": "http://drobilla.net/plugins/mda/DX10","fileName": "26.json"},{"pluginUri": "http://drobilla.net/plugins/mda/Detune","fileName": "27.json"},{"pluginUri": "http://drobilla.net/plugins/mda/JX10","fileName": "28.json"},{"pluginUri": "http://drobilla.net/plugins/mda/Leslie","fileName": "29.json"},{"pluginUri": "http://drobilla.net/plugins/mda/Piano","fileName": "30.json"},{"pluginUri": "http://drobilla.net/plugins/mda/Splitter","fileName": "31.json"},{"pluginUri": "http://drobilla.net/plugins/mda/ThruZero","fileName": "32.json"},{"pluginUri": "http://drobilla.net/plugins/mda/Vocoder","fileName": "33.json"},{"pluginUri": "http://drobilla.net/plugins/mda/EPiano","fileName": "34.json"}],"nextInstanceId": 35}
File diff suppressed because one or more lines are too long
+2 -2
View File
@@ -13,14 +13,14 @@ page_icon: img/Install4.jpg
Download the most recent Debian (.deb) package for your platform:
- [Ubuntu/Raspberry Pi OS (64-bit) v1.0.19](https://github.com/rerdavies/pipedal/releases/download/v1.0.19/pipedal_1.0.19_arm64.deb)
- [Ubuntu/Raspberry Pi OS (64-bit) v1.1.20](https://github.com/rerdavies/pipedal/releases/download/v1.1.20/pipedal_1.1.20_arm64.deb)
Install the package by running
```
sudo apt update
cd ~/Downloads
sudo apt-get install ./pipedal_1.0.19_arm64.deb
sudo apt-get install ./pipedal_1.1.20_arm64.deb
```
On Raspberry Pi OS, if you have a graphical desktop installed, you can also install the package by double-clicking on the downloaded package in the File Manager.
+19
View File
@@ -0,0 +1,19 @@
# Release Notes
## PiPedal 1.1.20
Features:
- Two new plugins: TooB Convolution Reverb, and TooB Cab IR.
- Output ports for LV2 plugins are now displayed (vu meters and status controls)
- File selection dialog, and uploads for LV2 atom:path Properties for 3rd party LV2 plugins.
Bug fixes:
- Improvements to onboarding procedure.
- Problems with restarting audio after changing audio parameters.
- Occasional loss of audio after reboot caused by ALSA USB initialization race conditions.
+2 -2
View File
@@ -4,14 +4,14 @@
Download the most recent Debian (.deb) package for your platform:
- [Ubuntu or Raspberry Pi OS (64-bit)](https://github.com/rerdavies/pipedal/releases/download/v1.0.19/pipedal_1.0.19_arm64.deb) v1.0.19
- [Ubuntu or Raspberry Pi OS (64-bit)](https://github.com/rerdavies/pipedal/releases/download/v1.1.20/pipedal_1.1.20_arm64.deb) v1.1.20
Install the package by running
```
sudo apt update
cd ~/Downloads
sudo apt-get install ./pipedal_1.0.19_arm64.deb
sudo apt-get install ./pipedal_1.1.20_arm64.deb
```
Follow the instructions in [_Configuring PiPedal After Installation_](https://rerdavies.github.io/pipedal/Configuring.html) to complete the installation.
+5 -1
View File
@@ -1,12 +1,16 @@
<img src="GithubBanner.png" width="100%"/>
<a href="Installing.html"><i>v1.0.19</i></a>
<a href="Installing.html"><i>v1.1.20</i></a>
&nbsp;
To download PiPedal, click [here](download.md).
<quote>
NEW version 1.1 release. See the [release notes](https://rerdavies.github.io/pipedal/ReleaseNotes) for details.
</quote>
Use your Raspberry Pi as a guitar effects pedal. Configure and control PiPedal with your phone or tablet.
PiPedal running on a Raspberry Pi 4 provides stable super-low-latency audio via external USB audio devices, or internal Raspberry Pi audio hats.
+431
View File
@@ -0,0 +1,431 @@
@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 pipedal_ui: <http://github.com/rerdavies/pipedal/ui#> .
@prefix ui: <http://lv2plug.in/ns/extensions/ui#> .
@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 cabir: <http://two-play.com/plugins/toob-cab-ir#> .
@prefix toobimpulse: <http://two-play.com/plugins/toob-impulse#> .
cabir:impulseFile1Group
a param:ControlGroup ,
pg:InputGroup ;
lv2:name "Impulse Response 1" ;
lv2:symbol "impulse1" .
cabir:impulseFile2Group
a param:ControlGroup ,
pg:InputGroup ;
lv2:name "Impulse Response 2" ;
lv2:symbol "impulse2" .
cabir:impulseFile3Group
a param:ControlGroup ,
pg:InputGroup ;
lv2:name "Impulse Response 3" ;
lv2:symbol "impulse3" .
cabir:impulseFile
a rdf:property;
rdfs:label "IR";
pg:group cabir:impulseFile1Group ;
rdfs:range atom:Path.
cabir:impulseFile2
a rdf:property;
rdfs:label "IR";
pg:group cabir:impulseFile2Group ;
rdfs:range atom:Path.
cabir:impulseFile3
a rdf:property;
rdfs:label "IR";
pg:group cabir:impulseFile3Group ;
rdfs:range atom:Path.
<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-cab-ir>
a lv2:Plugin ,
lv2:ReverbPlugin ;
doap:name "TooB Cab IR" ,
"TooB Cab IR"@en-gb-gb
;
doap:license <https://two-play.com/TooB/licenses/isc> ;
doap:maintainer <http://two-play.com/rerdavies#me> ;
lv2:minorVersion 0 ;
lv2:microVersion 14 ;
rdfs:comment """
TooB Cab IR is a convolution-based guitar cabinet impulse response simulator.
TooB Cab IR allows you to select and mix impulse responses for up to three microphone positions. Mixing is done before convolution FFTs are calculated,
so there is no performance cost for using more than one impulse response file.
Cab IR files are usually short, but sometimes include room response impulse files, which can be quite long. The Max T control determines the maximum length
to use for impulse response files. If the length of the impulse file is longer than the specified time, samples occuring after
the specified time are discarded, and the tail of the impulse convolution is fed back into the imput of the convolution. This ensures a smooth reverb tail,
and has little effect on the quality of the resulting reverb. If the impulse file is shorter than the specified time, then all samples in the impulse
file are used, and no feedback occurs.
Toob Convolution Reverb comes with a nominal set of cabinet impulse files to get you started. You are strongly encouraged to seek out reverb impulse files
on the internet.
Special thanks are extended to Kristoffer Ekstrand of Adventure Kid Research & Technology, who generously provided the base set of impulse files distributed with Toob Cab IR.
---
![CC-BY-4.0](/img/cc-by.png)
By: Kristoffer Ekstrand, Adventure Kid Research & Technology.
The following files are licensed under a [Creative Commons Attribution 4.0 International License.][1]
```
80s UK 001.wav
80s UK 002.wav
80s US 001.wav
80s US 002.wav
Modern UK 001.wav
Modern UK 002.wav
Modern US 001.wav
Modern US 002.wav
Modern US 003.wav
Modern US 004.wav
Radio 001.wav
Speaker 001.wav
Speaker 002.wav
Vintage UK 001.wav
Vintage UK 002.wav
Vintage US 001.wav
Vintage US 002.wav
```
Source: <https://www.adventurekid.se/akrt/free-reverb-impulse-responses/>
[1]: https://creativecommons.org/licenses/by/4.0/
""" ;
mod:brand "TooB";
mod:label "Convolution Reverb";
lv2:requiredFeature urid:map, state:makePath, state:mapPath ;
lv2:optionalFeature state::freePath;
lv2:extensionData state:interface;
lv2:optionalFeature lv2:hardRTCapable;
patch:readable
cabir:impulseFile, cabir:impulseFile2, cabir:impulseFile3;
patch:writable
cabir:impulseFile,cabir:impulseFile2,cabir:impulseFile3;
lv2:extensionData state:interface,
work:interface;
lv2:port
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 0 ;
lv2:symbol "reverb_mix" ;
lv2:name "Volume";
pg:group cabir:impulseFile1Group ;
lv2:default -10.0 ;
lv2:minimum -40.0 ;
lv2:maximum 20.0 ;
units:unit units:db ;
lv2:scalePoint [
rdfs:label "-INF" ;
rdf:value -40.0
];
rdfs:comment "Volume for impulse file #1." ;
],
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 1 ;
lv2:symbol "reverb_mix2" ;
lv2:name "Volume";
pg:group cabir:impulseFile2Group ;
lv2:default -10.0 ;
lv2:minimum -40.0 ;
lv2:maximum 20.0 ;
units:unit units:db ;
lv2:scalePoint [
rdfs:label "-INF" ;
rdf:value -40.0
];
rdfs:comment "Volume for impulse file #2." ;
],
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 2 ;
lv2:symbol "reverb_mix3" ;
lv2:name "Volume";
pg:group cabir:impulseFile3Group ;
lv2:default -10.0 ;
lv2:minimum -40.0 ;
lv2:maximum 20.0 ;
units:unit units:db ;
lv2:scalePoint [
rdfs:label "-INF" ;
rdf:value -40.0
];
rdfs:comment "Volume for impulse file #3." ;
],
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 3;
lv2:symbol "time" ;
lv2:name "Max T";
lv2:default 2.0 ;
lv2:minimum 0.1 ;
lv2:maximum 6.0 ;
lv2:portProperty epp:notAutomatic ;
lv2:portProperty epp:expensive ;
units:unit units:s ;
rdfs:comment "Maximum length of impulse data to use." ;
],
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 4;
lv2:symbol "direct_mix" ;
lv2:name "Direct";
lv2:default -40.0 ;
lv2:minimum -40.0 ;
lv2:maximum 20.0 ;
units:unit units:db ;
lv2:scalePoint [
rdfs:label "-INF" ;
rdf:value -40.0
];
rdfs:comment "Direct mix. Set to minimum to disable." ;
],
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 5 ;
lv2:symbol "predelay" ;
lv2:name "Predelay";
lv2:portProperty epp:notOnGUI;
lv2:default 0 ;
lv2:minimum 0 ;
lv2:maximum 1 ;
lv2:portProperty lv2:enumeration ;
lv2:scalePoint [
rdfs:label "Remove" ;
rdf:value 0.0;
],
[
rdfs:label "Keep" ;
rdf:value 1.0;
];
rdfs:comment "Removes leading silence in impulse when set to false." ;
],
[
a lv2:OutputPort ,
lv2:ControlPort ;
lv2:index 6 ;
lv2:symbol "loading_state" ;
lv2:name "Status";
lv2:portProperty lv2:enumeration ;
lv2:default 0.0 ;
lv2:minimum 0.0 ;
lv2:maximum 5.0 ;
# NotLoaded = 0,
# Idle = 1,
# Error = 2,
# SentRequest = 3,
# GotResponse = 4,
# CleaningUp = 5,
lv2:scalePoint [
rdfs:label "Not loaded" ;
rdf:value 0.0
],[
rdfs:label "Ready" ;
rdf:value 1.0
],[
rdfs:label "Error" ;
rdf:value 2.0
],[
rdfs:label "Loading" ;
rdf:value 3.0
],[
rdfs:label "Loading" ;
rdf:value 4.0
],[
rdfs:label "Loading" ;
rdf:value 5.0
];
rdfs:comment "Plugin status." ;
],
[
a lv2:AudioPort ,
lv2:InputPort ;
lv2:index 7 ;
lv2:symbol "in" ;
lv2:name "In"
],
[
a lv2:AudioPort ,
lv2:OutputPort ;
lv2:index 8 ;
lv2:symbol "out" ;
lv2:name "Out"
],
[
a atom:AtomPort ,
lv2:InputPort;
atom:bufferType atom:Sequence ;
atom:supports patch:Message;
lv2:designation lv2:control ;
atom:supports patch:Message ;
lv2:index 9 ;
lv2:symbol "control" ;
lv2:name "Control" ;
rdfs:comment "Control" ;
] , [
a atom:AtomPort ,
lv2:OutputPort ;
atom:bufferType atom:Sequence ;
atom:supports patch:Message;
lv2:designation lv2:control ;
lv2:index 10;
lv2:symbol "notify" ;
lv2:name "Notify" ;
rdfs:comment "Notification" ;
]
.
<http://two-play.com/plugins/toob-cab-ir> pipedal_ui:ui cabir:ui .
cabir:ui
a pipedal_ui:ui ;
pipedal_ui:fileProperties
[
a pipedal_ui:fileProperty;
rdfs:label "Impulse File" ;
lv2:index 0 ;
pg:group cabir:impulseFile1Group ;
pipedal_ui:directory "CabIR";
pipedal_ui:patchProperty cabir:impulseFile ;
pipedal_ui:fileTypes
[
a pipedal_ui:fileType;
rdfs:label "WAV File";
pipedal_ui:fileExtension ".wav";
];
],[
a pipedal_ui:fileProperty;
rdfs:label "Impulse File" ;
lv2:index 0 ;
pg:group cabir:impulseFile2Group ;
pipedal_ui:patchProperty cabir:impulseFile2 ;
pipedal_ui:directory "CabIR";
pipedal_ui:fileTypes
[
a pipedal_ui:fileType;
rdfs:label "WAV File";
pipedal_ui:fileExtension ".wav";
];
],[
a pipedal_ui:fileProperty;
rdfs:label "Impulse File" ;
lv2:index 0 ;
pg:group cabir:impulseFile3Group ;
pipedal_ui:patchProperty cabir:impulseFile3 ;
pipedal_ui:directory "CabIR";
pipedal_ui:fileTypes
[
a pipedal_ui:fileType;
rdfs:label "WAV File";
pipedal_ui:mimeType "audio/wav";
],
[
a pipedal_ui:fileType;
rdfs:label "FLAC File";
pipedal_ui:mimeType "audio/flac";
];
];
ui:portNotification
[
lv2:symbol "loading_state";
ui:plugin <http://two-play.com/plugins/toob-cab-ir>;
ui:protocol ui:floatProtocol;
# pipedal_ui:style pipedal_ui:text ;
# pipedal_ui:redLevel 0;
# pipedal_ui:yellowLevel -12;
# ui:portIndex 3;
]
.
+66 -18
View File
@@ -25,10 +25,10 @@
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix toobConvolutionReverb: <http://two-play.com/plugins/toob-convolution-reverb#> .
@prefix toobImpulse: <http://two-play.com/impulseFile#> .
toobImpulse:#impulseFile
@prefix toobcr: <http://two-play.com/plugins/toob-convolution-reverb#> .
@prefix toobimpulse: <http://two-play.com/plugins/toob-impulse#> .
toobimpulse:impulseFile
a rdf:property;
rdfs:label "File";
rdfs:range atom:Path.
@@ -154,16 +154,17 @@ Source: https://www.openair.hosted.york.ac.uk/?page_id=483
mod:brand "TooB";
mod:label "Convolution Reverb";
lv2:requiredFeature urid:map ;
lv2:requiredFeature urid:map, state:makePath, state:mapPath ;
lv2:optionalFeature state::freePath;
lv2:extensionData state:interface;
lv2:optionalFeature lv2:hardRTCapable;
patch:readable
toobImpulse:#impulseFile
toobimpulse:impulseFile
;
patch:writable
toobImpulse:#impulseFile
toobimpulse:impulseFile
;
lv2:extensionData state:interface,
work:interface;
@@ -220,6 +221,27 @@ Source: https://www.openair.hosted.york.ac.uk/?page_id=483
lv2:maximum 20.0 ;
units:unit units:db ;
lv2:scalePoint [
rdfs:label "-INF" ;
rdf:value -40.0
];
rdfs:comment "Reverb mix. Set to minimum to disable." ;
],
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 3 ;
lv2:portProperty epp:notOnGUI;
lv2:symbol "reverb_mix2" ;
lv2:name "IR Mix";
lv2:default -10.0 ;
lv2:minimum -40.0 ;
lv2:maximum 20.0 ;
units:unit units:db ;
lv2:scalePoint [
rdfs:label "-INF" ;
rdf:value -40.0
@@ -230,7 +252,28 @@ Source: https://www.openair.hosted.york.ac.uk/?page_id=483
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 3 ;
lv2:index 4 ;
lv2:portProperty epp:notOnGUI;
lv2:symbol "reverb_mix3" ;
lv2:name "IR Mix";
lv2:default -10.0 ;
lv2:minimum -40.0 ;
lv2:maximum 20.0 ;
units:unit units:db ;
lv2:scalePoint [
rdfs:label "-INF" ;
rdf:value -40.0
];
rdfs:comment "Reverb mix. Set to minimum to disable." ;
],
[
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 5 ;
lv2:symbol "predelay" ;
lv2:name "Predelay";
@@ -255,7 +298,7 @@ Source: https://www.openair.hosted.york.ac.uk/?page_id=483
a lv2:OutputPort ,
lv2:ControlPort ;
lv2:index 4 ;
lv2:index 6 ;
lv2:symbol "loading_state" ;
lv2:name "Status";
@@ -295,14 +338,14 @@ Source: https://www.openair.hosted.york.ac.uk/?page_id=483
[
a lv2:AudioPort ,
lv2:InputPort ;
lv2:index 5 ;
lv2:index 7 ;
lv2:symbol "in" ;
lv2:name "In"
],
[
a lv2:AudioPort ,
lv2:OutputPort ;
lv2:index 6 ;
lv2:index 8 ;
lv2:symbol "out" ;
lv2:name "Out"
],
@@ -314,7 +357,7 @@ Source: https://www.openair.hosted.york.ac.uk/?page_id=483
lv2:designation lv2:control ;
atom:supports patch:Message ;
lv2:index 7 ;
lv2:index 9 ;
lv2:symbol "control" ;
lv2:name "Control" ;
rdfs:comment "Control" ;
@@ -324,7 +367,7 @@ Source: https://www.openair.hosted.york.ac.uk/?page_id=483
atom:bufferType atom:Sequence ;
atom:supports patch:Message;
lv2:designation lv2:control ;
lv2:index 8;
lv2:index 10;
lv2:symbol "notify" ;
lv2:name "Notify" ;
rdfs:comment "Notification" ;
@@ -332,23 +375,28 @@ Source: https://www.openair.hosted.york.ac.uk/?page_id=483
.
<http://two-play.com/plugins/toob-convolution-reverb> pipedal_ui:ui toobConvolutionReverb:ui .
<http://two-play.com/plugins/toob-convolution-reverb> pipedal_ui:ui toobcr:ui .
toobConvolutionReverb:ui
toobcr:ui
a pipedal_ui:ui ;
pipedal_ui:fileProperties
[
a pipedal_ui:fileProperty;
rdfs:label "Impulse File" ;
lv2:index 4 ;
pipedal_ui:patchProperty toobImpulse:impulseFile ;
pipedal_ui:patchProperty toobimpulse:impulseFile ;
pipedal_ui:directory "ReverbImpulseFiles";
pipedal_ui:fileTypes
[
a pipedal_ui:fileType;
rdfs:label "WAV File";
pipedal_ui:fileExtension ".wav";
];
pipedal_ui:mimeType "audio/wav";
],
[
a pipedal_ui:fileType;
rdfs:label "FLAC File";
pipedal_ui:mimeType "audio/flac";
] ;
];
ui:portNotification
[
+1 -1
View File
@@ -1 +1 @@
ToobAmp.so.0.1.7
ToobAmp.so.1.0.8
Binary file not shown.
@@ -0,0 +1,26 @@
The following files have been graciously provided by Kristoffer Ekstrand (akak Adventure Kid),
and are licensed under a CC-BY-4.0 license:
https://creativecommons.org/licenses/by/4.0/
80s UK 001.wav
80s UK 002.wav
80s US 001.wav
80s US 002.wav
Modern UK 001.wav
Modern UK 002.wav
Modern US 001.wav
Modern US 002.wav
Modern US 003.wav
Modern US 004.wav
Radio 001.wav
Speaker 001.wav
Speaker 002.wav
Vintage UK 001.wav
Vintage UK 002.wav
Vintage US 001.wav
Vintage US 002.wav
By: Adventure Kid Research & Technology, Kristoffer Ekstrand.
Source: https://www.adventurekid.se/akrt/free-reverb-impulse-responses/
Binary file not shown.
+221 -216
View File
@@ -11,12 +11,17 @@
lv2:binary <ToobAmp.so> ;
rdfs:seeAlso <ConvolutionReverb.ttl> .
<http://two-play.com/plugins/toob-cab-ir> a lv2:Plugin ;
lv2:binary <ToobAmp.so> ;
rdfs:seeAlso <CabIR.ttl> .
<http://two-play.com/plugins/toob-ml> a lv2:Plugin ;
lv2:binary <ToobAmp.so> ;
rdfs:seeAlso <ToobML.ttl> .
<http://two-play.com/plugins/toob-power-stage-2> a lv2:Plugin ;
lv2:binary <ToobAmp.so> ;
rdfs:seeAlso <PowerStage2.ttl> .
@@ -52,231 +57,231 @@
<http://two-play.com/plugins/toob-power-stage>
modgui:gui [
modgui:resourcesDirectory <modgui> ;
modgui:iconTemplate <modgui/icon-toob-power-stage.html> ;
modgui:stylesheet <modgui/stylesheet-toob.css> ;
modgui:screenshot <modgui/screenshot-toob-power-stage.png> ;
modgui:thumbnail <modgui/thumbnail-toob-power-stage.png> ;
modgui:javascript <modgui/script-toob-power-stage.js> ;
# <http://two-play.com/plugins/toob-power-stage>
# modgui:gui [
# modgui:resourcesDirectory <modgui> ;
# modgui:iconTemplate <modgui/icon-toob-power-stage.html> ;
# modgui:stylesheet <modgui/stylesheet-toob.css> ;
# modgui:screenshot <modgui/screenshot-toob-power-stage.png> ;
# modgui:thumbnail <modgui/thumbnail-toob-power-stage.png> ;
# modgui:javascript <modgui/script-toob-power-stage.js> ;
modgui:brand "TooB" ;
modgui:label "TooB Power Stage" ;
# modgui:brand "TooB" ;
# modgui:label "TooB Power Stage" ;
modgui:monitoredOutputs [ lv2:symbol "notify"] ;
modgui:port [
lv2:index 0 ;
lv2:symbol "trim1" ;
lv2:name "TRIM" ;
] , [
lv2:index 1 ;
lv2:symbol "gain1" ;
lv2:name "GAIN" ;
] , [
lv2:index 2 ;
lv2:symbol "locut1" ;
lv2:name "LO CUT" ;
] , [
lv2:index 3 ;
lv2:symbol "hicut1" ;
lv2:name "HI CUT" ;
], [
lv2:index 22 ;
lv2:symbol "shape1" ;
lv2:name "SHAPE1" ;
], [
lv2:index 4 ;
lv2:symbol "gain2_enable" ;
lv2:name "Ena" ;
] , [
lv2:index 5 ;
lv2:symbol "trim2" ;
lv2:name "TRIM" ;
] , [
lv2:index 6 ;
lv2:symbol "gain2" ;
lv2:name "GAIN" ;
] , [
lv2:index 7 ;
lv2:symbol "locut2" ;
lv2:name "LO CUT" ;
] , [
lv2:index 8 ;
lv2:symbol "hicut2" ;
lv2:name "HI CUT" ;
], [
lv2:index 23 ;
lv2:symbol "shape2" ;
lv2:name "SHAPE2" ;
] , [
lv2:index 9 ;
lv2:symbol "gain3_enable" ;
lv2:name "Ena" ;
] ,
[
lv2:index 10 ;
lv2:symbol "trim3" ;
lv2:name "TRIM" ;
] , [
lv2:index 11 ;
lv2:symbol "gain3" ;
lv2:name "GAIN" ;
] , [
lv2:index 12 ;
lv2:symbol "locut3" ;
lv2:name "LO CUT" ;
] , [
lv2:index 13 ;
lv2:symbol "hicut3" ;
lv2:name "HI CUT" ;
] , [
lv2:index 24 ;
lv2:symbol "shape3" ;
lv2:name "SHAPE3" ;
], [
lv2:index 14 ;
lv2:symbol "sag" ;
lv2:name "SAG" ;
] , [
lv2:index 15 ;
lv2:symbol "sagd" ;
lv2:name "SAGD" ;
], [
lv2:index 16 ;
lv2:symbol "master" ;
lv2:name "MASTER" ;
],
[
a lv2:InputPort ,
lv2:ControlPort ;
# modgui:monitoredOutputs [ lv2:symbol "notify"] ;
# modgui:port [
# lv2:index 0 ;
# lv2:symbol "trim1" ;
# lv2:name "TRIM" ;
# ] , [
# lv2:index 1 ;
# lv2:symbol "gain1" ;
# lv2:name "GAIN" ;
# ] , [
# lv2:index 2 ;
# lv2:symbol "locut1" ;
# lv2:name "LO CUT" ;
# ] , [
# lv2:index 3 ;
# lv2:symbol "hicut1" ;
# lv2:name "HI CUT" ;
# ], [
# lv2:index 22 ;
# lv2:symbol "shape1" ;
# lv2:name "SHAPE1" ;
# ], [
# lv2:index 4 ;
# lv2:symbol "gain2_enable" ;
# lv2:name "Ena" ;
# ] , [
# lv2:index 5 ;
# lv2:symbol "trim2" ;
# lv2:name "TRIM" ;
# ] , [
# lv2:index 6 ;
# lv2:symbol "gain2" ;
# lv2:name "GAIN" ;
# ] , [
# lv2:index 7 ;
# lv2:symbol "locut2" ;
# lv2:name "LO CUT" ;
# ] , [
# lv2:index 8 ;
# lv2:symbol "hicut2" ;
# lv2:name "HI CUT" ;
# ], [
# lv2:index 23 ;
# lv2:symbol "shape2" ;
# lv2:name "SHAPE2" ;
# ] , [
# lv2:index 9 ;
# lv2:symbol "gain3_enable" ;
# lv2:name "Ena" ;
# ] ,
# [
# lv2:index 10 ;
# lv2:symbol "trim3" ;
# lv2:name "TRIM" ;
# ] , [
# lv2:index 11 ;
# lv2:symbol "gain3" ;
# lv2:name "GAIN" ;
# ] , [
# lv2:index 12 ;
# lv2:symbol "locut3" ;
# lv2:name "LO CUT" ;
# ] , [
# lv2:index 13 ;
# lv2:symbol "hicut3" ;
# lv2:name "HI CUT" ;
# ] , [
# lv2:index 24 ;
# lv2:symbol "shape3" ;
# lv2:name "SHAPE3" ;
# ], [
# lv2:index 14 ;
# lv2:symbol "sag" ;
# lv2:name "SAG" ;
# ] , [
# lv2:index 15 ;
# lv2:symbol "sagd" ;
# lv2:name "SAGD" ;
# ], [
# lv2:index 16 ;
# lv2:symbol "master" ;
# lv2:name "MASTER" ;
# ],
# [
# a lv2:InputPort ,
# lv2:ControlPort ;
lv2:index 21 ;
lv2:symbol "sagf" ;
lv2:name "SagF";
]
;
] .
# lv2:index 21 ;
# lv2:symbol "sagf" ;
# lv2:name "SagF";
# ]
# ;
# ] .
<http://two-play.com/plugins/toob-input_stage>
modgui:gui [
modgui:resourcesDirectory <modgui> ;
modgui:javascript <modgui/script-toob-input-stage.js> ;
modgui:iconTemplate <modgui/icon-toob-input-stage.html> ;
modgui:stylesheet <modgui/stylesheet-toob.css> ;
modgui:screenshot <modgui/screenshot-toob-input-stage.png> ;
modgui:thumbnail <modgui/thumbnail-toob-input-stage.png> ;
# <http://two-play.com/plugins/toob-input_stage>
# modgui:gui [
# modgui:resourcesDirectory <modgui> ;
# modgui:javascript <modgui/script-toob-input-stage.js> ;
# modgui:iconTemplate <modgui/icon-toob-input-stage.html> ;
# modgui:stylesheet <modgui/stylesheet-toob.css> ;
# modgui:screenshot <modgui/screenshot-toob-input-stage.png> ;
# modgui:thumbnail <modgui/thumbnail-toob-input-stage.png> ;
modgui:brand "TooB" ;
modgui:label "TooB Input Stage" ;
# modgui:brand "TooB" ;
# modgui:label "TooB Input Stage" ;
modgui:monitoredOutputs [ lv2:symbol "notify"] ;
modgui:port [
lv2:index 0 ;
lv2:symbol "trim" ;
lv2:name "Trim" ;
] , [
lv2:index 1 ;
lv2:symbol "locut" ;
lv2:name "Lo Cut" ;
] , [
lv2:index 2 ;
lv2:symbol "bright" ;
lv2:name "Bright" ;
] , [
lv2:index 3 ;
lv2:symbol "brightf" ;
lv2:name "Bright F" ;
] , [
lv2:index 4 ;
lv2:symbol "hicut" ;
lv2:name "Hi Cut" ;
] , [
lv2:index 5 ;
lv2:symbol "gate_t" ;
lv2:name "Gate T" ;
] , [
lv2:index 6 ;
lv2:symbol "boost" ;
lv2:name "Boost" ;
]
;
] .
# modgui:monitoredOutputs [ lv2:symbol "notify"] ;
# modgui:port [
# lv2:index 0 ;
# lv2:symbol "trim" ;
# lv2:name "Trim" ;
# ] , [
# lv2:index 1 ;
# lv2:symbol "locut" ;
# lv2:name "Lo Cut" ;
# ] , [
# lv2:index 2 ;
# lv2:symbol "bright" ;
# lv2:name "Bright" ;
# ] , [
# lv2:index 3 ;
# lv2:symbol "brightf" ;
# lv2:name "Bright F" ;
# ] , [
# lv2:index 4 ;
# lv2:symbol "hicut" ;
# lv2:name "Hi Cut" ;
# ] , [
# lv2:index 5 ;
# lv2:symbol "gate_t" ;
# lv2:name "Gate T" ;
# ] , [
# lv2:index 6 ;
# lv2:symbol "boost" ;
# lv2:name "Boost" ;
# ]
# ;
# ] .
<http://two-play.com/plugins/toob-cab-sim>
modgui:gui [
modgui:resourcesDirectory <modgui> ;
modgui:javascript <modgui/script-toob-cab-sim.js> ;
modgui:iconTemplate <modgui/icon-toob-cab-sim.html> ;
modgui:stylesheet <modgui/stylesheet-toob.css> ;
modgui:screenshot <modgui/screenshot-toob-cab-sim.png> ;
modgui:thumbnail <modgui/thumbnail-toob-cab-sim.png> ;
# <http://two-play.com/plugins/toob-cab-sim>
# modgui:gui [
# modgui:resourcesDirectory <modgui> ;
# modgui:javascript <modgui/script-toob-cab-sim.js> ;
# modgui:iconTemplate <modgui/icon-toob-cab-sim.html> ;
# modgui:stylesheet <modgui/stylesheet-toob.css> ;
# modgui:screenshot <modgui/screenshot-toob-cab-sim.png> ;
# modgui:thumbnail <modgui/thumbnail-toob-cab-sim.png> ;
modgui:brand "TooB" ;
modgui:label "TooB Cab Simulator" ;
# modgui:brand "TooB" ;
# modgui:label "TooB Cab Simulator" ;
modgui:monitoredOutputs [ lv2:symbol "notify"] ;
modgui:port [
lv2:index 0 ;
lv2:symbol "locut" ;
lv2:name "Lo Cut" ;
] , [
lv2:index 1 ;
lv2:symbol "bright" ;
lv2:name "Bright" ;
] , [
lv2:index 2 ;
lv2:symbol "brightf" ;
lv2:name "F" ;
] , [
lv2:index 3 ;
lv2:symbol "hicut" ;
lv2:name "Hi Cut" ;
], [
lv2:index 4 ;
lv2:symbol "comb" ;
lv2:name "Comb" ;
], [
lv2:index 5 ;
lv2:symbol "combf" ;
lv2:name "F" ;
], [
lv2:index 6 ;
lv2:symbol "trim" ;
lv2:name "Trim" ;
]
;
] .
# modgui:monitoredOutputs [ lv2:symbol "notify"] ;
# modgui:port [
# lv2:index 0 ;
# lv2:symbol "locut" ;
# lv2:name "Lo Cut" ;
# ] , [
# lv2:index 1 ;
# lv2:symbol "bright" ;
# lv2:name "Bright" ;
# ] , [
# lv2:index 2 ;
# lv2:symbol "brightf" ;
# lv2:name "F" ;
# ] , [
# lv2:index 3 ;
# lv2:symbol "hicut" ;
# lv2:name "Hi Cut" ;
# ], [
# lv2:index 4 ;
# lv2:symbol "comb" ;
# lv2:name "Comb" ;
# ], [
# lv2:index 5 ;
# lv2:symbol "combf" ;
# lv2:name "F" ;
# ], [
# lv2:index 6 ;
# lv2:symbol "trim" ;
# lv2:name "Trim" ;
# ]
# ;
# ] .
<http://two-play.com/plugins/toob-tone-stack>
modgui:gui [
modgui:resourcesDirectory <modgui> ;
modgui:javascript <modgui/script-toob-tone-stack.js> ;
modgui:iconTemplate <modgui/icon-toob-tone-stack.html> ;
modgui:stylesheet <modgui/stylesheet-toob.css> ;
modgui:screenshot <modgui/screenshot-toob-tone-stack.png> ;
modgui:thumbnail <modgui/thumbnail-toob-tone-stack.png> ;
# <http://two-play.com/plugins/toob-tone-stack>
# modgui:gui [
# modgui:resourcesDirectory <modgui> ;
# modgui:javascript <modgui/script-toob-tone-stack.js> ;
# modgui:iconTemplate <modgui/icon-toob-tone-stack.html> ;
# modgui:stylesheet <modgui/stylesheet-toob.css> ;
# modgui:screenshot <modgui/screenshot-toob-tone-stack.png> ;
# modgui:thumbnail <modgui/thumbnail-toob-tone-stack.png> ;
modgui:brand "TooB" ;
modgui:label "TooB Tone Stack" ;
# modgui:brand "TooB" ;
# modgui:label "TooB Tone Stack" ;
modgui:monitoredOutputs [ lv2:symbol "notify"] ;
modgui:port [
lv2:index 0 ;
lv2:symbol "bass" ;
lv2:name "Bass" ;
] , [
lv2:index 1 ;
lv2:symbol "mid" ;
lv2:name "Mid" ;
], [
lv2:index 2 ;
lv2:symbol "treble" ;
lv2:name "Treble" ;
] , [
lv2:index 3 ;
lv2:symbol "ampmodel" ;
lv2:name "Amp Model" ;
]
;
] .
# modgui:monitoredOutputs [ lv2:symbol "notify"] ;
# modgui:port [
# lv2:index 0 ;
# lv2:symbol "bass" ;
# lv2:name "Bass" ;
# ] , [
# lv2:index 1 ;
# lv2:symbol "mid" ;
# lv2:name "Mid" ;
# ], [
# lv2:index 2 ;
# lv2:symbol "treble" ;
# lv2:name "Treble" ;
# ] , [
# lv2:index 3 ;
# lv2:symbol "ampmodel" ;
# lv2:name "Amp Model" ;
# ]
# ;
# ] .
+189 -159
View File
@@ -21,176 +21,206 @@ add_custom_command(
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/react
DEPENDS
src/AlsaMidiDeviceInfo.tsx
src/SearchControl.tsx
src/SplitControlView.tsx
src/WifiConfigSettings.tsx
src/FullScreenIME.tsx
src/OkCancelDialog.tsx
src/PluginControl.tsx
src/reportWebVitals.ts
src/JackHostStatus.tsx
src/PluginPresetsDialog.tsx
src/ToobSpectrumAnalyzerView.tsx
src/MidiBindingsDialog.tsx
src/MidiBinding.tsx
src/TemporaryDrawer.tsx
src/ToobFrequencyResponseView.tsx
src/index.css
src/setupTests.ts
src/SearchFilter.tsx
src/PluginOutputControl.tsx
src/BankDialog.tsx
src/VuMeter.tsx
src/StringBuilder.tsx
src/FilePropertyDialog.tsx
src/GxTunerControl.tsx
src/App.tsx
src/GxTunerView.tsx
src/Rect.tsx
src/ToobSpectrumResponseView.tsx
src/DialogEx.tsx
src/GovernorSettings.tsx
src/FilePropertyControl.tsx
src/JackServerSettingsDialog.tsx
src/ZoomedUiControl.tsx
src/Pedal.tsx
src/FullScreenIME.tsx
src/PluginPreset.tsx
src/SystemMidiBindingsDialog.tsx
src/AppThemed.tsx
src/MainPage.tsx
src/PiPedalModel.tsx
src/AppThemed.css
src/PedalboardView.tsx
src/ControlViewFactory.tsx
src/PiPedalSocket.tsx
src/PluginClass.tsx
src/SplitControlView.tsx
src/logo.svg
src/ToobToneStackView.tsx
src/Banks.tsx
src/ToobPowerStage2View.tsx
src/ListSelectDialog.tsx
src/ToobWaveShapeView.tsx
src/PluginInfoDialog.tsx
src/SearchFilter.tsx
src/SearchControl.tsx
src/JackServerSettings.tsx
src/WifiChannel.tsx
src/WifiConfigDialog.tsx
src/App.test.tsx
src/PluginPresetSelector.tsx
src/Pedal.tsx
src/ToobMLView.tsx
src/SettingsDialog.tsx
src/ObservableProperty.tsx
src/PresetDialog.tsx
src/AndroidHost.tsx
src/SelectHoverBackground.tsx
src/WifiDirectConfigDialog.tsx
src/WifiDirectConfigSettings.tsx
src/PiPedalSocket.tsx
src/ToobFrequencyResponseView.tsx
src/ControlViewFactory.tsx
src/Utility.tsx
src/ToobToneStackView.tsx
src/SelectHoverBackground.tsx
src/MidiBindingsDialog.tsx
src/TemporaryDrawer.tsx
src/GxTunerView.tsx
src/ToobInputStageView.tsx
src/DraggableGrid.tsx
src/JackStatusView.tsx
src/PluginControl.tsx
src/XxxSnippet.tsx
src/PluginPreset.tsx
src/Jack.tsx
src/AlsaDeviceInfo.tsx
src/MidiBinding.tsx
src/PiPedalError.tsx
src/IControlViewFactory.tsx
src/Lv2Plugin.tsx
src/Pedalboard.tsx
src/AndroidHost.tsx
src/PedalboardView.tsx
src/PresetDialog.tsx
src/AppThemed.tsx
src/ZoomedDial.tsx
src/RenameDialog.tsx
src/SplitUiControls.tsx
src/GovernorSettings.tsx
src/AboutDialog.tsx
src/ToobSpectrumResponseView.tsx
src/PluginControlView.tsx
src/NoChangePassword.tsx
src/ToobSpectrumAnalyzerView.tsx
src/MidiBindingView.tsx
src/GxTunerControl.tsx
src/Banks.tsx
src/PluginPresetsDialog.tsx
src/BankDialog.tsx
src/UploadPresetDialog.tsx
src/ToobPowerStage2View.tsx
src/index.tsx
src/Units.tsx
src/VuMeter.tsx
src/App.test.tsx
src/DialogEx.tsx
src/StringBuilder.tsx
src/SelectChannelsDialog.tsx
src/WifiConfigSettings.tsx
src/Draggable.tsx
src/ZoomedUiControl.tsx
src/logo.svg
src/Rect.tsx
src/PluginClass.tsx
src/reportWebVitals.ts
src/PluginIcon.tsx
src/App.tsx
src/ResizeResponsiveComponent.tsx
src/SvgPathBuilder.tsx
src/JsonAtom.tsx
src/SplitUiControls.tsx
src/SelectChannelsDialog.tsx
src/ToobMLView.tsx
src/IControlViewFactory.tsx
src/AppThemed.css
src/ZoomedDial.tsx
src/Units.tsx
src/UploadPresetDialog.tsx
src/NumericInput.tsx
src/JackServerSettings.tsx
src/ListSelectDialog.tsx
src/react-app-env.d.ts
src/JackServerSettingsDialog.tsx
src/ObservableProperty.tsx
src/Pedalboard.tsx
src/SelectMidiChannelsDialog.tsx
src/WifiChannel.tsx
src/LoadPluginDialog.tsx
src/WifiConfigDialog.tsx
src/PluginInfoDialog.tsx
src/ToobWaveShapeView.tsx
src/ToobCabSimView.tsx
src/AlsaMidiDeviceInfo.tsx
src/ResizeResponsiveComponent.tsx
src/RenameDialog.tsx
src/SystemMidiBindingView.tsx
src/OldDeleteIcon.tsx
src/ToobInputStageView.tsx
src/XxxSnippet.tsx
src/NoChangePassword.tsx
src/react-app-env.d.ts
src/PiPedalError.tsx
src/AlsaDeviceInfo.tsx
src/index.tsx
src/SettingsDialog.tsx
src/PluginControlView.tsx
src/PresetSelector.tsx
src/OkCancelDialog.tsx
public/css/roboto.css
public/fonts/Roboto-BlackItalic.woff2
public/fonts/Roboto-Black.woff2
public/fonts/Roboto-BoldItalic.woff2
public/fonts/Roboto-Bold.woff2
public/fonts/Roboto-Italic.woff2
public/fonts/Roboto-LightItalic.woff2
public/fonts/Roboto-Light.woff2
public/fonts/Roboto-MediumItalic.woff2
public/fonts/Roboto-Medium.woff2
public/fonts/Roboto-Regular.woff2
public/fonts/Roboto-ThinItalic.woff2
public/fonts/Roboto-Thin.woff2
public/iso_codes.json
public/logo512.png
public/index.html
public/manifest.json
public/var
public/var/current_pedalboard.json
public/var/uiplugins.json
public/var/config.json
public/var/plugin_classes.json
public/logo192.png
public/serve.json
public/robots.txt
public/sample_lv2_plugins.json
public/logo192x.png
public/img/fx_analyzer.svg
public/img/fx_flanger.svg
public/img/cx_stereo.svg
public/img/fx_split_a.svg
public/img/fx_dial.svg
public/img/drive_file_rename_outline_black_24dp.svg
public/img/fx_filter.svg
public/img/fx_filter_hp.svg
public/img/cx_mono.svg
public/img/fx_limiter.svg
public/img/fx_converter.svg
public/img/fx_simulator.svg
public/img/fx_delay.svg
public/img/fx_reverb.svg
public/img/fx_empty.svg
public/img/fx_eq.svg
public/img/edit_banks.svg
public/img/fx_gate.svg
public/img/settings_black_24dp.svg
public/img/help_outline_black_24dp.svg
public/img/fx_oscillator.svg
public/img/fx_split_b.svg
public/img/fx_phaser.svg
public/img/fx_amplifier.svg
public/img/fx_plugin.svg
public/img/ic_drawer.svg
public/img/ic_drawer_2.png
public/img/fx_terminal.svg
public/img/fx_spatial.svg
public/img/fx_pitch.svg
public/img/ic_logo.svg
public/img/fx_flanger2.svg
public/img/fx_function.svg
public/img/fx_lr.svg
public/img/fx_generator.svg
public/img/fx_spectral.svg
public/img/fx_chorus.svg
public/img/fx_utility.svg
public/img/fx_mixer.svg
public/img/ic_presets.svg
public/img/fx_instrument.svg
public/img/fx_modulator.svg
public/img/fx_compressor.svg
public/img/fx_constant.svg
public/img/fx_distortion.svg
public/img/save_bank_as.svg
public/favicon.ico
src/ToobCabSimView.tsx
src/Utility.tsx
src/Lv2Plugin.tsx
src/Jack.tsx
src/JackStatusView.tsx
src/AboutDialog.tsx
src/setupTests.ts
src/DraggableGrid.tsx
src/SvgPathBuilder.tsx
src/LoadPluginDialog.tsx
src/MidiBindingView.tsx
src/PluginIcon.tsx
src/UploadFileDialog.tsx
public/
public/css
public/css/roboto.css
public/logo192x.png
public/robots.txt
public/img
public/img/ic_drawer_2.png
public/img/fx_constant.svg
public/img/cx_mono.svg
public/img/cx_stereo.svg
public/img/fx_distortion.svg
public/img/fx_oscillator.svg
public/img/settings_black_24dp.svg
public/img/fx_filter.svg
public/img/delete_outline_black_24dp.svg
public/img/fx_function.svg
public/img/fx_generator.svg
public/img/old_delete_outline_black_24dp.svg
public/img/ic_bank.svg
public/img/fx_compressor.svg
public/img/file_download_black_24dp.svg
public/img/fx_filter_hp.svg
public/img/fx_plugin.svg
public/img/fx_error.svg
public/img/fx_gate.svg
public/img/cc-by.png
public/img/ic_midi.svg
public/img/ic_pluginpreset.svg
public/img/fx_split_a.svg
public/img/fx_utility.svg
public/img/ic_navigate_before.svg
public/img/ic_drawer_2.svg
public/img/ic_pluginpreset2.svg
public/img/fx_parametric_eq.svg
public/img/fx_terminal.svg
public/img/ic_presets.svg
public/img/VST_Logo_Steinberg.ico
public/img/fx_flanger.svg
public/img/fx_analyzer.svg
public/img/fx_delay.svg
public/img/fx_spectral.svg
public/img/edit_banks.svg
public/img/fx_chorus.svg
public/img/fx_simulator.svg
public/img/drive_file_rename_outline_black_24dp.svg
public/img/fx_mixer.svg
public/img/fx_eq.svg
public/img/fx_modulator.svg
public/img/file_upload_black_24dp.svg
public/img/fx_pitch.svg
public/img/ic_navigate_next.svg
public/img/fx_phaser.svg
public/img/ic_drawer.svg
public/img/fx_amplifier.svg
public/img/save_bank_as.svg
public/img/fx_lr.svg
public/img/fx_instrument.svg
public/img/fx_reverb.svg
public/img/fx_limiter.svg
public/img/VST_Logo_Steinberg.png
public/img/fx_empty.svg
public/img/fx_dial.svg
public/img/ic_logo.svg
public/img/help_outline_black_24dp.svg
public/img/fx_flanger2.svg
public/img/old_delete_outline_white_24dp.svg
public/img/fx_split_b.svg
public/img/fx_spatial.svg
public/img/fx_converter.svg
public/img/vst.svg
public/img/vst.png
public/sample_lv2_plugins.json
public/serve.json
public/fonts
public/fonts/Roboto-LightItalic.woff2
public/fonts/Roboto-Light.woff2
public/fonts/Roboto-BlackItalic.woff2
public/fonts/Roboto-ThinItalic.woff2
public/fonts/Roboto-Bold.woff2
public/fonts/Roboto-Italic.woff2
public/fonts/Roboto-Black.woff2
public/fonts/Roboto-BoldItalic.woff2
public/fonts/Roboto-Regular.woff2
public/fonts/Roboto-Medium.woff2
public/fonts/Roboto-Thin.woff2
public/fonts/LICENSE.txt
public/fonts/Roboto-MediumItalic.woff2
public/favicon.ico
public/iso_codes.json
public/logo192.png
public/logo512.png
public/index.html
public/manifest.json
public/var
public/var/config.json
public/var/current_pedalboard.json
public/var/uiplugins.json
public/var/plugin_classes.json
)
add_custom_target (
+5 -3
View File
@@ -837,9 +837,11 @@ const AppThemed = withStyles(appStyles)(class extends ResizeResponsiveComponent<
>
<DialogContent>
<DialogContentText id="alert-dialog-description">
{
this.model_.alertMessage.get()
}
<Typography variant="body2">
{
this.state.alertDialogMessage
}
</Typography>
</DialogContentText>
</DialogContent>
<DialogActions>
+27 -16
View File
@@ -27,15 +27,12 @@ import { Theme } from '@mui/material/styles';
import { WithStyles } from '@mui/styles';
import createStyles from '@mui/styles/createStyles';
import withStyles from '@mui/styles/withStyles';
import { PiPedalFileProperty } from './Lv2Plugin';
import { UiFileProperty } from './Lv2Plugin';
import Typography from '@mui/material/Typography';
import { PiPedalModel, PiPedalModelFactory, ListenHandle, StateChangedHandle } from './PiPedalModel';
import ButtonBase from '@mui/material/ButtonBase'
import MoreHorizIcon from '@mui/icons-material/MoreHoriz';
import {PedalboardItem} from './Pedalboard';
export const StandardItemSize = { width: 80, height: 140 }
@@ -73,13 +70,14 @@ const styles = (theme: Theme) => createStyles({
export interface FilePropertyControlProps extends WithStyles<typeof styles> {
instanceId: number;
fileProperty: PiPedalFileProperty;
onFileClick: (fileProperty: PiPedalFileProperty, value: string) => void;
fileProperty: UiFileProperty;
pedalboardItem: PedalboardItem;
onFileClick: (fileProperty: UiFileProperty, value: string) => void;
theme: Theme;
}
type FilePropertyControlState = {
error: boolean;
hasValue: boolean;
value: string;
};
@@ -96,6 +94,7 @@ const FilePropertyControl =
this.state = {
error: false,
hasValue: false,
value: "",
};
this.model = PiPedalModelFactory.getInstance();
@@ -108,12 +107,12 @@ const FilePropertyControl =
refreshPatchProperty()
{
this.model.getPatchProperty(this.props.instanceId, this.props.fileProperty.patchProperty)
this.model.getPatchProperty(this.props.pedalboardItem.instanceId, this.props.fileProperty.patchProperty)
.then(
(json: any) => {
if (json && json.otype_ === "Path") {
let path = json.value as string;
this.setState({ value: path });
this.setState({ value: path, hasValue: true });
}
}
)
@@ -138,7 +137,7 @@ const FilePropertyControl =
}
this.refreshPatchProperty();
this.stateChangedHandle = this.model.addLv2StateChangedListener(
this.props.instanceId,
this.props.pedalboardItem.instanceId,
() => {
this.refreshPatchProperty();
});
@@ -149,19 +148,25 @@ const FilePropertyControl =
this.model.removeLv2StateChangedListener(this.stateChangedHandle);
}
}
private mounted: boolean = false;
componentDidMount() {
this.mounted = true;
this.subscribeToPropertyGet();
}
componentWillUnmount() {
this.unsubscribeToPropertyGet();
this.mounted = false;
}
componentDidUpdate(prevProps: Readonly<FilePropertyControlProps>, prevState: Readonly<FilePropertyControlState>, snapshot?: any): void {
if (prevProps.fileProperty.patchProperty !== this.props.fileProperty.patchProperty
|| prevProps.instanceId !== this.props.instanceId) {
this.setState({ value: "" });
|| prevProps.pedalboardItem.instanceId !== this.props.pedalboardItem.instanceId
|| prevProps.pedalboardItem.stateUpdateCount !== this.props.pedalboardItem.stateUpdateCount
) {
this.unsubscribeToPropertyGet();
this.subscribeToPropertyGet();
}
}
@@ -193,9 +198,15 @@ const FilePropertyControl =
//let classes = this.props.classes;
let fileProperty = this.props.fileProperty;
let value = this.fileNameOnly(this.state.value);
if (!value || value.length === 0) {
value = "\u00A0";
let value = "\u00A0";
if (this.state.hasValue)
{
if (this.state.value.length === 0)
{
value = "<none>";
} else {
value = this.fileNameOnly(this.state.value);
}
}
let item_width = 264;
+98 -12
View File
@@ -33,7 +33,7 @@ import IconButton from '@mui/material/IconButton';
import OldDeleteIcon from './OldDeleteIcon';
import ResizeResponsiveComponent from './ResizeResponsiveComponent';
import { PiPedalFileProperty } from './Lv2Plugin';
import { UiFileProperty } from './Lv2Plugin';
import ButtonBase from '@mui/material/ButtonBase';
import Typography from '@mui/material/Typography';
import DialogEx from './DialogEx';
@@ -42,9 +42,9 @@ import OkCancelDialog from './OkCancelDialog';
export interface FilePropertyDialogProps {
open: boolean,
fileProperty: PiPedalFileProperty,
fileProperty: UiFileProperty,
selectedFile: string,
onOk: (fileProperty: PiPedalFileProperty, selectedItem: string) => void,
onOk: (fileProperty: UiFileProperty, selectedItem: string) => void,
onCancel: () => void
};
@@ -53,6 +53,8 @@ export interface FilePropertyDialogState {
selectedFile: string;
hasSelection: boolean;
files: string[];
columns: number;
columnWidth: number;
openUploadFileDialog: boolean;
openConfirmDeleteDialog: boolean;
};
@@ -70,13 +72,33 @@ export default class FilePropertyDialog extends ResizeResponsiveComponent<FilePr
fullScreen: false,
selectedFile: props.selectedFile,
hasSelection: false,
columns: 0,
columnWidth: 1,
files: [],
openUploadFileDialog: false,
openConfirmDeleteDialog: false
};
this.requestScroll = true;
this.requestFiles();
}
private scrollRef: HTMLDivElement | null = null;
onScrollRef(element: HTMLDivElement | null) {
this.scrollRef = element;
this.maybeScrollIntoView();
}
private maybeScrollIntoView()
{
if (this.scrollRef !== null && this.state.files.length !== 0 && this.mounted && this.requestScroll)
{
this.requestScroll = false;
let options: ScrollIntoViewOptions = { block: "nearest"};
options.block = "nearest";
this.scrollRef.scrollIntoView(options);
}
}
private mounted: boolean = false;
private model: PiPedalModel;
@@ -91,6 +113,7 @@ export default class FilePropertyDialog extends ResizeResponsiveComponent<FilePr
this.model.requestFileList(this.props.fileProperty)
.then((files) => {
if (this.mounted) {
files.splice(0,0,"");
this.setState({ files: files, hasSelection: this.isFileInList(files, this.state.selectedFile) });
}
}).catch((error) => {
@@ -98,10 +121,39 @@ export default class FilePropertyDialog extends ResizeResponsiveComponent<FilePr
});
}
private lastDivRef : HTMLDivElement | null = null;
onMeasureRef(div: HTMLDivElement | null)
{
this.lastDivRef = div;
if (div) {
let width = div.offsetWidth;
if (width === 0) return;
let columns = Math.floor((width-40)/280);
if(columns === 0)
{
columns = 1;
}
let columnWidth = (width-40)/columns;
if (columns !== this.state.columns || columnWidth !== this.state.columnWidth)
{
this.setState({columns: columns, columnWidth: columnWidth});
}
}
}
onWindowSizeChanged(width: number, height: number): void {
this.setState({ fullScreen: height < 200 })
this.setState({
fullScreen: height < 200
})
if (this.lastDivRef !== null)
{
this.onMeasureRef(this.lastDivRef);
}
}
private requestScroll: boolean = false;
componentDidMount() {
super.componentDidMount();
@@ -110,6 +162,7 @@ export default class FilePropertyDialog extends ResizeResponsiveComponent<FilePr
componentWillUnmount() {
super.componentWillUnmount();
this.mounted = false;
this.lastDivRef = null;
}
componentDidUpdate(prevProps: Readonly<FilePropertyDialogProps>, prevState: Readonly<FilePropertyDialogState>, snapshot?: any): void {
super.componentDidUpdate?.(prevProps, prevState, snapshot);
@@ -118,6 +171,11 @@ export default class FilePropertyDialog extends ResizeResponsiveComponent<FilePr
if (this.props.open)
{
this.requestFiles()
this.requestScroll = true;
if (this.state.selectedFile !== this.props.selectedFile)
{
this.setState({selectedFile: this.props.selectedFile});
}
}
} else if (prevProps.fileProperty !== this.props.fileProperty) {
this.requestFiles()
@@ -144,6 +202,7 @@ export default class FilePropertyDialog extends ResizeResponsiveComponent<FilePr
private isFileInList(files: string[], file: string) {
let hasSelection = false;
if (file === "") return true;
for (var listFile of files) {
if (listFile === file) {
hasSelection = true;
@@ -154,6 +213,7 @@ export default class FilePropertyDialog extends ResizeResponsiveComponent<FilePr
}
onSelectValue(selectedFile: string) {
this.requestScroll = true;
this.setState({ selectedFile: selectedFile, hasSelection: this.isFileInList(this.state.files, selectedFile) })
}
onDoubleClickValue(selectedFile: string) {
@@ -205,9 +265,13 @@ export default class FilePropertyDialog extends ResizeResponsiveComponent<FilePr
}
}
private wantsScrollRef: boolean = true;
mapKey: number = 0;
render() {
this.mapKey = 0;
let columnWidth = this.state.columnWidth;
return this.props.open &&
(
<DialogEx onClose={() => this.props.onCancel()} open={this.props.open} tag="FilePropertyDialog" fullWidth maxWidth="xl" style={{ height: "90%" }}
@@ -223,22 +287,40 @@ export default class FilePropertyDialog extends ResizeResponsiveComponent<FilePr
</div>
</DialogTitle>
<div style={{ flex: "0 0 auto", height: "1px", background: "rgba(0,0,0,0.2" }}>&nbsp;</div>
<div style={{ flex: "1 1 auto", height: "300", display: "flex", flexFlow: "row nowrap", overflowX: "auto", overflowY: "visible" }}>
<div style={{ flex: "1 1 100%", display: "flex", flexFlow: "column wrap", justifyContent: "start", alignItems: "flex-start", paddingLeft: 16, paddingTop: 16 }}>
<div style={{ flex: "1 1 auto", height: "300", display: "flex", flexFlow: "row wrap", overflowX: "hidden", overflowY: "auto" }}>
<div
ref={(element)=> this.onMeasureRef(element)}
style={{ flex: "1 1 100%", display: "flex", flexFlow: "row wrap",
justifyContent: "flex-start", alignContent: "flex-start", paddingLeft: 16, paddingTop: 16,paddingBottom: 16 }}>
{
(this.state.columns !== 0) && // don't render until we have number of columns derived from layout.
this.state.files.map(
(value: string, index: number) => {
let displayValue = value;
if (displayValue === "")
{
displayValue = "<none>";
} else {
displayValue = this.fileNameOnly(value);
}
let selected = value === this.state.selectedFile;
let selectBg = selected ? "rgba(0,0,0,0.15)" : "rgba(0,0,0,0.0)";
let scrollRef: ((element: HTMLDivElement | null) => void) | undefined = undefined;
if (selected)
{
scrollRef = (element)=> { this.onScrollRef(element)};
}
return (
<ButtonBase key={this.mapKey++}
style={{ width: "320px", flex: "0 0 48px", position: "relative" }}
style={{ width: columnWidth, flex: "0 0 auto", height: 48, position: "relative" }}
onClick={() => this.onSelectValue(value)} onDoubleClick={()=> {this.onDoubleClickValue(value);}}
>
<div style={{ position: "absolute", background: selectBg, width: "100%", height: "100%", borderRadius: 4 }} />
<div style={{ display: "flex", flexFlow: "row nowrap", justifyContent: "start", alignItems: "center", width: "100%", height: "100%" }}>
<div ref={scrollRef} style={{ position: "absolute", background: selectBg, width: "100%", height: "100%", borderRadius: 4 }} />
<div style={{ display: "flex", flexFlow: "row nowrap", textOverflow: "ellipsis", justifyContent: "start", alignItems: "center", width: "100%", height: "100%" }}>
<AudioFileIcon style={{ flex: "0 0 auto", opacity: 0.7, marginRight: 8, marginLeft: 8 }} />
<Typography noWrap style={{ flex: "1 1 auto", textAlign: "left" }}>{this.fileNameOnly(value)}</Typography>
<Typography noWrap style={{ flex: "1 1 auto", textAlign: "left" }}>{displayValue}</Typography>
</div>
</ButtonBase>
);
@@ -265,7 +347,11 @@ export default class FilePropertyDialog extends ResizeResponsiveComponent<FilePr
<Button onClick={() => { this.props.onCancel(); }} aria-label="cancel">
Cancel
</Button>
<Button style={{ flex: "0 0 auto" }} onClick={() => { this.props.onOk(this.props.fileProperty, this.state.selectedFile); }} color="secondary" disabled={!this.state.hasSelection} aria-label="select">
<Button style={{ flex: "0 0 auto" }}
onClick={() => { this.props.onOk(this.props.fileProperty, this.state.selectedFile); }}
color="secondary"
disabled={(!this.state.hasSelection) && this.state.selectedFile !== ""} aria-label="select"
>
Select
</Button>
</div>
+73 -18
View File
@@ -107,23 +107,78 @@ export class PortGroup {
program_list_id: number = -1;
};
export class PiPedalFileType {
deserialize(input: any): PiPedalFileType {
export class UiFileType {
deserialize(input: any): UiFileType {
this.name = input.name;
this.fileExtension = input.fileExtension;
this.mimeType = input.mimeType;
return this;
}
static deserialize_array(input: any): PiPedalFileType[]
static deserialize_array(input: any): UiFileType[]
{
let result: PiPedalFileType[] = [];
let result: UiFileType[] = [];
for (let i = 0; i < input.length; ++i)
{
result[i] = new PiPedalFileType().deserialize(input[i]);
result[i] = new UiFileType().deserialize(input[i]);
}
return result;
}
private static IsAndroid() : boolean
{
return /Android/i.test(navigator.userAgent);
}
static MergeMimeTypes(fileTypes: UiFileType[]): string
{
if (fileTypes.length === 0) {
return "";
}
let result = fileTypes[0].mimeType;
for (let i = 1; i < fileTypes.length; ++i)
{
let fileType = fileTypes[i];
if (fileType.mimeType !== result)
{
if (result.startsWith("audio/") && fileType.mimeType.startsWith("audio/"))
{
result = "audio/*";
} else if (result.startsWith("video/") && fileType.mimeType.startsWith("video/"))
{
result = "video/*";
} else if (result.startsWith("text/") && fileType.mimeType.startsWith("text/"))
{
result = "text/*";
} else {
result = "application/octet-stream";
}
}
}
if (this.IsAndroid())
{
if (result.startsWith("audio/")) result = "audio/*";
if (result.startsWith("video/")) result = "video/*";
if (result.startsWith("text/")) result = "text/*";
} else {
// chrome desktop thinks "application/octet-stream" is .exe, .com, or .bat.
// Feed it file extensions isntead.
if (result = "application/octet-stream")
{
result = "";
for (let i = 0; i < fileTypes.length; ++i)
{
if (i !== 0)
{
result += ',';
}
result += fileTypes[i].fileExtension;
}
}
}
return result;
}
name: string = "";
fileExtension: string = "";
mimeType: string = "";
}
export class UiPropertyNotification {
@@ -150,23 +205,23 @@ export class UiPropertyNotification {
protocol: string = "";
};
export class PiPedalFileProperty {
deserialize(input: any): PiPedalFileProperty
export class UiFileProperty {
deserialize(input: any): UiFileProperty
{
this.label = input.label;
this.fileTypes = PiPedalFileType.deserialize_array(input.fileTypes);
this.fileTypes = UiFileType.deserialize_array(input.fileTypes);
this.patchProperty = input.patchProperty;
this.directory = input.directory;
this.index = input.index;
this.portGroup = input.portGroup;
return this;
}
static deserialize_array(input: any): PiPedalFileProperty[]
static deserialize_array(input: any): UiFileProperty[]
{
let result: PiPedalFileProperty[] = [];
let result: UiFileProperty[] = [];
for (let i = 0; i < input.length; ++i)
{
result[i] = new PiPedalFileProperty().deserialize(input[i]);
result[i] = new UiFileProperty().deserialize(input[i]);
}
return result;
}
@@ -191,7 +246,7 @@ export class PiPedalFileProperty {
if (this.fileTypes.length === 0) {
return true;
}
let extension = PiPedalFileProperty.getFileExtension(filename);
let extension = UiFileProperty.getFileExtension(filename);
for (let fileType of this.fileTypes)
{
if (fileType.fileExtension === extension )
@@ -203,7 +258,7 @@ export class PiPedalFileProperty {
}
label: string = "";
fileTypes: PiPedalFileType[] = [];
fileTypes: UiFileType[] = [];
patchProperty: string = "";
directory: string = "";
index: number = -1;
@@ -226,7 +281,7 @@ export class Lv2Plugin implements Deserializable<Lv2Plugin> {
this.port_groups = PortGroup.deserialize_array(input.port_groups);
if (input.fileProperties)
{
this.fileProperties = PiPedalFileProperty.deserialize_array(input.fileProperties)
this.fileProperties = UiFileProperty.deserialize_array(input.fileProperties)
} else {
this.fileProperties = [];
}
@@ -251,7 +306,7 @@ export class Lv2Plugin implements Deserializable<Lv2Plugin> {
comment: string = "";
ports: Port[] = Port.EmptyPorts;
port_groups: PortGroup[] = [];
fileProperties: PiPedalFileProperty[] = [];
fileProperties: UiFileProperty[] = [];
uiPortNotifications: UiPropertyNotification[] = [];
}
@@ -508,7 +563,7 @@ export class UiControl implements Deserializable<UiControl> {
}
formatDisplayValue(value: number): string {
if (this.integer_property || this.enumeration_property) {
if (this.integer_property) {
value = Math.round(value);
}
@@ -614,7 +669,7 @@ export class UiPlugin implements Deserializable<UiPlugin> {
this.port_groups = PortGroup.deserialize_array(input.port_groups);
if (input.fileProperties)
{
this.fileProperties = PiPedalFileProperty.deserialize_array(input.fileProperties)
this.fileProperties = UiFileProperty.deserialize_array(input.fileProperties)
} else {
this.fileProperties = [];
}
@@ -682,7 +737,7 @@ export class UiPlugin implements Deserializable<UiPlugin> {
description: string = "";
controls: UiControl[] = [];
port_groups: PortGroup[] = [];
fileProperties: PiPedalFileProperty[] = [];
fileProperties: UiFileProperty[] = [];
is_vst3 : boolean = false;
}
+2
View File
@@ -67,6 +67,7 @@ export class PedalboardItem implements Deserializable<PedalboardItem> {
this.controlValues = ControlValue.deserializeArray(input.controlValues);
this.vstState = input.vstState ?? "";
this.stateUpdateCount = input.stateUpdateCount;
this.lv2State = input.lv2State;
return this;
}
@@ -195,6 +196,7 @@ export class PedalboardItem implements Deserializable<PedalboardItem> {
controlValues: ControlValue[] = ControlValue.EmptyArray;
midiBindings: MidiBinding[] = [];
vstState: string = "";
stateUpdateCount: number = 0;
lv2State: [boolean,any] = [false,{}]
};
+11 -3
View File
@@ -17,7 +17,7 @@
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
import { UiPlugin, UiControl, PluginType, PiPedalFileProperty } from './Lv2Plugin';
import { UiPlugin, UiControl, PluginType, UiFileProperty } from './Lv2Plugin';
import { PiPedalArgumentError, PiPedalStateError } from './PiPedalError';
@@ -588,6 +588,10 @@ export class PiPedalModel //implements PiPedalModel
} else if (message === "onSystemMidiBindingsChanged") {
let bindings = MidiBinding.deserialize_array(body);
this.systemMidiBindings.set(bindings);
} else if (message === "onErrorMessage")
{
this.showAlert(body as string);
} else {
throw new PiPedalStateError("Unrecognized message received from server: " + message);
}
@@ -1054,6 +1058,8 @@ export class PiPedalModel //implements PiPedalModel
handleOnLoadPluginPreset(instanceId: number, controlValues: ControlValue[]) {
// note that plugins with state are dealt with server-side.
// if we made it here, we can just load the controls.
let pedalboard = this.pedalboard.get();
if (pedalboard === undefined) throw new PiPedalStateError("Pedalboard not ready.");
let newPedalboard = pedalboard.clone();
@@ -1342,13 +1348,15 @@ export class PiPedalModel //implements PiPedalModel
while (true) {
let v = it.next();
if (v.done) break;
let item = v.value;
let item = v.value;
if (item.instanceId === itemId) {
item.deserialize(new PedalboardItem()); // skeezy way to re-initialize.
item.instanceId = ++newPedalboard.nextInstanceId;
item.uri = selectedUri;
item.pluginName = plugin.name;
item.controlValues = this.getDefaultValues(item.uri);
item.isEnabled = true;
// lv2State: not valid. vstState : not valid.
this.pedalboard.set(newPedalboard);
this.updateServerPedalboard()
return item.instanceId;
@@ -1590,7 +1598,7 @@ export class PiPedalModel //implements PiPedalModel
});
}
requestFileList(piPedalFileProperty: PiPedalFileProperty): Promise<string[]> {
requestFileList(piPedalFileProperty: UiFileProperty): Promise<string[]> {
return nullCast(this.webSocket)
.request<string[]>('requestFileList', piPedalFileProperty);
}
+5 -5
View File
@@ -23,7 +23,7 @@ import { WithStyles } from '@mui/styles';
import createStyles from '@mui/styles/createStyles';
import withStyles from '@mui/styles/withStyles';
import { PiPedalModel, PiPedalModelFactory } from './PiPedalModel';
import { UiPlugin, UiControl, PiPedalFileProperty, ScalePoint } from './Lv2Plugin';
import { UiPlugin, UiControl, UiFileProperty, ScalePoint } from './Lv2Plugin';
import {
Pedalboard, PedalboardItem, ControlValue
} from './Pedalboard';
@@ -239,7 +239,7 @@ type PluginControlViewState = {
imeCaption: string;
imeInitialHeight: number;
showFileDialog: boolean,
dialogFileProperty: PiPedalFileProperty,
dialogFileProperty: UiFileProperty,
dialogFileValue: string
};
@@ -260,7 +260,7 @@ const PluginControlView =
imeCaption: "",
imeInitialHeight: 0,
showFileDialog: false,
dialogFileProperty: new PiPedalFileProperty(),
dialogFileProperty: new UiFileProperty(),
dialogFileValue: ""
}
@@ -323,10 +323,10 @@ const PluginControlView =
});
}
makeFilePropertyUI(fileProperty: PiPedalFileProperty): ReactNode {
makeFilePropertyUI(fileProperty: UiFileProperty): ReactNode {
return ((
<FilePropertyControl instanceId={this.props.instanceId}
<FilePropertyControl pedalboardItem={this.props.item}
fileProperty={fileProperty}
onFileClick={(fileProperty, selectedFile) => {
this.setState({ showFileDialog: true, dialogFileProperty: fileProperty, dialogFileValue: selectedFile });
+1 -1
View File
@@ -259,7 +259,7 @@ const PluginPresetsDialog = withStyles(styles, { withTheme: true })(
<img src="img/ic_pluginpreset2.svg" className={classes.itemIcon} alt="" />
</div>
<div className={classes.itemLabel}>
<Typography> noWrap
<Typography noWrap>
{presetEntry.label}
</Typography>
</div>
+1 -6
View File
@@ -80,13 +80,10 @@ export const SelectHoverBackground =
}
handleMouseOver(e: SyntheticEvent): void {
console.log("onMouseOver")
if (this.props.showHover ?? true) {
if (this.hoverElementRef.current)
{
this.hoverElementRef.current.style.display = "block";
} else {
console.log("No hoverElementRef")
}
}
@@ -96,9 +93,7 @@ export const SelectHoverBackground =
if (this.hoverElementRef.current)
{
this.hoverElementRef.current.style.display = "none";
} else {
console.log("No hoverElementRef")
}
}
}
}
+20 -17
View File
@@ -27,7 +27,7 @@ import DialogActions from '@mui/material/DialogActions';
import DialogContent from '@mui/material/DialogContent';
import ResizeResponsiveComponent from './ResizeResponsiveComponent';
import Typography from '@mui/material/Typography';
import { PiPedalFileProperty } from './Lv2Plugin';
import { UiFileProperty,UiFileType } from './Lv2Plugin';
import SvgIcon from '@mui/material/SvgIcon';
import ErrorIcon from '@mui/icons-material/Error';
import ArrowBackIcon from '@mui/icons-material/ArrowBack';
@@ -45,7 +45,7 @@ export interface UploadFileDialogProps {
onClose: () => void,
onUploaded: (fileName: string) => void,
uploadPage: string,
fileProperty: PiPedalFileProperty
fileProperty: UiFileProperty
};
@@ -204,6 +204,10 @@ export default class UploadFileDialog extends ResizeResponsiveComponent<UploadFi
this.updateUploadDisplayList();
try {
upload.abortController = new AbortController();
if (!this.wantsFile(this.uploadList[i].file))
{
throw new Error("Invalid file type.");
}
let filename = await this.model.uploadFile(this.props.uploadPage, this.uploadList[i].file, "application/octet-stream", upload.abortController);
this.props.onUploaded(filename);
upload.status = FileUploadStatus.Uploaded;
@@ -262,7 +266,12 @@ export default class UploadFileDialog extends ResizeResponsiveComponent<UploadFi
e.currentTarget.style.background = "#D8D8D8";
}
handleButtonSelect(e: React.ChangeEvent<HTMLInputElement>) {
private static IsAndroid() : boolean
{
return /Android/i.test(navigator.userAgent);
}
handleButtonSelect(e: any) {
if (e.currentTarget.files) {
this.uploadFiles(e.currentTarget.files);
}
@@ -290,20 +299,13 @@ export default class UploadFileDialog extends ResizeResponsiveComponent<UploadFi
}
}
makeBrowserAcceptList() {
let fileTypes = this.props.fileProperty.fileTypes;
let result = "";
for (let i = 0; i < fileTypes.length; ++i) {
if (result.length !== 0) {
result += ',';
}
result += fileTypes[i].fileExtension;
}
let result = UiFileType.MergeMimeTypes(this.props.fileProperty.fileTypes);
return result;
}
render() {
let isAndroid = UploadFileDialog.IsAndroid();
return (
<DialogEx tag="UploadFileDialog" open={this.props.open} fullWidth onClose={() => this.handleClose()}
fullScreen={this.state.fullScreen}
@@ -321,7 +323,7 @@ export default class UploadFileDialog extends ResizeResponsiveComponent<UploadFi
<DialogContent style={{ paddingBottom: 0 }}>
<div style={{
width: "100%", height: 140, marginBottom: 0,
border: "2px dashed #CCC",
border: (isAndroid? "2px solid #CCC" :"2px dashed #CCC"),
borderRadius: "10px",
fontFamily: "Roboto",
padding: 0
@@ -334,7 +336,8 @@ export default class UploadFileDialog extends ResizeResponsiveComponent<UploadFi
}}
>
{!this.hasFileList() && (
<Typography noWrap color="textSecondary" align="center" display="block" variant="caption" style={{ width: "100%", marginTop: 20, verticalAlign: "middle" }} >Drop files here</Typography>
<Typography noWrap color="textSecondary" align="center" display="block" variant="caption" style={{ width: "100%", marginTop: 20, verticalAlign: "middle" }} >
{ isAndroid? "Select files": "Drop files here" }</Typography>
)}
{this.hasFileList() && (
<div style={{ width: "100%", height: "100%", overflow: "auto" }}>
@@ -381,15 +384,15 @@ export default class UploadFileDialog extends ResizeResponsiveComponent<UploadFi
<DialogActions >
<Button
component="label" color="primary" style={{ marginLeft: 16, width: 120, flex: "0 0 auto" }}
component="label" color="primary" style={{ whiteSpace: "nowrap", textOverflow: "ellipsis", marginLeft: 16, width: 120, flex: "0 0 auto" }}
>
Select Files
Select&nbsp;Files
<input
type="file"
hidden
accept={this.makeBrowserAcceptList()}
multiple
onChange={(e) => this.handleButtonSelect(e)}
onInput={(e) => this.handleButtonSelect(e)}
/>
</Button>
<div style={{ flex: "1 1 20px" }} />
-81
View File
@@ -1,81 +0,0 @@
src/SearchControl.tsx
src/SplitControlView.tsx
src/WifiConfigSettings.tsx
src/FullScreenIME.tsx
src/JackHostStatus.tsx
src/SearchFilter.tsx
src/MainPage.tsx
src/PiPedalModel.tsx
src/PluginPresetSelector.tsx
src/Pedal.tsx
src/ToobMLView.tsx
src/SettingsDialog.tsx
src/PiPedalSocket.tsx
src/ToobFrequencyResponseView.tsx
src/ControlViewFactory.tsx
src/Utility.tsx
src/ToobToneStackView.tsx
src/SelectHoverBackground.tsx
src/MidiBindingsDialog.tsx
src/TemporaryDrawer.tsx
src/GxTunerView.tsx
src/ToobInputStageView.tsx
src/DraggableGrid.tsx
src/JackStatusView.tsx
src/PluginControl.tsx
src/XxxSnippet.tsx
src/PluginPreset.tsx
src/Jack.tsx
src/AlsaDeviceInfo.tsx
src/MidiBinding.tsx
src/PiPedalError.tsx
src/IControlViewFactory.tsx
src/Lv2Plugin.tsx
src/Pedalboard.tsx
src/PedalboardView.tsx
src/PresetDialog.tsx
src/AppThemed.tsx
src/ZoomedDial.tsx
src/RenameDialog.tsx
src/SplitUiControls.tsx
src/GovernorSettings.tsx
src/AboutDialog.tsx
src/ToobSpectrumResponseView.tsx
src/PluginControlView.tsx
src/NoChangePassword.tsx
src/ToobSpectrumAnalyzerView.tsx
src/MidiBindingView.tsx
src/GxTunerControl.tsx
src/Banks.tsx
src/PluginPresetsDialog.tsx
src/BankDialog.tsx
src/UploadPresetDialog.tsx
src/ToobPowerStage2View.tsx
src/index.tsx
src/Units.tsx
src/VuMeter.tsx
src/App.test.tsx
src/DialogEx.tsx
src/StringBuilder.tsx
src/SelectChannelsDialog.tsx
src/Draggable.tsx
src/ZoomedUiControl.tsx
src/Rect.tsx
src/PluginClass.tsx
src/PluginIcon.tsx
src/App.tsx
src/ResizeResponsiveComponent.tsx
src/SvgPathBuilder.tsx
src/NumericInput.tsx
src/JackServerSettings.tsx
src/ListSelectDialog.tsx
src/JackServerSettingsDialog.tsx
src/ObservableProperty.tsx
src/SelectMidiChannelsDialog.tsx
src/WifiChannel.tsx
src/LoadPluginDialog.tsx
src/WifiConfigDialog.tsx
src/PluginInfoDialog.tsx
src/ToobWaveShapeView.tsx
src/ToobCabSimView.tsx
src/PresetSelector.tsx
Executable
+8
View File
@@ -0,0 +1,8 @@
#!/usr/bin/bash
# Set presets and plugin presets to default.
rm -rf /var/pipedal/plugin_presets
rm -rf /var/pipedal/presets
mkdir /var/pipedal/plugin_presets
mkdir /var/pipedal/presets
cp -r default_presets/plugin_presets /var/pipedal/plugin_presets/
cp -r default_presets/presets /var/pipedal/presets/
+19 -1
View File
@@ -349,7 +349,6 @@ private:
audioDriver->Close();
StopReaderThread();
pHost->GetHostWorkerThread()->Close();
// release any pdealboards owned by the process thread.
@@ -1164,6 +1163,21 @@ public:
RealtimeNextMidiProgramRequest request;
hostReader.read(&request);
pNotifyCallbacks->OnNotifyNextMidiProgram(request);
} else if (command == RingBufferCommand::Lv2ErrorMessage)
{
size_t size;
int64_t instanceId;
hostReader.read(&instanceId);
hostReader.read(&size);
if (this->atomBuffer.size() < size+1)
{
this->atomBuffer.resize(size+1);
}
hostReader.read(size, &(atomBuffer[0]));
char *p = (char*)&(atomBuffer[0]);
p[size] = 0;
std::string message(p);
pNotifyCallbacks->OnNotifyLv2RealtimeError(instanceId,message);
}
else
{
@@ -1243,6 +1257,10 @@ public:
this->inputRingBuffer.reset();
this->outputRingBuffer.reset();
this->hostReader.Reset();
this->hostWriter.Reset();
this->realtimeReader.Reset();
this->realtimeWriter.Reset();
this->channelSelection = channelSelection;
+2
View File
@@ -154,6 +154,7 @@ public:
virtual void OnNotifyMidiProgramChange(RealtimeMidiProgramRequest&midiProgramRequest) = 0;
virtual void OnNotifyNextMidiProgram(const RealtimeNextMidiProgramRequest&request) = 0;
virtual void OnNotifyLv2RealtimeError(int64_t instanceId,const std::string &error) = 0;
};
@@ -195,6 +196,7 @@ public:
virtual void SetListenForAtomOutput(bool listen) = 0;
virtual void UpdatePluginStates(Pedalboard& pedalboard) = 0;
virtual void UpdatePluginState(PedalboardItem& pedalboardItem) = 0;
virtual void Open(const JackServerSettings&jackServerSettings,const JackChannelSelection & channelSelection) = 0;
+4
View File
@@ -141,6 +141,8 @@ else()
endif()
set (PIPEDAL_SOURCES
MimeTypes.cpp MimeTypes.hpp
inverting_mutex.hpp
DbDezipper.hpp DbDezipper.cpp
WebServerLog.hpp
@@ -277,6 +279,8 @@ target_link_libraries(pipedald PRIVATE
#################################
add_executable(pipedaltest testMain.cpp
InvertingMutexTest.cpp
jsonTest.cpp
json_variant.cpp
json_variant.hpp
+3
View File
@@ -59,5 +59,8 @@ namespace pipedal {
virtual bool IsVst3() const = 0;
virtual bool GetLv2State(Lv2PluginState*state) = 0;
virtual bool HasErrorMessage() const = 0;
virtual const char*TakeErrorMessage() = 0;
};
} //namespace
+1
View File
@@ -49,5 +49,6 @@ namespace pipedal {
virtual std::shared_ptr<HostWorkerThread> GetHostWorkerThread() = 0;
virtual IEffect *CreateEffect(PedalboardItem &pedalboard) = 0;
};
}
+71
View File
@@ -0,0 +1,71 @@
// Copyright (c) 2022 Robin Davies
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "pch.h"
#include "catch.hpp"
#include <sstream>
#include <cstdint>
#include <string>
#include "json.hpp"
#include "json_variant.hpp"
#include <concepts>
#include <type_traits>
#include "inverting_mutex.hpp"
#include <iostream>
#include <thread>
#include <functional>
#include "util.hpp"
using namespace pipedal;
using namespace std;
using namespace std::chrono;
TEST_CASE("inverting_mutext test", "[inverting_mutex_test]")
{
inverting_mutex mutex;
{
std::thread thread(
[&mutex]() mutable
{
nice(5);
{
std::lock_guard<inverting_mutex> lock(mutex);
SetThreadName("imTest");
cout << "Thread holds lock" << endl;
std::this_thread::sleep_for(3s);
std::this_thread::sleep_for(1s);
cout << "Thread releases lock" << endl;
}
});
std::this_thread::sleep_for(std::chrono::seconds(1));
{
std::lock_guard<inverting_mutex> lock(mutex); // cause the thread to avoid priority-inversion.
cout << "Main resumed." << endl;
}
{
std::lock_guard<inverting_mutex> lock(mutex);
}
thread.join();
}
}
+33 -22
View File
@@ -50,29 +50,38 @@ int LogFeature::vprintf(LV2_URID type,const char*fmt, va_list va)
{
std::lock_guard<std::mutex> guard(logMutex);
const char* prefix = "";
char buffer[1024];
int result = vsnprintf(buffer, sizeof(buffer), fmt, va);
int result = 0;
if (this->logMessageListener)
{
const char* prefix = "";
char buffer[1024];
strcpy(buffer,messagePrefix.c_str());
char *p = buffer+messagePrefix.length();
if (type == uris.ridError)
{
Lv2Log::error(buffer);
result = vsnprintf(p, sizeof(buffer)-messagePrefix.length(), fmt, va);
buffer[sizeof(buffer)-1] = '\0';
if (type == uris.ridError)
{
logMessageListener->OnLogError(buffer);
}
else if (type == uris.ridWarning)
{
logMessageListener->OnLogWarning(buffer);
}
else if (type == uris.ridNote)
{
logMessageListener->OnLogInfo(buffer);
}
else if (type == uris.ridTrace)
{
logMessageListener->OnLogDebug(buffer);
}
else {
logMessageListener->OnLogInfo(buffer);
}
}
else if (type == uris.ridWarning)
{
Lv2Log::warning(buffer);
}
else if (type == uris.ridNote)
{
Lv2Log::info(buffer);
}
else if (type == uris.ridTrace)
{
Lv2Log::debug(buffer);
}
else {
Lv2Log::info(buffer);
}
return result;
}
@@ -85,9 +94,11 @@ LogFeature::LogFeature()
log.printf = printfFn;
log.vprintf = vprintfFn;
}
void LogFeature::Prepare(MapFeature*map)
void LogFeature::Prepare(MapFeature*map, const std::string &messagePrefix, LogMessageListener*listener)
{
uris.Map(map);
this->messagePrefix = messagePrefix;
this->logMessageListener = listener;
}
+13 -2
View File
@@ -35,8 +35,17 @@
namespace pipedal {
class LogFeature {
public:
class LogMessageListener {
public:
virtual void OnLogError(const char*message) = 0;
virtual void OnLogWarning(const char*message) = 0;
virtual void OnLogInfo(const char*message) = 0;
virtual void OnLogDebug(const char*message) = 0;
};
private:
LogMessageListener *logMessageListener = nullptr;
std::string messagePrefix;
LV2_URID nextAtom = 0;
LV2_Feature feature;
LV2_Log_Log log;
@@ -59,7 +68,8 @@ namespace pipedal {
public:
LogFeature();
void Prepare(MapFeature* map);
void Prepare(MapFeature* map, const std::string &messagePrefix, LogMessageListener*listener);
void LogError(const char*fmt,...);
void LogWarning(const char*fmt,...);
@@ -84,5 +94,6 @@ namespace pipedal {
int vprintf(LV2_URID type, const char* fmt, va_list va);
};
}
+28 -1
View File
@@ -54,6 +54,7 @@ Lv2Effect::Lv2Effect(
{
auto pWorld = pHost_->getWorld();
logFeature.Prepare(&(pHost_->GetMapFeature()),info_->name() + ": ",this);
this->bypassStartingSamples = (uint32_t)(pHost->GetSampleRate() * BYPASS_TIME_S);
this->bypass = pedalboardItem.isEnabled();
@@ -71,6 +72,8 @@ Lv2Effect::Lv2Effect(
LV2_Feature *const *features = pHost_->GetLv2Features();
this->features.push_back(logFeature.GetFeature());
for (auto p = features; *p != nullptr; ++p)
{
this->features.push_back(*p);
@@ -92,7 +95,7 @@ Lv2Effect::Lv2Effect(
}
this->features.push_back(nullptr);
LV2_Feature **myFeatures = &this->features[0];
const LV2_Feature **myFeatures = &this->features[0];
LilvInstance *pInstance = nullptr;
try {
@@ -676,4 +679,28 @@ bool Lv2Effect::GetLv2State(Lv2PluginState*state)
}
void Lv2Effect::OnLogError(const char*message)
{
// only errors get transmitted to the client.
strncpy(this->errorMessage,message,sizeof(errorMessage));
errorMessage[sizeof(errorMessage)-1] = '\0';
this->hasErrorMessage = true;
}
void Lv2Effect::OnLogWarning(const char*message)
{
Lv2Log::warning(message);
}
void Lv2Effect::OnLogInfo(const char*message)
{
Lv2Log::info(message);
}
void Lv2Effect::OnLogDebug(const char*message)
{
Lv2Log::debug(message);
}
+16 -5
View File
@@ -34,6 +34,7 @@
#include "lv2/atom.lv2/forge.h"
#include "AtomBuffer.hpp"
#include "StateInterface.hpp"
#include "LogFeature.hpp"
namespace pipedal
@@ -41,12 +42,19 @@ namespace pipedal
class RealtimeRingBufferWriter;
class Lv2Effect : public IEffect
class Lv2Effect : public IEffect, private LogFeature::LogMessageListener
{
private:
virtual void OnLogError(const char*message);
virtual void OnLogWarning(const char*message);
virtual void OnLogInfo(const char*message);
virtual void OnLogDebug(const char*message);
private:
std::unique_ptr<StateInterface> stateInterface;
void RestoreState(const PedalboardItem&pedalboardItem);
LogFeature logFeature;
std::map<std::string,AtomBuffer> patchPropertyPrototypes;
IHost *pHost = nullptr;
@@ -74,7 +82,7 @@ namespace pipedal
std::vector<char *> inputAtomBuffers;
std::vector<char *> outputAtomBuffers;
std::vector<LV2_Feature *> features;
std::vector<const LV2_Feature *> features;
LV2_Feature *work_schedule_feature = nullptr;
virtual std::string GetUri() const { return info->uri(); }
@@ -169,6 +177,7 @@ namespace pipedal
void BypassTo(float value);
public:
virtual bool GetLv2State(Lv2PluginState*state);
virtual void RequestPatchProperty(LV2_URID uridUri);
virtual void SetPatchProperty(LV2_URID uridUri,size_t size, LV2_Atom*value);
@@ -187,7 +196,8 @@ namespace pipedal
}
bool hasErrorMessage = false;
char errorMessage[1024];
public:
Lv2Effect(
IHost *pHost,
@@ -195,7 +205,8 @@ namespace pipedal
const PedalboardItem &pedalboardItem);
~Lv2Effect();
bool HasErrorMessage() const { return this->hasErrorMessage; }
const char*TakeErrorMessage() { this->hasErrorMessage = false; return this->errorMessage; }
virtual void ResetAtomBuffers();
virtual uint64_t GetInstanceId() const { return instanceId; }
+23 -5
View File
@@ -46,6 +46,8 @@ std::vector<float *> Lv2Pedalboard::AllocateAudioBuffers(int nChannels)
return result;
}
int Lv2Pedalboard::GetControlIndex(uint64_t instanceId, const std::string &symbol)
{
for (int i = 0; i < realtimeEffects.size(); ++i)
@@ -60,7 +62,9 @@ int Lv2Pedalboard::GetControlIndex(uint64_t instanceId, const std::string &symbo
}
std::vector<float *> Lv2Pedalboard::PrepareItems(
std::vector<PedalboardItem> &items,
std::vector<float *> inputBuffers)
std::vector<float *> inputBuffers,
Lv2PedalboardErrorList&errorList
)
{
for (int i = 0; i < items.size(); ++i)
{
@@ -84,8 +88,8 @@ std::vector<float *> Lv2Pedalboard::PrepareItems(
this->processActions.push_back(preMixAction);
std::vector<float *> topResult = PrepareItems(item.topChain(), topInputs);
std::vector<float *> bottomResult = PrepareItems(item.bottomChain(), bottomInputs);
std::vector<float *> topResult = PrepareItems(item.topChain(), topInputs,errorList);
std::vector<float *> bottomResult = PrepareItems(item.bottomChain(), bottomInputs,errorList);
this->processActions.push_back(
[pSplit](uint32_t frames)
@@ -113,6 +117,12 @@ std::vector<float *> Lv2Pedalboard::PrepareItems(
{
Lv2Log::warning(SS(e.what()));
}
if (pLv2Effect->HasErrorMessage())
{
std::string error = pLv2Effect->TakeErrorMessage();
Lv2Log::error(error);
errorList.push_back({item.instanceId(), error});
}
if (pLv2Effect)
{
@@ -206,7 +216,7 @@ std::vector<float *> Lv2Pedalboard::PrepareItems(
return inputBuffers;
}
void Lv2Pedalboard::Prepare(IHost *pHost, Pedalboard &pedalboard)
void Lv2Pedalboard::Prepare(IHost *pHost, Pedalboard &pedalboard, Lv2PedalboardErrorList &errorList)
{
this->pHost = pHost;
@@ -224,7 +234,7 @@ void Lv2Pedalboard::Prepare(IHost *pHost, Pedalboard &pedalboard)
this->pedalboardInputBuffers.push_back(bufferPool.AllocateBuffer<float>(pHost->GetMaxAudioBufferSize()));
}
auto outputs = PrepareItems(pedalboard.items(), this->pedalboardInputBuffers);
auto outputs = PrepareItems(pedalboard.items(), this->pedalboardInputBuffers,errorList);
int nOutputs = pHost->GetNumberOfOutputAudioChannels();
if (nOutputs == 1)
{
@@ -396,6 +406,14 @@ bool Lv2Pedalboard::Run(float **inputBuffers, float **outputBuffers, uint32_t sa
{
processActions[i](samples);
}
for (size_t i = 0; i < this->effects.size(); ++i)
{
IEffect* effect = effects[i].get();
if (effect->HasErrorMessage())
{
ringBufferWriter->WriteLv2ErrorMessage(effect->GetInstanceId(),effect->TakeErrorMessage());
}
}
for (size_t i = 0; i < samples; ++i)
{
float volume = outputVolume.Tick();
+13 -2
View File
@@ -35,6 +35,16 @@ class RealtimeVuBuffers;
class RealtimePatchPropertyRequest;
class RealtimeRingBufferWriter;
struct Lv2PedalboardError {
int64_t intanceId;
std::string message;
};
class Lv2PedalboardErrorList: public std::vector<Lv2PedalboardError> // (forward declaration issues with a using statement)
{
};
class Lv2Pedalboard {
IHost *pHost = nullptr;
@@ -86,7 +96,8 @@ class Lv2Pedalboard {
std::vector<float*> PrepareItems(
std::vector<PedalboardItem> & items,
std::vector<float*> inputBuffers
std::vector<float*> inputBuffers,
Lv2PedalboardErrorList &errorList
);
void PrepareMidiMap(const Pedalboard&pedalboard);
@@ -99,7 +110,7 @@ public:
Lv2Pedalboard() { }
~Lv2Pedalboard() { }
void Prepare(IHost *pHost,Pedalboard&pedalboard);
void Prepare(IHost *pHost,Pedalboard&pedalboard, Lv2PedalboardErrorList &errorList);
std::vector<IEffect* > GetEffects() { return realtimeEffects; }
+23
View File
@@ -36,10 +36,15 @@ MapPathFeature::MapPathFeature(const std::filesystem::path &storagePath)
lv2_state_make_path.handle = (LV2_State_Make_Path_Handle*)this;
lv2_state_make_path.path = FnAbsolutePath;
lv2_state_free_path.handle = (LV2_State_Free_Path_Handle*)this;
lv2_state_free_path.free_path = FnFreePath;
mapPathFeature.URI = LV2_STATE__mapPath;
mapPathFeature.data = (void*)&lv2_state_map_path;
makePathFeature.URI = LV2_STATE__makePath;
makePathFeature.data = (void*)&lv2_state_make_path;
freePathFeature.URI = LV2_STATE__freePath;
freePathFeature.data = (void*)&lv2_state_free_path;
}
void MapPathFeature::Prepare(MapFeature* map)
@@ -47,6 +52,16 @@ void MapPathFeature::Prepare(MapFeature* map)
}
void MapPathFeature::FreePath(char *path)
{
free(path);
}
void MapPathFeature::FnFreePath(LV2_State_Free_Path_Handle handle, char* path)
{
((MapPathFeature*)handle)->FreePath(path);
}
/*static*/ char *MapPathFeature::FnAbsolutePath(
LV2_State_Map_Path_Handle handle,
@@ -57,6 +72,10 @@ void MapPathFeature::Prepare(MapFeature* map)
char *MapPathFeature::AbsolutePath(const char *abstract_path)
{
if (strlen(abstract_path) == 0)
{
return strdup("");
}
std::filesystem::path t (abstract_path);
if (t.is_absolute()) {
return strdup(abstract_path);
@@ -75,6 +94,10 @@ char *MapPathFeature::FnAbstractPath(
char *MapPathFeature::AbstractPath(const char *absolute_path)
{
if (strlen(absolute_path) == 0)
{
return strdup("");
}
if (strncmp(storagePath.c_str(),absolute_path,storagePath.length()) == 0)
{
const char*result = absolute_path + storagePath.length();
+9
View File
@@ -32,16 +32,25 @@ namespace pipedal
void SetPluginStoragePath(const std::filesystem::path&path) { storagePath = path;}
const LV2_Feature*GetMapPathFeature() { return &mapPathFeature;}
const LV2_Feature*GetMakePathFeature() { return &makePathFeature;}
const LV2_Feature*GetFreePathFeature() { return &freePathFeature;}
private:
char *AbsolutePath(const char *abstract_path);
static char *FnAbsolutePath(LV2_State_Map_Path_Handle handle,
const char *abstract_path);
LV2_State_Map_Path lv2_state_map_path;
LV2_State_Make_Path lv2_state_make_path;
LV2_State_Free_Path lv2_state_free_path;
void FreePath(char *path);
static void FnFreePath(LV2_State_Free_Path_Handle handle, char* path);
LV2_Feature mapPathFeature;
LV2_Feature makePathFeature;
LV2_Feature freePathFeature;
char *AbstractPath(const char *abstract_path);
static char * FnAbstractPath(
+160
View File
@@ -0,0 +1,160 @@
// Copyright (c) 2023 Robin Davies
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "MimeTypes.hpp"
using namespace pipedal;
void MimeTypes::MaybeInitialize()
{
if (!initialized)
{
initialized = true;
AddMimeType("MP3", "audio/mpeg");
AddMimeType("MPGA", "audio/mpeg");
AddMimeType("M4A", "audio/mp4");
AddMimeType("WAV", "audio/x-wav");
AddMimeType("WAV", "audio/wav");
AddMimeType("AMR", "audio/amr");
AddMimeType("AWB", "audio/amr-wb");
AddMimeType("WMA", "audio/x-ms-wma");
AddMimeType("OGG", "audio/ogg");
AddMimeType("OGG", "application/ogg");
AddMimeType("OGA", "application/ogg");
AddMimeType("AAC", "audio/aac");
AddMimeType("AAC", "audio/aac-adts");
AddMimeType("MKA", "audio/x-matroska");
AddMimeType("MID", "audio/midi");
AddMimeType("MIDI", "audio/midi");
AddMimeType("XMF", "audio/midi");
AddMimeType("RTTTL", "audio/midi");
AddMimeType("SMF", "audio/sp-midi");
AddMimeType("IMY", "audio/imelody");
AddMimeType("RTX", "audio/midi");
AddMimeType("OTA", "audio/midi");
AddMimeType("MXMF", "audio/midi");
AddMimeType("MPEG", "video/mpeg");
AddMimeType("MPG", "video/mpeg");
AddMimeType("MP4", "video/mp4");
AddMimeType("M4V", "video/mp4");
AddMimeType("3GP", "video/3gpp");
AddMimeType("3GPP", "video/3gpp");
AddMimeType("3G2", "video/3gpp2");
AddMimeType("3GPP2", "video/3gpp2");
AddMimeType("MKV", "video/x-matroska");
AddMimeType("WEBM", "video/webm");
AddMimeType("TS", "video/mp2ts");
AddMimeType("AVI", "video/avi");
AddMimeType("WMV", "video/x-ms-wmv");
AddMimeType("ASF", "video/x-ms-asf");
AddMimeType("JPG", "image/jpeg");
AddMimeType("JPEG", "image/jpeg");
AddMimeType("GIF", "image/gif");
AddMimeType("PNG", "image/png");
AddMimeType("BMP", "image/x-ms-bmp");
AddMimeType("WBMP", "image/vnd.wap.wbmp");
AddMimeType("WEBP", "image/webp");
AddMimeType("M3U", "audio/x-mpegurl");
AddMimeType("M3U", "application/x-mpegurl");
AddMimeType("PLS", "audio/x-scpls");
AddMimeType("WPL", "application/vnd.ms-wpl");
AddMimeType("M3U8", "application/vnd.apple.mpegurl");
AddMimeType("M3U8", "audio/mpegurl");
AddMimeType("M3U8", "audio/x-mpegurl");
AddMimeType("FL", "application/x-android-drm-fl");
AddMimeType("TXT", "text/plain");
AddMimeType("HTM", "text/html");
AddMimeType("HTML", "text/html");
AddMimeType("PDF", "application/pdf");
AddMimeType("DOC", "application/msword");
AddMimeType("XLS", "application/vnd.ms-excel");
AddMimeType("PPT", "application/mspowerpoint");
AddMimeType("FLAC", "audio/x-flac");
AddMimeType("FLAC", "audio/flac");
AddMimeType("ZIP", "application/zip");
AddMimeType("MPG", "video/mp2p");
AddMimeType("MPEG", "video/mp2p");
}
}
static MimeTypes staticContruct;
static std::string empty;
const std::string& MimeTypes::MimeTypeFromExtension(const std::string &extension)
{
MaybeInitialize();
auto iter = extensionToMimeType.find(extension);
if (iter == extensionToMimeType.end()) return empty;
return iter->second;
}
const std::string& MimeTypes::ExtensionFromMimeType(const std::string &mimeType)
{
MaybeInitialize();
auto iter = mimeTypeToExtension.find(mimeType);
if (iter == mimeTypeToExtension.end()) return empty;
return iter->second;
}
static std::string toLower(const std::string&value)
{
std::string result;
result.resize(value.length());
for (size_t i = 0; i < value.length(); ++i)
{
char c = value[i];
if (c >= 'A' && c <= 'Z')
{
c += 'a'-'A';
}
result[i] = c;
}
return result;
}
void MimeTypes::AddMimeType(const std::string&extension_, const std::string&mimeType)
{
std::string extension = "." + toLower(extension_);
mimeTypeToExtension[mimeType] = extension;
extensionToMimeType[extension] = mimeType;
if (mimeType.starts_with("audio/"))
{
audioExtensions.insert(extension);
}
if (mimeType.starts_with("video/"))
{
videoExtensions.insert(extension);
}
}
std::map<std::string,std::string> MimeTypes::mimeTypeToExtension;
std::map<std::string,std::string> MimeTypes::extensionToMimeType;
std::set<std::string> MimeTypes::audioExtensions;
std::set<std::string> MimeTypes::videoExtensions;
bool MimeTypes::initialized;

Some files were not shown because too many files have changed in this diff Show More