From c082ce998bde35e8fd779968532b3ee19b65c89d Mon Sep 17 00:00:00 2001 From: Andrew Belt Date: Fri, 23 Aug 2019 09:55:24 -0400 Subject: [PATCH 01/17] Use dev version --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index a0df47af..251224ea 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ RACK_DIR ?= . -# VERSION := 1.dev.$(shell git rev-parse --short HEAD) -VERSION := 1.1.4 +VERSION := 1.dev.$(shell git rev-parse --short HEAD) +# VERSION := 1.1.4 FLAGS += -DVERSION=$(VERSION) FLAGS += -Iinclude -Idep/include From 07099e9ccb501521a00fde9cffde5e5d6f33b18c Mon Sep 17 00:00:00 2001 From: Andrew Belt Date: Wed, 28 Aug 2019 17:19:51 -0400 Subject: [PATCH 02/17] MIDI-Map: Jump value for MIDI CC buttons. --- src/core/MIDI_Map.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/core/MIDI_Map.cpp b/src/core/MIDI_Map.cpp index 7435bf8d..111d964e 100644 --- a/src/core/MIDI_Map.cpp +++ b/src/core/MIDI_Map.cpp @@ -103,13 +103,20 @@ struct MIDI_Map : Module { if (!filterInitialized[id]) { valueFilters[id].out = paramQuantity->getScaledValue(); filterInitialized[id] = true; + continue; } // Set param if value has been initialized - if (values[cc] >= 0) { - float v = values[cc] / 127.f; - v = valueFilters[id].process(args.sampleTime * divider.getDivision(), v); - paramQuantity->setScaledValue(v); + float value = values[cc] / 127.f; + // Detect behavior from MIDI buttons. + if (std::fabs(valueFilters[id].out - value) >= 1.f) { + // Jump value + valueFilters[id].out = value; + } + else { + // Smooth value with filter + valueFilters[id].process(args.sampleTime * divider.getDivision(), value); } + paramQuantity->setScaledValue(valueFilters[id].out); } } } From 38fb2c8682ccc634dfcc9d1f3c6bfb7ef71f3b2d Mon Sep 17 00:00:00 2001 From: Andrew Belt Date: Wed, 28 Aug 2019 17:20:16 -0400 Subject: [PATCH 03/17] Line-break descriptions for tags --- src/tag.cpp | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/src/tag.cpp b/src/tag.cpp index 78e6daaf..f316780c 100644 --- a/src/tag.cpp +++ b/src/tag.cpp @@ -9,24 +9,31 @@ namespace tag { const std::vector> tagAliases = { {"Arpeggiator"}, - {"Attenuator"}, // With a level knob and not much else. - {"Blank"}, // No parameters or ports. Serves no purpose except visual. + // With a level knob and not much else. + {"Attenuator"}, + // No parameters or ports. Serves no purpose except visual. + {"Blank"}, {"Chorus"}, {"Clock generator", "Clock"}, - {"Clock modulator"}, // Clock dividers, multipliers, etc. - {"Compressor"}, // With threshold, ratio, knee, etc parameters. - {"Controller"}, // Use only if the artist "performs" with this module. Simply having knobs is not enough. Examples: on-screen keyboard, XY pad. + // Clock dividers, multipliers, etc. + {"Clock modulator"}, + // With threshold, ratio, knee, etc parameters. + {"Compressor"}, + // Use only if the artist "performs" with this module. Simply having knobs is not enough. Examples: on-screen keyboard, XY pad. + {"Controller"}, {"Delay"}, {"Digital"}, {"Distortion"}, {"Drum", "Drums", "Percussion"}, - {"Dual"}, // The core functionality times two. If multiple channels are a requirement for the module to exist (ring modulator, mixer, etc), it is not a Dual module. + // The core functionality times two. If multiple channels are a requirement for the module to exist (ring modulator, mixer, etc), it is not a Dual module. + {"Dual"}, {"Dynamics"}, {"Effect"}, {"Envelope follower"}, {"Envelope generator"}, {"Equalizer", "EQ"}, - {"Expander"}, // Expands the functionality of a "mother" module when placed next to it. Expanders should inherit the tags of its mother module. + // Expands the functionality of a "mother" module when placed next to it. Expanders should inherit the tags of its mother module. + {"Expander"}, {"External"}, {"Filter", "VCF", "Voltage controlled filter"}, {"Flanger"}, @@ -45,7 +52,8 @@ const std::vector> tagAliases = { {"Phaser"}, {"Physical modeling"}, {"Polyphonic", "Poly"}, - {"Quad"}, // The core functionality times four. If multiple channels are a requirement for the module to exist (ring modulator, mixer, etc), it is not a Quad module. + // The core functionality times four. If multiple channels are a requirement for the module to exist (ring modulator, mixer, etc), it is not a Quad module. + {"Quad"}, {"Quantizer"}, {"Random"}, {"Recording"}, @@ -56,9 +64,11 @@ const std::vector> tagAliases = { {"Sequencer"}, {"Slew limiter"}, {"Switch"}, - {"Synth voice"}, // A synth voice must have, at the minimum, a built-in oscillator and envelope. + // A synth voice must have, at the minimum, a built-in oscillator and envelope. + {"Synth voice"}, {"Tuner"}, - {"Utility"}, // Serves only extremely basic functions, like inverting, max, min, multiplying by 2, etc. + // Serves only extremely basic functions, like inverting, max, min, multiplying by 2, etc. + {"Utility"}, {"Visual"}, {"Vocoder"}, {"Voltage-controlled amplifier", "Amplifier", "VCA", "Voltage controlled amplifier"}, From 7f5eb46724c5135e982bbc3e58e2f0421746be76 Mon Sep 17 00:00:00 2001 From: Andrew Belt Date: Wed, 28 Aug 2019 19:30:55 -0400 Subject: [PATCH 04/17] Add libsamplerate to deps. Reorder dep Makefile. --- Makefile | 2 +- dep/Makefile | 63 +++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 46 insertions(+), 19 deletions(-) diff --git a/Makefile b/Makefile index 251224ea..f5e4b9c1 100644 --- a/Makefile +++ b/Makefile @@ -21,7 +21,7 @@ ifdef ARCH_LIN build/dep/osdialog/osdialog_gtk2.c.o: FLAGS += $(shell pkg-config --cflags gtk+-2.0) LDFLAGS += -rdynamic \ - dep/lib/libglfw3.a dep/lib/libGLEW.a dep/lib/libjansson.a dep/lib/libspeexdsp.a dep/lib/libzip.a dep/lib/libz.a dep/lib/librtmidi.a dep/lib/librtaudio.a dep/lib/libcurl.a dep/lib/libssl.a dep/lib/libcrypto.a \ + dep/lib/libGLEW.a dep/lib/libglfw3.a dep/lib/libjansson.a dep/lib/libcurl.a dep/lib/libssl.a dep/lib/libcrypto.a dep/lib/libzip.a dep/lib/libz.a dep/lib/libspeexdsp.a dep/lib/libsamplerate.a dep/lib/librtmidi.a dep/lib/librtaudio.a \ -lpthread -lGL -ldl -lX11 -lasound -ljack \ $(shell pkg-config --libs gtk+-2.0) TARGET := Rack diff --git a/dep/Makefile b/dep/Makefile index 2fe91d3e..501d1d0e 100755 --- a/dep/Makefile +++ b/dep/Makefile @@ -10,39 +10,42 @@ ifdef ARCH_LIN glew = lib/libGLEW.a glfw = lib/libglfw3.a jansson = lib/libjansson.a - libspeexdsp = lib/libspeexdsp.a + openssl = lib/libssl.a libcurl = lib/libcurl.a libzip = lib/libzip.a zlib = lib/libz.a + libspeexdsp = lib/libspeexdsp.a + libsamplerate = lib/libsamplerate.a rtmidi = lib/librtmidi.a rtaudio = lib/librtaudio.a - openssl = lib/libssl.a endif ifdef ARCH_MAC glew = lib/libGLEW.a glfw = lib/libglfw3.a jansson = lib/libjansson.a - libspeexdsp = lib/libspeexdsp.a + openssl = lib/libssl.a libcurl = lib/libcurl.a libzip = lib/libzip.a zlib = lib/libz.a + libspeexdsp = lib/libspeexdsp.a + libsamplerate = lib/libsamplerate.a rtmidi = lib/librtmidi.a rtaudio = lib/librtaudio.a - openssl = lib/libssl.a endif ifdef ARCH_WIN glew = lib/libglew32.a glfw = lib/libglfw3.a jansson = lib/libjansson.a - libspeexdsp = lib/libspeexdsp.a + openssl = lib/libssl.a libcurl = lib/libcurl.a libzip = lib/libzip.a zlib = lib/libz.a + libspeexdsp = lib/libspeexdsp.a + libsamplerate = lib/libsamplerate.a rtmidi = lib/librtmidi.a rtaudio = lib/librtaudio.a - openssl = lib/libssl.a endif nanovg = include/nanovg.h @@ -51,7 +54,20 @@ oui-blendish = include/blendish.h osdialog = include/osdialog.h pffft = include/pffft.h -DEPS += $(glew) $(glfw) $(jansson) $(libspeexdsp) $(libcurl) $(libzip) $(rtmidi) $(rtaudio) $(nanovg) $(nanosvg) $(oui-blendish) $(osdialog) $(pffft) +DEPS += $(glew) +DEPS += $(glfw) +DEPS += $(jansson) +DEPS += $(libcurl) +DEPS += $(libzip) +DEPS += $(libspeexdsp) +DEPS += $(libsamplerate) +DEPS += $(rtmidi) +DEPS += $(rtaudio) +DEPS += $(nanovg) +DEPS += $(nanosvg) +DEPS += $(oui-blendish) +DEPS += $(osdialog) +DEPS += $(pffft) DEP_LOCAL := . @@ -90,17 +106,6 @@ $(jansson): jansson-2.12 $(MAKE) -C jansson-2.12 $(MAKE) -C jansson-2.12 install -speexdsp-SpeexDSP-1.2rc3: - $(WGET) "https://vcvrack.com/downloads/dep/speexdsp-SpeexDSP-1.2rc3.tgz" - $(SHA256) speexdsp-SpeexDSP-1.2rc3.tgz c8dded1454747f65956f981c95e7f89a06abdaa2a53e8aeaa66bab2a3d59cebd - $(UNTAR) speexdsp-SpeexDSP-1.2rc3.tgz - rm speexdsp-SpeexDSP-1.2rc3.tgz - -$(libspeexdsp): speexdsp-SpeexDSP-1.2rc3 - cd speexdsp-SpeexDSP-1.2rc3 && $(CONFIGURE) - $(MAKE) -C speexdsp-SpeexDSP-1.2rc3 - $(MAKE) -C speexdsp-SpeexDSP-1.2rc3 install - openssl-1.1.1b: $(WGET) "https://www.openssl.org/source/openssl-1.1.1b.tar.gz" $(SHA256) openssl-1.1.1b.tar.gz 5c557b023230413dfb0756f3137a13e6d726838ccd1430888ad15bfb2b43ea4b @@ -157,6 +162,28 @@ else $(MAKE) -C zlib-1.2.11 install endif +speexdsp-SpeexDSP-1.2rc3: + $(WGET) "https://vcvrack.com/downloads/dep/speexdsp-SpeexDSP-1.2rc3.tgz" + $(SHA256) speexdsp-SpeexDSP-1.2rc3.tgz c8dded1454747f65956f981c95e7f89a06abdaa2a53e8aeaa66bab2a3d59cebd + $(UNTAR) speexdsp-SpeexDSP-1.2rc3.tgz + rm speexdsp-SpeexDSP-1.2rc3.tgz + +$(libspeexdsp): speexdsp-SpeexDSP-1.2rc3 + cd speexdsp-SpeexDSP-1.2rc3 && $(CONFIGURE) + $(MAKE) -C speexdsp-SpeexDSP-1.2rc3 + $(MAKE) -C speexdsp-SpeexDSP-1.2rc3 install + +libsamplerate-0.1.9: + $(WGET) "http://www.mega-nerd.com/SRC/libsamplerate-0.1.9.tar.gz" + $(SHA256) libsamplerate-0.1.9.tar.gz 0a7eb168e2f21353fb6d84da152e4512126f7dc48ccb0be80578c565413444c1 + $(UNTAR) libsamplerate-0.1.9.tar.gz + rm libsamplerate-0.1.9.tar.gz + +$(libsamplerate): libsamplerate-0.1.9 + cd libsamplerate-0.1.9 && $(CONFIGURE) --disable-fftw --disable-sndfile + $(MAKE) -C libsamplerate-0.1.9 + $(MAKE) -C libsamplerate-0.1.9 install + rtmidi-4.0.0: $(WGET) "http://www.music.mcgill.ca/~gary/rtmidi/release/rtmidi-4.0.0.tar.gz" $(SHA256) rtmidi-4.0.0.tar.gz 370cfe710f43fbeba8d2b8c8bc310f314338c519c2cf2865e2d2737b251526cd From 4d895f2a3093a99c82b33f09b58829e12040faa8 Mon Sep 17 00:00:00 2001 From: Andrew Belt Date: Wed, 28 Aug 2019 19:32:25 -0400 Subject: [PATCH 05/17] Add libsamplerate license to LICENSE-dist. --- LICENSE-dist.txt | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/LICENSE-dist.txt b/LICENSE-dist.txt index 57db3252..76e0db40 100644 --- a/LICENSE-dist.txt +++ b/LICENSE-dist.txt @@ -536,4 +536,33 @@ 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. \ No newline at end of file +SOFTWARE. + + +# libsamplerate + +Copyright (c) 2012-2016, Erik de Castro Lopo +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. From 1dd0538ef0daa2f7c4c66fbf4f23817483200f43 Mon Sep 17 00:00:00 2001 From: Andrew Belt Date: Wed, 28 Aug 2019 20:19:11 -0400 Subject: [PATCH 06/17] Add libsamplerate to Mac build --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index f5e4b9c1..0b83ea81 100644 --- a/Makefile +++ b/Makefile @@ -31,7 +31,7 @@ ifdef ARCH_MAC SOURCES += dep/osdialog/osdialog_mac.m LDFLAGS += -lpthread -ldl \ -framework Cocoa -framework OpenGL -framework IOKit -framework CoreVideo -framework CoreAudio -framework CoreMIDI \ - dep/lib/libglfw3.a dep/lib/libGLEW.a dep/lib/libjansson.a dep/lib/libspeexdsp.a dep/lib/libzip.a dep/lib/libz.a dep/lib/librtaudio.a dep/lib/librtmidi.a dep/lib/libcrypto.a dep/lib/libssl.a dep/lib/libcurl.a + dep/lib/libGLEW.a dep/lib/libglfw3.a dep/lib/libjansson.a dep/lib/libcurl.a dep/lib/libssl.a dep/lib/libcrypto.a dep/lib/libzip.a dep/lib/libz.a dep/lib/libspeexdsp.a dep/lib/libsamplerate.a dep/lib/librtmidi.a dep/lib/librtaudio.a TARGET := Rack endif From 2902dbb01bc22fdbed34a449806bdf44512f8229 Mon Sep 17 00:00:00 2001 From: Andrew Belt Date: Wed, 28 Aug 2019 20:19:41 -0400 Subject: [PATCH 07/17] Add libsamplerate to Windows build --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 0b83ea81..bef63c93 100644 --- a/Makefile +++ b/Makefile @@ -38,7 +38,7 @@ endif ifdef ARCH_WIN SOURCES += dep/osdialog/osdialog_win.c LDFLAGS += -Wl,--export-all-symbols,--out-implib,libRack.a -mwindows \ - dep/lib/libglew32.a dep/lib/libglfw3.a dep/lib/libjansson.a dep/lib/libspeexdsp.a dep/lib/libzip.a dep/lib/libz.a dep/lib/libcurl.a dep/lib/libssl.a dep/lib/libcrypto.a dep/lib/librtaudio.a dep/lib/librtmidi.a \ + dep/lib/libglew32.a dep/lib/libglfw3.a dep/lib/libjansson.a dep/lib/libspeexdsp.a dep/lib/libsamplerate.a dep/lib/libzip.a dep/lib/libz.a dep/lib/libcurl.a dep/lib/libssl.a dep/lib/libcrypto.a dep/lib/librtaudio.a dep/lib/librtmidi.a \ -lpthread -lopengl32 -lgdi32 -lws2_32 -lcomdlg32 -lole32 -ldsound -lwinmm -lksuser -lshlwapi -lmfplat -lmfuuid -lwmcodecdspuuid -ldbghelp TARGET := Rack.exe OBJECTS += Rack.res From 0053517ec77f4690d27fa84bb8aed6d84c32c5e2 Mon Sep 17 00:00:00 2001 From: Andrew Belt Date: Tue, 3 Sep 2019 18:48:48 -0400 Subject: [PATCH 08/17] Delete ModuleWidget children before deleting Module. --- src/app/ModuleWidget.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/app/ModuleWidget.cpp b/src/app/ModuleWidget.cpp index b88aaec9..998ac245 100644 --- a/src/app/ModuleWidget.cpp +++ b/src/app/ModuleWidget.cpp @@ -246,6 +246,7 @@ ModuleWidget::ModuleWidget() { } ModuleWidget::~ModuleWidget() { + clearChildren(); setModule(NULL); } From 7b74d0a2a8a3c479d31a377a211430d0bbb7010f Mon Sep 17 00:00:00 2001 From: Andrew Belt Date: Mon, 9 Sep 2019 09:43:12 -0400 Subject: [PATCH 09/17] Add Hardware tag. --- src/tag.cpp | 31 +++++++++++-------------------- 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/src/tag.cpp b/src/tag.cpp index f316780c..3557f915 100644 --- a/src/tag.cpp +++ b/src/tag.cpp @@ -8,37 +8,31 @@ namespace tag { const std::vector> tagAliases = { - {"Arpeggiator"}, - // With a level knob and not much else. - {"Attenuator"}, - // No parameters or ports. Serves no purpose except visual. + {"Arpeggiator"}, // With a level knob and not much else. + {"Attenuator"}, // No parameters or ports. Serves no purpose except visual. {"Blank"}, {"Chorus"}, - {"Clock generator", "Clock"}, - // Clock dividers, multipliers, etc. - {"Clock modulator"}, - // With threshold, ratio, knee, etc parameters. - {"Compressor"}, - // Use only if the artist "performs" with this module. Simply having knobs is not enough. Examples: on-screen keyboard, XY pad. + {"Clock generator", "Clock"}, // Clock dividers, multipliers, etc. + {"Clock modulator"}, // With threshold, ratio, knee, etc parameters. + {"Compressor"}, // Use only if the artist "performs" with this module. Simply having knobs is not enough. Examples: on-screen keyboard, XY pad. {"Controller"}, {"Delay"}, {"Digital"}, {"Distortion"}, - {"Drum", "Drums", "Percussion"}, - // The core functionality times two. If multiple channels are a requirement for the module to exist (ring modulator, mixer, etc), it is not a Dual module. + {"Drum", "Drums", "Percussion"}, // The core functionality times two. If multiple channels are a requirement for the module to exist (ring modulator, mixer, etc), it is not a Dual module. {"Dual"}, {"Dynamics"}, {"Effect"}, {"Envelope follower"}, {"Envelope generator"}, - {"Equalizer", "EQ"}, - // Expands the functionality of a "mother" module when placed next to it. Expanders should inherit the tags of its mother module. + {"Equalizer", "EQ"}, // Expands the functionality of a "mother" module when placed next to it. Expanders should inherit the tags of its mother module. {"Expander"}, {"External"}, {"Filter", "VCF", "Voltage controlled filter"}, {"Flanger"}, {"Function generator"}, {"Granular"}, + {"Hardware clone", "Hardware"}, // Clones the functionality *and* appearance of a real-world hardware module. {"Limiter"}, {"Logic"}, {"Low-frequency oscillator", "LFO", "Low frequency oscillator"}, @@ -51,8 +45,7 @@ const std::vector> tagAliases = { {"Panning", "Pan"}, {"Phaser"}, {"Physical modeling"}, - {"Polyphonic", "Poly"}, - // The core functionality times four. If multiple channels are a requirement for the module to exist (ring modulator, mixer, etc), it is not a Quad module. + {"Polyphonic", "Poly"}, // The core functionality times four. If multiple channels are a requirement for the module to exist (ring modulator, mixer, etc), it is not a Quad module. {"Quad"}, {"Quantizer"}, {"Random"}, @@ -63,11 +56,9 @@ const std::vector> tagAliases = { {"Sampler"}, {"Sequencer"}, {"Slew limiter"}, - {"Switch"}, - // A synth voice must have, at the minimum, a built-in oscillator and envelope. + {"Switch"}, // A synth voice must have, at the minimum, a built-in oscillator and envelope. {"Synth voice"}, - {"Tuner"}, - // Serves only extremely basic functions, like inverting, max, min, multiplying by 2, etc. + {"Tuner"}, // Serves only extremely basic functions, like inverting, max, min, multiplying by 2, etc. {"Utility"}, {"Visual"}, {"Vocoder"}, From 3b2a12559fd6a038701ac8572b24b23733fc08e3 Mon Sep 17 00:00:00 2001 From: Andrew Belt Date: Mon, 9 Sep 2019 09:59:05 -0400 Subject: [PATCH 10/17] Reorder tag and brand lists in Module Browser --- src/app/ModuleBrowser.cpp | 66 +++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/src/app/ModuleBrowser.cpp b/src/app/ModuleBrowser.cpp index 21a1386d..c8c16073 100644 --- a/src/app/ModuleBrowser.cpp +++ b/src/app/ModuleBrowser.cpp @@ -320,12 +320,12 @@ struct ClearButton : ui::Button { struct BrowserSidebar : widget::Widget { BrowserSearchField* searchField; ClearButton* clearButton; - ui::Label* brandLabel; - ui::List* brandList; - ui::ScrollWidget* brandScroll; ui::Label* tagLabel; ui::List* tagList; ui::ScrollWidget* tagScroll; + ui::Label* brandLabel; + ui::List* brandList; + ui::ScrollWidget* brandScroll; BrowserSidebar() { // Search @@ -337,7 +337,28 @@ struct BrowserSidebar : widget::Widget { clearButton->text = "Reset filters"; addChild(clearButton); - // Bbrand label + // Tag label + tagLabel = new ui::Label; + // tagLabel->fontSize = 16; + tagLabel->color = nvgRGB(0x80, 0x80, 0x80); + tagLabel->text = "Tags"; + addChild(tagLabel); + + // Tag list + tagScroll = new ui::ScrollWidget; + addChild(tagScroll); + + tagList = new ui::List; + tagScroll->container->addChild(tagList); + + for (int tagId = 0; tagId < (int) tag::tagAliases.size(); tagId++) { + TagItem* item = new TagItem; + item->text = tag::tagAliases[tagId][0]; + item->tagId = tagId; + tagList->addChild(item); + } + + // Brand label brandLabel = new ui::Label; // brandLabel->fontSize = 16; brandLabel->color = nvgRGB(0x80, 0x80, 0x80); @@ -362,27 +383,6 @@ struct BrowserSidebar : widget::Widget { item->text = brand; brandList->addChild(item); } - - // Tag label - tagLabel = new ui::Label; - // tagLabel->fontSize = 16; - tagLabel->color = nvgRGB(0x80, 0x80, 0x80); - tagLabel->text = "Tags"; - addChild(tagLabel); - - // Tag list - tagScroll = new ui::ScrollWidget; - addChild(tagScroll); - - tagList = new ui::List; - tagScroll->container->addChild(tagList); - - for (int tagId = 0; tagId < (int) tag::tagAliases.size(); tagId++) { - TagItem* item = new TagItem; - item->text = tag::tagAliases[tagId][0]; - item->tagId = tagId; - tagList->addChild(item); - } } void step() override { @@ -393,20 +393,20 @@ struct BrowserSidebar : widget::Widget { float listHeight = (box.size.y - clearButton->box.getBottom()) / 2; listHeight = std::floor(listHeight); - brandLabel->box.pos = clearButton->box.getBottomLeft(); - brandLabel->box.size.x = box.size.x; - brandScroll->box.pos = brandLabel->box.getBottomLeft(); - brandScroll->box.size.y = listHeight - brandLabel->box.size.y; - brandScroll->box.size.x = box.size.x; - brandList->box.size.x = brandScroll->box.size.x; - - tagLabel->box.pos = brandScroll->box.getBottomLeft(); + tagLabel->box.pos = clearButton->box.getBottomLeft(); tagLabel->box.size.x = box.size.x; tagScroll->box.pos = tagLabel->box.getBottomLeft(); tagScroll->box.size.y = listHeight - tagLabel->box.size.y; tagScroll->box.size.x = box.size.x; tagList->box.size.x = tagScroll->box.size.x; + brandLabel->box.pos = tagScroll->box.getBottomLeft(); + brandLabel->box.size.x = box.size.x; + brandScroll->box.pos = brandLabel->box.getBottomLeft(); + brandScroll->box.size.y = listHeight - brandLabel->box.size.y; + brandScroll->box.size.x = box.size.x; + brandList->box.size.x = brandScroll->box.size.x; + Widget::step(); } }; From 52d838d28ff02b3ca86726b3507f5590d1d6d81e Mon Sep 17 00:00:00 2001 From: Andrew Belt Date: Mon, 9 Sep 2019 10:50:01 -0400 Subject: [PATCH 11/17] Accept backspace key command on key-repeat with Module Browser search box. --- src/app/ModuleBrowser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/ModuleBrowser.cpp b/src/app/ModuleBrowser.cpp index c8c16073..17432edf 100644 --- a/src/app/ModuleBrowser.cpp +++ b/src/app/ModuleBrowser.cpp @@ -615,7 +615,7 @@ inline void TagItem::step() { } inline void BrowserSearchField::onSelectKey(const event::SelectKey& e) { - if (e.action == GLFW_PRESS) { + if (e.action == GLFW_PRESS || e.action == GLFW_REPEAT) { switch (e.key) { case GLFW_KEY_ESCAPE: { BrowserOverlay* overlay = getAncestorOfType(); From a629561f580fbd922edd99087cb6817770af4932 Mon Sep 17 00:00:00 2001 From: Andrew Belt Date: Wed, 11 Sep 2019 15:56:47 -0400 Subject: [PATCH 12/17] Move plugin.cpp's extractZip to system::unzipToFolder(). --- include/system.hpp | 5 ++++ src/plugin.cpp | 74 ++-------------------------------------------- src/system.cpp | 71 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+), 72 deletions(-) diff --git a/include/system.hpp b/include/system.hpp index c4519498..c482f0b2 100644 --- a/include/system.hpp +++ b/include/system.hpp @@ -47,6 +47,11 @@ The launched process will continue running if the current process is closed. */ void runProcessDetached(const std::string& path); std::string getOperatingSystemInfo(); +/** Unzips a ZIP file to a folder. +The folder must exist. +Returns 0 if successful. +*/ +int unzipToFolder(const std::string& zipPath, const std::string& dir); } // namespace system diff --git a/src/plugin.cpp b/src/plugin.cpp index 3f80e06f..91c0d0fd 100644 --- a/src/plugin.cpp +++ b/src/plugin.cpp @@ -17,8 +17,6 @@ #include #include -#define ZIP_STATIC -#include #include #if defined ARCH_WIN @@ -174,74 +172,6 @@ static void loadPlugins(std::string path) { } } -/** Returns 0 if successful */ -static int extractZipHandle(zip_t* za, std::string dir) { - int err; - for (int i = 0; i < zip_get_num_entries(za, 0); i++) { - zip_stat_t zs; - err = zip_stat_index(za, i, 0, &zs); - if (err) { - WARN("zip_stat_index() failed: error %d", err); - return err; - } - - std::string path = dir + "/" + zs.name; - - if (path[path.size() - 1] == '/') { - system::createDirectory(path); - // HACK - // Create and delete file to update the directory's mtime. - std::string tmpPath = path + "/.tmp"; - FILE* tmpFile = fopen(tmpPath.c_str(), "w"); - fclose(tmpFile); - std::remove(tmpPath.c_str()); - } - else { - zip_file_t* zf = zip_fopen_index(za, i, 0); - if (!zf) { - WARN("zip_fopen_index() failed"); - return -1; - } - - FILE* outFile = fopen(path.c_str(), "wb"); - if (!outFile) - continue; - - while (1) { - char buffer[1 << 15]; - int len = zip_fread(zf, buffer, sizeof(buffer)); - if (len <= 0) - break; - fwrite(buffer, 1, len, outFile); - } - - err = zip_fclose(zf); - if (err) { - WARN("zip_fclose() failed: error %d", err); - return err; - } - fclose(outFile); - } - } - return 0; -} - -/** Returns 0 if successful */ -static int extractZip(std::string filename, std::string path) { - int err; - zip_t* za = zip_open(filename.c_str(), 0, &err); - if (!za) { - WARN("Could not open zip %s: error %d", filename.c_str(), err); - return err; - } - DEFER({ - zip_close(za); - }); - - err = extractZipHandle(za, path); - return err; -} - static void extractPackages(std::string path) { std::string message; @@ -250,7 +180,7 @@ static void extractPackages(std::string path) { continue; INFO("Extracting package %s", packagePath.c_str()); // Extract package - if (extractZip(packagePath, path)) { + if (system::unzipToFolder(packagePath, path)) { WARN("Package %s failed to extract", packagePath.c_str()); message += string::f("Could not extract package %s\n", packagePath.c_str()); continue; @@ -289,7 +219,7 @@ void init() { std::string fundamentalDir = asset::pluginsPath + "/Fundamental"; if (!settings::devMode && !getPlugin("Fundamental") && system::isFile(fundamentalSrc)) { INFO("Extracting bundled Fundamental package"); - extractZip(fundamentalSrc.c_str(), asset::pluginsPath.c_str()); + system::unzipToFolder(fundamentalSrc.c_str(), asset::pluginsPath.c_str()); loadPlugin(fundamentalDir); } diff --git a/src/system.cpp b/src/system.cpp index 920bae0f..f0d78093 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -27,6 +27,9 @@ #include #endif +#define ZIP_STATIC +#include + namespace rack { namespace system { @@ -324,5 +327,73 @@ std::string getOperatingSystemInfo() { } +int unzipToFolder(const std::string& zipPath, const std::string& dir) { + int err; + // Open ZIP file + zip_t* za = zip_open(zipPath.c_str(), 0, &err); + if (!za) { + WARN("Could not open ZIP file %s: error %d", zipPath.c_str(), err); + return err; + } + DEFER({ + zip_close(za); + }); + + // Iterate ZIP entries + for (int i = 0; i < zip_get_num_entries(za, 0); i++) { + zip_stat_t zs; + err = zip_stat_index(za, i, 0, &zs); + if (err) { + WARN("zip_stat_index() failed: error %d", err); + return err; + } + + std::string path = dir + "/" + zs.name; + + if (path[path.size() - 1] == '/') { + // Create directory + system::createDirectory(path); + // HACK + // Create and delete file to update the directory's mtime. + std::string tmpPath = path + "/.tmp"; + FILE* tmpFile = fopen(tmpPath.c_str(), "w"); + fclose(tmpFile); + std::remove(tmpPath.c_str()); + } + else { + // Open ZIP entry + zip_file_t* zf = zip_fopen_index(za, i, 0); + if (!zf) { + WARN("zip_fopen_index() failed"); + return -1; + } + DEFER({ + zip_fclose(zf); + }); + + // Create file + FILE* outFile = fopen(path.c_str(), "wb"); + if (!outFile) { + WARN("Could not create file %s", path.c_str()); + return -1; + } + DEFER({ + fclose(outFile); + }); + + // Read buffer and copy to file + while (true) { + char buffer[1 << 15]; + int len = zip_fread(zf, buffer, sizeof(buffer)); + if (len <= 0) + break; + fwrite(buffer, 1, len, outFile); + } + } + } + return 0; +} + + } // namespace system } // namespace rack From 40b258e84f5bad8b5e3f8005e5effbe76cac2f6a Mon Sep 17 00:00:00 2001 From: Andrew Belt Date: Thu, 12 Sep 2019 12:18:36 -0400 Subject: [PATCH 13/17] Correct documentation for math::interpolateLinear. --- include/math.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/math.hpp b/include/math.hpp index 8011ac05..2c345cee 100644 --- a/include/math.hpp +++ b/include/math.hpp @@ -147,7 +147,7 @@ inline float crossfade(float a, float b, float p) { } /** Linearly interpolates an array `p` with index `x`. -Assumes that the array at `p` is of length at least `floor(x) + 1`. +The array at `p` must be at least length `floor(x) + 2`. */ inline float interpolateLinear(const float* p, float x) { int xi = x; From 18e463c01ebab8d8b9aec3c0be590fd7188cda45 Mon Sep 17 00:00:00 2001 From: Andrew Belt Date: Thu, 12 Sep 2019 14:02:33 -0400 Subject: [PATCH 14/17] Add changelog entry for 1.1.5. --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f6e05915..35f2c01f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ In this document, Mod is Ctrl on Windows/Linux and Cmd on Mac. +### 1.1.5 (in development) +- Swap order of tags and brands in Module Browser. +- Disable smoothing for MIDI CC buttons in MIDI-Map. +- API + - Add libsamplerate library. + ### 1.1.4 (2019-08-22) - Fix parameter smoothing of MIDI-Map. - Sort modules within plugin in the Module Browser according to plugin rather than alphabetically. From 7f6f9334204fc86281707b66414ba9959144c692 Mon Sep 17 00:00:00 2001 From: Andrew Belt Date: Thu, 12 Sep 2019 14:39:25 -0400 Subject: [PATCH 15/17] Add automatic unzipping when updating on Mac. --- CHANGELOG.md | 1 + src/updater.cpp | 13 ++++++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 35f2c01f..eddb5de4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ In this document, Mod is Ctrl on Windows/Linux and Cmd on Mac. ### 1.1.5 (in development) - Swap order of tags and brands in Module Browser. - Disable smoothing for MIDI CC buttons in MIDI-Map. +- Automatically unzip update on Mac. - API - Add libsamplerate library. diff --git a/src/updater.cpp b/src/updater.cpp index 5b2f7a7f..15a93fcc 100644 --- a/src/updater.cpp +++ b/src/updater.cpp @@ -61,16 +61,23 @@ void update() { if (downloadUrl == "") return; -#if defined ARCH_WIN - // Download and launch the installer on Windows +#if defined ARCH_WIN || defined ARCH_MAC + // Download update std::string filename = string::filename(network::urlPath(downloadUrl)); std::string path = asset::user(filename); INFO("Download update %s to %s", downloadUrl.c_str(), path.c_str()); network::requestDownload(downloadUrl, path, &progress); +#endif + +#if defined ARCH_WIN + // Launch the installer INFO("Launching update %s", path.c_str()); system::runProcessDetached(path); +#elif defined ARCH_MAC + // Unzip app using Apple's unzipper, since Rack's unzipper doesn't handle the metadata stuff correctly. + std::string cmd = "open \"" + path + "\""; + std::system(cmd.c_str()); #else - // Open the browser on Mac and Linux. The user will know what to do. system::openBrowser(downloadUrl); #endif From fb140075d1e464811b6b843d65aa05dad63ea915 Mon Sep 17 00:00:00 2001 From: Andrew Belt Date: Thu, 12 Sep 2019 23:18:56 -0400 Subject: [PATCH 16/17] Update formatting of code generated by helper script. --- helper.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/helper.py b/helper.py index b34dfb22..c4e388bc 100755 --- a/helper.py +++ b/helper.py @@ -100,10 +100,10 @@ include $(RACK_DIR)/plugin.mk using namespace rack; // Declare the Plugin, defined in plugin.cpp -extern Plugin *pluginInstance; +extern Plugin* pluginInstance; // Declare each Model, defined in each module source file -// extern Model *modelMyModule; +// extern Model* modelMyModule; """ with open(os.path.join(plugin_dir, "src/plugin.hpp"), "w") as f: f.write(plugin_hpp) @@ -112,10 +112,10 @@ extern Plugin *pluginInstance; plugin_cpp = """#include "plugin.hpp" -Plugin *pluginInstance; +Plugin* pluginInstance; -void init(Plugin *p) { +void init(Plugin* p) { pluginInstance = p; // Add modules here @@ -245,7 +245,7 @@ def create_module(slug, panel_filename=None, source_filename=None): # Tell user to add model to plugin.hpp and plugin.cpp print(f""" To enable the module, add -extern Model *model{identifier}; +extern Model* model{identifier}; to plugin.hpp, and add p->addModel(model{identifier}); to the init() function in plugin.cpp.""") @@ -396,7 +396,7 @@ struct {identifier} : Module {{""" source += """ } - void process(const ProcessArgs &args) override { + void process(const ProcessArgs& args) override { } };""" @@ -404,7 +404,7 @@ struct {identifier} : Module {{""" struct {identifier}Widget : ModuleWidget {{ - {identifier}Widget({identifier} *module) {{ + {identifier}Widget({identifier}* module) {{ setModule(module); setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/{slug}.svg"))); @@ -475,7 +475,7 @@ struct {identifier}Widget : ModuleWidget {{ }}; -Model *model{identifier} = createModel<{identifier}, {identifier}Widget>("{slug}");""" +Model* model{identifier} = createModel<{identifier}, {identifier}Widget>("{slug}");""" return source From f74a36c11509e49f9c321760638b4799bb022743 Mon Sep 17 00:00:00 2001 From: The XOR <1h3x0r@gmail.com> Date: Thu, 19 Sep 2019 08:40:53 +0200 Subject: [PATCH 17/17] git ignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 0ca91393..32290977 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,5 @@ /autosave.vcv /settings.json /screenshots +.vs/ +_ReSharper.Caches/