diff --git a/.gitignore b/.gitignore index 8e77f61a..d22540ef 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ /Rack /Rack.exe +/libRack.a /autosave.json /settings.json /plugins diff --git a/.gitmodules b/.gitmodules index 0d52f7cb..1dc85fb4 100644 --- a/.gitmodules +++ b/.gitmodules @@ -10,3 +10,9 @@ [submodule "ext/oui-blendish"] path = ext/oui-blendish url = https://github.com/AndrewBelt/oui-blendish.git +[submodule "dep/glfw"] + path = dep/glfw + url = https://github.com/glfw/glfw.git +[submodule "dep/rtaudio"] + path = dep/rtaudio + url = https://github.com/thestk/rtaudio.git diff --git a/CHANGELOG.md b/CHANGELOG.md index d39a2f16..edb6a485 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,15 @@ Tip: Use `git checkout v0.4.0` for example to check out any previous version mentioned here. +### v0.5.1 (2017-12-19) + +- Added Plugin Manager support +- Fixed metadata panel in the Add Module window + +- Fundamental + - Added Sequential Switch 1 & 2 + + ### v0.5.0 (2017-11-21) - Added zoom scaling from 25% to 200% @@ -27,6 +36,7 @@ Tip: Use `git checkout v0.4.0` for example to check out any previous version men ### v0.4.0 (2017-10-13) + - Cables can now stack on output ports - Added sub-menus for each plugin, includes optional plugin metadata like URLs - Added MIDI CC-to-CV Interface, updated MIDI-to-CV Interface @@ -49,6 +59,7 @@ Tip: Use `git checkout v0.4.0` for example to check out any previous version men ### v0.3.2 (2017-09-25) + - Added key commands - Fixed "invisible knobs/ports" rendering bug for ~2010 Macs - Added "allowCursorLock" to settings.json (set to "false" for touch screen support) @@ -73,4 +84,5 @@ Tip: Use `git checkout v0.4.0` for example to check out any previous version men ### v0.3.0 (2017-09-10) + - Knobcon public Beta release diff --git a/Makefile b/Makefile index 792cdbb5..93455b7a 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ ifeq ($(ARCH), lin) LDFLAGS += -rdynamic \ -lpthread -lGL -ldl \ $(shell pkg-config --libs gtk+-2.0) \ - -Ldep/lib -lGLEW -lglfw -ljansson -lsamplerate -lcurl -lzip -lrtaudio -lrtmidi -lcrypto -lssl + -Ldep/lib -lGLEW -lglfw -ljansson -lspeexdsp -lcurl -lzip -lrtaudio -lrtmidi -lcrypto -lssl -lossia TARGET = Rack endif @@ -23,7 +23,7 @@ ifeq ($(ARCH), mac) CXXFLAGS += -DAPPLE -stdlib=libc++ LDFLAGS += -stdlib=libc++ -lpthread -ldl \ -framework Cocoa -framework OpenGL -framework IOKit -framework CoreVideo \ - -Ldep/lib -lGLEW -lglfw -ljansson -lsamplerate -lcurl -lzip -lrtaudio -lrtmidi -lcrypto + -Ldep/lib -lGLEW -lglfw -ljansson -lspeexdsp -lcurl -lzip -lrtaudio -lrtmidi -lcrypto -lssl -lossia TARGET = Rack BUNDLE = dist/$(TARGET).app endif @@ -33,8 +33,8 @@ ifeq ($(ARCH), win) LDFLAGS += -static-libgcc -static-libstdc++ -lpthread \ -Wl,--export-all-symbols,--out-implib,libRack.a -mwindows \ -lgdi32 -lopengl32 -lcomdlg32 -lole32 \ - -Ldep/lib -lglew32 -lglfw3dll -lcurl -lzip -lrtaudio -lrtmidi \ - -Wl,-Bstatic -ljansson -lsamplerate -lcrypto + -Ldep/lib -lglew32 -lglfw3dll -lcurl -lzip -lrtaudio -lrtmidi -lcrypto -lssl \ + -Wl,-Bstatic -ljansson -lspeexdsp -lossia TARGET = Rack.exe OBJECTS = Rack.res endif @@ -69,8 +69,14 @@ ifeq ($(ARCH), win) env PATH=dep/bin:/mingw64/bin gdb -ex run ./Rack endif +perf: $(TARGET) +ifeq ($(ARCH), lin) + LD_LIBRARY_PATH=dep/lib perf record --call-graph dwarf ./Rack +endif + clean: + rm -fv libRack.a rm -rfv $(TARGET) build dist # For Windows resources @@ -103,7 +109,7 @@ ifeq ($(ARCH), mac) cp dep/lib/libGLEW.2.1.0.dylib $(BUNDLE)/Contents/MacOS/ cp dep/lib/libglfw.3.dylib $(BUNDLE)/Contents/MacOS/ cp dep/lib/libjansson.4.dylib $(BUNDLE)/Contents/MacOS/ - cp dep/lib/libsamplerate.0.dylib $(BUNDLE)/Contents/MacOS/ + cp dep/lib/libspeexdsp.1.dylib $(BUNDLE)/Contents/MacOS/ cp dep/lib/libcurl.4.dylib $(BUNDLE)/Contents/MacOS/ cp dep/lib/libzip.5.dylib $(BUNDLE)/Contents/MacOS/ cp dep/lib/librtaudio.dylib $(BUNDLE)/Contents/MacOS/ @@ -114,7 +120,7 @@ ifeq ($(ARCH), mac) install_name_tool -change /usr/local/lib/libGLEW.2.1.0.dylib @executable_path/libGLEW.2.1.0.dylib $(BUNDLE)/Contents/MacOS/Rack install_name_tool -change lib/libglfw.3.dylib @executable_path/libglfw.3.dylib $(BUNDLE)/Contents/MacOS/Rack install_name_tool -change $(PWD)/dep/lib/libjansson.4.dylib @executable_path/libjansson.4.dylib $(BUNDLE)/Contents/MacOS/Rack - install_name_tool -change $(PWD)/dep/lib/libsamplerate.0.dylib @executable_path/libsamplerate.0.dylib $(BUNDLE)/Contents/MacOS/Rack + install_name_tool -change $(PWD)/dep/lib/libspeexdsp.1.dylib @executable_path/libspeexdsp.1.dylib $(BUNDLE)/Contents/MacOS/Rack install_name_tool -change $(PWD)/dep/lib/libcurl.4.dylib @executable_path/libcurl.4.dylib $(BUNDLE)/Contents/MacOS/Rack install_name_tool -change $(PWD)/dep/lib/libzip.5.dylib @executable_path/libzip.5.dylib $(BUNDLE)/Contents/MacOS/Rack install_name_tool -change librtaudio.dylib @executable_path/librtaudio.dylib $(BUNDLE)/Contents/MacOS/Rack @@ -144,7 +150,7 @@ ifeq ($(ARCH), win) cp dep/bin/libcurl-4.dll dist/Rack/ cp dep/bin/libjansson-4.dll dist/Rack/ cp dep/bin/librtmidi-4.dll dist/Rack/ - cp dep/bin/libsamplerate-0.dll dist/Rack/ + cp dep/bin/libspeexdsp-1.dll dist/Rack/ cp dep/bin/libzip-5.dll dist/Rack/ cp dep/bin/librtaudio.dll dist/Rack/ cp dep/bin/libcrypto-1_1-x64.dll dist/Rack/ @@ -161,7 +167,7 @@ ifeq ($(ARCH), lin) mkdir -p dist/Rack cp -R LICENSE* res dist/Rack/ cp Rack Rack.sh dist/Rack/ - cp dep/lib/libsamplerate.so.0 dist/Rack/ + cp dep/lib/libspeexdsp.so dist/Rack/ cp dep/lib/libjansson.so.4 dist/Rack/ cp dep/lib/libGLEW.so.2.1 dist/Rack/ cp dep/lib/libglfw.so.3 dist/Rack/ diff --git a/README.md b/README.md index 40204931..6f9d0e72 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,8 @@ You may use make's `-j$(nproc)` flag to parallelize builds across all your CPU c make dep +You may use `make dep RTAUDIO_ALL_APIS=1` to attempt to build with all audio driver APIs enabled for your operating system. + You should see a message that all dependencies built successfully. Build Rack. diff --git a/compile.mk b/compile.mk index 0ebc1501..a620a636 100644 --- a/compile.mk +++ b/compile.mk @@ -1,5 +1,5 @@ ifdef VERSION -FLAGS += -DVERSION=$(VERSION) + FLAGS += -DVERSION=$(VERSION) endif # Generate dependency files alongside the object files @@ -9,9 +9,9 @@ FLAGS += -g FLAGS += -O3 -march=nocona -ffast-math -fno-finite-math-only FLAGS += -Wall -Wextra -Wno-unused-parameter ifneq ($(ARCH), mac) -CXXFLAGS += -Wsuggest-override + CXXFLAGS += -Wsuggest-override endif -CXXFLAGS += -std=c++11 +CXXFLAGS += -std=c++14 ifeq ($(ARCH), lin) @@ -32,6 +32,9 @@ ifeq ($(ARCH), win) FLAGS += -D_USE_MATH_DEFINES endif +CFLAGS += $(FLAGS) +CXXFLAGS += $(FLAGS) + OBJECTS += $(patsubst %, build/%.o, $(SOURCES)) DEPS = $(patsubst %, build/%.d, $(SOURCES)) @@ -47,16 +50,16 @@ $(TARGET): $(OBJECTS) build/%.c.o: %.c @mkdir -p $(@D) - $(CC) $(FLAGS) $(CFLAGS) -c -o $@ $< + $(CC) $(CFLAGS) -c -o $@ $< build/%.cpp.o: %.cpp @mkdir -p $(@D) - $(CXX) $(FLAGS) $(CXXFLAGS) -c -o $@ $< + $(CXX) $(CXXFLAGS) -c -o $@ $< build/%.cc.o: %.cc @mkdir -p $(@D) - $(CXX) $(FLAGS) $(CXXFLAGS) -c -o $@ $< + $(CXX) $(CXXFLAGS) -c -o $@ $< build/%.m.o: %.m @mkdir -p $(@D) - $(CC) $(FLAGS) $(CFLAGS) -c -o $@ $< + $(CC) $(CFLAGS) -c -o $@ $< diff --git a/dep/Makefile b/dep/Makefile index 8af02fcb..d36c3343 100755 --- a/dep/Makefile +++ b/dep/Makefile @@ -26,36 +26,39 @@ ifeq ($(ARCH),lin) glew = lib/libGLEW.so glfw = lib/libglfw.so jansson = lib/libjansson.so - libsamplerate = lib/libsamplerate.so + libspeexdsp = lib/libspeexdsp.so libcurl = lib/libcurl.so libzip = lib/libzip.so rtmidi = lib/librtmidi.so rtaudio = lib/librtaudio.so openssl = lib/libssl.so + ossia = lib/libossia.so endif ifeq ($(ARCH),mac) glew = lib/libGLEW.dylib glfw = lib/libglfw.dylib jansson = lib/libjansson.dylib - libsamplerate = lib/libsamplerate.dylib + libspeexdsp = lib/libspeexdsp.dylib libcurl = lib/libcurl.dylib libzip = lib/libzip.dylib rtmidi = lib/librtmidi.dylib rtaudio = lib/librtaudio.dylib openssl = lib/libssl.dylib + ossia = lib/libossia.so endif ifeq ($(ARCH),win) glew = bin/glew32.dll glfw = bin/glfw3.dll jansson = bin/libjansson-4.dll - libsamplerate = bin/libsamplerate-0.dll + libspeexdsp = bin/libspeexdsp.dll libcurl = bin/libcurl-4.dll libzip = bin/libzip-5.dll rtmidi = bin/librtmidi-4.dll rtaudio = bin/librtaudio.dll openssl = bin/libssl-1_1-x64.dll + ossia = bin/ossia.dll endif # Library configuration @@ -74,7 +77,7 @@ endif .NOTPARALLEL: -all: $(glew) $(glfw) $(jansson) $(libsamplerate) $(libcurl) $(libzip) $(rtmidi) $(rtaudio) +all: $(glew) $(glfw) $(jansson) $(libspeexdsp) $(libcurl) $(libzip) $(rtmidi) $(rtaudio) $(ossia) @echo "" @echo "#######################################" @echo "# Built all dependencies successfully #" @@ -89,17 +92,11 @@ $(glew): $(MAKE) -C glew-2.1.0 GLEW_DEST="$(LOCAL)" LIBDIR="$(LOCAL)/lib" install $(glfw): - $(WGET) https://github.com/glfw/glfw/releases/download/3.2.1/glfw-3.2.1.zip - $(UNZIP) glfw-3.2.1.zip - cd glfw-3.2.1 && $(CMAKE) . \ + cd glfw && $(CMAKE) . \ -DCMAKE_INSTALL_PREFIX="$(LOCAL)" -DBUILD_SHARED_LIBS=ON \ - -DGLFW_USE_CHDIR=OFF -DGLFW_USE_MENUBAR=ON -DGLFW_USE_RETINA=ON - $(MAKE) -C glfw-3.2.1 - $(MAKE) -C glfw-3.2.1 install -ifeq ($(ARCH),win) - # Not sure why the GLFW build system puts a .dll in the lib directory - mv "$(LOCAL)/lib/glfw3.dll" "$(LOCAL)/bin/" -endif + -DGLFW_COCOA_CHDIR_RESOURCES=OFF -DGLFW_COCOA_MENUBAR=ON -DGLFW_COCOA_RETINA_FRAMEBUFFER=ON + $(MAKE) -C glfw + $(MAKE) -C glfw install $(jansson): $(WGET) http://www.digip.org/jansson/releases/jansson-2.10.tar.gz @@ -108,12 +105,12 @@ $(jansson): $(MAKE) -C jansson-2.10 $(MAKE) -C jansson-2.10 install -$(libsamplerate): - $(WGET) http://www.mega-nerd.com/SRC/libsamplerate-0.1.9.tar.gz - $(UNTAR) libsamplerate-0.1.9.tar.gz - cd libsamplerate-0.1.9 && ./configure --prefix="$(LOCAL)" --disable-fftw --disable-sndfile - $(MAKE) -C libsamplerate-0.1.9/src - $(MAKE) -C libsamplerate-0.1.9/src install +$(libspeexdsp): + $(WGET) https://github.com/xiph/speexdsp/archive/SpeexDSP-1.2rc3.tar.gz + $(UNTAR) SpeexDSP-1.2rc3.tar.gz + cd speexdsp-SpeexDSP-1.2rc3 && ./autogen.sh && ./configure --prefix="$(LOCAL)" + $(MAKE) -C speexdsp-SpeexDSP-1.2rc3 + $(MAKE) -C speexdsp-SpeexDSP-1.2rc3 install $(openssl): $(WGET) https://www.openssl.org/source/openssl-1.1.0g.tar.gz @@ -151,18 +148,25 @@ $(libzip): $(MAKE) -C libzip-1.2.0 install $(rtmidi): - $(WGET) http://www.music.mcgill.ca/~gary/rtmidi/release/rtmidi-3.0.0.tar.gz - $(UNTAR) rtmidi-3.0.0.tar.gz - cd rtmidi-3.0.0 && ./configure --prefix="$(LOCAL)" - $(MAKE) -C rtmidi-3.0.0 - $(MAKE) -C rtmidi-3.0.0 install + git clone https://github.com/thestk/rtmidi.git + cd rtmidi && ./autogen.sh --no-configure && ./configure --prefix="$(LOCAL)" + $(MAKE) -C rtmidi + $(MAKE) -C rtmidi install $(rtaudio): - git clone https://github.com/thestk/rtaudio.git cd rtaudio && mkdir -p cmakebuild cd rtaudio/cmakebuild && cmake -G 'Unix Makefiles' -DCMAKE_INSTALL_PREFIX="$(LOCAL)" $(RTAUDIO_FLAGS) .. $(MAKE) -C rtaudio/cmakebuild $(MAKE) -C rtaudio/cmakebuild install +$(ossia): + git clone https://github.com/OSSIA/libossia --depth=1 + mkdir -p build-libossia && cd build-libossia && $(CMAKE) \ + -DCMAKE_INSTALL_PREFIX="$(LOCAL)" -DOSSIA_PD=OFF \ + -DOSSIA_COTIRE=OFF -DOSSIA_PROTOCOL_MIDI=OFF \ + -DOSSIA_EDITOR=OFF -DBUILD_TYPE=Release ../libossia && \ + $(MAKE) -j4 && \ + $(MAKE) install + clean: - git clean -ffdxi + git clean -ffdx diff --git a/dep/glfw b/dep/glfw new file mode 160000 index 00000000..682f1cf2 --- /dev/null +++ b/dep/glfw @@ -0,0 +1 @@ +Subproject commit 682f1cf203707f21c2eed4fa3f89c23c52accc49 diff --git a/dep/rtaudio b/dep/rtaudio new file mode 160000 index 00000000..ce13dfbf --- /dev/null +++ b/dep/rtaudio @@ -0,0 +1 @@ +Subproject commit ce13dfbf30fd1ab4e7f7eff8886a80f144c75e5d diff --git a/include/app.hpp b/include/app.hpp index 5acb6bef..bad646d0 100644 --- a/include/app.hpp +++ b/include/app.hpp @@ -20,10 +20,9 @@ struct SVGPanel; // module //////////////////// -// A 1U module should be 15x380. Thus the width of a module should be a factor of 15. +// A 1HPx3U module should be 15x380. Thus the width of a module should be a factor of 15. #define RACK_GRID_WIDTH 15 #define RACK_GRID_HEIGHT 380 - static const Vec RACK_GRID_SIZE = Vec(15, 380); @@ -48,6 +47,8 @@ struct ModuleWidget : OpaqueWidget { virtual json_t *toJson(); virtual void fromJson(json_t *rootJ); + virtual void create(); + virtual void _delete(); /** Disconnects cables from all ports Called when the user clicks Disconnect Cables in the context menu. */ @@ -75,14 +76,11 @@ struct ModuleWidget : OpaqueWidget { void onDragMove(EventDragMove &e) override; }; -struct ValueLight; struct WireWidget : OpaqueWidget { Port *outputPort = NULL; Port *inputPort = NULL; Port *hoveredOutputPort = NULL; Port *hoveredInputPort = NULL; - ValueLight *inputLight; - ValueLight *outputLight; Wire *wire = NULL; NVGcolor color; @@ -199,6 +197,8 @@ struct ParamWidget : OpaqueWidget, QuantityWidget { struct Knob : ParamWidget { /** Snap to nearest integer while dragging */ bool snap = false; + /** Multiplier for mouse movement to adjust knob value */ + float speed = 1.0; float dragValue; void onDragStart(EventDragStart &e) override; void onDragMove(EventDragMove &e) override; @@ -226,14 +226,14 @@ struct SVGKnob : virtual Knob, FramebufferWidget { void onChange(EventChange &e) override; }; -struct SVGSlider : Knob, FramebufferWidget { +struct SVGFader : Knob, FramebufferWidget { /** Intermediate positions will be interpolated between these positions */ Vec minHandlePos, maxHandlePos; /** Not owned */ SVGWidget *background; SVGWidget *handle; - SVGSlider(); + SVGFader(); void step() override; void onChange(EventChange &e) override; }; @@ -249,7 +249,6 @@ struct SVGSwitch : virtual Switch, FramebufferWidget { SVGSwitch(); /** Adds an SVG file to represent the next switch position */ void addFrame(std::shared_ptr svg); - void step() override; void onChange(EventChange &e) override; }; @@ -271,6 +270,8 @@ struct MomentarySwitch : virtual Switch { void randomize() override {} void onDragStart(EventDragStart &e) override { setValue(maxValue); + EventAction eAction; + onAction(eAction); } void onDragEnd(EventDragEnd &e) override { setValue(minValue); @@ -285,6 +286,8 @@ struct LightWidget : TransparentWidget { NVGcolor bgColor = nvgRGBf(0, 0, 0); NVGcolor color = nvgRGBf(1, 1, 1); void draw(NVGcontext *vg) override; + virtual void drawLight(NVGcontext *vg); + virtual void drawHalo(NVGcontext *vg); }; /** Mixes a list of colors based on a list of brightness values */ diff --git a/include/components.hpp b/include/components.hpp index 6e4807c3..cac1cf91 100644 --- a/include/components.hpp +++ b/include/components.hpp @@ -322,7 +322,7 @@ struct BefacoTinyKnob : SVGKnob { } }; -struct BefacoSlidePot : SVGSlider { +struct BefacoSlidePot : SVGFader { BefacoSlidePot() { Vec margin = Vec(3.5, 3.5); maxHandlePos = Vec(-1, -2).plus(margin); diff --git a/include/dsp/filter.hpp b/include/dsp/filter.hpp index 35098ecf..a29785bd 100644 --- a/include/dsp/filter.hpp +++ b/include/dsp/filter.hpp @@ -51,6 +51,11 @@ struct SlewLimiter { float rise = 1.0; float fall = 1.0; float out = 0.0; + + void setRiseFall(float _rise, float _fall) { + rise = _rise; + fall = _fall; + } float process(float in) { float delta = clampf(in - out, -fall, rise); out += delta; diff --git a/include/dsp/samplerate.hpp b/include/dsp/samplerate.hpp index 7cc988cf..a4a99880 100644 --- a/include/dsp/samplerate.hpp +++ b/include/dsp/samplerate.hpp @@ -1,7 +1,8 @@ #pragma once #include -#include +#include +#include #include "frame.hpp" @@ -9,41 +10,46 @@ namespace rack { template struct SampleRateConverter { - SRC_STATE *state; - SRC_DATA data; + SpeexResamplerState *state = NULL; + bool bypass = false; SampleRateConverter() { int error; - state = src_new(SRC_SINC_FASTEST, CHANNELS, &error); - assert(!error); - - data.src_ratio = 1.0; - data.end_of_input = false; + state = speex_resampler_init(CHANNELS, 44100, 44100, SPEEX_RESAMPLER_QUALITY_DEFAULT, &error); + assert(error == RESAMPLER_ERR_SUCCESS); } ~SampleRateConverter() { - src_delete(state); + speex_resampler_destroy(state); } - /** output_sample_rate / input_sample_rate */ - void setRatio(float r) { - src_set_ratio(state, r); - data.src_ratio = r; + + void setQuality(int quality) { + speex_resampler_set_quality(state, quality); } - void setRatioSmooth(float r) { - data.src_ratio = r; + + void setRates(int inRate, int outRate) { + spx_uint32_t oldInRate, oldOutRate; + speex_resampler_get_rate(state, &oldInRate, &oldOutRate); + if (inRate == (int) oldInRate && outRate == (int) oldOutRate) + return; + int error = speex_resampler_set_rate(state, inRate, outRate); + assert(error == RESAMPLER_ERR_SUCCESS); } + /** `in` and `out` are interlaced with the number of channels */ void process(const Frame *in, int *inFrames, Frame *out, int *outFrames) { - // Old versions of libsamplerate use float* here instead of const float* - data.data_in = (float*) in; - data.input_frames = *inFrames; - data.data_out = (float*) out; - data.output_frames = *outFrames; - src_process(state, &data); - *inFrames = data.input_frames_used; - *outFrames = data.output_frames_gen; + if (bypass) { + int len = std::min(*inFrames, *outFrames); + memcpy(out, in, len * sizeof(Frame)); + *inFrames = len; + *outFrames = len; + return; + } + speex_resampler_process_interleaved_float(state, (const float*)in, (unsigned int*)inFrames, (float*)out, (unsigned int*)outFrames); } + void reset() { - src_reset(state); + int error = speex_resampler_reset_mem(state); + assert(error == RESAMPLER_ERR_SUCCESS); } }; diff --git a/include/engine.hpp b/include/engine.hpp index ad3cf9e5..a387105a 100644 --- a/include/engine.hpp +++ b/include/engine.hpp @@ -3,12 +3,17 @@ #include "util.hpp" #include +#include +#include namespace rack { +extern ossia::net::generic_device& root_dev(); struct Param { float value = 0.0; + std::string name = "param.1"; + ossia::net::parameter_base* ossia_param; }; struct Light { @@ -16,7 +21,7 @@ struct Light { float value = 0.0; float getBrightness(); void setBrightness(float brightness) { - value = brightness * brightness; + value = (brightness > 0.f) ? brightness * brightness : 0.f; } void setBrightnessSmooth(float brightness); }; @@ -41,7 +46,6 @@ struct Output { Light plugLights[2]; }; - struct Module { std::vector params; std::vector