├── .astylerc ├── .github └── CONTRIBUTING.md ├── .gitignore ├── .gitmodules ├── CHANGELOG.md ├── Component.plist ├── Core.json ├── Distribution.xml ├── Entitlements.plist ├── Info.plist ├── LICENSE-GPLv3.txt ├── LICENSE-dist.md ├── LICENSE.md ├── Makefile ├── README.md ├── Rack.rc ├── adapters └── standalone.cpp ├── arch.mk ├── cacert.pem ├── compile.mk ├── dep.mk ├── dep └── Makefile ├── docs ├── .gitignore ├── Doxyfile ├── Makefile ├── index.md └── logo.png ├── helper.py ├── icon.icns ├── icon.ico ├── include ├── Quantity.hpp ├── app │ ├── AudioDisplay.hpp │ ├── Browser.hpp │ ├── CableWidget.hpp │ ├── CircularShadow.hpp │ ├── Knob.hpp │ ├── LedDisplay.hpp │ ├── LightWidget.hpp │ ├── MenuBar.hpp │ ├── MidiDisplay.hpp │ ├── ModuleLightWidget.hpp │ ├── ModuleWidget.hpp │ ├── MultiLightWidget.hpp │ ├── ParamWidget.hpp │ ├── PortWidget.hpp │ ├── RackScrollWidget.hpp │ ├── RackWidget.hpp │ ├── RailWidget.hpp │ ├── Scene.hpp │ ├── SliderKnob.hpp │ ├── SvgButton.hpp │ ├── SvgKnob.hpp │ ├── SvgPanel.hpp │ ├── SvgPort.hpp │ ├── SvgScrew.hpp │ ├── SvgSlider.hpp │ ├── SvgSwitch.hpp │ ├── Switch.hpp │ ├── TipWindow.hpp │ └── common.hpp ├── arch.hpp ├── asset.hpp ├── audio.hpp ├── color.hpp ├── common.hpp ├── componentlibrary.hpp ├── context.hpp ├── dsp │ ├── approx.hpp │ ├── common.hpp │ ├── convert.hpp │ ├── digital.hpp │ ├── fft.hpp │ ├── filter.hpp │ ├── fir.hpp │ ├── midi.hpp │ ├── minblep.hpp │ ├── ode.hpp │ ├── resampler.hpp │ ├── ringbuffer.hpp │ ├── vumeter.hpp │ └── window.hpp ├── engine │ ├── Cable.hpp │ ├── Engine.hpp │ ├── Light.hpp │ ├── LightInfo.hpp │ ├── Module.hpp │ ├── Param.hpp │ ├── ParamHandle.hpp │ ├── ParamQuantity.hpp │ ├── Port.hpp │ └── PortInfo.hpp ├── gamepad.hpp ├── helpers.hpp ├── history.hpp ├── keyboard.hpp ├── library.hpp ├── logger.hpp ├── math.hpp ├── midi.hpp ├── midiloopback.hpp ├── mutex.hpp ├── network.hpp ├── patch.hpp ├── plugin.hpp ├── plugin │ ├── Model.hpp │ ├── Plugin.hpp │ └── callbacks.hpp ├── rack.hpp ├── rack0.hpp ├── random.hpp ├── rtaudio.hpp ├── rtmidi.hpp ├── settings.hpp ├── simd │ ├── Vector.hpp │ ├── common.hpp │ ├── functions.hpp │ ├── sse_mathfun.h │ └── sse_mathfun_extension.h ├── string.hpp ├── system.hpp ├── tag.hpp ├── ui │ ├── Button.hpp │ ├── ChoiceButton.hpp │ ├── Label.hpp │ ├── List.hpp │ ├── Menu.hpp │ ├── MenuEntry.hpp │ ├── MenuItem.hpp │ ├── MenuLabel.hpp │ ├── MenuOverlay.hpp │ ├── MenuSeparator.hpp │ ├── OptionButton.hpp │ ├── ProgressBar.hpp │ ├── RadioButton.hpp │ ├── ScrollWidget.hpp │ ├── Scrollbar.hpp │ ├── SequentialLayout.hpp │ ├── Slider.hpp │ ├── TextField.hpp │ ├── Tooltip.hpp │ ├── TooltipOverlay.hpp │ └── common.hpp ├── weakptr.hpp ├── widget │ ├── FramebufferWidget.hpp │ ├── OpaqueWidget.hpp │ ├── OpenGlWidget.hpp │ ├── SvgWidget.hpp │ ├── TransformWidget.hpp │ ├── TransparentWidget.hpp │ ├── Widget.hpp │ ├── ZoomWidget.hpp │ └── event.hpp └── window │ ├── Svg.hpp │ └── Window.hpp ├── installer.nsi ├── plugin.mk ├── plugins └── .gitignore ├── presets ├── CV-CC │ ├── 0_CC 0-15.vcvm │ ├── 1_CC 16-31.vcvm │ ├── 2_CC 32-47.vcvm │ ├── 3_CC 48-63.vcvm │ ├── 4_CC 64-79.vcvm │ ├── 5_CC 80-95.vcvm │ ├── 6_CC 96-111.vcvm │ └── 7_CC 112-127.vcvm ├── CV-Gate │ ├── 0_C-1-D#0.vcvm │ ├── 1_C0-D#1.vcvm │ ├── 2_C1-D#2.vcvm │ ├── 3_C2-D#3.vcvm │ ├── 4_C3-D#4.vcvm │ ├── 5_C4-D#5.vcvm │ ├── 6_C5-D#6.vcvm │ ├── 7_C6-D#7.vcvm │ ├── 8_C7-D#8.vcvm │ └── 9_C8-D#9.vcvm ├── MIDICCToCVInterface │ ├── 0_CC 0-15.vcvm │ ├── 1_CC 16-31.vcvm │ ├── 2_CC 32-47.vcvm │ ├── 3_CC 48-63.vcvm │ ├── 4_CC 64-79.vcvm │ ├── 5_CC 80-95.vcvm │ ├── 6_CC 96-111.vcvm │ └── 7_CC 112-127.vcvm └── MIDITriggerToCVInterface │ ├── 0_C-1-D#0.vcvm │ ├── 1_C0-D#1.vcvm │ ├── 2_C1-D#2.vcvm │ ├── 3_C2-D#3.vcvm │ ├── 4_C3-D#4.vcvm │ ├── 5_C4-D#5.vcvm │ ├── 6_C5-D#6.vcvm │ ├── 7_C6-D#7.vcvm │ ├── 8_C7-D#8.vcvm │ └── 9_C8-D#9.vcvm ├── res ├── ComponentLibrary │ ├── ADAT.svg │ ├── BefacoBigKnob.svg │ ├── BefacoBigKnob_bg.svg │ ├── BefacoPush_0.svg │ ├── BefacoPush_1.svg │ ├── BefacoSlidePot.svg │ ├── BefacoSlidePotHandle.svg │ ├── BefacoSwitch.svg │ ├── BefacoSwitch_0.svg │ ├── BefacoSwitch_1.svg │ ├── BefacoSwitch_2.svg │ ├── BefacoTinyKnobWhite_bg.svg │ ├── BefacoTinyPointBlack.svg │ ├── CKD6_0.svg │ ├── CKD6_1.svg │ ├── CKSSThreeHorizontal_0.svg │ ├── CKSSThreeHorizontal_1.svg │ ├── CKSSThreeHorizontal_2.svg │ ├── CKSSThree_0.svg │ ├── CKSSThree_1.svg │ ├── CKSSThree_2.svg │ ├── CKSS_0.svg │ ├── CKSS_1.svg │ ├── CL1362.svg │ ├── Davies1900hBlack.svg │ ├── Davies1900hBlack_bg.svg │ ├── Davies1900hLargeBlack.svg │ ├── Davies1900hLargeBlack_bg.svg │ ├── Davies1900hLargeRed.svg │ ├── Davies1900hLargeRed_bg.svg │ ├── Davies1900hLargeWhite.svg │ ├── Davies1900hLargeWhite_bg.svg │ ├── Davies1900hRed.svg │ ├── Davies1900hRed_bg.svg │ ├── Davies1900hWhite.svg │ ├── Davies1900hWhite_bg.svg │ ├── LargeLight.svg │ ├── MIDI_DIN.svg │ ├── MediumLight.svg │ ├── NKK_0.svg │ ├── NKK_1.svg │ ├── NKK_2.svg │ ├── PB61303.svg │ ├── PJ301M-dark.svg │ ├── PJ301M.svg │ ├── PJ3410.svg │ ├── Plug.svg │ ├── PlugPort.svg │ ├── Rail-hcdark.svg │ ├── Rail-light.svg │ ├── Rail.svg │ ├── Rogan1PBlue.svg │ ├── Rogan1PBlue_fg.svg │ ├── Rogan1PGreen.svg │ ├── Rogan1PGreen_fg.svg │ ├── Rogan1PRed.svg │ ├── Rogan1PRed_fg.svg │ ├── Rogan1PSBlue.svg │ ├── Rogan1PSBlue_fg.svg │ ├── Rogan1PSGreen.svg │ ├── Rogan1PSGreen_fg.svg │ ├── Rogan1PSRed.svg │ ├── Rogan1PSRed_fg.svg │ ├── Rogan1PSWhite.svg │ ├── Rogan1PSWhite_fg.svg │ ├── Rogan1PS_bg.svg │ ├── Rogan1PWhite.svg │ ├── Rogan1PWhite_fg.svg │ ├── Rogan1P_bg.svg │ ├── Rogan2PBlue.svg │ ├── Rogan2PBlue_fg.svg │ ├── Rogan2PGreen.svg │ ├── Rogan2PGreen_fg.svg │ ├── Rogan2PRed.svg │ ├── Rogan2PRed_fg.svg │ ├── Rogan2PSBlue.svg │ ├── Rogan2PSBlue_fg.svg │ ├── Rogan2PSGreen.svg │ ├── Rogan2PSGreen_fg.svg │ ├── Rogan2PSRed.svg │ ├── Rogan2PSRed_fg.svg │ ├── Rogan2PSWhite.svg │ ├── Rogan2PSWhite_fg.svg │ ├── Rogan2PS_bg.svg │ ├── Rogan2PWhite.svg │ ├── Rogan2PWhite_fg.svg │ ├── Rogan2P_bg.svg │ ├── Rogan2SGray.svg │ ├── Rogan2SGray_fg.svg │ ├── Rogan2S_bg.svg │ ├── Rogan3PBlue.svg │ ├── Rogan3PBlue_fg.svg │ ├── Rogan3PGreen.svg │ ├── Rogan3PGreen_fg.svg │ ├── Rogan3PRed.svg │ ├── Rogan3PRed_fg.svg │ ├── Rogan3PSBlue.svg │ ├── Rogan3PSBlue_fg.svg │ ├── Rogan3PSGreen.svg │ ├── Rogan3PSGreen_fg.svg │ ├── Rogan3PSRed.svg │ ├── Rogan3PSRed_fg.svg │ ├── Rogan3PSWhite.svg │ ├── Rogan3PSWhite_fg.svg │ ├── Rogan3PS_bg.svg │ ├── Rogan3PWhite.svg │ ├── Rogan3PWhite_fg.svg │ ├── Rogan3P_bg.svg │ ├── Rogan5PSGray.svg │ ├── Rogan5PSGray_fg.svg │ ├── Rogan5PS_bg.svg │ ├── Rogan6PSWhite.svg │ ├── Rogan6PSWhite_fg.svg │ ├── Rogan6PS_bg.svg │ ├── RoundBigBlackKnob.svg │ ├── RoundBigBlackKnob_bg.svg │ ├── RoundBlackKnob.svg │ ├── RoundBlackKnob_bg.svg │ ├── RoundHugeBlackKnob.svg │ ├── RoundHugeBlackKnob_bg.svg │ ├── RoundLargeBlackKnob.svg │ ├── RoundLargeBlackKnob_bg.svg │ ├── RoundSmallBlackKnob.svg │ ├── RoundSmallBlackKnob_bg.svg │ ├── ScrewBlack.svg │ ├── ScrewSilver.svg │ ├── SmallLight.svg │ ├── SynthTechAlco.svg │ ├── SynthTechAlco_bg.svg │ ├── TL1105_0.svg │ ├── TL1105_1.svg │ ├── TinyLight.svg │ ├── Trimpot.svg │ ├── Trimpot_bg.svg │ ├── USB_B.svg │ ├── VCVBezel.svg │ ├── VCVButton_0.svg │ ├── VCVButton_1.svg │ ├── VCVSlider.svg │ ├── VCVSliderHandle.svg │ └── VCVSliderLight.svg ├── Core │ ├── Audio16-dark.svg │ ├── Audio16.svg │ ├── Audio2-dark.svg │ ├── Audio2.svg │ ├── Audio8-dark.svg │ ├── Audio8.svg │ ├── CV_MIDI-dark.svg │ ├── CV_MIDI.svg │ ├── CV_MIDICC-dark.svg │ ├── CV_MIDICC.svg │ ├── Gate_MIDI-dark.svg │ ├── Gate_MIDI.svg │ ├── MIDICC_CV-dark.svg │ ├── MIDICC_CV.svg │ ├── MIDIMap-dark.svg │ ├── MIDIMap.svg │ ├── MIDI_CV-dark.svg │ ├── MIDI_CV.svg │ ├── MIDI_Gate-dark.svg │ ├── MIDI_Gate.svg │ ├── Notes-dark.svg │ └── Notes.svg ├── fonts │ ├── DSEG-LICENSE.txt │ ├── DSEG7ClassicMini-Bold.ttf │ ├── DSEG7ClassicMini-BoldItalic.ttf │ ├── DSEG7ClassicMini-Italic.ttf │ ├── DSEG7ClassicMini-Light.ttf │ ├── DSEG7ClassicMini-LightItalic.ttf │ ├── DSEG7ClassicMini-Regular.ttf │ ├── DejaVuSans-LICENSE.txt │ ├── DejaVuSans.ttf │ ├── Noto-LICENSE.txt │ ├── NotoEmoji-Medium.ttf │ ├── NotoSansJP-Medium.otf │ ├── NotoSansSC-Medium.otf │ ├── Nunito-Bold.ttf │ ├── Nunito-LICENSE.txt │ ├── ShareTechMono-Regular-LICENSE.txt │ └── ShareTechMono-Regular.ttf └── icon.png ├── src ├── Quantity.cpp ├── app │ ├── AudioDisplay.cpp │ ├── Browser.cpp │ ├── CableWidget.cpp │ ├── CircularShadow.cpp │ ├── Knob.cpp │ ├── LedDisplay.cpp │ ├── LightWidget.cpp │ ├── MenuBar.cpp │ ├── MidiDisplay.cpp │ ├── ModuleLightWidget.cpp │ ├── ModuleWidget.cpp │ ├── MultiLightWidget.cpp │ ├── ParamWidget.cpp │ ├── PortWidget.cpp │ ├── RackScrollWidget.cpp │ ├── RackWidget.cpp │ ├── RailWidget.cpp │ ├── Scene.cpp │ ├── SliderKnob.cpp │ ├── SvgButton.cpp │ ├── SvgKnob.cpp │ ├── SvgPanel.cpp │ ├── SvgPort.cpp │ ├── SvgScrew.cpp │ ├── SvgSlider.cpp │ ├── SvgSwitch.cpp │ ├── Switch.cpp │ └── TipWindow.cpp ├── asset.cpp ├── asset.mm ├── audio.cpp ├── color.cpp ├── common.cpp ├── context.cpp ├── core │ ├── Audio.cpp │ ├── Blank.cpp │ ├── CV_MIDI.cpp │ ├── CV_MIDICC.cpp │ ├── Gate_MIDI.cpp │ ├── MIDICC_CV.cpp │ ├── MIDIMap.cpp │ ├── MIDI_CV.cpp │ ├── MIDI_Gate.cpp │ ├── Notes.cpp │ ├── plugin.cpp │ └── plugin.hpp ├── dep.cpp ├── dsp │ └── minblep.cpp ├── engine │ ├── Cable.cpp │ ├── Engine.cpp │ ├── LightInfo.cpp │ ├── Module.cpp │ ├── ParamQuantity.cpp │ └── PortInfo.cpp ├── gamepad.cpp ├── history.cpp ├── keyboard.cpp ├── library.cpp ├── logger.cpp ├── midi.cpp ├── midiloopback.cpp ├── network.cpp ├── patch.cpp ├── plugin.cpp ├── plugin │ ├── Model.cpp │ └── Plugin.cpp ├── random.cpp ├── rtaudio.cpp ├── rtaudio.mm ├── rtmidi.cpp ├── settings.cpp ├── string.cpp ├── system.cpp ├── tag.cpp ├── ui │ ├── Button.cpp │ ├── ChoiceButton.cpp │ ├── Label.cpp │ ├── List.cpp │ ├── Menu.cpp │ ├── MenuEntry.cpp │ ├── MenuItem.cpp │ ├── MenuLabel.cpp │ ├── MenuOverlay.cpp │ ├── MenuSeparator.cpp │ ├── OptionButton.cpp │ ├── ProgressBar.cpp │ ├── RadioButton.cpp │ ├── ScrollWidget.cpp │ ├── Scrollbar.cpp │ ├── SequentialLayout.cpp │ ├── Slider.cpp │ ├── TextField.cpp │ ├── Tooltip.cpp │ └── common.cpp ├── widget │ ├── FramebufferWidget.cpp │ ├── OpenGlWidget.cpp │ ├── SvgWidget.cpp │ ├── Widget.cpp │ ├── ZoomWidget.cpp │ └── event.cpp └── window │ ├── Svg.cpp │ └── Window.cpp ├── template.vcv ├── translations ├── de.json ├── en.json ├── es.json ├── fr.json ├── it.json ├── ja.json └── zh.json └── valgrind.supp /.astylerc: -------------------------------------------------------------------------------- 1 | # astyle settings file 2 | 3 | # Requires Artistic Style 3.1 4 | # http://astyle.sourceforge.net/ 5 | 6 | # Usage: 7 | # astyle --suffix=none --options=.astylerc filename.cpp 8 | # or recursively 9 | # astyle --suffix=none --options=.astylerc -r 'include/*' 'src/*' 10 | # or using find 11 | # find src include -type f | xargs astyle --suffix=none --options=.astylerc 12 | 13 | style=java 14 | indent=tab=2 15 | attach-closing-while 16 | indent-switches 17 | indent-preproc-block 18 | indent-preproc-define 19 | indent-col1-comments 20 | pad-oper 21 | pad-comma 22 | pad-header 23 | unpad-paren 24 | align-pointer=type 25 | align-reference=type 26 | break-closing-braces 27 | break-one-line-headers 28 | attach-return-type 29 | attach-return-type-decl 30 | keep-one-line-statements 31 | close-templates 32 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | 2 | VCV Rack is [open-source](https://opensource.org/osd) and [free software](https://www.gnu.org/philosophy/free-sw.en.html) but not open-contribution. 3 | VCV is unable to accept outside code contributions to Rack itself. 4 | 5 | However there are several ways you can be involved in the Rack project. 6 | - Answer questions in the [VCV communities](https://vcvrack.com/manual/Communities). 7 | - [Develop your own Rack plugin](https://vcvrack.com/manual/PluginDevelopmentTutorial), or help maintain an existing plugin. 8 | - Apply for a [job at VCV](https://vcvrack.com/jobs). 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore all dotfiles except git dotfiles 2 | .* 3 | !.git* 4 | 5 | # Binaries and build targets 6 | *.a 7 | *.so 8 | *.dylib 9 | *.dll 10 | *.exe 11 | *.res 12 | *.d 13 | *.dSYM 14 | *.vcvplugin 15 | /build 16 | /Rack 17 | /dep 18 | /dist 19 | 20 | # Rack folders 21 | /plugins 22 | /disabledplugins 23 | /patches 24 | /presets 25 | /licenses 26 | /autosave 27 | /settings.json 28 | /screenshots 29 | /selections 30 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "dep/nanovg"] 2 | path = dep/nanovg 3 | url = https://github.com/VCVRack/nanovg.git 4 | ignore = untracked 5 | [submodule "dep/nanosvg"] 6 | path = dep/nanosvg 7 | url = https://github.com/memononen/nanosvg.git 8 | ignore = untracked 9 | [submodule "dep/osdialog"] 10 | path = dep/osdialog 11 | url = https://github.com/AndrewBelt/osdialog.git 12 | ignore = untracked 13 | [submodule "dep/oui-blendish"] 14 | path = dep/oui-blendish 15 | url = https://github.com/VCVRack/oui-blendish.git 16 | ignore = untracked 17 | [submodule "dep/rtaudio"] 18 | path = dep/rtaudio 19 | url = https://github.com/VCVRack/rtaudio.git 20 | ignore = untracked 21 | [submodule "dep/glfw"] 22 | path = dep/glfw 23 | url = https://github.com/VCVRack/glfw.git 24 | ignore = untracked 25 | [submodule "dep/fuzzysearchdatabase"] 26 | path = dep/fuzzysearchdatabase 27 | url = https://bitbucket.org/j_norberg/fuzzysearchdatabase.git 28 | [submodule "dep/filesystem"] 29 | path = dep/filesystem 30 | url = https://github.com/gulrak/filesystem.git 31 | [submodule "dep/pffft"] 32 | path = dep/pffft 33 | url = https://bitbucket.org/jpommier/pffft.git 34 | [submodule "dep/rtmidi"] 35 | path = dep/rtmidi 36 | url = https://github.com/VCVRack/rtmidi.git 37 | [submodule "dep/tinyexpr"] 38 | path = dep/tinyexpr 39 | url = https://github.com/codeplea/tinyexpr.git 40 | [submodule "dep/speexdsp"] 41 | path = dep/speexdsp 42 | url = https://gitlab.xiph.org/xiph/speexdsp.git 43 | ignore = untracked 44 | [submodule "dep/simde"] 45 | path = dep/simde 46 | url = https://github.com/simd-everywhere/simde.git 47 | -------------------------------------------------------------------------------- /Component.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | BundleHasStrictIdentifier 7 | BundleIsVersionChecked 8 | BundleIsRelocatable 9 | BundleOverwriteActionupgrade 10 | RootRelativeBundlePathVCV Rack 2 Free.app 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Distribution.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | VCV Rack 2 Free 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | Component.pkg 20 | -------------------------------------------------------------------------------- /Entitlements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.get-task-allow 6 | com.apple.security.cs.allow-jit 7 | com.apple.security.cs.allow-unsigned-executable-memory 8 | com.apple.security.cs.disable-executable-page-protection 9 | com.apple.security.cs.disable-library-validation 10 | com.apple.security.device.audio-input 11 | com.apple.security.device.camera 12 | 13 | 14 | -------------------------------------------------------------------------------- /Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleInfoDictionaryVersion6.0 6 | CFBundleDevelopmentRegionEnglish 7 | CFBundleNameVCV Rack 2 Free 8 | CFBundleDisplayNameVCV Rack 2 Free 9 | CFBundleIdentifiercom.vcvrack.rack2 10 | CFBundleVersion{RACK_VERSION} 11 | CFBundlePackageTypeAPPL 12 | CFBundleSignatureRACK 13 | CFBundleExecutableRack 14 | CFBundleIconFileicon 15 | CFBundleShortVersionString{RACK_VERSION} 16 | NSHumanReadableCopyrightCopyright © VCV 17 | NSPrincipalClassNSApplication 18 | NSHighResolutionCapable 19 | NSMicrophoneUsageDescriptionThis is required for using line input from audio interfaces. 20 | 21 | CFBundleDocumentTypes 22 | 23 | 24 | CFBundleTypeExtensions 25 | 26 | vcv 27 | 28 | CFBundleTypeIconFileicon.icns 29 | CFBundleTypeNameVCV Rack Patch 30 | CFBundleTypeRoleEditor 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /Rack.rc: -------------------------------------------------------------------------------- 1 | GLFW_ICON ICON icon.ico -------------------------------------------------------------------------------- /arch.mk: -------------------------------------------------------------------------------- 1 | ifdef CROSS_COMPILE 2 | MACHINE := $(CROSS_COMPILE) 3 | else 4 | MACHINE ?= $(shell $(CC) -dumpmachine) 5 | endif 6 | 7 | ifneq (,$(findstring x86_64-,$(MACHINE))) 8 | ARCH_X64 := 1 9 | ARCH_CPU := x64 10 | else ifneq (,$(findstring arm64-,$(MACHINE))) 11 | ARCH_ARM64 := 1 12 | ARCH_CPU := arm64 13 | else ifneq (,$(findstring aarch64-,$(MACHINE))) 14 | ARCH_ARM64 := 1 15 | ARCH_CPU := arm64 16 | else 17 | $(error Could not determine CPU architecture of $(MACHINE)) 18 | endif 19 | 20 | ifneq (,$(findstring -darwin,$(MACHINE))) 21 | ARCH_MAC := 1 22 | ARCH_OS := mac 23 | else ifneq (,$(findstring -mingw32,$(MACHINE))) 24 | ARCH_WIN := 1 25 | ARCH_OS := win 26 | else ifneq (,$(findstring -linux,$(MACHINE))) 27 | ARCH_LIN := 1 28 | ARCH_OS := lin 29 | else 30 | $(error Could not determine operating system of $(MACHINE)) 31 | endif 32 | 33 | ARCH_NAME = $(ARCH_OS)-$(ARCH_CPU) 34 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | /html -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | 2 | all: doxygen 3 | 4 | doxygen: 5 | doxygen Doxyfile 6 | # Fix 700 and 500 permissions that Doxygen generates for some reason 7 | find html -type d -exec chmod 755 {} \; 8 | find html -type f -exec chmod 644 {} \; 9 | 10 | run: doxygen 11 | http-server html 12 | 13 | upload: doxygen 14 | rsync html/ vcvrack.com:docs-v2/ -ruz --info=progress2 --delete 15 | 16 | clean: 17 | rm -rfv html 18 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | This documentation is generated by [Doxygen](https://www.doxygen.nl/index.html) as a convenience to Rack plugin developers and might not include certain functions, macros, and structures that are present in header files. 2 | It is therefore recommended to refer to Rack's header files as a true reference. 3 | -------------------------------------------------------------------------------- /docs/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VCVRack/Rack/768d859187d64aed4d3d3db1f9c3aef596676116/docs/logo.png -------------------------------------------------------------------------------- /icon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VCVRack/Rack/768d859187d64aed4d3d3db1f9c3aef596676116/icon.icns -------------------------------------------------------------------------------- /icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VCVRack/Rack/768d859187d64aed4d3d3db1f9c3aef596676116/icon.ico -------------------------------------------------------------------------------- /include/app/AudioDisplay.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | 9 | namespace rack { 10 | namespace app { 11 | 12 | 13 | struct AudioDriverChoice : LedDisplayChoice { 14 | audio::Port* port; 15 | void onAction(const ActionEvent& e) override; 16 | void step() override; 17 | }; 18 | 19 | 20 | struct AudioDeviceChoice : LedDisplayChoice { 21 | audio::Port* port; 22 | void onAction(const ActionEvent& e) override; 23 | void step() override; 24 | }; 25 | 26 | 27 | struct AudioSampleRateChoice : LedDisplayChoice { 28 | audio::Port* port; 29 | void onAction(const ActionEvent& e) override; 30 | void step() override; 31 | }; 32 | 33 | 34 | struct AudioBlockSizeChoice : LedDisplayChoice { 35 | audio::Port* port; 36 | void onAction(const ActionEvent& e) override; 37 | void step() override; 38 | }; 39 | 40 | 41 | struct AudioDeviceMenuChoice : AudioDeviceChoice { 42 | void onAction(const ActionEvent& e) override; 43 | }; 44 | 45 | 46 | /** Designed for Audio-8 and Audio-16 module. */ 47 | struct AudioDisplay : LedDisplay { 48 | AudioDriverChoice* driverChoice; 49 | LedDisplaySeparator* driverSeparator; 50 | AudioDeviceChoice* deviceChoice; 51 | LedDisplaySeparator* deviceSeparator; 52 | AudioSampleRateChoice* sampleRateChoice; 53 | LedDisplaySeparator* sampleRateSeparator; 54 | AudioBlockSizeChoice* bufferSizeChoice; 55 | void setAudioPort(audio::Port* port); 56 | }; 57 | 58 | 59 | /** A virtual audio port graphic that displays an audio menu when clicked. */ 60 | struct AudioButton : SvgButton { 61 | audio::Port* port; 62 | void setAudioPort(audio::Port* port); 63 | void onAction(const ActionEvent& e) override; 64 | }; 65 | 66 | 67 | /** Appends menu items to the given menu with driver, device, etc. 68 | Useful alternative to putting an AudioDisplay on your module's panel. 69 | */ 70 | void appendAudioMenu(ui::Menu* menu, audio::Port* port); 71 | 72 | 73 | } // namespace app 74 | } // namespace rack 75 | -------------------------------------------------------------------------------- /include/app/Browser.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | 6 | namespace rack { 7 | namespace app { 8 | 9 | 10 | PRIVATE void browserInit(); 11 | PRIVATE widget::Widget* browserCreate(); 12 | 13 | 14 | } // namespace app 15 | } // namespace rack 16 | -------------------------------------------------------------------------------- /include/app/CircularShadow.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | 6 | namespace rack { 7 | namespace app { 8 | 9 | 10 | struct CircularShadow : widget::TransparentWidget { 11 | float blurRadius; 12 | float opacity; 13 | 14 | CircularShadow(); 15 | void draw(const DrawArgs& args) override; 16 | }; 17 | 18 | 19 | } // namespace app 20 | } // namespace rack 21 | -------------------------------------------------------------------------------- /include/app/Knob.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | 7 | namespace rack { 8 | namespace app { 9 | 10 | 11 | /** Implements vertical dragging behavior for ParamWidgets */ 12 | struct Knob : ParamWidget { 13 | struct Internal; 14 | Internal* internal; 15 | 16 | /** Drag horizontally instead of vertically. */ 17 | bool horizontal = false; 18 | /** Enables per-sample value smoothing while dragging. 19 | Alternatively, use ParamQuantity::smoothEnabled. 20 | */ 21 | bool smooth = true; 22 | /** Enables value snapping to the nearest integer. 23 | Alternatively, use ParamQuantity::snapEnabled. 24 | */ 25 | bool snap = false; 26 | /** Multiplier for mouse movement to adjust knob value */ 27 | float speed = 1.f; 28 | /** Force dragging to linear, e.g. for sliders. */ 29 | bool forceLinear = false; 30 | /** Angles in radians. 31 | For drawing and handling the global radial knob setting. 32 | */ 33 | float minAngle = -M_PI; 34 | float maxAngle = M_PI; 35 | 36 | Knob(); 37 | ~Knob(); 38 | void initParamQuantity() override; 39 | void onHover(const HoverEvent& e) override; 40 | void onButton(const ButtonEvent& e) override; 41 | void onDragStart(const DragStartEvent& e) override; 42 | void onDragEnd(const DragEndEvent& e) override; 43 | void onDragMove(const DragMoveEvent& e) override; 44 | void onDragLeave(const DragLeaveEvent& e) override; 45 | void onHoverScroll(const HoverScrollEvent& e) override; 46 | void onLeave(const LeaveEvent& e) override; 47 | /** Called when user clicks the knob without moving it. 48 | Useful for handling emulating push-knobs in hardware. 49 | */ 50 | void onAction(const ActionEvent& e) override {} 51 | }; 52 | 53 | 54 | } // namespace app 55 | } // namespace rack 56 | -------------------------------------------------------------------------------- /include/app/LedDisplay.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | 8 | namespace rack { 9 | namespace app { 10 | 11 | 12 | struct LedDisplay : widget::Widget { 13 | void draw(const DrawArgs& args) override; 14 | void drawLayer(const DrawArgs& args, int layer) override; 15 | }; 16 | 17 | struct LedDisplaySeparator : widget::Widget { 18 | LedDisplaySeparator(); 19 | void draw(const DrawArgs& args) override; 20 | }; 21 | 22 | struct LedDisplayChoice : widget::OpaqueWidget { 23 | std::string text; 24 | std::string fontPath; 25 | math::Vec textOffset; 26 | NVGcolor color; 27 | NVGcolor bgColor; 28 | LedDisplayChoice(); 29 | void draw(const DrawArgs& args) override; 30 | void drawLayer(const DrawArgs& args, int layer) override; 31 | void onButton(const ButtonEvent& e) override; 32 | }; 33 | 34 | struct LedDisplayTextField : ui::TextField { 35 | std::string fontPath; 36 | math::Vec textOffset; 37 | NVGcolor color; 38 | NVGcolor bgColor; 39 | LedDisplayTextField(); 40 | void draw(const DrawArgs& args) override; 41 | void drawLayer(const DrawArgs& args, int layer) override; 42 | int getTextPosition(math::Vec mousePos) override; 43 | }; 44 | 45 | 46 | } // namespace app 47 | } // namespace rack 48 | -------------------------------------------------------------------------------- /include/app/LightWidget.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | 6 | namespace rack { 7 | namespace app { 8 | 9 | 10 | struct LightWidget : widget::TransparentWidget { 11 | NVGcolor bgColor = nvgRGBA(0, 0, 0, 0); 12 | NVGcolor color = nvgRGBA(0, 0, 0, 0); 13 | NVGcolor borderColor = nvgRGBA(0, 0, 0, 0); 14 | 15 | void draw(const DrawArgs& args) override; 16 | void drawLayer(const DrawArgs& args, int layer) override; 17 | virtual void drawBackground(const DrawArgs& args); 18 | virtual void drawLight(const DrawArgs& args); 19 | virtual void drawHalo(const DrawArgs& args); 20 | }; 21 | 22 | 23 | } // namespace app 24 | } // namespace rack 25 | -------------------------------------------------------------------------------- /include/app/MenuBar.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | 7 | namespace rack { 8 | namespace app { 9 | 10 | 11 | PRIVATE widget::Widget* createMenuBar(); 12 | PRIVATE void appendLanguageMenu(ui::Menu* menu); 13 | 14 | 15 | } // namespace app 16 | } // namespace rack 17 | -------------------------------------------------------------------------------- /include/app/MidiDisplay.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | 9 | namespace rack { 10 | namespace app { 11 | 12 | 13 | struct MidiDriverChoice : LedDisplayChoice { 14 | midi::Port* port; 15 | void onAction(const ActionEvent& e) override; 16 | void step() override; 17 | }; 18 | 19 | 20 | struct MidiDeviceChoice : LedDisplayChoice { 21 | midi::Port* port; 22 | void onAction(const ActionEvent& e) override; 23 | void step() override; 24 | }; 25 | 26 | 27 | struct MidiChannelChoice : LedDisplayChoice { 28 | midi::Port* port; 29 | void onAction(const ActionEvent& e) override; 30 | void step() override; 31 | }; 32 | 33 | 34 | struct MidiDisplay : LedDisplay { 35 | MidiDriverChoice* driverChoice; 36 | LedDisplaySeparator* driverSeparator; 37 | MidiDeviceChoice* deviceChoice; 38 | LedDisplaySeparator* deviceSeparator; 39 | MidiChannelChoice* channelChoice; 40 | void setMidiPort(midi::Port* port); 41 | }; 42 | 43 | 44 | /** A virtual MIDI port graphic that displays an MIDI menu when clicked. */ 45 | struct MidiButton : SvgButton { 46 | midi::Port* port; 47 | void setMidiPort(midi::Port* port); 48 | void onAction(const ActionEvent& e) override; 49 | }; 50 | 51 | 52 | /** Appends menu items to the given menu with driver, device, etc. 53 | Useful alternative to putting a MidiDisplay on your module's panel. 54 | */ 55 | void appendMidiMenu(ui::Menu* menu, midi::Port* port); 56 | 57 | 58 | } // namespace app 59 | } // namespace rack 60 | -------------------------------------------------------------------------------- /include/app/ModuleLightWidget.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | 8 | namespace rack { 9 | namespace app { 10 | 11 | 12 | /** A MultiLightWidget that points to a module's Light or a range of lights 13 | Will access firstLightId, firstLightId + 1, etc. for each added color 14 | */ 15 | struct ModuleLightWidget : MultiLightWidget { 16 | struct Internal; 17 | Internal* internal; 18 | 19 | engine::Module* module = NULL; 20 | int firstLightId = -1; 21 | 22 | ModuleLightWidget(); 23 | ~ModuleLightWidget(); 24 | engine::Light* getLight(int colorId); 25 | engine::LightInfo* getLightInfo(); 26 | void createTooltip(); 27 | void destroyTooltip(); 28 | 29 | void step() override; 30 | void onHover(const HoverEvent& e) override; 31 | void onEnter(const EnterEvent& e) override; 32 | void onLeave(const LeaveEvent& e) override; 33 | }; 34 | 35 | 36 | } // namespace app 37 | } // namespace rack 38 | -------------------------------------------------------------------------------- /include/app/MultiLightWidget.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | 6 | namespace rack { 7 | namespace app { 8 | 9 | 10 | /** Mixes a list of colors based on a list of brightness values */ 11 | struct MultiLightWidget : LightWidget { 12 | /** Colors of each value state */ 13 | std::vector baseColors; 14 | 15 | int getNumColors(); 16 | void addBaseColor(NVGcolor baseColor); 17 | /** Sets the color to a linear combination of the baseColors with the given weights */ 18 | void setBrightnesses(const std::vector& brightnesses); 19 | }; 20 | 21 | 22 | } // namespace app 23 | } // namespace rack 24 | -------------------------------------------------------------------------------- /include/app/ParamWidget.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | 9 | namespace rack { 10 | namespace app { 11 | 12 | 13 | /** Manages an engine::Param on a ModuleWidget. */ 14 | struct ParamWidget : widget::OpaqueWidget { 15 | struct Internal; 16 | Internal* internal; 17 | 18 | engine::Module* module = NULL; 19 | int paramId = -1; 20 | 21 | ParamWidget(); 22 | ~ParamWidget(); 23 | /** Configures ParamQuantity properties based on the type of ParamWidget. 24 | This seems a bit hacky, but it's easier than requiring plugin developers to set `ParamQuantity::randomizeEnabled`, etc. 25 | */ 26 | virtual void initParamQuantity() {} 27 | engine::ParamQuantity* getParamQuantity(); 28 | void createTooltip(); 29 | void destroyTooltip(); 30 | 31 | void step() override; 32 | void draw(const DrawArgs& args) override; 33 | 34 | void onButton(const ButtonEvent& e) override; 35 | void onDoubleClick(const DoubleClickEvent& e) override; 36 | void onEnter(const EnterEvent& e) override; 37 | void onLeave(const LeaveEvent& e) override; 38 | 39 | void createContextMenu(); 40 | /** Override to add custom menu items at the bottom of the parameter context menu. 41 | It is recommended to add a MenuSeparator before other menu items. 42 | 43 | menu->addChild(new MenuSeparator); 44 | */ 45 | virtual void appendContextMenu(ui::Menu* menu) {} 46 | void resetAction(); 47 | }; 48 | 49 | 50 | } // namespace app 51 | } // namespace rack 52 | -------------------------------------------------------------------------------- /include/app/PortWidget.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | 9 | namespace rack { 10 | namespace app { 11 | 12 | 13 | /** Manages an engine::Port on a ModuleWidget. */ 14 | struct PortWidget : widget::OpaqueWidget { 15 | struct Internal; 16 | Internal* internal; 17 | 18 | engine::Module* module = NULL; 19 | engine::Port::Type type = engine::Port::INPUT; 20 | int portId = -1; 21 | 22 | PortWidget(); 23 | ~PortWidget(); 24 | engine::Port* getPort(); 25 | engine::PortInfo* getPortInfo(); 26 | void createTooltip(); 27 | void destroyTooltip(); 28 | void createContextMenu(); 29 | virtual void appendContextMenu(ui::Menu* menu) {} 30 | void deleteTopCableAction(); 31 | 32 | void step() override; 33 | void draw(const DrawArgs& args) override; 34 | 35 | void onButton(const ButtonEvent& e) override; 36 | void onEnter(const EnterEvent& e) override; 37 | void onLeave(const LeaveEvent& e) override; 38 | void onDragStart(const DragStartEvent& e) override; 39 | void onDragEnd(const DragEndEvent& e) override; 40 | void onDragDrop(const DragDropEvent& e) override; 41 | void onDragEnter(const DragEnterEvent& e) override; 42 | void onDragLeave(const DragLeaveEvent& e) override; 43 | }; 44 | 45 | 46 | } // namespace app 47 | } // namespace rack 48 | -------------------------------------------------------------------------------- /include/app/RackScrollWidget.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | 8 | namespace rack { 9 | namespace app { 10 | 11 | 12 | struct RackScrollWidget : ui::ScrollWidget { 13 | struct Internal; 14 | Internal* internal; 15 | 16 | widget::ZoomWidget* zoomWidget; 17 | RackWidget* rackWidget; 18 | 19 | PRIVATE RackScrollWidget(); 20 | PRIVATE ~RackScrollWidget(); 21 | 22 | void reset(); 23 | /** Gets the top-left scroll offset in grid coordinates. 24 | */ 25 | math::Vec getGridOffset(); 26 | void setGridOffset(math::Vec gridOffset); 27 | float getZoom(); 28 | /** Sets the zoom level, with a pivot at the center of the scroll viewport. 29 | */ 30 | void setZoom(float zoom); 31 | void setZoom(float zoom, math::Vec pivot); 32 | /** Sets offset and zoom to fit module bounding box to view. */ 33 | void zoomToModules(); 34 | /** Sets offset and zoom to fit given bound (in module coordinates) to view. */ 35 | void zoomToBound(math::Rect bound); 36 | 37 | void step() override; 38 | void draw(const DrawArgs& args) override; 39 | void onHoverKey(const HoverKeyEvent& e) override; 40 | void onHoverScroll(const HoverScrollEvent& e) override; 41 | void onHover(const HoverEvent& e) override; 42 | void onButton(const ButtonEvent& e) override; 43 | }; 44 | 45 | 46 | } // namespace app 47 | } // namespace rack 48 | -------------------------------------------------------------------------------- /include/app/RailWidget.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | 6 | namespace rack { 7 | namespace app { 8 | 9 | 10 | struct RailWidget : widget::TransparentWidget { 11 | struct Internal; 12 | Internal* internal; 13 | 14 | RailWidget(); 15 | ~RailWidget(); 16 | void step() override; 17 | void draw(const DrawArgs& args) override; 18 | }; 19 | 20 | 21 | } // namespace app 22 | } // namespace rack 23 | -------------------------------------------------------------------------------- /include/app/Scene.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | 8 | namespace rack { 9 | namespace app { 10 | 11 | 12 | struct Scene : widget::OpaqueWidget { 13 | struct Internal; 14 | Internal* internal; 15 | 16 | // Convenience variables for accessing important widgets 17 | RackScrollWidget* rackScroll; 18 | RackWidget* rack; 19 | widget::Widget* menuBar; 20 | widget::Widget* browser; 21 | 22 | /** The last mouse position in the Scene. 23 | DEPRECATED. Use getMousePos() instead. 24 | */ 25 | math::Vec mousePos; 26 | 27 | PRIVATE Scene(); 28 | PRIVATE ~Scene(); 29 | math::Vec getMousePos(); 30 | void step() override; 31 | void draw(const DrawArgs& args) override; 32 | void onHover(const HoverEvent& e) override; 33 | void onDragHover(const DragHoverEvent& e) override; 34 | void onHoverKey(const HoverKeyEvent& e) override; 35 | void onPathDrop(const PathDropEvent& e) override; 36 | }; 37 | 38 | 39 | } // namespace app 40 | } // namespace rack 41 | -------------------------------------------------------------------------------- /include/app/SliderKnob.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | 6 | namespace rack { 7 | namespace app { 8 | 9 | 10 | struct SliderKnob : Knob { 11 | SliderKnob(); 12 | 13 | void onHover(const HoverEvent& e) override; 14 | void onButton(const ButtonEvent& e) override; 15 | }; 16 | 17 | 18 | } // namespace app 19 | } // namespace rack 20 | -------------------------------------------------------------------------------- /include/app/SvgButton.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | 9 | namespace rack { 10 | namespace app { 11 | 12 | 13 | struct SvgButton : widget::OpaqueWidget { 14 | widget::FramebufferWidget* fb; 15 | CircularShadow* shadow; 16 | widget::SvgWidget* sw; 17 | std::vector> frames; 18 | 19 | SvgButton(); 20 | void addFrame(std::shared_ptr svg); 21 | void onButton(const ButtonEvent& e) override; 22 | void onDragStart(const DragStartEvent& e) override; 23 | void onDragEnd(const DragEndEvent& e) override; 24 | void onDragDrop(const DragDropEvent& e) override; 25 | }; 26 | 27 | 28 | DEPRECATED typedef SvgButton SVGButton; 29 | 30 | 31 | } // namespace app 32 | } // namespace rack 33 | -------------------------------------------------------------------------------- /include/app/SvgKnob.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | 10 | namespace rack { 11 | namespace app { 12 | 13 | 14 | /** A knob which rotates an SVG and caches it in a framebuffer */ 15 | struct SvgKnob : Knob { 16 | widget::FramebufferWidget* fb; 17 | CircularShadow* shadow; 18 | widget::TransformWidget* tw; 19 | widget::SvgWidget* sw; 20 | 21 | SvgKnob(); 22 | void setSvg(std::shared_ptr svg); 23 | DEPRECATED void setSVG(std::shared_ptr svg) { 24 | setSvg(svg); 25 | } 26 | void onChange(const ChangeEvent& e) override; 27 | }; 28 | 29 | 30 | DEPRECATED typedef SvgKnob SVGKnob; 31 | 32 | 33 | } // namespace app 34 | } // namespace rack 35 | -------------------------------------------------------------------------------- /include/app/SvgPanel.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | 9 | namespace rack { 10 | namespace app { 11 | 12 | 13 | struct PanelBorder : widget::TransparentWidget { 14 | void draw(const DrawArgs& args) override; 15 | }; 16 | 17 | 18 | struct SvgPanel : widget::Widget { 19 | widget::FramebufferWidget* fb; 20 | widget::SvgWidget* sw; 21 | PanelBorder* panelBorder; 22 | std::shared_ptr svg; 23 | 24 | SvgPanel(); 25 | void step() override; 26 | void setBackground(std::shared_ptr svg); 27 | }; 28 | 29 | 30 | DEPRECATED typedef SvgPanel SVGPanel; 31 | 32 | 33 | struct ThemedSvgPanel : SvgPanel { 34 | std::shared_ptr lightSvg; 35 | std::shared_ptr darkSvg; 36 | 37 | void setBackground(std::shared_ptr lightSvg, std::shared_ptr darkSvg) { 38 | this->lightSvg = lightSvg; 39 | this->darkSvg = darkSvg; 40 | SvgPanel::setBackground(settings::preferDarkPanels ? darkSvg : lightSvg); 41 | } 42 | 43 | void step() override { 44 | SvgPanel::setBackground(settings::preferDarkPanels ? darkSvg : lightSvg); 45 | SvgPanel::step(); 46 | } 47 | }; 48 | 49 | 50 | } // namespace app 51 | } // namespace rack 52 | -------------------------------------------------------------------------------- /include/app/SvgPort.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | 10 | namespace rack { 11 | namespace app { 12 | 13 | 14 | struct SvgPort : PortWidget { 15 | widget::FramebufferWidget* fb; 16 | CircularShadow* shadow; 17 | widget::SvgWidget* sw; 18 | 19 | SvgPort(); 20 | void setSvg(std::shared_ptr svg); 21 | DEPRECATED void setSVG(std::shared_ptr svg) { 22 | setSvg(svg); 23 | } 24 | }; 25 | 26 | 27 | DEPRECATED typedef SvgPort SVGPort; 28 | 29 | 30 | struct ThemedSvgPort : SvgPort { 31 | std::shared_ptr lightSvg; 32 | std::shared_ptr darkSvg; 33 | 34 | void setSvg(std::shared_ptr lightSvg, std::shared_ptr darkSvg) { 35 | this->lightSvg = lightSvg; 36 | this->darkSvg = darkSvg; 37 | SvgPort::setSvg(settings::preferDarkPanels ? darkSvg : lightSvg); 38 | } 39 | 40 | void step() override { 41 | SvgPort::setSvg(settings::preferDarkPanels ? darkSvg : lightSvg); 42 | SvgPort::step(); 43 | } 44 | }; 45 | 46 | 47 | } // namespace app 48 | } // namespace rack 49 | -------------------------------------------------------------------------------- /include/app/SvgScrew.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | 9 | namespace rack { 10 | namespace app { 11 | 12 | 13 | /** If you don't add these to your ModuleWidget, they will fall out of the rack... */ 14 | struct SvgScrew : widget::Widget { 15 | widget::FramebufferWidget* fb; 16 | widget::SvgWidget* sw; 17 | 18 | SvgScrew(); 19 | void setSvg(std::shared_ptr svg); 20 | }; 21 | 22 | 23 | DEPRECATED typedef SvgScrew SVGScrew; 24 | 25 | 26 | struct ThemedSvgScrew : SvgScrew { 27 | std::shared_ptr lightSvg; 28 | std::shared_ptr darkSvg; 29 | 30 | void setSvg(std::shared_ptr lightSvg, std::shared_ptr darkSvg) { 31 | this->lightSvg = lightSvg; 32 | this->darkSvg = darkSvg; 33 | SvgScrew::setSvg(settings::preferDarkPanels ? darkSvg : lightSvg); 34 | } 35 | 36 | void step() override { 37 | SvgScrew::setSvg(settings::preferDarkPanels ? darkSvg : lightSvg); 38 | SvgScrew::step(); 39 | } 40 | }; 41 | 42 | 43 | 44 | } // namespace app 45 | } // namespace rack 46 | -------------------------------------------------------------------------------- /include/app/SvgSlider.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | 8 | namespace rack { 9 | namespace app { 10 | 11 | 12 | /** Behaves like a knob but linearly moves an widget::SvgWidget between two points. 13 | Can be used for horizontal or vertical linear faders. 14 | */ 15 | struct SvgSlider : app::SliderKnob { 16 | widget::FramebufferWidget* fb; 17 | widget::SvgWidget* background; 18 | widget::SvgWidget* handle; 19 | /** Intermediate positions will be interpolated between these positions */ 20 | math::Vec minHandlePos, maxHandlePos; 21 | 22 | SvgSlider(); 23 | void setBackgroundSvg(std::shared_ptr svg); 24 | void setHandleSvg(std::shared_ptr svg); 25 | void setHandlePos(math::Vec minHandlePos, math::Vec maxHandlePos); 26 | void setHandlePosCentered(math::Vec minHandlePosCentered, math::Vec maxHandlePosCentered); 27 | void onChange(const ChangeEvent& e) override; 28 | 29 | DEPRECATED void setBackgroundSVG(std::shared_ptr svg) { 30 | setBackgroundSvg(svg); 31 | } 32 | DEPRECATED void setHandleSVG(std::shared_ptr svg) { 33 | setHandleSvg(svg); 34 | } 35 | DEPRECATED void setSVGs(std::shared_ptr backgroundSvg, std::shared_ptr handleSvg) { 36 | setBackgroundSvg(backgroundSvg); 37 | setHandleSvg(handleSvg); 38 | } 39 | }; 40 | 41 | 42 | DEPRECATED typedef SvgSlider SVGSlider; 43 | 44 | 45 | } // namespace app 46 | } // namespace rack 47 | -------------------------------------------------------------------------------- /include/app/SvgSwitch.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | 9 | namespace rack { 10 | namespace app { 11 | 12 | 13 | /** A ParamWidget with multiple frames corresponding to its value */ 14 | struct SvgSwitch : Switch { 15 | struct Internal; 16 | Internal* internal; 17 | 18 | widget::FramebufferWidget* fb; 19 | CircularShadow* shadow; 20 | widget::SvgWidget* sw; 21 | std::vector> frames; 22 | 23 | /** Use frames 0 and 1 when the mouse is pressed and released, instead of using the param value as the frame index. 24 | */ 25 | bool latch = false; 26 | 27 | SvgSwitch(); 28 | ~SvgSwitch(); 29 | /** Adds an SVG file to represent the next switch position */ 30 | void addFrame(std::shared_ptr svg); 31 | 32 | void onDragStart(const DragStartEvent& e) override; 33 | void onDragEnd(const DragEndEvent& e) override; 34 | void onChange(const ChangeEvent& e) override; 35 | }; 36 | 37 | 38 | DEPRECATED typedef SvgSwitch SVGSwitch; 39 | 40 | 41 | } // namespace app 42 | } // namespace rack 43 | -------------------------------------------------------------------------------- /include/app/Switch.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | 6 | namespace rack { 7 | namespace app { 8 | 9 | 10 | /** A ParamWidget that represents an integer. 11 | Increases by 1 each time it is clicked. 12 | When maxValue is reached, the next click resets to minValue. 13 | In momentary mode, the value is instead set to maxValue when the mouse is held and minValue when released. 14 | */ 15 | struct Switch : ParamWidget { 16 | struct Internal; 17 | Internal* internal; 18 | 19 | /** Instead of incrementing values on each click, sets maxValue on press and minValue on release. 20 | */ 21 | bool momentary = false; 22 | 23 | Switch(); 24 | ~Switch(); 25 | void initParamQuantity() override; 26 | void step() override; 27 | void onDoubleClick(const DoubleClickEvent& e) override; 28 | void onDragStart(const DragStartEvent& e) override; 29 | void onDragEnd(const DragEndEvent& e) override; 30 | }; 31 | 32 | 33 | } // namespace app 34 | } // namespace rack 35 | -------------------------------------------------------------------------------- /include/app/TipWindow.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | 6 | namespace rack { 7 | namespace app { 8 | 9 | 10 | PRIVATE widget::Widget* tipWindowCreate(); 11 | 12 | 13 | } // namespace app 14 | } // namespace rack 15 | -------------------------------------------------------------------------------- /include/app/common.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | 9 | namespace rack { 10 | 11 | 12 | /** Rack's custom UI widgets that control the Rack state and engine. 13 | */ 14 | namespace app { 15 | 16 | 17 | // A 1HPx3U module should be 15x380 pixels. Thus the width of a module should be a factor of 15. 18 | static const float RACK_GRID_WIDTH = 15; 19 | static const float RACK_GRID_HEIGHT = 380; 20 | static const math::Vec RACK_GRID_SIZE = math::Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT); 21 | static const math::Vec RACK_OFFSET = RACK_GRID_SIZE.mult(math::Vec(2000, 100)); 22 | 23 | 24 | } // namespace app 25 | } // namespace rack 26 | -------------------------------------------------------------------------------- /include/arch.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Check CPU 4 | #if defined __x86_64__ 5 | #define ARCH_X64 1 6 | #endif 7 | #if defined __aarch64__ 8 | #define ARCH_ARM64 1 9 | #endif 10 | 11 | // Check OS 12 | #if defined _WIN32 13 | #define ARCH_WIN 1 14 | #endif 15 | #if defined __APPLE__ 16 | #define ARCH_MAC 1 17 | #endif 18 | #if defined __linux__ 19 | #define ARCH_LIN 1 20 | #endif 21 | -------------------------------------------------------------------------------- /include/asset.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | 5 | namespace rack { 6 | 7 | 8 | namespace plugin { 9 | struct Plugin; 10 | } // namespace plugin 11 | 12 | 13 | namespace engine { 14 | struct Module; 15 | } // namespace engine 16 | 17 | 18 | /** Handles common path locations */ 19 | namespace asset { 20 | 21 | 22 | PRIVATE void init(); 23 | 24 | /** Returns the path of a system asset. Read-only files. */ 25 | std::string system(std::string filename = ""); 26 | 27 | /** Returns the path of a user asset. Readable/writable files. */ 28 | std::string user(std::string filename = ""); 29 | 30 | /** Returns the path of an asset in the plugin's dir. Read-only files. 31 | 32 | Examples: 33 | 34 | asset::plugin(pluginInstance, "samples/00.wav") // "//plugins/MyPlugin/samples/00.wav" 35 | */ 36 | std::string plugin(plugin::Plugin* plugin, std::string filename = ""); 37 | 38 | 39 | // Set these before calling init() to override the default paths 40 | extern std::string systemDir; 41 | extern std::string userDir; 42 | extern std::string oldUserDir; 43 | // Only defined on Mac 44 | extern std::string bundlePath; 45 | 46 | 47 | } // namespace asset 48 | } // namespace rack 49 | -------------------------------------------------------------------------------- /include/context.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | 5 | namespace rack { 6 | 7 | 8 | namespace history { 9 | struct State; 10 | } // namespace history 11 | 12 | 13 | namespace engine { 14 | struct Engine; 15 | } // namespace engine 16 | 17 | 18 | namespace window { 19 | struct Window; 20 | } // namespace window 21 | 22 | 23 | namespace patch { 24 | struct Manager; 25 | } // namespace patch 26 | 27 | 28 | namespace widget { 29 | struct EventState; 30 | } // namespace widget 31 | 32 | 33 | namespace app { 34 | struct Scene; 35 | } // namespace app 36 | 37 | 38 | namespace midiloopback { 39 | struct Context; 40 | } // namespace midiloopback 41 | 42 | 43 | /** Rack instance state 44 | */ 45 | struct Context { 46 | widget::EventState* event = NULL; 47 | app::Scene* scene = NULL; 48 | engine::Engine* engine = NULL; 49 | window::Window* window = NULL; 50 | history::State* history = NULL; 51 | patch::Manager* patch = NULL; 52 | midiloopback::Context* midiLoopbackContext = NULL; 53 | 54 | ~Context(); 55 | }; 56 | 57 | 58 | /** Returns the global Context pointer */ 59 | Context* contextGet(); 60 | /** Sets the context for this thread. 61 | You must set the context when preparing each thread if the code uses the APP macro in that thread. 62 | */ 63 | void contextSet(Context* context); 64 | 65 | /** Deprecated. Use contextGet() or the APP macro to get the current Context. */ 66 | DEPRECATED inline Context* appGet() { 67 | return contextGet(); 68 | } 69 | 70 | /** Accesses the global Context pointer. Just an alias for contextGet(). */ 71 | #define APP rack::contextGet() 72 | 73 | 74 | } // namespace rack 75 | -------------------------------------------------------------------------------- /include/dsp/convert.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | 6 | namespace rack { 7 | namespace dsp { 8 | 9 | 10 | /** 24-bit integer, using int32_t for conversions. */ 11 | struct 12 | #ifdef __clang__ 13 | __attribute__((packed, aligned(1))) 14 | #else 15 | __attribute__((packed, aligned(1), gcc_struct)) 16 | #endif 17 | Int24 { 18 | int32_t i : 24; 19 | Int24() {} 20 | Int24(int32_t i) : i(i) {} 21 | operator int32_t() {return i;} 22 | }; 23 | static_assert(sizeof(Int24) == 3, "Int24 type must be 3 bytes"); 24 | 25 | 26 | /** Converts between normalized types. 27 | */ 28 | template 29 | To convert(From x) = delete; 30 | 31 | 32 | /** Trivial conversions */ 33 | template <> 34 | inline float convert(float x) {return x;} 35 | 36 | 37 | /** Integer to float */ 38 | template <> 39 | inline float convert(int8_t x) {return x / 128.f;} 40 | template <> 41 | inline float convert(int16_t x) {return x / 32768.f;} 42 | template <> 43 | inline float convert(Int24 x) {return x / 8388608.f;} 44 | template <> 45 | inline float convert(int32_t x) {return x / 2147483648.f;} 46 | template <> 47 | inline float convert(int64_t x) {return x / 9223372036854775808.f;} 48 | 49 | 50 | /** Float to integer */ 51 | template <> 52 | inline int8_t convert(float x) {return std::min(std::llround(x * 128.f), 127LL);} 53 | template <> 54 | inline int16_t convert(float x) {return std::min(std::llround(x * 32768.f), 32767LL);} 55 | template <> 56 | inline Int24 convert(float x) {return std::min(std::llround(x * 8388608.f), 8388607LL);} 57 | template <> 58 | inline int32_t convert(float x) {return std::min(std::llround(x * 2147483648.f), 2147483647LL);} 59 | template <> 60 | inline int64_t convert(float x) {return std::min(std::llround(x * 9223372036854775808.f), 9223372036854775807LL);} 61 | 62 | 63 | /** Buffer conversion */ 64 | template 65 | void convert(const From* in, To* out, size_t len) { 66 | for (size_t i = 0; i < len; i++) { 67 | out[i] = convert(in[i]); 68 | } 69 | } 70 | 71 | 72 | } // namespace dsp 73 | } // namespace rack 74 | -------------------------------------------------------------------------------- /include/dsp/minblep.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | 5 | namespace rack { 6 | namespace dsp { 7 | 8 | 9 | /** Computes the minimum-phase bandlimited step (MinBLEP) 10 | z: number of zero-crossings 11 | o: oversample factor 12 | output: must be length `2 * z * o`. 13 | https://www.cs.cmu.edu/~eli/papers/icmc01-hardsync.pdf 14 | */ 15 | void minBlepImpulse(int z, int o, float* output); 16 | 17 | 18 | template 19 | struct MinBlepGenerator { 20 | T buf[2 * Z] = {}; 21 | int pos = 0; 22 | float impulse[2 * Z * O + 1]; 23 | 24 | MinBlepGenerator() { 25 | minBlepImpulse(Z, O, impulse); 26 | impulse[2 * Z * O] = 1.f; 27 | } 28 | 29 | /** Places a discontinuity with magnitude `x` at -1 < p <= 0 relative to the current frame */ 30 | void insertDiscontinuity(float p, T x) { 31 | if (!(-1 < p && p <= 0)) 32 | return; 33 | for (int j = 0; j < 2 * Z; j++) { 34 | float minBlepIndex = ((float)j - p) * O; 35 | int index = (pos + j) % (2 * Z); 36 | buf[index] += x * (-1.f + math::interpolateLinear(impulse, minBlepIndex)); 37 | } 38 | } 39 | 40 | T process() { 41 | T v = buf[pos]; 42 | buf[pos] = T(0); 43 | pos = (pos + 1) % (2 * Z); 44 | return v; 45 | } 46 | }; 47 | 48 | 49 | } // namespace dsp 50 | } // namespace rack 51 | -------------------------------------------------------------------------------- /include/engine/Cable.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | 6 | namespace rack { 7 | namespace engine { 8 | 9 | 10 | struct Cable { 11 | /** Unique ID for referring to the cable in the engine. 12 | Between 0 and 2^53 since this is serialized with JSON. 13 | Assigned when added to the engine. 14 | */ 15 | int64_t id = -1; 16 | Module* inputModule = NULL; 17 | int inputId = -1; 18 | Module* outputModule = NULL; 19 | int outputId = -1; 20 | 21 | json_t* toJson(); 22 | void fromJson(json_t* rootJ); 23 | PRIVATE static void jsonStripIds(json_t* rootJ); 24 | }; 25 | 26 | 27 | } // namespace engine 28 | } // namespace rack 29 | -------------------------------------------------------------------------------- /include/engine/Light.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | 5 | namespace rack { 6 | namespace engine { 7 | 8 | 9 | struct Light { 10 | /** The square of the brightness. 11 | Unstable API. Use set/getBrightness(). 12 | */ 13 | float value = 0.f; 14 | 15 | /** Sets the brightness immediately with no light decay. */ 16 | void setBrightness(float brightness) { 17 | value = brightness; 18 | } 19 | 20 | float getBrightness() { 21 | return value; 22 | } 23 | 24 | /** Emulates light decay with slow fall but immediate rise. 25 | Default lambda set to roughly 2 screen frames. 26 | */ 27 | void setBrightnessSmooth(float brightness, float deltaTime, float lambda = 30.f) { 28 | if (brightness < value) { 29 | // Fade out light 30 | value += (brightness - value) * lambda * deltaTime; 31 | } 32 | else { 33 | // Immediately illuminate light 34 | value = brightness; 35 | } 36 | } 37 | /** DEPRECATED Alias for setBrightnessSmooth() */ 38 | void setSmoothBrightness(float brightness, float deltaTime) { 39 | setBrightnessSmooth(brightness, deltaTime); 40 | } 41 | 42 | /** Use `setBrightnessSmooth(brightness, sampleTime * frames)` instead. */ 43 | DEPRECATED void setBrightnessSmooth(float brightness, int frames = 1) { 44 | setBrightnessSmooth(brightness, frames / 44100.f); 45 | } 46 | }; 47 | 48 | 49 | } // namespace engine 50 | } // namespace rack 51 | -------------------------------------------------------------------------------- /include/engine/LightInfo.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | 5 | namespace rack { 6 | namespace engine { 7 | 8 | 9 | struct Module; 10 | 11 | 12 | struct LightInfo { 13 | Module* module = NULL; 14 | int lightId = -1; 15 | 16 | /** The name of the light, using sentence capitalization. 17 | e.g. "Level", "Oscillator phase", "Mode CV". 18 | 19 | Don't use the word "light" or "LED" in the name. 20 | Since this text is often prepended or appended to the name, the name will appear as e.g. "Level light light". 21 | */ 22 | std::string name; 23 | 24 | /** An optional one-sentence description of the light. */ 25 | std::string description; 26 | 27 | virtual ~LightInfo() {} 28 | virtual std::string getName(); 29 | virtual std::string getDescription(); 30 | }; 31 | 32 | 33 | } // namespace engine 34 | } // namespace rack 35 | -------------------------------------------------------------------------------- /include/engine/Param.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | 6 | namespace rack { 7 | namespace engine { 8 | 9 | 10 | struct Param { 11 | /** Unstable API. Use setValue() and getValue() instead. */ 12 | float value = 0.f; 13 | 14 | float getValue() { 15 | return value; 16 | } 17 | 18 | void setValue(float value) { 19 | this->value = value; 20 | } 21 | }; 22 | 23 | 24 | } // namespace engine 25 | } // namespace rack 26 | -------------------------------------------------------------------------------- /include/engine/ParamHandle.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | 8 | namespace rack { 9 | namespace engine { 10 | 11 | 12 | /** A weak handle to a Param. Managed by Engine */ 13 | struct ParamHandle { 14 | /** Do not set these directly. 15 | Use Engine ParamHandle methods. 16 | */ 17 | int64_t moduleId = -1; 18 | int paramId = 0; 19 | Module* module = NULL; 20 | 21 | std::string text; 22 | NVGcolor color; 23 | }; 24 | 25 | 26 | } // namespace engine 27 | } // namespace rack 28 | -------------------------------------------------------------------------------- /include/engine/PortInfo.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | 6 | namespace rack { 7 | namespace engine { 8 | 9 | 10 | struct Module; 11 | 12 | 13 | struct PortInfo { 14 | Module* module = NULL; 15 | Port::Type type = Port::INPUT; 16 | int portId = -1; 17 | 18 | /** The name of the port, using sentence capitalization. 19 | e.g. "Sine", "Pitch input", "Mode CV". 20 | 21 | Don't use the words "input" or "output" in the name. 22 | Since this text is often prepended or appended to the name, the name will appear as e.g. "Sine input input", "Input: Sine input". 23 | */ 24 | std::string name; 25 | 26 | /** An optional one-sentence description of the parameter. */ 27 | std::string description; 28 | 29 | virtual ~PortInfo() {} 30 | virtual std::string getName(); 31 | /** Returns name with "input" or "output" appended. */ 32 | std::string getFullName(); 33 | virtual std::string getDescription(); 34 | }; 35 | 36 | 37 | } // namespace engine 38 | } // namespace rack 39 | -------------------------------------------------------------------------------- /include/gamepad.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | 5 | namespace rack { 6 | /** Gamepad/joystick/controller MIDI driver */ 7 | namespace gamepad { 8 | 9 | 10 | PRIVATE void init(); 11 | PRIVATE void step(); 12 | 13 | 14 | } // namespace gamepad 15 | } // namespace rack 16 | -------------------------------------------------------------------------------- /include/keyboard.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | 6 | namespace rack { 7 | /** Computer keyboard MIDI driver */ 8 | namespace keyboard { 9 | 10 | 11 | PRIVATE void init(); 12 | void press(int key); 13 | void release(int key); 14 | /** pos is in the unit box. */ 15 | void mouseMove(math::Vec pos); 16 | 17 | 18 | } // namespace keyboard 19 | } // namespace rack 20 | -------------------------------------------------------------------------------- /include/library.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #include 5 | 6 | 7 | namespace rack { 8 | /** Synchronizes plugins with the VCV Library and handles VCV accounts with the vcvrack.com API */ 9 | namespace library { 10 | 11 | 12 | struct UpdateInfo { 13 | std::string name; 14 | std::string version; 15 | std::string changelogUrl; 16 | /** Only defined if plugin does not meet Rack version requirement */ 17 | std::string minRackVersion; 18 | bool downloaded = false; 19 | }; 20 | 21 | 22 | PRIVATE void init(); 23 | PRIVATE void destroy(); 24 | 25 | PRIVATE void checkAppUpdate(); 26 | bool isAppUpdateAvailable(); 27 | 28 | bool isLoggedIn(); 29 | PRIVATE void logIn(std::string email, std::string password); 30 | PRIVATE void logOut(); 31 | PRIVATE void checkUpdates(); 32 | PRIVATE bool hasUpdates(); 33 | PRIVATE void syncUpdate(std::string slug); 34 | PRIVATE void syncUpdates(); 35 | 36 | 37 | extern std::string appVersion; 38 | extern std::string appDownloadUrl; 39 | extern std::string appChangelogUrl; 40 | 41 | extern std::string loginStatus; 42 | // plugin slug -> UpdateInfo 43 | extern std::map updateInfos; 44 | extern std::string updateStatus; 45 | extern std::string updateSlug; 46 | extern float updateProgress; 47 | /** Whether plugins are currently downloading. */ 48 | extern bool isSyncing; 49 | /** Whether the UI should ask the user to restart after updating plugins. */ 50 | extern bool restartRequested; 51 | /** Whether the UI should refresh the plugin updates menu. */ 52 | extern bool refreshRequested; 53 | 54 | 55 | } // namespace library 56 | } // namespace rack 57 | -------------------------------------------------------------------------------- /include/logger.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | 5 | /** Example usage: 6 | 7 | DEBUG("error: %d", errno); 8 | 9 | will print something like 10 | 11 | [0.123 debug myfile.cpp:45] error: 67 12 | */ 13 | #define DEBUG(format, ...) rack::logger::log(rack::logger::DEBUG_LEVEL, __FILE__, __LINE__, __FUNCTION__, format, ##__VA_ARGS__) 14 | #define INFO(format, ...) rack::logger::log(rack::logger::INFO_LEVEL, __FILE__, __LINE__, __FUNCTION__, format, ##__VA_ARGS__) 15 | #define WARN(format, ...) rack::logger::log(rack::logger::WARN_LEVEL, __FILE__, __LINE__, __FUNCTION__, format, ##__VA_ARGS__) 16 | #define FATAL(format, ...) rack::logger::log(rack::logger::FATAL_LEVEL, __FILE__, __LINE__, __FUNCTION__, format, ##__VA_ARGS__) 17 | 18 | 19 | namespace rack { 20 | /** Logs messages to a file or the terminal */ 21 | namespace logger { 22 | 23 | 24 | extern std::string logPath; 25 | 26 | 27 | enum Level { 28 | DEBUG_LEVEL, 29 | INFO_LEVEL, 30 | WARN_LEVEL, 31 | FATAL_LEVEL 32 | }; 33 | 34 | /** Returns whether logger was successfully initialized. */ 35 | PRIVATE bool init(); 36 | PRIVATE void destroy(); 37 | /** Do not use this function directly. Use the macros above. 38 | Thread-safe, meaning messages cannot overlap each other in the log. 39 | */ 40 | __attribute__((format(printf, 5, 6))) 41 | void log(Level level, const char* filename, int line, const char* func, const char* format, ...); 42 | /** Returns whether the last log file failed to end properly, due to a possible crash. 43 | */ 44 | PRIVATE bool wasTruncated(); 45 | 46 | 47 | } // namespace logger 48 | } // namespace rack 49 | -------------------------------------------------------------------------------- /include/midiloopback.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | 7 | namespace rack { 8 | namespace midiloopback { 9 | 10 | 11 | struct Device; 12 | 13 | 14 | struct Context { 15 | std::vector devices; 16 | 17 | Context(); 18 | ~Context(); 19 | }; 20 | 21 | 22 | PRIVATE void init(); 23 | 24 | 25 | } // namespace midiloopback 26 | } // namespace rack 27 | -------------------------------------------------------------------------------- /include/mutex.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | 6 | namespace rack { 7 | 8 | 9 | /** Allows multiple "reader" threads to obtain a lock simultaneously, but only one "writer" thread. 10 | 11 | This implementation is currently just a wrapper for pthreads, which works on Linux/Mac/. 12 | This is available in C++17 as std::shared_mutex, but unfortunately we're using C++11. 13 | 14 | Locking should be avoided in real-time audio threads. 15 | */ 16 | struct SharedMutex { 17 | pthread_rwlock_t rwlock; 18 | 19 | SharedMutex() { 20 | int err = pthread_rwlock_init(&rwlock, NULL); 21 | (void) err; 22 | assert(!err); 23 | } 24 | ~SharedMutex() { 25 | pthread_rwlock_destroy(&rwlock); 26 | } 27 | 28 | void lock() { 29 | int err = pthread_rwlock_wrlock(&rwlock); 30 | (void) err; 31 | assert(!err); 32 | } 33 | /** Returns whether the lock was acquired. */ 34 | bool try_lock() { 35 | return pthread_rwlock_trywrlock(&rwlock) == 0; 36 | } 37 | void unlock() { 38 | int err = pthread_rwlock_unlock(&rwlock); 39 | (void) err; 40 | assert(!err); 41 | } 42 | 43 | void lock_shared() { 44 | int err = pthread_rwlock_rdlock(&rwlock); 45 | (void) err; 46 | assert(!err); 47 | } 48 | /** Returns whether the lock was acquired. */ 49 | bool try_lock_shared() { 50 | return pthread_rwlock_tryrdlock(&rwlock) == 0; 51 | } 52 | void unlock_shared() { 53 | unlock(); 54 | } 55 | }; 56 | 57 | 58 | template 59 | struct SharedLock { 60 | TMutex& m; 61 | 62 | SharedLock(TMutex& m) : m(m) { 63 | m.lock_shared(); 64 | } 65 | ~SharedLock() { 66 | m.unlock_shared(); 67 | } 68 | }; 69 | 70 | 71 | } // namespace rack 72 | -------------------------------------------------------------------------------- /include/network.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #include 5 | 6 | #include 7 | 8 | 9 | namespace rack { 10 | /** Networking functions for HTTP requests, downloads, and URLs */ 11 | namespace network { 12 | 13 | 14 | typedef std::map CookieMap; 15 | 16 | enum Method { 17 | METHOD_GET, 18 | METHOD_POST, 19 | METHOD_PUT, 20 | METHOD_DELETE, 21 | }; 22 | 23 | PRIVATE void init(); 24 | PRIVATE void destroy(); 25 | /** Requests a JSON API URL over HTTP(S), using the data as the query (GET) or the body (POST, etc) 26 | Caller must json_decref() if return value is non-NULL. 27 | */ 28 | json_t* requestJson(Method method, const std::string& url, json_t* dataJ = NULL, const CookieMap& cookies = {}); 29 | /** Returns true if downloaded successfully. 30 | If `progress` is non-NULL, the value is updated from 0 to 1 while downloading. 31 | */ 32 | bool requestDownload(const std::string& url, const std::string& filename, float* progress = NULL, const CookieMap& cookies = {}); 33 | /** URL-encodes a string. */ 34 | std::string encodeUrl(const std::string& s); 35 | /** Returns the path portion of the URL. 36 | Example: 37 | 38 | urlPath("https://example.com/foo/index.html") // Returns "/foo/index.html" 39 | */ 40 | std::string urlPath(const std::string& url); 41 | 42 | 43 | } // namespace network 44 | } // namespace rack 45 | -------------------------------------------------------------------------------- /include/plugin.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | 9 | namespace rack { 10 | /** Loads and manages Rack plugins */ 11 | namespace plugin { 12 | 13 | 14 | PRIVATE void init(); 15 | PRIVATE void destroy(); 16 | PRIVATE void settingsMergeJson(json_t* rootJ); 17 | 18 | /** Finds a loaded Plugin by slug. */ 19 | Plugin* getPlugin(const std::string& pluginSlug); 20 | /** Finds a loaded Plugin by slug, or a fallback plugin if exists. */ 21 | Plugin* getPluginFallback(const std::string& pluginSlug); 22 | /** Finds a loaded Model by plugin and model slug. */ 23 | Model* getModel(const std::string& pluginSlug, const std::string& modelSlug); 24 | /** Finds a loaded Model by plugin and model slug, or a fallback model if exists. */ 25 | Model* getModelFallback(const std::string& pluginSlug, const std::string& modelSlug); 26 | 27 | /** Creates a Model from a JSON module object. 28 | Throws an Exception if the model is not found. 29 | */ 30 | Model* modelFromJson(json_t* moduleJ); 31 | /** Checks that the slug contains only alphanumeric characters, "-", and "_" */ 32 | bool isSlugValid(const std::string& slug); 33 | /** Returns a string containing only the valid slug characters. */ 34 | std::string normalizeSlug(const std::string& slug); 35 | 36 | 37 | /** Path to plugins installation dir */ 38 | extern std::string pluginsPath; 39 | extern std::vector plugins; 40 | 41 | 42 | } // namespace plugin 43 | } // namespace rack 44 | -------------------------------------------------------------------------------- /include/plugin/callbacks.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | 5 | /** Called immediately after loading your plugin. 6 | 7 | Use this to save `plugin` to a global variable and add Models to it. 8 | Required in plugins. 9 | */ 10 | extern "C" 11 | void init(rack::plugin::Plugin* plugin); 12 | 13 | /** Called before your plugin library is unloaded. 14 | 15 | Optional in plugins. 16 | */ 17 | extern "C" 18 | void destroy(); 19 | 20 | /** Called when saving user settings. 21 | Stored in `settings["pluginSettings"][pluginSlug]`. 22 | Useful for persisting plugin-wide settings. 23 | 24 | Optional in plugins. 25 | */ 26 | extern "C" 27 | json_t* settingsToJson(); 28 | 29 | /** Called after initializing plugin if user plugin settings property is defined. 30 | 31 | Optional in plugins. 32 | */ 33 | extern "C" 34 | void settingsFromJson(json_t* rootJ); 35 | -------------------------------------------------------------------------------- /include/rtaudio.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | 5 | namespace rack { 6 | 7 | 8 | PRIVATE void rtaudioInit(); 9 | 10 | #if defined ARCH_MAC 11 | /** Checks if Microphone permission is blocked on Mac. */ 12 | bool rtaudioIsMicrophoneBlocked(); 13 | #endif 14 | 15 | 16 | } // namespace rack 17 | -------------------------------------------------------------------------------- /include/rtmidi.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | 5 | namespace rack { 6 | 7 | 8 | PRIVATE void rtmidiInit(); 9 | 10 | 11 | } // namespace rack 12 | -------------------------------------------------------------------------------- /include/simd/common.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef __SSE4_2__ 4 | #include 5 | #else 6 | #define SIMDE_ENABLE_NATIVE_ALIASES 7 | #include 8 | #endif 9 | -------------------------------------------------------------------------------- /include/tag.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #include 5 | 6 | 7 | namespace rack { 8 | /** Tags describing the function(s) of modules */ 9 | namespace tag { 10 | 11 | 12 | /** List of tags and their aliases. 13 | The first alias of each tag `tag[tagId][0]` is the "canonical" alias. 14 | It is guaranteed to exist and should be used as the human-readable form. 15 | 16 | This list is manually alphabetized by the canonical alias. 17 | */ 18 | extern const std::vector> tagAliases; 19 | 20 | 21 | /** Searches for a tag ID. 22 | Searches tag aliases. 23 | Case-insensitive. 24 | Returns -1 if not found. 25 | */ 26 | int findId(const std::string& tag); 27 | 28 | /** Returns the main tag name by tag ID. */ 29 | std::string getTag(int tagId); 30 | 31 | 32 | } // namespace tag 33 | } // namespace rack 34 | -------------------------------------------------------------------------------- /include/ui/Button.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | 7 | namespace rack { 8 | namespace ui { 9 | 10 | 11 | /** A clickable button with text. 12 | Dispatches Action event when clicked. 13 | 14 | If quantity is set, its value is set to 1.0 when pressed, 0.0 when released. 15 | 16 | If text is not set, the quantity label is used. 17 | */ 18 | struct Button : widget::OpaqueWidget { 19 | std::string text; 20 | /** Not owned. Tracks the pressed state of the button.*/ 21 | Quantity* quantity = NULL; 22 | 23 | Button(); 24 | void draw(const DrawArgs& args) override; 25 | void onDragStart(const DragStartEvent& e) override; 26 | void onDragEnd(const DragEndEvent& e) override; 27 | void onDragDrop(const DragDropEvent& e) override; 28 | }; 29 | 30 | 31 | } // namespace ui 32 | } // namespace rack 33 | -------------------------------------------------------------------------------- /include/ui/ChoiceButton.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | 6 | namespace rack { 7 | namespace ui { 8 | 9 | 10 | /** Button with a dropdown icon on its right. 11 | */ 12 | struct ChoiceButton : Button { 13 | void draw(const DrawArgs& args) override; 14 | }; 15 | 16 | 17 | } // namespace ui 18 | } // namespace rack 19 | -------------------------------------------------------------------------------- /include/ui/Label.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | 6 | namespace rack { 7 | namespace ui { 8 | 9 | 10 | struct Label : widget::Widget { 11 | enum Alignment { 12 | LEFT_ALIGNMENT, 13 | CENTER_ALIGNMENT, 14 | RIGHT_ALIGNMENT, 15 | }; 16 | 17 | std::string text; 18 | float fontSize; 19 | float lineHeight; 20 | NVGcolor color; 21 | Alignment alignment = LEFT_ALIGNMENT; 22 | 23 | Label(); 24 | void draw(const DrawArgs& args) override; 25 | }; 26 | 27 | 28 | } // namespace ui 29 | } // namespace rack 30 | -------------------------------------------------------------------------------- /include/ui/List.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | 6 | namespace rack { 7 | namespace ui { 8 | 9 | 10 | struct List : widget::OpaqueWidget { 11 | void step() override; 12 | }; 13 | 14 | 15 | } // namespace ui 16 | } // namespace rack 17 | -------------------------------------------------------------------------------- /include/ui/Menu.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | 7 | namespace rack { 8 | namespace ui { 9 | 10 | 11 | struct Menu : widget::OpaqueWidget { 12 | Menu* parentMenu = NULL; 13 | Menu* childMenu = NULL; 14 | /** The entry which created the child menu */ 15 | MenuEntry* activeEntry = NULL; 16 | BNDcornerFlags cornerFlags = BND_CORNER_NONE; 17 | 18 | Menu(); 19 | ~Menu(); 20 | void setChildMenu(Menu* menu); 21 | void step() override; 22 | void draw(const DrawArgs& args) override; 23 | void onHoverScroll(const HoverScrollEvent& e) override; 24 | }; 25 | 26 | 27 | } // namespace ui 28 | } // namespace rack 29 | -------------------------------------------------------------------------------- /include/ui/MenuEntry.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | 6 | namespace rack { 7 | namespace ui { 8 | 9 | 10 | struct MenuEntry : widget::OpaqueWidget { 11 | MenuEntry(); 12 | }; 13 | 14 | 15 | } // namespace ui 16 | } // namespace rack 17 | -------------------------------------------------------------------------------- /include/ui/MenuItem.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | 8 | namespace rack { 9 | namespace ui { 10 | 11 | 12 | struct MenuItem : MenuEntry { 13 | std::string text; 14 | std::string rightText; 15 | bool disabled = false; 16 | 17 | void draw(const DrawArgs& args) override; 18 | PRIVATE void drawOffset(NVGcontext* vg, float offset = 0); 19 | void step() override; 20 | void onEnter(const EnterEvent& e) override; 21 | void onDragDrop(const DragDropEvent& e) override; 22 | void doAction(bool consume = true); 23 | virtual Menu* createChildMenu() { 24 | return NULL; 25 | } 26 | /** Override to handle behavior when user clicks the menu item. 27 | Event is consumed by default. Unconsume to prevent the menu from being closed. 28 | If Ctrl (Cmd on Mac) is held, the event is *not* pre-consumed, so if your menu must be closed, always consume the event. 29 | */ 30 | void onAction(const ActionEvent& e) override; 31 | }; 32 | 33 | 34 | struct ColorDotMenuItem : MenuItem { 35 | NVGcolor color = color::BLACK_TRANSPARENT; 36 | 37 | void draw(const DrawArgs& args) override; 38 | void step() override; 39 | }; 40 | 41 | 42 | } // namespace ui 43 | } // namespace rack 44 | -------------------------------------------------------------------------------- /include/ui/MenuLabel.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | 6 | namespace rack { 7 | namespace ui { 8 | 9 | 10 | struct MenuLabel : MenuEntry { 11 | std::string text; 12 | 13 | void draw(const DrawArgs& args) override; 14 | void step() override; 15 | }; 16 | 17 | 18 | } // namespace ui 19 | } // namespace rack 20 | -------------------------------------------------------------------------------- /include/ui/MenuOverlay.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | 6 | namespace rack { 7 | namespace ui { 8 | 9 | 10 | /** Deletes itself from parent when clicked */ 11 | struct MenuOverlay : widget::OpaqueWidget { 12 | NVGcolor bgColor; 13 | 14 | MenuOverlay(); 15 | void draw(const DrawArgs& args) override; 16 | void step() override; 17 | void onButton(const ButtonEvent& e) override; 18 | void onHoverKey(const HoverKeyEvent& e) override; 19 | void onAction(const ActionEvent& e) override; 20 | }; 21 | 22 | 23 | } // namespace ui 24 | } // namespace rack 25 | -------------------------------------------------------------------------------- /include/ui/MenuSeparator.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | 6 | namespace rack { 7 | namespace ui { 8 | 9 | 10 | struct MenuSeparator : MenuEntry { 11 | MenuSeparator(); 12 | void draw(const DrawArgs& args) override; 13 | }; 14 | 15 | 16 | } // namespace ui 17 | } // namespace rack 18 | -------------------------------------------------------------------------------- /include/ui/OptionButton.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | 6 | namespace rack { 7 | namespace ui { 8 | 9 | 10 | /** Behaves like a RadioButton and appears with a checkmark beside text. 11 | */ 12 | struct OptionButton : RadioButton { 13 | void draw(const DrawArgs& args) override; 14 | }; 15 | 16 | 17 | } // namespace ui 18 | } // namespace rack 19 | -------------------------------------------------------------------------------- /include/ui/ProgressBar.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | 7 | namespace rack { 8 | namespace ui { 9 | 10 | 11 | struct ProgressBar : widget::Widget { 12 | /** Not owned. Stores the progress value and label. */ 13 | Quantity* quantity = NULL; 14 | 15 | ProgressBar(); 16 | void draw(const DrawArgs& args) override; 17 | }; 18 | 19 | 20 | } // namespace ui 21 | } // namespace rack 22 | -------------------------------------------------------------------------------- /include/ui/RadioButton.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | 6 | namespace rack { 7 | namespace ui { 8 | 9 | 10 | /** Toggles a Quantity between 1.0 and 0.0 when clicked. 11 | */ 12 | struct RadioButton : Button { 13 | void draw(const DrawArgs& args) override; 14 | void onDragStart(const DragStartEvent& e) override; 15 | void onDragEnd(const DragEndEvent& e) override; 16 | void onDragDrop(const DragDropEvent& e) override; 17 | }; 18 | 19 | 20 | } // namespace ui 21 | } // namespace rack 22 | -------------------------------------------------------------------------------- /include/ui/ScrollWidget.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | 7 | namespace rack { 8 | namespace ui { 9 | 10 | 11 | /** Handles a container with Scrollbar */ 12 | struct ScrollWidget : widget::OpaqueWidget { 13 | struct Internal; 14 | Internal* internal; 15 | 16 | widget::Widget* container; 17 | Scrollbar* horizontalScrollbar; 18 | Scrollbar* verticalScrollbar; 19 | 20 | math::Vec offset; 21 | math::Rect containerBox; 22 | bool hideScrollbars = false; 23 | 24 | ScrollWidget(); 25 | ~ScrollWidget(); 26 | math::Vec getScrollOffset() { 27 | return offset; 28 | } 29 | void scrollTo(math::Rect r); 30 | /** Returns the bound of allowed `offset` values in pixels. */ 31 | math::Rect getContainerOffsetBound(); 32 | /** Returns the handle position relative to the scrollbar. [0, 1]. */ 33 | math::Vec getHandleOffset(); 34 | /** Returns the handle size relative to the scrollbar. [0, 1]. */ 35 | math::Vec getHandleSize(); 36 | /** The user is considered scrolling with the wheel until the mouse is moved. */ 37 | bool isScrolling(); 38 | void draw(const DrawArgs& args) override; 39 | void step() override; 40 | void onHover(const HoverEvent& e) override; 41 | void onButton(const ButtonEvent& e) override; 42 | void onDragStart(const DragStartEvent& e) override; 43 | void onDragMove(const DragMoveEvent& e) override; 44 | void onHoverScroll(const HoverScrollEvent& e) override; 45 | void onHoverKey(const HoverKeyEvent& e) override; 46 | }; 47 | 48 | 49 | } // namespace ui 50 | } // namespace rack 51 | -------------------------------------------------------------------------------- /include/ui/Scrollbar.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | 6 | namespace rack { 7 | namespace ui { 8 | 9 | 10 | /** Parent must be a ScrollWidget */ 11 | struct Scrollbar : widget::OpaqueWidget { 12 | struct Internal; 13 | Internal* internal; 14 | 15 | bool vertical = false; 16 | 17 | Scrollbar(); 18 | ~Scrollbar(); 19 | void draw(const DrawArgs& args) override; 20 | void onButton(const ButtonEvent& e) override; 21 | void onDragStart(const DragStartEvent& e) override; 22 | void onDragEnd(const DragEndEvent& e) override; 23 | void onDragMove(const DragMoveEvent& e) override; 24 | }; 25 | 26 | 27 | DEPRECATED typedef Scrollbar ScrollBar; 28 | 29 | 30 | } // namespace ui 31 | } // namespace rack 32 | -------------------------------------------------------------------------------- /include/ui/SequentialLayout.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | 6 | namespace rack { 7 | namespace ui { 8 | 9 | 10 | /** Positions children in a row/column based on their widths/heights */ 11 | struct SequentialLayout : widget::Widget { 12 | enum Orientation { 13 | HORIZONTAL_ORIENTATION, 14 | VERTICAL_ORIENTATION, 15 | }; 16 | enum Alignment { 17 | LEFT_ALIGNMENT, 18 | CENTER_ALIGNMENT, 19 | RIGHT_ALIGNMENT, 20 | 21 | TOP_ALIGNMENT = LEFT_ALIGNMENT, 22 | MIDDLE_ALIGNMENT = CENTER_ALIGNMENT, 23 | BOTTOM_ALIGNMENT = RIGHT_ALIGNMENT, 24 | }; 25 | 26 | Orientation orientation = HORIZONTAL_ORIENTATION; 27 | Alignment alignment = LEFT_ALIGNMENT; 28 | bool wrap = true; 29 | /** Space between box bounds. */ 30 | math::Vec margin; 31 | /** Space between adjacent elements, and adjacent lines if wrapped. */ 32 | math::Vec spacing; 33 | 34 | void step() override; 35 | }; 36 | 37 | 38 | } // namespace ui 39 | } // namespace rack 40 | -------------------------------------------------------------------------------- /include/ui/Slider.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | 8 | namespace rack { 9 | namespace ui { 10 | 11 | 12 | struct Slider : widget::OpaqueWidget { 13 | /** Not owned. */ 14 | Quantity* quantity = NULL; 15 | 16 | Slider(); 17 | void draw(const DrawArgs& args) override; 18 | void onDragStart(const DragStartEvent& e) override; 19 | void onDragMove(const DragMoveEvent& e) override; 20 | void onDragEnd(const DragEndEvent& e) override; 21 | void onDoubleClick(const DoubleClickEvent& e) override; 22 | }; 23 | 24 | 25 | } // namespace ui 26 | } // namespace rack 27 | -------------------------------------------------------------------------------- /include/ui/TextField.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | 7 | namespace rack { 8 | namespace ui { 9 | 10 | 11 | struct TextField : widget::OpaqueWidget { 12 | std::string text; 13 | std::string placeholder; 14 | /** Masks text with "*". */ 15 | bool password = false; 16 | bool multiline = false; 17 | /** The index of the text cursor */ 18 | int cursor = 0; 19 | /** The index of the other end of the selection. 20 | If nothing is selected, this is equal to `cursor`. 21 | */ 22 | int selection = 0; 23 | 24 | /** For Tab and Shift-Tab focusing. 25 | */ 26 | Widget* prevField = NULL; 27 | Widget* nextField = NULL; 28 | 29 | TextField(); 30 | void draw(const DrawArgs& args) override; 31 | void onDragHover(const DragHoverEvent& e) override; 32 | void onButton(const ButtonEvent& e) override; 33 | void onSelectText(const SelectTextEvent& e) override; 34 | void onSelectKey(const SelectKeyEvent& e) override; 35 | virtual int getTextPosition(math::Vec mousePos); 36 | 37 | std::string getText(); 38 | /** Replaces the entire text */ 39 | void setText(std::string text); 40 | void selectAll(); 41 | std::string getSelectedText(); 42 | /** Inserts text at the cursor, replacing the selection if necessary */ 43 | void insertText(std::string text); 44 | void copyClipboard(); 45 | void cutClipboard(); 46 | void pasteClipboard(); 47 | void cursorToPrevWord(); 48 | void cursorToNextWord(); 49 | void createContextMenu(); 50 | }; 51 | 52 | 53 | struct PasswordField : TextField { 54 | PasswordField() { 55 | password = true; 56 | } 57 | }; 58 | 59 | 60 | } // namespace ui 61 | } // namespace rack 62 | -------------------------------------------------------------------------------- /include/ui/Tooltip.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | 6 | namespace rack { 7 | namespace ui { 8 | 9 | 10 | struct Tooltip : widget::Widget { 11 | std::string text; 12 | 13 | void step() override; 14 | void draw(const DrawArgs& args) override; 15 | }; 16 | 17 | 18 | } // namespace ui 19 | } // namespace rack 20 | -------------------------------------------------------------------------------- /include/ui/TooltipOverlay.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | 6 | namespace rack { 7 | namespace ui { 8 | 9 | 10 | struct TooltipOverlay : widget::TransparentWidget { 11 | }; 12 | 13 | 14 | } // namespace ui 15 | } // namespace rack 16 | -------------------------------------------------------------------------------- /include/ui/common.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | /** Useful for menu items with a "true" boolean state */ 9 | #define CHECKMARK_STRING "✔" 10 | #define CHECKMARK(_cond) ((_cond) ? CHECKMARK_STRING : "") 11 | 12 | /** Useful for menu items that open a sub-menu */ 13 | #define RIGHT_ARROW "▸" 14 | 15 | 16 | namespace rack { 17 | 18 | 19 | /** Common graphical user interface widgets 20 | */ 21 | namespace ui { 22 | 23 | 24 | PRIVATE void init(); 25 | PRIVATE void destroy(); 26 | void setTheme(NVGcolor bg, NVGcolor fg); 27 | /** Sets theme from settings. */ 28 | void refreshTheme(); 29 | 30 | 31 | } // namespace ui 32 | } // namespace rack 33 | -------------------------------------------------------------------------------- /include/widget/FramebufferWidget.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | 5 | namespace rack { 6 | namespace widget { 7 | 8 | 9 | /** Caches its children's draw() result to a framebuffer image. 10 | When dirty, its children will be re-rendered on the next call to step(). 11 | */ 12 | struct FramebufferWidget : Widget { 13 | struct Internal; 14 | Internal* internal; 15 | 16 | bool dirty = true; 17 | bool bypassed = false; 18 | float oversample = 1.0; 19 | /** Redraw when the world offset of the FramebufferWidget changes its fractional value. */ 20 | bool dirtyOnSubpixelChange = true; 21 | /** If finite, the maximum size of the framebuffer is the viewport expanded by this margin. 22 | The framebuffer is re-rendered when the viewport moves outside the margin. 23 | */ 24 | math::Vec viewportMargin = math::Vec(INFINITY, INFINITY); 25 | 26 | FramebufferWidget(); 27 | ~FramebufferWidget(); 28 | /** Requests to re-render children to the framebuffer on the next draw(). */ 29 | void setDirty(bool dirty = true); 30 | int getImageHandle(); 31 | NVGLUframebuffer* getFramebuffer(); 32 | math::Vec getFramebufferSize(); 33 | void deleteFramebuffer(); 34 | 35 | void step() override; 36 | /** Draws the framebuffer to the NanoVG scene, re-rendering it if necessary. 37 | */ 38 | void draw(const DrawArgs& args) override; 39 | /** Re-renders the framebuffer, re-creating it if necessary. 40 | Handles oversampling (if >1) by rendering to a temporary (larger) framebuffer and then downscaling it to the main persistent framebuffer. 41 | */ 42 | void render(math::Vec scale = math::Vec(1, 1), math::Vec offsetF = math::Vec(0, 0), math::Rect clipBox = math::Rect::inf()); 43 | /** Initializes the current GL context and draws children to it. 44 | */ 45 | virtual void drawFramebuffer(); 46 | 47 | void onDirty(const DirtyEvent& e) override; 48 | void onContextCreate(const ContextCreateEvent& e) override; 49 | void onContextDestroy(const ContextDestroyEvent& e) override; 50 | }; 51 | 52 | 53 | } // namespace widget 54 | } // namespace rack 55 | -------------------------------------------------------------------------------- /include/widget/OpaqueWidget.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | 5 | namespace rack { 6 | namespace widget { 7 | 8 | 9 | /** A Widget that stops propagation of all recursive PositionEvents (such as ButtonEvent) but gives a chance for children to consume first. 10 | Also consumes HoverEvent and ButtonEvent for left-clicks. 11 | */ 12 | struct OpaqueWidget : Widget { 13 | void onHover(const HoverEvent& e) override { 14 | Widget::onHover(e); 15 | e.stopPropagating(); 16 | // Consume if not consumed by child 17 | if (!e.isConsumed()) 18 | e.consume(this); 19 | } 20 | void onButton(const ButtonEvent& e) override { 21 | Widget::onButton(e); 22 | e.stopPropagating(); 23 | if (e.button == GLFW_MOUSE_BUTTON_LEFT) { 24 | // Consume if not consumed by child 25 | if (!e.isConsumed()) 26 | e.consume(this); 27 | } 28 | } 29 | void onHoverKey(const HoverKeyEvent& e) override { 30 | Widget::onHoverKey(e); 31 | e.stopPropagating(); 32 | } 33 | void onHoverText(const HoverTextEvent& e) override { 34 | Widget::onHoverText(e); 35 | e.stopPropagating(); 36 | } 37 | void onHoverScroll(const HoverScrollEvent& e) override { 38 | Widget::onHoverScroll(e); 39 | e.stopPropagating(); 40 | } 41 | void onDragHover(const DragHoverEvent& e) override { 42 | Widget::onDragHover(e); 43 | e.stopPropagating(); 44 | // Consume if not consumed by child 45 | if (!e.isConsumed()) 46 | e.consume(this); 47 | } 48 | void onPathDrop(const PathDropEvent& e) override { 49 | Widget::onPathDrop(e); 50 | e.stopPropagating(); 51 | } 52 | }; 53 | 54 | 55 | } // namespace widget 56 | } // namespace rack 57 | -------------------------------------------------------------------------------- /include/widget/OpenGlWidget.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | 5 | namespace rack { 6 | namespace widget { 7 | 8 | 9 | /** A FramebufferWidget that can be drawn on with OpenGL commands */ 10 | struct OpenGlWidget : FramebufferWidget { 11 | /** Draws every frame by default 12 | Override this and call `FramebufferWidget::step()` to restore the default behavior of FramebufferWidget. 13 | */ 14 | void step() override; 15 | /** Draws to the framebuffer. 16 | Override to initialize, draw, and flush the OpenGL state. 17 | */ 18 | void drawFramebuffer() override; 19 | }; 20 | 21 | 22 | } // namespace widget 23 | } // namespace rack 24 | -------------------------------------------------------------------------------- /include/widget/SvgWidget.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | 5 | namespace rack { 6 | namespace widget { 7 | 8 | 9 | /** Owns and draws a window::Svg */ 10 | struct SvgWidget : Widget { 11 | std::shared_ptr svg; 12 | 13 | SvgWidget(); 14 | 15 | /** Sets the box size to the SVG image size */ 16 | void wrap(); 17 | 18 | /** Sets and wraps the SVG */ 19 | void setSvg(std::shared_ptr svg); 20 | DEPRECATED void setSVG(std::shared_ptr svg) { 21 | setSvg(svg); 22 | } 23 | 24 | void draw(const DrawArgs& args) override; 25 | }; 26 | 27 | 28 | DEPRECATED typedef SvgWidget SVGWidget; 29 | 30 | 31 | } // namespace widget 32 | } // namespace rack 33 | -------------------------------------------------------------------------------- /include/widget/TransformWidget.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | 5 | namespace rack { 6 | namespace widget { 7 | 8 | 9 | /** Transforms appearance only, not positions of events */ 10 | struct TransformWidget : Widget { 11 | /** The transformation matrix */ 12 | float transform[6]; 13 | 14 | TransformWidget() { 15 | identity(); 16 | } 17 | 18 | void identity() { 19 | nvgTransformIdentity(transform); 20 | } 21 | 22 | void translate(math::Vec delta) { 23 | float t[6]; 24 | nvgTransformTranslate(t, VEC_ARGS(delta)); 25 | nvgTransformPremultiply(transform, t); 26 | } 27 | 28 | void rotate(float angle) { 29 | float t[6]; 30 | nvgTransformRotate(t, angle); 31 | nvgTransformPremultiply(transform, t); 32 | } 33 | 34 | void rotate(float angle, math::Vec origin) { 35 | translate(origin); 36 | rotate(angle); 37 | translate(origin.neg()); 38 | } 39 | 40 | void scale(math::Vec s) { 41 | float t[6]; 42 | nvgTransformScale(t, s.x, s.y); 43 | nvgTransformPremultiply(transform, t); 44 | } 45 | 46 | void draw(const DrawArgs& args) override { 47 | // No need to save the state because that is done in the parent 48 | nvgTransform(args.vg, transform[0], transform[1], transform[2], transform[3], transform[4], transform[5]); 49 | Widget::draw(args); 50 | } 51 | 52 | void drawLayer(const DrawArgs& args, int layer) override { 53 | // No need to save the state because that is done in the parent 54 | nvgTransform(args.vg, transform[0], transform[1], transform[2], transform[3], transform[4], transform[5]); 55 | Widget::drawLayer(args, layer); 56 | } 57 | }; 58 | 59 | 60 | } // namespace widget 61 | } // namespace rack 62 | -------------------------------------------------------------------------------- /include/widget/TransparentWidget.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | 5 | namespace rack { 6 | namespace widget { 7 | 8 | 9 | /** A Widget that does not respond to events and does not pass events to children */ 10 | struct TransparentWidget : Widget { 11 | /** Override behavior to do nothing instead. */ 12 | void onHover(const HoverEvent& e) override {} 13 | void onButton(const ButtonEvent& e) override {} 14 | void onHoverKey(const HoverKeyEvent& e) override {} 15 | void onHoverText(const HoverTextEvent& e) override {} 16 | void onHoverScroll(const HoverScrollEvent& e) override {} 17 | void onDragHover(const DragHoverEvent& e) override {} 18 | void onPathDrop(const PathDropEvent& e) override {} 19 | }; 20 | 21 | 22 | } // namespace widget 23 | } // namespace rack 24 | -------------------------------------------------------------------------------- /include/widget/ZoomWidget.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | 5 | namespace rack { 6 | namespace widget { 7 | 8 | 9 | /** Resizes the scale of appearance and PositionEvents of children. */ 10 | struct ZoomWidget : Widget { 11 | /** Use setZoom() and getZoom() instead of using this variable directly. */ 12 | float zoom = 1.f; 13 | 14 | math::Vec getRelativeOffset(math::Vec v, Widget* ancestor) override; 15 | float getRelativeZoom(Widget* ancestor) override; 16 | math::Rect getViewport(math::Rect r) override; 17 | float getZoom(); 18 | /** Sets zoom scale and triggers DirtyEvent recursively if scale is changed, so children FramebufferWidgets are redrawn. */ 19 | void setZoom(float zoom); 20 | void draw(const DrawArgs& args) override; 21 | void drawLayer(const DrawArgs& args, int layer) override; 22 | 23 | void onHover(const HoverEvent& e) override { 24 | HoverEvent e2 = e; 25 | e2.pos = e.pos.div(zoom); 26 | Widget::onHover(e2); 27 | } 28 | void onButton(const ButtonEvent& e) override { 29 | ButtonEvent e2 = e; 30 | e2.pos = e.pos.div(zoom); 31 | Widget::onButton(e2); 32 | } 33 | void onHoverKey(const HoverKeyEvent& e) override { 34 | HoverKeyEvent e2 = e; 35 | e2.pos = e.pos.div(zoom); 36 | Widget::onHoverKey(e2); 37 | } 38 | void onHoverText(const HoverTextEvent& e) override { 39 | HoverTextEvent e2 = e; 40 | e2.pos = e.pos.div(zoom); 41 | Widget::onHoverText(e2); 42 | } 43 | void onHoverScroll(const HoverScrollEvent& e) override { 44 | HoverScrollEvent e2 = e; 45 | e2.pos = e.pos.div(zoom); 46 | Widget::onHoverScroll(e2); 47 | } 48 | void onDragHover(const DragHoverEvent& e) override { 49 | DragHoverEvent e2 = e; 50 | e2.pos = e.pos.div(zoom); 51 | Widget::onDragHover(e2); 52 | } 53 | void onPathDrop(const PathDropEvent& e) override { 54 | PathDropEvent e2 = e; 55 | e2.pos = e.pos.div(zoom); 56 | Widget::onPathDrop(e2); 57 | } 58 | }; 59 | 60 | 61 | } // namespace widget 62 | } // namespace rack 63 | -------------------------------------------------------------------------------- /include/window/Svg.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | 11 | namespace rack { 12 | namespace window { 13 | 14 | 15 | /** Arbitrary DPI, standardized for Rack. */ 16 | static const float SVG_DPI = 75.f; 17 | static const float MM_PER_IN = 25.4f; 18 | 19 | 20 | /** Converts inch measurements to pixels */ 21 | inline float in2px(float in) { 22 | return in * SVG_DPI; 23 | } 24 | 25 | inline math::Vec in2px(math::Vec in) { 26 | return in.mult(SVG_DPI); 27 | } 28 | 29 | /** Converts millimeter measurements to pixels */ 30 | inline float mm2px(float mm) { 31 | return mm * (SVG_DPI / MM_PER_IN); 32 | } 33 | 34 | inline math::Vec mm2px(math::Vec mm) { 35 | return mm.mult(SVG_DPI / MM_PER_IN); 36 | } 37 | 38 | 39 | /** Scalable Vector Graphics document */ 40 | struct Svg { 41 | NSVGimage* handle = NULL; 42 | 43 | ~Svg(); 44 | /** Don't call this directly. Use `Svg::load()` for caching. */ 45 | void loadFile(const std::string& filename); 46 | /** Loads SVG data from a string. */ 47 | void loadString(const std::string& str); 48 | /** Returns the SVG page size in pixels. */ 49 | math::Vec getSize(); 50 | int getNumShapes(); 51 | int getNumPaths(); 52 | int getNumPoints(); 53 | void draw(NVGcontext* vg); 54 | 55 | /** Loads Svg from a cache. */ 56 | static std::shared_ptr load(const std::string& filename); 57 | }; 58 | 59 | DEPRECATED typedef Svg SVG; 60 | 61 | 62 | void svgDraw(NVGcontext* vg, NSVGimage* svg); 63 | 64 | 65 | } // namespace window 66 | } // namespace rack 67 | -------------------------------------------------------------------------------- /plugins/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VCVRack/Rack/768d859187d64aed4d3d3db1f9c3aef596676116/plugins/.gitignore -------------------------------------------------------------------------------- /presets/CV-CC/0_CC 0-15.vcvm: -------------------------------------------------------------------------------- 1 | { 2 | "plugin": "Core", 3 | "version": "2.0.0", 4 | "model": "CV-CC", 5 | "data": { 6 | "ccs": [ 7 | 0, 8 | 1, 9 | 2, 10 | 3, 11 | 4, 12 | 5, 13 | 6, 14 | 7, 15 | 8, 16 | 9, 17 | 10, 18 | 11, 19 | 12, 20 | 13, 21 | 14, 22 | 15 23 | ] 24 | } 25 | } -------------------------------------------------------------------------------- /presets/CV-CC/1_CC 16-31.vcvm: -------------------------------------------------------------------------------- 1 | { 2 | "plugin": "Core", 3 | "version": "2.0.0", 4 | "model": "CV-CC", 5 | "data": { 6 | "ccs": [ 7 | 16, 8 | 17, 9 | 18, 10 | 19, 11 | 20, 12 | 21, 13 | 22, 14 | 23, 15 | 24, 16 | 25, 17 | 26, 18 | 27, 19 | 28, 20 | 29, 21 | 30, 22 | 31 23 | ] 24 | } 25 | } -------------------------------------------------------------------------------- /presets/CV-CC/2_CC 32-47.vcvm: -------------------------------------------------------------------------------- 1 | { 2 | "plugin": "Core", 3 | "version": "2.0.0", 4 | "model": "CV-CC", 5 | "data": { 6 | "ccs": [ 7 | 32, 8 | 33, 9 | 34, 10 | 35, 11 | 36, 12 | 37, 13 | 38, 14 | 39, 15 | 40, 16 | 41, 17 | 42, 18 | 43, 19 | 44, 20 | 45, 21 | 46, 22 | 47 23 | ] 24 | } 25 | } -------------------------------------------------------------------------------- /presets/CV-CC/3_CC 48-63.vcvm: -------------------------------------------------------------------------------- 1 | { 2 | "plugin": "Core", 3 | "version": "2.0.0", 4 | "model": "CV-CC", 5 | "data": { 6 | "ccs": [ 7 | 48, 8 | 49, 9 | 50, 10 | 51, 11 | 52, 12 | 53, 13 | 54, 14 | 55, 15 | 56, 16 | 57, 17 | 58, 18 | 59, 19 | 60, 20 | 61, 21 | 62, 22 | 63 23 | ] 24 | } 25 | } -------------------------------------------------------------------------------- /presets/CV-CC/4_CC 64-79.vcvm: -------------------------------------------------------------------------------- 1 | { 2 | "plugin": "Core", 3 | "version": "2.0.0", 4 | "model": "CV-CC", 5 | "data": { 6 | "ccs": [ 7 | 64, 8 | 65, 9 | 66, 10 | 67, 11 | 68, 12 | 69, 13 | 70, 14 | 71, 15 | 72, 16 | 73, 17 | 74, 18 | 75, 19 | 76, 20 | 77, 21 | 78, 22 | 79 23 | ] 24 | } 25 | } -------------------------------------------------------------------------------- /presets/CV-CC/5_CC 80-95.vcvm: -------------------------------------------------------------------------------- 1 | { 2 | "plugin": "Core", 3 | "version": "2.0.0", 4 | "model": "CV-CC", 5 | "data": { 6 | "ccs": [ 7 | 80, 8 | 81, 9 | 82, 10 | 83, 11 | 84, 12 | 85, 13 | 86, 14 | 87, 15 | 88, 16 | 89, 17 | 90, 18 | 91, 19 | 92, 20 | 93, 21 | 94, 22 | 95 23 | ] 24 | } 25 | } -------------------------------------------------------------------------------- /presets/CV-CC/6_CC 96-111.vcvm: -------------------------------------------------------------------------------- 1 | { 2 | "plugin": "Core", 3 | "version": "2.0.0", 4 | "model": "CV-CC", 5 | "data": { 6 | "ccs": [ 7 | 96, 8 | 97, 9 | 98, 10 | 99, 11 | 100, 12 | 101, 13 | 102, 14 | 103, 15 | 104, 16 | 105, 17 | 106, 18 | 107, 19 | 108, 20 | 109, 21 | 110, 22 | 111 23 | ] 24 | } 25 | } -------------------------------------------------------------------------------- /presets/CV-CC/7_CC 112-127.vcvm: -------------------------------------------------------------------------------- 1 | { 2 | "plugin": "Core", 3 | "version": "2.0.0", 4 | "model": "CV-CC", 5 | "data": { 6 | "ccs": [ 7 | 112, 8 | 113, 9 | 114, 10 | 115, 11 | 116, 12 | 117, 13 | 118, 14 | 119, 15 | 120, 16 | 121, 17 | 122, 18 | 123, 19 | 124, 20 | 125, 21 | 126, 22 | 127 23 | ] 24 | } 25 | } -------------------------------------------------------------------------------- /presets/CV-Gate/0_C-1-D#0.vcvm: -------------------------------------------------------------------------------- 1 | { 2 | "plugin": "Core", 3 | "version": "2.0.0", 4 | "model": "CV-Gate", 5 | "data": { 6 | "notes": [ 7 | 12, 8 | 13, 9 | 14, 10 | 15, 11 | 8, 12 | 9, 13 | 10, 14 | 11, 15 | 4, 16 | 5, 17 | 6, 18 | 7, 19 | 0, 20 | 1, 21 | 2, 22 | 3 23 | ] 24 | } 25 | } -------------------------------------------------------------------------------- /presets/CV-Gate/1_C0-D#1.vcvm: -------------------------------------------------------------------------------- 1 | { 2 | "plugin": "Core", 3 | "version": "2.0.0", 4 | "model": "CV-Gate", 5 | "data": { 6 | "notes": [ 7 | 24, 8 | 25, 9 | 26, 10 | 27, 11 | 20, 12 | 21, 13 | 22, 14 | 23, 15 | 16, 16 | 17, 17 | 18, 18 | 19, 19 | 12, 20 | 13, 21 | 14, 22 | 15 23 | ] 24 | } 25 | } -------------------------------------------------------------------------------- /presets/CV-Gate/2_C1-D#2.vcvm: -------------------------------------------------------------------------------- 1 | { 2 | "plugin": "Core", 3 | "version": "2.0.0", 4 | "model": "CV-Gate", 5 | "data": { 6 | "notes": [ 7 | 36, 8 | 37, 9 | 38, 10 | 39, 11 | 32, 12 | 33, 13 | 34, 14 | 35, 15 | 28, 16 | 29, 17 | 30, 18 | 31, 19 | 24, 20 | 25, 21 | 26, 22 | 27 23 | ] 24 | } 25 | } -------------------------------------------------------------------------------- /presets/CV-Gate/3_C2-D#3.vcvm: -------------------------------------------------------------------------------- 1 | { 2 | "plugin": "Core", 3 | "version": "2.0.0", 4 | "model": "CV-Gate", 5 | "data": { 6 | "notes": [ 7 | 48, 8 | 49, 9 | 50, 10 | 51, 11 | 44, 12 | 45, 13 | 46, 14 | 47, 15 | 40, 16 | 41, 17 | 42, 18 | 43, 19 | 36, 20 | 37, 21 | 38, 22 | 39 23 | ] 24 | } 25 | } -------------------------------------------------------------------------------- /presets/CV-Gate/4_C3-D#4.vcvm: -------------------------------------------------------------------------------- 1 | { 2 | "plugin": "Core", 3 | "version": "2.0.0", 4 | "model": "CV-Gate", 5 | "data": { 6 | "notes": [ 7 | 60, 8 | 61, 9 | 62, 10 | 63, 11 | 56, 12 | 57, 13 | 58, 14 | 59, 15 | 52, 16 | 53, 17 | 54, 18 | 55, 19 | 48, 20 | 49, 21 | 50, 22 | 51 23 | ] 24 | } 25 | } -------------------------------------------------------------------------------- /presets/CV-Gate/5_C4-D#5.vcvm: -------------------------------------------------------------------------------- 1 | { 2 | "plugin": "Core", 3 | "version": "2.0.0", 4 | "model": "CV-Gate", 5 | "data": { 6 | "notes": [ 7 | 72, 8 | 73, 9 | 74, 10 | 75, 11 | 68, 12 | 69, 13 | 70, 14 | 71, 15 | 64, 16 | 65, 17 | 66, 18 | 67, 19 | 60, 20 | 61, 21 | 62, 22 | 63 23 | ] 24 | } 25 | } -------------------------------------------------------------------------------- /presets/CV-Gate/6_C5-D#6.vcvm: -------------------------------------------------------------------------------- 1 | { 2 | "plugin": "Core", 3 | "version": "2.0.0", 4 | "model": "CV-Gate", 5 | "data": { 6 | "notes": [ 7 | 84, 8 | 85, 9 | 86, 10 | 87, 11 | 80, 12 | 81, 13 | 82, 14 | 83, 15 | 76, 16 | 77, 17 | 78, 18 | 79, 19 | 72, 20 | 73, 21 | 74, 22 | 75 23 | ] 24 | } 25 | } -------------------------------------------------------------------------------- /presets/CV-Gate/7_C6-D#7.vcvm: -------------------------------------------------------------------------------- 1 | { 2 | "plugin": "Core", 3 | "version": "2.0.0", 4 | "model": "CV-Gate", 5 | "data": { 6 | "notes": [ 7 | 96, 8 | 97, 9 | 98, 10 | 99, 11 | 92, 12 | 93, 13 | 94, 14 | 95, 15 | 88, 16 | 89, 17 | 90, 18 | 91, 19 | 84, 20 | 85, 21 | 86, 22 | 87 23 | ] 24 | } 25 | } -------------------------------------------------------------------------------- /presets/CV-Gate/8_C7-D#8.vcvm: -------------------------------------------------------------------------------- 1 | { 2 | "plugin": "Core", 3 | "version": "2.0.0", 4 | "model": "CV-Gate", 5 | "data": { 6 | "notes": [ 7 | 108, 8 | 109, 9 | 110, 10 | 111, 11 | 104, 12 | 105, 13 | 106, 14 | 107, 15 | 100, 16 | 101, 17 | 102, 18 | 103, 19 | 96, 20 | 97, 21 | 98, 22 | 99 23 | ] 24 | } 25 | } -------------------------------------------------------------------------------- /presets/CV-Gate/9_C8-D#9.vcvm: -------------------------------------------------------------------------------- 1 | { 2 | "plugin": "Core", 3 | "version": "2.0.0", 4 | "model": "CV-Gate", 5 | "data": { 6 | "notes": [ 7 | 120, 8 | 121, 9 | 122, 10 | 123, 11 | 116, 12 | 117, 13 | 118, 14 | 119, 15 | 112, 16 | 113, 17 | 114, 18 | 115, 19 | 108, 20 | 109, 21 | 110, 22 | 111 23 | ] 24 | } 25 | } -------------------------------------------------------------------------------- /presets/MIDICCToCVInterface/0_CC 0-15.vcvm: -------------------------------------------------------------------------------- 1 | { 2 | "plugin": "Core", 3 | "version": "2.0.0", 4 | "model": "MIDICCToCVInterface", 5 | "data": { 6 | "ccs": [ 7 | 0, 8 | 1, 9 | 2, 10 | 3, 11 | 4, 12 | 5, 13 | 6, 14 | 7, 15 | 8, 16 | 9, 17 | 10, 18 | 11, 19 | 12, 20 | 13, 21 | 14, 22 | 15 23 | ] 24 | } 25 | } -------------------------------------------------------------------------------- /presets/MIDICCToCVInterface/1_CC 16-31.vcvm: -------------------------------------------------------------------------------- 1 | { 2 | "plugin": "Core", 3 | "version": "2.0.0", 4 | "model": "MIDICCToCVInterface", 5 | "data": { 6 | "ccs": [ 7 | 16, 8 | 17, 9 | 18, 10 | 19, 11 | 20, 12 | 21, 13 | 22, 14 | 23, 15 | 24, 16 | 25, 17 | 26, 18 | 27, 19 | 28, 20 | 29, 21 | 30, 22 | 31 23 | ] 24 | } 25 | } -------------------------------------------------------------------------------- /presets/MIDICCToCVInterface/2_CC 32-47.vcvm: -------------------------------------------------------------------------------- 1 | { 2 | "plugin": "Core", 3 | "version": "2.0.0", 4 | "model": "MIDICCToCVInterface", 5 | "data": { 6 | "ccs": [ 7 | 32, 8 | 33, 9 | 34, 10 | 35, 11 | 36, 12 | 37, 13 | 38, 14 | 39, 15 | 40, 16 | 41, 17 | 42, 18 | 43, 19 | 44, 20 | 45, 21 | 46, 22 | 47 23 | ] 24 | } 25 | } -------------------------------------------------------------------------------- /presets/MIDICCToCVInterface/3_CC 48-63.vcvm: -------------------------------------------------------------------------------- 1 | { 2 | "plugin": "Core", 3 | "version": "2.0.0", 4 | "model": "MIDICCToCVInterface", 5 | "data": { 6 | "ccs": [ 7 | 48, 8 | 49, 9 | 50, 10 | 51, 11 | 52, 12 | 53, 13 | 54, 14 | 55, 15 | 56, 16 | 57, 17 | 58, 18 | 59, 19 | 60, 20 | 61, 21 | 62, 22 | 63 23 | ] 24 | } 25 | } -------------------------------------------------------------------------------- /presets/MIDICCToCVInterface/4_CC 64-79.vcvm: -------------------------------------------------------------------------------- 1 | { 2 | "plugin": "Core", 3 | "version": "2.0.0", 4 | "model": "MIDICCToCVInterface", 5 | "data": { 6 | "ccs": [ 7 | 64, 8 | 65, 9 | 66, 10 | 67, 11 | 68, 12 | 69, 13 | 70, 14 | 71, 15 | 72, 16 | 73, 17 | 74, 18 | 75, 19 | 76, 20 | 77, 21 | 78, 22 | 79 23 | ] 24 | } 25 | } -------------------------------------------------------------------------------- /presets/MIDICCToCVInterface/5_CC 80-95.vcvm: -------------------------------------------------------------------------------- 1 | { 2 | "plugin": "Core", 3 | "version": "2.0.0", 4 | "model": "MIDICCToCVInterface", 5 | "data": { 6 | "ccs": [ 7 | 80, 8 | 81, 9 | 82, 10 | 83, 11 | 84, 12 | 85, 13 | 86, 14 | 87, 15 | 88, 16 | 89, 17 | 90, 18 | 91, 19 | 92, 20 | 93, 21 | 94, 22 | 95 23 | ] 24 | } 25 | } -------------------------------------------------------------------------------- /presets/MIDICCToCVInterface/6_CC 96-111.vcvm: -------------------------------------------------------------------------------- 1 | { 2 | "plugin": "Core", 3 | "version": "2.0.0", 4 | "model": "MIDICCToCVInterface", 5 | "data": { 6 | "ccs": [ 7 | 96, 8 | 97, 9 | 98, 10 | 99, 11 | 100, 12 | 101, 13 | 102, 14 | 103, 15 | 104, 16 | 105, 17 | 106, 18 | 107, 19 | 108, 20 | 109, 21 | 110, 22 | 111 23 | ] 24 | } 25 | } -------------------------------------------------------------------------------- /presets/MIDICCToCVInterface/7_CC 112-127.vcvm: -------------------------------------------------------------------------------- 1 | { 2 | "plugin": "Core", 3 | "version": "2.0.0", 4 | "model": "MIDICCToCVInterface", 5 | "data": { 6 | "ccs": [ 7 | 112, 8 | 113, 9 | 114, 10 | 115, 11 | 116, 12 | 117, 13 | 118, 14 | 119, 15 | 120, 16 | 121, 17 | 122, 18 | 123, 19 | 124, 20 | 125, 21 | 126, 22 | 127 23 | ] 24 | } 25 | } -------------------------------------------------------------------------------- /presets/MIDITriggerToCVInterface/0_C-1-D#0.vcvm: -------------------------------------------------------------------------------- 1 | { 2 | "plugin": "Core", 3 | "version": "2.0.0", 4 | "model": "MIDITriggerToCVInterface", 5 | "data": { 6 | "notes": [ 7 | 12, 8 | 13, 9 | 14, 10 | 15, 11 | 8, 12 | 9, 13 | 10, 14 | 11, 15 | 4, 16 | 5, 17 | 6, 18 | 7, 19 | 0, 20 | 1, 21 | 2, 22 | 3 23 | ] 24 | } 25 | } -------------------------------------------------------------------------------- /presets/MIDITriggerToCVInterface/1_C0-D#1.vcvm: -------------------------------------------------------------------------------- 1 | { 2 | "plugin": "Core", 3 | "version": "2.0.0", 4 | "model": "MIDITriggerToCVInterface", 5 | "data": { 6 | "notes": [ 7 | 24, 8 | 25, 9 | 26, 10 | 27, 11 | 20, 12 | 21, 13 | 22, 14 | 23, 15 | 16, 16 | 17, 17 | 18, 18 | 19, 19 | 12, 20 | 13, 21 | 14, 22 | 15 23 | ] 24 | } 25 | } -------------------------------------------------------------------------------- /presets/MIDITriggerToCVInterface/2_C1-D#2.vcvm: -------------------------------------------------------------------------------- 1 | { 2 | "plugin": "Core", 3 | "version": "2.0.0", 4 | "model": "MIDITriggerToCVInterface", 5 | "data": { 6 | "notes": [ 7 | 36, 8 | 37, 9 | 38, 10 | 39, 11 | 32, 12 | 33, 13 | 34, 14 | 35, 15 | 28, 16 | 29, 17 | 30, 18 | 31, 19 | 24, 20 | 25, 21 | 26, 22 | 27 23 | ] 24 | } 25 | } -------------------------------------------------------------------------------- /presets/MIDITriggerToCVInterface/3_C2-D#3.vcvm: -------------------------------------------------------------------------------- 1 | { 2 | "plugin": "Core", 3 | "version": "2.0.0", 4 | "model": "MIDITriggerToCVInterface", 5 | "data": { 6 | "notes": [ 7 | 48, 8 | 49, 9 | 50, 10 | 51, 11 | 44, 12 | 45, 13 | 46, 14 | 47, 15 | 40, 16 | 41, 17 | 42, 18 | 43, 19 | 36, 20 | 37, 21 | 38, 22 | 39 23 | ] 24 | } 25 | } -------------------------------------------------------------------------------- /presets/MIDITriggerToCVInterface/4_C3-D#4.vcvm: -------------------------------------------------------------------------------- 1 | { 2 | "plugin": "Core", 3 | "version": "2.0.0", 4 | "model": "MIDITriggerToCVInterface", 5 | "data": { 6 | "notes": [ 7 | 60, 8 | 61, 9 | 62, 10 | 63, 11 | 56, 12 | 57, 13 | 58, 14 | 59, 15 | 52, 16 | 53, 17 | 54, 18 | 55, 19 | 48, 20 | 49, 21 | 50, 22 | 51 23 | ] 24 | } 25 | } -------------------------------------------------------------------------------- /presets/MIDITriggerToCVInterface/5_C4-D#5.vcvm: -------------------------------------------------------------------------------- 1 | { 2 | "plugin": "Core", 3 | "version": "2.0.0", 4 | "model": "MIDITriggerToCVInterface", 5 | "data": { 6 | "notes": [ 7 | 72, 8 | 73, 9 | 74, 10 | 75, 11 | 68, 12 | 69, 13 | 70, 14 | 71, 15 | 64, 16 | 65, 17 | 66, 18 | 67, 19 | 60, 20 | 61, 21 | 62, 22 | 63 23 | ] 24 | } 25 | } -------------------------------------------------------------------------------- /presets/MIDITriggerToCVInterface/6_C5-D#6.vcvm: -------------------------------------------------------------------------------- 1 | { 2 | "plugin": "Core", 3 | "version": "2.0.0", 4 | "model": "MIDITriggerToCVInterface", 5 | "data": { 6 | "notes": [ 7 | 84, 8 | 85, 9 | 86, 10 | 87, 11 | 80, 12 | 81, 13 | 82, 14 | 83, 15 | 76, 16 | 77, 17 | 78, 18 | 79, 19 | 72, 20 | 73, 21 | 74, 22 | 75 23 | ] 24 | } 25 | } -------------------------------------------------------------------------------- /presets/MIDITriggerToCVInterface/7_C6-D#7.vcvm: -------------------------------------------------------------------------------- 1 | { 2 | "plugin": "Core", 3 | "version": "2.0.0", 4 | "model": "MIDITriggerToCVInterface", 5 | "data": { 6 | "notes": [ 7 | 96, 8 | 97, 9 | 98, 10 | 99, 11 | 92, 12 | 93, 13 | 94, 14 | 95, 15 | 88, 16 | 89, 17 | 90, 18 | 91, 19 | 84, 20 | 85, 21 | 86, 22 | 87 23 | ] 24 | } 25 | } -------------------------------------------------------------------------------- /presets/MIDITriggerToCVInterface/8_C7-D#8.vcvm: -------------------------------------------------------------------------------- 1 | { 2 | "plugin": "Core", 3 | "version": "2.0.0", 4 | "model": "MIDITriggerToCVInterface", 5 | "data": { 6 | "notes": [ 7 | 108, 8 | 109, 9 | 110, 10 | 111, 11 | 104, 12 | 105, 13 | 106, 14 | 107, 15 | 100, 16 | 101, 17 | 102, 18 | 103, 19 | 96, 20 | 97, 21 | 98, 22 | 99 23 | ] 24 | } 25 | } -------------------------------------------------------------------------------- /presets/MIDITriggerToCVInterface/9_C8-D#9.vcvm: -------------------------------------------------------------------------------- 1 | { 2 | "plugin": "Core", 3 | "version": "2.0.0", 4 | "model": "MIDITriggerToCVInterface", 5 | "data": { 6 | "notes": [ 7 | 120, 8 | 121, 9 | 122, 10 | 123, 11 | 116, 12 | 117, 13 | 118, 14 | 119, 15 | 112, 16 | 113, 17 | 114, 18 | 115, 19 | 108, 20 | 109, 21 | 110, 22 | 111 23 | ] 24 | } 25 | } -------------------------------------------------------------------------------- /res/ComponentLibrary/BefacoSlidePot.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 11 | 12 | -------------------------------------------------------------------------------- /res/ComponentLibrary/Davies1900hBlack_bg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /res/ComponentLibrary/Davies1900hRed_bg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /res/ComponentLibrary/Rogan1PBlue_fg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /res/ComponentLibrary/Rogan1PGreen_fg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /res/ComponentLibrary/Rogan1PRed_fg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /res/ComponentLibrary/Rogan1PSBlue_fg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /res/ComponentLibrary/Rogan1PSGreen_fg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /res/ComponentLibrary/Rogan1PSRed_fg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /res/ComponentLibrary/Rogan1PSWhite_fg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /res/ComponentLibrary/Rogan1PS_bg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /res/ComponentLibrary/Rogan1PWhite_fg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /res/ComponentLibrary/Rogan1P_bg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /res/ComponentLibrary/Rogan2PBlue_fg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /res/ComponentLibrary/Rogan2PGreen_fg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /res/ComponentLibrary/Rogan2PRed_fg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /res/ComponentLibrary/Rogan2PSBlue_fg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /res/ComponentLibrary/Rogan2PSGreen_fg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /res/ComponentLibrary/Rogan2PSRed_fg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /res/ComponentLibrary/Rogan2PSWhite_fg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /res/ComponentLibrary/Rogan2PS_bg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /res/ComponentLibrary/Rogan2PWhite_fg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /res/ComponentLibrary/Rogan2P_bg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /res/ComponentLibrary/Rogan2SGray_fg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /res/ComponentLibrary/Rogan2S_bg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /res/ComponentLibrary/Rogan3PBlue_fg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /res/ComponentLibrary/Rogan3PGreen_fg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /res/ComponentLibrary/Rogan3PRed_fg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /res/ComponentLibrary/Rogan3PWhite_fg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /res/ComponentLibrary/Rogan3P_bg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /res/ComponentLibrary/Rogan5PSGray_fg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /res/ComponentLibrary/Rogan5PS_bg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /res/ComponentLibrary/Rogan6PSWhite_fg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /res/ComponentLibrary/Rogan6PS_bg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /res/ComponentLibrary/Trimpot.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 10 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /res/ComponentLibrary/Trimpot_bg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /res/ComponentLibrary/VCVSlider.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /res/ComponentLibrary/VCVSliderHandle.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /res/fonts/DSEG7ClassicMini-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VCVRack/Rack/768d859187d64aed4d3d3db1f9c3aef596676116/res/fonts/DSEG7ClassicMini-Bold.ttf -------------------------------------------------------------------------------- /res/fonts/DSEG7ClassicMini-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VCVRack/Rack/768d859187d64aed4d3d3db1f9c3aef596676116/res/fonts/DSEG7ClassicMini-BoldItalic.ttf -------------------------------------------------------------------------------- /res/fonts/DSEG7ClassicMini-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VCVRack/Rack/768d859187d64aed4d3d3db1f9c3aef596676116/res/fonts/DSEG7ClassicMini-Italic.ttf -------------------------------------------------------------------------------- /res/fonts/DSEG7ClassicMini-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VCVRack/Rack/768d859187d64aed4d3d3db1f9c3aef596676116/res/fonts/DSEG7ClassicMini-Light.ttf -------------------------------------------------------------------------------- /res/fonts/DSEG7ClassicMini-LightItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VCVRack/Rack/768d859187d64aed4d3d3db1f9c3aef596676116/res/fonts/DSEG7ClassicMini-LightItalic.ttf -------------------------------------------------------------------------------- /res/fonts/DSEG7ClassicMini-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VCVRack/Rack/768d859187d64aed4d3d3db1f9c3aef596676116/res/fonts/DSEG7ClassicMini-Regular.ttf -------------------------------------------------------------------------------- /res/fonts/DejaVuSans.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VCVRack/Rack/768d859187d64aed4d3d3db1f9c3aef596676116/res/fonts/DejaVuSans.ttf -------------------------------------------------------------------------------- /res/fonts/NotoEmoji-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VCVRack/Rack/768d859187d64aed4d3d3db1f9c3aef596676116/res/fonts/NotoEmoji-Medium.ttf -------------------------------------------------------------------------------- /res/fonts/NotoSansJP-Medium.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VCVRack/Rack/768d859187d64aed4d3d3db1f9c3aef596676116/res/fonts/NotoSansJP-Medium.otf -------------------------------------------------------------------------------- /res/fonts/NotoSansSC-Medium.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VCVRack/Rack/768d859187d64aed4d3d3db1f9c3aef596676116/res/fonts/NotoSansSC-Medium.otf -------------------------------------------------------------------------------- /res/fonts/Nunito-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VCVRack/Rack/768d859187d64aed4d3d3db1f9c3aef596676116/res/fonts/Nunito-Bold.ttf -------------------------------------------------------------------------------- /res/fonts/ShareTechMono-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VCVRack/Rack/768d859187d64aed4d3d3db1f9c3aef596676116/res/fonts/ShareTechMono-Regular.ttf -------------------------------------------------------------------------------- /res/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VCVRack/Rack/768d859187d64aed4d3d3db1f9c3aef596676116/res/icon.png -------------------------------------------------------------------------------- /src/app/CircularShadow.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | namespace rack { 5 | namespace app { 6 | 7 | 8 | CircularShadow::CircularShadow() { 9 | blurRadius = 0; 10 | opacity = 0.15; 11 | } 12 | 13 | void CircularShadow::draw(const DrawArgs& args) { 14 | if (opacity <= 0.0) 15 | return; 16 | 17 | math::Vec center = box.size.div(2.0); 18 | float radius = center.x; 19 | NVGcolor icol = nvgRGBAf(0.0, 0.0, 0.0, opacity); 20 | NVGcolor ocol = nvgRGBAf(0.0, 0.0, 0.0, 0.0); 21 | nvgBeginPath(args.vg); 22 | if (blurRadius > 0.0) { 23 | nvgRect(args.vg, -blurRadius, -blurRadius, box.size.x + 2 * blurRadius, box.size.y + 2 * blurRadius); 24 | NVGpaint paint = nvgRadialGradient(args.vg, center.x, center.y, radius - blurRadius, radius, icol, ocol); 25 | nvgFillPaint(args.vg, paint); 26 | } 27 | else { 28 | nvgCircle(args.vg, center.x, center.y, radius); 29 | nvgFillColor(args.vg, icol); 30 | } 31 | nvgFill(args.vg); 32 | } 33 | 34 | 35 | } // namespace app 36 | } // namespace rack 37 | -------------------------------------------------------------------------------- /src/app/MultiLightWidget.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | namespace rack { 6 | namespace app { 7 | 8 | 9 | int MultiLightWidget::getNumColors() { 10 | return baseColors.size(); 11 | } 12 | 13 | 14 | void MultiLightWidget::addBaseColor(NVGcolor baseColor) { 15 | baseColors.push_back(baseColor); 16 | } 17 | 18 | void MultiLightWidget::setBrightnesses(const std::vector& brightnesses) { 19 | assert(brightnesses.size() == baseColors.size()); 20 | color = nvgRGBAf(0, 0, 0, 0); 21 | for (size_t i = 0; i < baseColors.size(); i++) { 22 | NVGcolor c = baseColors[i]; 23 | c.a *= math::clamp(brightnesses[i], 0.f, 1.f); 24 | color = color::screen(color, c); 25 | } 26 | color = color::clamp(color); 27 | } 28 | 29 | 30 | } // namespace app 31 | } // namespace rack 32 | -------------------------------------------------------------------------------- /src/app/SliderKnob.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | namespace rack { 5 | namespace app { 6 | 7 | 8 | SliderKnob::SliderKnob() { 9 | forceLinear = true; 10 | } 11 | 12 | void SliderKnob::onHover(const HoverEvent& e) { 13 | // Bypass Knob's circular hitbox detection 14 | ParamWidget::onHover(e); 15 | } 16 | 17 | void SliderKnob::onButton(const ButtonEvent& e) { 18 | ParamWidget::onButton(e); 19 | } 20 | 21 | 22 | } // namespace app 23 | } // namespace rack 24 | -------------------------------------------------------------------------------- /src/app/SvgButton.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | namespace rack { 5 | namespace app { 6 | 7 | 8 | SvgButton::SvgButton() { 9 | fb = new widget::FramebufferWidget; 10 | addChild(fb); 11 | 12 | shadow = new CircularShadow; 13 | fb->addChild(shadow); 14 | shadow->box.size = math::Vec(); 15 | 16 | sw = new widget::SvgWidget; 17 | fb->addChild(sw); 18 | } 19 | 20 | 21 | void SvgButton::onButton(const ButtonEvent& e) { 22 | OpaqueWidget::onButton(e); 23 | 24 | // Dispatch ActionEvent on left click 25 | if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_LEFT) { 26 | ActionEvent eAction; 27 | onAction(eAction); 28 | } 29 | } 30 | 31 | 32 | void SvgButton::addFrame(std::shared_ptr svg) { 33 | frames.push_back(svg); 34 | // If this is our first frame, automatically set SVG and size 35 | if (!sw->svg) { 36 | sw->setSvg(svg); 37 | box.size = sw->box.size; 38 | fb->box.size = sw->box.size; 39 | // Move shadow downward by 10% 40 | shadow->box.size = sw->box.size; 41 | shadow->box.pos = math::Vec(0, sw->box.size.y * 0.10); 42 | fb->setDirty(); 43 | } 44 | } 45 | 46 | 47 | void SvgButton::onDragStart(const DragStartEvent& e) { 48 | if (e.button != GLFW_MOUSE_BUTTON_LEFT) 49 | return; 50 | 51 | if (frames.size() >= 2) { 52 | sw->setSvg(frames[1]); 53 | fb->setDirty(); 54 | } 55 | } 56 | 57 | 58 | void SvgButton::onDragEnd(const DragEndEvent& e) { 59 | if (frames.size() >= 1) { 60 | sw->setSvg(frames[0]); 61 | fb->setDirty(); 62 | } 63 | } 64 | 65 | 66 | void SvgButton::onDragDrop(const DragDropEvent& e) { 67 | // Don't dispatch ActionEvent on DragDrop because it's already called on mouse down. 68 | // if (e.origin == this) { 69 | // ActionEvent eAction; 70 | // onAction(eAction); 71 | // } 72 | } 73 | 74 | 75 | } // namespace app 76 | } // namespace rack 77 | -------------------------------------------------------------------------------- /src/app/SvgKnob.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | namespace rack { 5 | namespace app { 6 | 7 | 8 | SvgKnob::SvgKnob() { 9 | fb = new widget::FramebufferWidget; 10 | addChild(fb); 11 | 12 | shadow = new CircularShadow; 13 | fb->addChild(shadow); 14 | shadow->box.size = math::Vec(); 15 | 16 | tw = new widget::TransformWidget; 17 | fb->addChild(tw); 18 | 19 | sw = new widget::SvgWidget; 20 | tw->addChild(sw); 21 | } 22 | 23 | void SvgKnob::setSvg(std::shared_ptr svg) { 24 | if (svg == sw->svg) 25 | return; 26 | 27 | sw->setSvg(svg); 28 | tw->box.size = sw->box.size; 29 | fb->box.size = sw->box.size; 30 | box.size = sw->box.size; 31 | 32 | shadow->box.size = sw->box.size; 33 | // Move shadow downward by 10% 34 | shadow->box.pos = math::Vec(0, sw->box.size.y * 0.10); 35 | // shadow->box = shadow->box.grow(math::Vec(2, 2)); 36 | 37 | fb->setDirty(); 38 | } 39 | 40 | void SvgKnob::onChange(const ChangeEvent& e) { 41 | float angle = 0.f; 42 | 43 | // Calculate angle from value 44 | engine::ParamQuantity* pq = getParamQuantity(); 45 | if (pq) { 46 | float value = pq->getValue(); 47 | if (!pq->isBounded()) { 48 | // Number of rotations equals value for unbounded range 49 | angle = value * (2 * M_PI); 50 | } 51 | else if (pq->getRange() == 0.f) { 52 | // Center angle for zero range 53 | angle = (minAngle + maxAngle) / 2.f; 54 | } 55 | else { 56 | // Proportional angle for finite range 57 | angle = math::rescale(value, pq->getMinValue(), pq->getMaxValue(), minAngle, maxAngle); 58 | } 59 | angle = std::fmod(angle, 2 * M_PI); 60 | } 61 | 62 | tw->identity(); 63 | // Rotate SVG 64 | math::Vec center = sw->box.getCenter(); 65 | tw->translate(center); 66 | tw->rotate(angle); 67 | tw->translate(center.neg()); 68 | fb->setDirty(); 69 | 70 | Knob::onChange(e); 71 | } 72 | 73 | 74 | } // namespace app 75 | } // namespace rack 76 | -------------------------------------------------------------------------------- /src/app/SvgPanel.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | namespace rack { 6 | namespace app { 7 | 8 | 9 | void PanelBorder::draw(const DrawArgs& args) { 10 | NVGcolor borderColor = nvgRGBAf(0.5, 0.5, 0.5, 0.5); 11 | nvgBeginPath(args.vg); 12 | nvgRect(args.vg, 0.5, 0.5, box.size.x - 1.0, box.size.y - 1.0); 13 | nvgStrokeColor(args.vg, borderColor); 14 | nvgStrokeWidth(args.vg, 1.0); 15 | nvgStroke(args.vg); 16 | } 17 | 18 | 19 | SvgPanel::SvgPanel() { 20 | fb = new widget::FramebufferWidget; 21 | addChild(fb); 22 | 23 | sw = new widget::SvgWidget; 24 | fb->addChild(sw); 25 | 26 | panelBorder = new PanelBorder; 27 | fb->addChild(panelBorder); 28 | } 29 | 30 | 31 | void SvgPanel::step() { 32 | if (APP->window->pixelRatio < 2.0) { 33 | // Small details draw poorly at low DPI, so oversample when drawing to the framebuffer 34 | fb->oversample = 2.0; 35 | } 36 | else { 37 | fb->oversample = 1.0; 38 | } 39 | 40 | Widget::step(); 41 | } 42 | 43 | 44 | void SvgPanel::setBackground(std::shared_ptr svg) { 45 | if (svg == this->svg) 46 | return; 47 | this->svg = svg; 48 | 49 | sw->setSvg(svg); 50 | 51 | // Round framebuffer size to nearest grid 52 | fb->box.size = sw->box.size.div(RACK_GRID_SIZE).round().mult(RACK_GRID_SIZE); 53 | panelBorder->box.size = fb->box.size; 54 | box.size = fb->box.size; 55 | 56 | fb->setDirty(); 57 | } 58 | 59 | 60 | } // namespace app 61 | } // namespace rack 62 | -------------------------------------------------------------------------------- /src/app/SvgPort.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | namespace rack { 5 | namespace app { 6 | 7 | 8 | SvgPort::SvgPort() { 9 | fb = new widget::FramebufferWidget; 10 | addChild(fb); 11 | 12 | shadow = new CircularShadow; 13 | fb->addChild(shadow); 14 | // Avoid breakage if plugins fail to call setSvg() 15 | // In that case, just disable the shadow. 16 | shadow->box.size = math::Vec(); 17 | 18 | sw = new widget::SvgWidget; 19 | fb->addChild(sw); 20 | } 21 | 22 | void SvgPort::setSvg(std::shared_ptr svg) { 23 | if (svg == sw->svg) 24 | return; 25 | 26 | sw->setSvg(svg); 27 | fb->box.size = sw->box.size; 28 | box.size = sw->box.size; 29 | 30 | // Move shadow downward by 10% 31 | shadow->box.size = sw->box.size; 32 | shadow->box.pos = math::Vec(0, sw->box.size.y * 0.10); 33 | 34 | fb->setDirty(); 35 | } 36 | 37 | 38 | } // namespace app 39 | } // namespace rack 40 | -------------------------------------------------------------------------------- /src/app/SvgScrew.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | namespace rack { 6 | namespace app { 7 | 8 | 9 | SvgScrew::SvgScrew() { 10 | fb = new widget::FramebufferWidget; 11 | addChild(fb); 12 | 13 | sw = new widget::SvgWidget; 14 | fb->addChild(sw); 15 | } 16 | 17 | 18 | void SvgScrew::setSvg(std::shared_ptr svg) { 19 | if (sw->svg == svg) 20 | return; 21 | 22 | sw->setSvg(svg); 23 | fb->box.size = sw->box.size; 24 | box.size = sw->box.size; 25 | 26 | fb->setDirty(); 27 | } 28 | 29 | 30 | } // namespace app 31 | } // namespace rack 32 | -------------------------------------------------------------------------------- /src/app/SvgSlider.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | namespace rack { 5 | namespace app { 6 | 7 | 8 | SvgSlider::SvgSlider() { 9 | fb = new widget::FramebufferWidget; 10 | addChild(fb); 11 | 12 | background = new widget::SvgWidget; 13 | fb->addChild(background); 14 | 15 | handle = new widget::SvgWidget; 16 | fb->addChild(handle); 17 | 18 | speed = 2.0; 19 | } 20 | 21 | 22 | void SvgSlider::setBackgroundSvg(std::shared_ptr svg) { 23 | if (svg == background->svg) 24 | return; 25 | 26 | background->setSvg(svg); 27 | box.size = background->box.size; 28 | fb->box.size = background->box.size; 29 | fb->setDirty(); 30 | } 31 | 32 | 33 | void SvgSlider::setHandleSvg(std::shared_ptr svg) { 34 | if (svg == handle->svg) 35 | return; 36 | 37 | handle->setSvg(svg); 38 | handle->box.pos = maxHandlePos; 39 | fb->setDirty(); 40 | } 41 | 42 | 43 | void SvgSlider::setHandlePos(math::Vec minHandlePos, math::Vec maxHandlePos) { 44 | this->minHandlePos = minHandlePos; 45 | this->maxHandlePos = maxHandlePos; 46 | 47 | // Set handle pos to maximum by default 48 | handle->box.pos = maxHandlePos; 49 | } 50 | 51 | 52 | void SvgSlider::setHandlePosCentered(math::Vec minHandlePosCentered, math::Vec maxHandlePosCentered) { 53 | setHandlePos( 54 | minHandlePosCentered.minus(handle->box.size.div(2)), 55 | maxHandlePosCentered.minus(handle->box.size.div(2)) 56 | ); 57 | } 58 | 59 | 60 | void SvgSlider::onChange(const ChangeEvent& e) { 61 | // Default position is max value 62 | float v = 1.f; 63 | engine::ParamQuantity* pq = getParamQuantity(); 64 | if (pq) { 65 | v = pq->getScaledValue(); 66 | } 67 | 68 | // Interpolate handle position 69 | handle->box.pos = minHandlePos.crossfade(maxHandlePos, v); 70 | fb->setDirty(); 71 | 72 | ParamWidget::onChange(e); 73 | } 74 | 75 | 76 | } // namespace app 77 | } // namespace rack 78 | -------------------------------------------------------------------------------- /src/app/SvgSwitch.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | namespace rack { 5 | namespace app { 6 | 7 | 8 | SvgSwitch::SvgSwitch() { 9 | fb = new widget::FramebufferWidget; 10 | addChild(fb); 11 | 12 | shadow = new CircularShadow; 13 | fb->addChild(shadow); 14 | shadow->box.size = math::Vec(); 15 | 16 | sw = new widget::SvgWidget; 17 | fb->addChild(sw); 18 | } 19 | 20 | 21 | SvgSwitch::~SvgSwitch() { 22 | } 23 | 24 | 25 | void SvgSwitch::addFrame(std::shared_ptr svg) { 26 | frames.push_back(svg); 27 | // If this is our first frame, automatically set SVG and size 28 | if (!sw->svg) { 29 | sw->setSvg(svg); 30 | box.size = sw->box.size; 31 | fb->box.size = sw->box.size; 32 | // Move shadow downward by 10% 33 | shadow->box.size = sw->box.size; 34 | shadow->box.pos = math::Vec(0, sw->box.size.y * 0.10); 35 | } 36 | } 37 | 38 | 39 | void SvgSwitch::onDragStart(const DragStartEvent& e) { 40 | Switch::onDragStart(e); 41 | if (e.button != GLFW_MOUSE_BUTTON_LEFT) 42 | return; 43 | 44 | // Set down frame if latch 45 | if (latch) { 46 | if (frames.size() >= 2) { 47 | sw->setSvg(frames[1]); 48 | fb->setDirty(); 49 | } 50 | } 51 | } 52 | 53 | 54 | void SvgSwitch::onDragEnd(const DragEndEvent& e) { 55 | Switch::onDragEnd(e); 56 | if (e.button != GLFW_MOUSE_BUTTON_LEFT) 57 | return; 58 | 59 | // Set up frame if latch 60 | if (latch) { 61 | if (frames.size() >= 1) { 62 | sw->setSvg(frames[0]); 63 | fb->setDirty(); 64 | } 65 | } 66 | } 67 | 68 | 69 | void SvgSwitch::onChange(const ChangeEvent& e) { 70 | if (!latch) { 71 | engine::ParamQuantity* pq = getParamQuantity(); 72 | if (!frames.empty() && pq) { 73 | int index = (int) std::round(pq->getValue() - pq->getMinValue()); 74 | index = math::clamp(index, 0, (int) frames.size() - 1); 75 | sw->setSvg(frames[index]); 76 | fb->setDirty(); 77 | } 78 | } 79 | ParamWidget::onChange(e); 80 | } 81 | 82 | 83 | } // namespace app 84 | } // namespace rack 85 | -------------------------------------------------------------------------------- /src/asset.mm: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | 5 | namespace rack { 6 | namespace asset { 7 | 8 | 9 | std::string getApplicationSupportDir() { 10 | @autoreleasepool { 11 | NSArray* paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES); 12 | NSString* path = [paths firstObject]; 13 | return [path UTF8String]; 14 | } 15 | } 16 | 17 | 18 | } // namespace asset 19 | } // namespace rack 20 | -------------------------------------------------------------------------------- /src/common.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | #if defined ARCH_WIN 6 | #include 7 | 8 | FILE* fopen_u8(const char* filename, const char* mode) { 9 | return _wfopen(rack::string::UTF8toUTF16(filename).c_str(), rack::string::UTF8toUTF16(mode).c_str()); 10 | } 11 | 12 | #endif 13 | 14 | 15 | namespace rack { 16 | 17 | 18 | const std::string APP_NAME = "VCV Rack"; 19 | const std::string APP_EDITION = "Free"; 20 | const std::string APP_EDITION_NAME = "Free"; 21 | const std::string APP_VERSION_MAJOR = "2"; 22 | const std::string APP_VERSION = TOSTRING(_RACK_VERSION); 23 | #if defined ARCH_WIN 24 | const std::string APP_OS = "win"; 25 | const std::string APP_OS_NAME = "Windows"; 26 | #elif defined ARCH_MAC 27 | const std::string APP_OS = "mac"; 28 | const std::string APP_OS_NAME = "macOS"; 29 | #elif defined ARCH_LIN 30 | const std::string APP_OS = "lin"; 31 | const std::string APP_OS_NAME = "Linux"; 32 | #endif 33 | #if defined ARCH_X64 34 | const std::string APP_CPU = "x64"; 35 | const std::string APP_CPU_NAME = "x64"; 36 | #elif defined ARCH_ARM64 37 | const std::string APP_CPU = "arm64"; 38 | const std::string APP_CPU_NAME = "ARM64"; 39 | #endif 40 | const std::string API_URL = "https://api.vcvrack.com"; 41 | 42 | 43 | Exception::Exception(const char* format, ...) { 44 | va_list args; 45 | va_start(args, format); 46 | msg = string::fV(format, args); 47 | va_end(args); 48 | } 49 | 50 | 51 | } // namespace rack 52 | -------------------------------------------------------------------------------- /src/context.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | 10 | namespace rack { 11 | 12 | 13 | Context::~Context() { 14 | // Deleting NULL is safe in C++. 15 | 16 | // Set pointers to NULL so other objects will segfault when attempting to access them 17 | 18 | INFO("Deleting window"); 19 | delete window; 20 | window = NULL; 21 | 22 | INFO("Deleting patch manager"); 23 | delete patch; 24 | patch = NULL; 25 | 26 | INFO("Deleting scene"); 27 | delete scene; 28 | scene = NULL; 29 | 30 | INFO("Deleting event state"); 31 | delete event; 32 | event = NULL; 33 | 34 | INFO("Deleting history state"); 35 | delete history; 36 | history = NULL; 37 | 38 | INFO("Deleting engine"); 39 | delete engine; 40 | engine = NULL; 41 | 42 | INFO("Deleting MIDI loopback"); 43 | delete midiLoopbackContext; 44 | midiLoopbackContext = NULL; 45 | } 46 | 47 | 48 | static thread_local Context* threadContext = NULL; 49 | 50 | Context* contextGet() { 51 | return threadContext; 52 | } 53 | 54 | // Apple's clang incorrectly compiles this function when -O2 or higher is enabled. 55 | #ifdef ARCH_MAC 56 | __attribute__((optnone)) 57 | #endif 58 | void contextSet(Context* context) { 59 | threadContext = context; 60 | } 61 | 62 | 63 | } // namespace rack 64 | -------------------------------------------------------------------------------- /src/core/plugin.cpp: -------------------------------------------------------------------------------- 1 | #include "plugin.hpp" 2 | 3 | 4 | namespace rack { 5 | namespace core { 6 | 7 | 8 | void init(rack::Plugin* p) { 9 | p->addModel(modelAudio2); 10 | p->addModel(modelAudio8); 11 | p->addModel(modelAudio16); 12 | p->addModel(modelMIDI_CV); 13 | p->addModel(modelMIDICC_CV); 14 | p->addModel(modelMIDI_Gate); 15 | p->addModel(modelMIDIMap); 16 | p->addModel(modelCV_MIDI); 17 | p->addModel(modelCV_MIDICC); 18 | p->addModel(modelGate_MIDI); 19 | p->addModel(modelBlank); 20 | p->addModel(modelNotes); 21 | } 22 | 23 | 24 | } // namespace core 25 | } // namespace rack 26 | -------------------------------------------------------------------------------- /src/dep.cpp: -------------------------------------------------------------------------------- 1 | // This source file compiles those annoying implementation-in-header libraries 2 | 3 | #include // for fopen_u8 4 | 5 | #define GLEW_STATIC 6 | #define GLEW_NO_GLU 7 | #include 8 | 9 | #include 10 | 11 | #define NANOVG_GL2_IMPLEMENTATION 12 | // #define NANOVG_GL3_IMPLEMENTATION 13 | // #define NANOVG_GLES2_IMPLEMENTATION 14 | // #define NANOVG_GLES3_IMPLEMENTATION 15 | #include 16 | 17 | // Hack to get framebuffer objects working on OpenGL 2 (we blindly assume the extension is supported) 18 | #define NANOVG_FBO_VALID 19 | #include 20 | 21 | #define BLENDISH_IMPLEMENTATION 22 | #include 23 | 24 | #define NANOSVG_IMPLEMENTATION 25 | #define NANOSVG_ALL_COLOR_KEYWORDS 26 | #include 27 | 28 | #define STB_IMAGE_WRITE_IMPLEMENTATION 29 | #include 30 | -------------------------------------------------------------------------------- /src/engine/LightInfo.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | namespace rack { 6 | namespace engine { 7 | 8 | 9 | std::string LightInfo::getName() { 10 | return name; 11 | } 12 | 13 | std::string LightInfo::getDescription() { 14 | return description; 15 | } 16 | 17 | 18 | } // namespace engine 19 | } // namespace rack 20 | -------------------------------------------------------------------------------- /src/engine/PortInfo.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | namespace rack { 6 | namespace engine { 7 | 8 | 9 | std::string PortInfo::getName() { 10 | if (name == "") 11 | return string::f("#%d", portId + 1); 12 | return name; 13 | } 14 | 15 | 16 | std::string PortInfo::getFullName() { 17 | std::string name = getName(); 18 | return string::f((type == Port::INPUT) ? string::translate("PortInfo.input") : string::translate("PortInfo.output"), name); 19 | } 20 | 21 | 22 | std::string PortInfo::getDescription() { 23 | return description; 24 | } 25 | 26 | 27 | } // namespace engine 28 | } // namespace rack 29 | -------------------------------------------------------------------------------- /src/random.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | 6 | namespace rack { 7 | namespace random { 8 | 9 | 10 | static Xoroshiro128Plus rng; 11 | 12 | 13 | void init() { 14 | // Don't reset state if already seeded 15 | if (rng.isSeeded()) 16 | return; 17 | 18 | // Get epoch time for seed 19 | double time = system::getUnixTime(); 20 | uint64_t sec = time; 21 | uint64_t nsec = std::fmod(time, 1.0) * 1e9; 22 | rng.seed(sec, nsec); 23 | 24 | // Shift state a few times due to low seed entropy 25 | for (int i = 0; i < 4; i++) { 26 | rng(); 27 | } 28 | } 29 | 30 | 31 | Xoroshiro128Plus& local() { 32 | return rng; 33 | } 34 | 35 | 36 | } // namespace random 37 | } // namespace rack 38 | -------------------------------------------------------------------------------- /src/rtaudio.mm: -------------------------------------------------------------------------------- 1 | #include 2 | #import 3 | 4 | namespace rack { 5 | 6 | 7 | bool rtaudioIsMicrophoneBlocked() { 8 | // authorizationStatusForMediaType is only available on Mac 10.14+. 9 | if (@available(macOS 10.14, *)) { 10 | AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio]; 11 | return status == AVAuthorizationStatusRestricted || status == AVAuthorizationStatusDenied; 12 | } 13 | // On earlier versions, assume microphone is not blocked. 14 | return false; 15 | } 16 | 17 | 18 | } // namespace rack 19 | -------------------------------------------------------------------------------- /src/ui/Button.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | namespace rack { 6 | namespace ui { 7 | 8 | 9 | Button::Button() { 10 | box.size.y = BND_WIDGET_HEIGHT; 11 | } 12 | 13 | 14 | void Button::draw(const DrawArgs& args) { 15 | BNDwidgetState state = BND_DEFAULT; 16 | if (APP->event->getHoveredWidget() == this) 17 | state = BND_HOVER; 18 | if (APP->event->getDraggedWidget() == this) 19 | state = BND_ACTIVE; 20 | 21 | std::string text = this->text; 22 | if (text.empty() && quantity) 23 | text = quantity->getLabel(); 24 | bndToolButton(args.vg, 0.0, 0.0, box.size.x, box.size.y, BND_CORNER_NONE, state, -1, text.c_str()); 25 | } 26 | 27 | 28 | void Button::onDragStart(const DragStartEvent& e) { 29 | if (e.button != GLFW_MOUSE_BUTTON_LEFT) 30 | return; 31 | 32 | if (quantity) 33 | quantity->setMax(); 34 | } 35 | 36 | 37 | void Button::onDragEnd(const DragEndEvent& e) { 38 | if (quantity) 39 | quantity->setMin(); 40 | } 41 | 42 | 43 | void Button::onDragDrop(const DragDropEvent& e) { 44 | if (e.origin == this) { 45 | ActionEvent eAction; 46 | onAction(eAction); 47 | } 48 | } 49 | 50 | 51 | } // namespace ui 52 | } // namespace rack 53 | -------------------------------------------------------------------------------- /src/ui/ChoiceButton.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | namespace rack { 6 | namespace ui { 7 | 8 | 9 | void ChoiceButton::draw(const DrawArgs& args) { 10 | BNDwidgetState state = BND_DEFAULT; 11 | if (APP->event->getHoveredWidget() == this) 12 | state = BND_HOVER; 13 | if (APP->event->getDraggedWidget() == this) 14 | state = BND_ACTIVE; 15 | 16 | std::string text = this->text; 17 | if (text.empty() && quantity) 18 | text = quantity->getLabel(); 19 | bndChoiceButton(args.vg, 0.0, 0.0, box.size.x, box.size.y, BND_CORNER_NONE, state, -1, text.c_str()); 20 | } 21 | 22 | 23 | } // namespace ui 24 | } // namespace rack 25 | -------------------------------------------------------------------------------- /src/ui/Label.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | namespace rack { 5 | namespace ui { 6 | 7 | 8 | Label::Label() { 9 | box.size.y = BND_WIDGET_HEIGHT; 10 | fontSize = BND_LABEL_FONT_SIZE; 11 | lineHeight = 1.2; 12 | color = color::BLACK_TRANSPARENT; 13 | } 14 | 15 | void Label::draw(const DrawArgs& args) { 16 | // TODO 17 | // Custom font sizes do not work with right or center alignment 18 | float x; 19 | switch (alignment) { 20 | default: 21 | case LEFT_ALIGNMENT: { 22 | x = 0.0; 23 | } break; 24 | case RIGHT_ALIGNMENT: { 25 | x = box.size.x - bndLabelWidth(args.vg, -1, text.c_str()); 26 | } break; 27 | case CENTER_ALIGNMENT: { 28 | x = (box.size.x - bndLabelWidth(args.vg, -1, text.c_str())) / 2.0; 29 | } break; 30 | } 31 | 32 | nvgTextLineHeight(args.vg, lineHeight); 33 | NVGcolor colorActual = (color.a > 0.f) ? color : bndGetTheme()->regularTheme.textColor; 34 | bndIconLabelValue(args.vg, x, 0.0, box.size.x, box.size.y, -1, colorActual, BND_LEFT, fontSize, text.c_str(), NULL); 35 | } 36 | 37 | 38 | } // namespace ui 39 | } // namespace rack 40 | -------------------------------------------------------------------------------- /src/ui/List.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | namespace rack { 5 | namespace ui { 6 | 7 | 8 | void List::step() { 9 | Widget::step(); 10 | 11 | // Set positions of children 12 | box.size.y = 0.0; 13 | for (widget::Widget* child : children) { 14 | if (!child->visible) 15 | continue; 16 | // Set position of child 17 | child->box.pos = math::Vec(0.0, box.size.y); 18 | // Increment height 19 | box.size.y += child->box.size.y; 20 | // Resize width of child 21 | child->box.size.x = box.size.x; 22 | } 23 | } 24 | 25 | 26 | } // namespace ui 27 | } // namespace rack 28 | -------------------------------------------------------------------------------- /src/ui/Menu.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | namespace rack { 5 | namespace ui { 6 | 7 | 8 | Menu::Menu() { 9 | box.size = math::Vec(0, 0); 10 | } 11 | 12 | Menu::~Menu() { 13 | setChildMenu(NULL); 14 | } 15 | 16 | void Menu::setChildMenu(Menu* menu) { 17 | if (childMenu) { 18 | childMenu->parent->removeChild(childMenu); 19 | delete childMenu; 20 | childMenu = NULL; 21 | } 22 | if (menu) { 23 | childMenu = menu; 24 | assert(parent); 25 | parent->addChild(childMenu); 26 | } 27 | } 28 | 29 | void Menu::step() { 30 | Widget::step(); 31 | 32 | // Set positions of children 33 | box.size = math::Vec(0, 0); 34 | for (widget::Widget* child : children) { 35 | if (!child->visible) 36 | continue; 37 | // Increment height, set position of child 38 | child->box.pos = math::Vec(0, box.size.y); 39 | box.size.y += child->box.size.y; 40 | // Increase width based on maximum width of child 41 | if (child->box.size.x > box.size.x) { 42 | box.size.x = child->box.size.x; 43 | } 44 | } 45 | 46 | // Set widths of all children to maximum width 47 | for (widget::Widget* child : children) { 48 | child->box.size.x = box.size.x; 49 | } 50 | 51 | // Fit inside parent 52 | assert(parent); 53 | box = box.nudge(parent->box.zeroPos()); 54 | } 55 | 56 | void Menu::draw(const DrawArgs& args) { 57 | bndMenuBackground(args.vg, 0.0, 0.0, box.size.x, box.size.y, cornerFlags); 58 | Widget::draw(args); 59 | } 60 | 61 | void Menu::onHoverScroll(const HoverScrollEvent& e) { 62 | if (parent && !parent->box.contains(box)) 63 | box.pos.y += e.scrollDelta.y; 64 | } 65 | 66 | 67 | } // namespace ui 68 | } // namespace rack 69 | -------------------------------------------------------------------------------- /src/ui/MenuEntry.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | namespace rack { 5 | namespace ui { 6 | 7 | 8 | MenuEntry::MenuEntry() { 9 | box.size = math::Vec(0, BND_WIDGET_HEIGHT); 10 | } 11 | 12 | 13 | } // namespace ui 14 | } // namespace rack 15 | -------------------------------------------------------------------------------- /src/ui/MenuLabel.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | namespace rack { 6 | namespace ui { 7 | 8 | 9 | void MenuLabel::draw(const DrawArgs& args) { 10 | bndMenuLabel(args.vg, 0.0, 0.0, box.size.x, box.size.y, -1, text.c_str()); 11 | } 12 | 13 | void MenuLabel::step() { 14 | // Add 10 more pixels because Retina measurements are sometimes too small 15 | const float rightPadding = 10.0; 16 | // HACK use APP->window->vg from the window. 17 | box.size.x = bndLabelWidth(APP->window->vg, -1, text.c_str()) + rightPadding; 18 | Widget::step(); 19 | } 20 | 21 | 22 | } // namespace ui 23 | } // namespace rack 24 | -------------------------------------------------------------------------------- /src/ui/MenuOverlay.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | namespace rack { 5 | namespace ui { 6 | 7 | 8 | MenuOverlay::MenuOverlay() { 9 | bgColor = nvgRGBA(0, 0, 0, 0); 10 | } 11 | 12 | 13 | void MenuOverlay::draw(const DrawArgs& args) { 14 | if (bgColor.a > 0.f) { 15 | nvgBeginPath(args.vg); 16 | nvgRect(args.vg, 0, 0, VEC_ARGS(box.size)); 17 | nvgFillColor(args.vg, bgColor); 18 | nvgFill(args.vg); 19 | } 20 | 21 | OpaqueWidget::draw(args); 22 | } 23 | 24 | 25 | void MenuOverlay::step() { 26 | // Adopt parent's size 27 | box = parent->box.zeroPos(); 28 | 29 | Widget::step(); 30 | } 31 | 32 | 33 | void MenuOverlay::onButton(const ButtonEvent& e) { 34 | OpaqueWidget::onButton(e); 35 | if (e.isConsumed() && e.getTarget() != this) 36 | return; 37 | 38 | if (e.action == GLFW_PRESS) { 39 | ActionEvent eAction; 40 | onAction(eAction); 41 | } 42 | 43 | // Consume all buttons. 44 | e.consume(this); 45 | } 46 | 47 | 48 | void MenuOverlay::onHoverKey(const HoverKeyEvent& e) { 49 | OpaqueWidget::onHoverKey(e); 50 | if (e.isConsumed()) 51 | return; 52 | 53 | if (e.action == GLFW_PRESS && e.isKeyCommand(GLFW_KEY_ESCAPE)) { 54 | ActionEvent eAction; 55 | onAction(eAction); 56 | } 57 | 58 | // Consume all keys. 59 | // Unfortunately this prevents MIDI computer keyboard from playing while a menu is open, but that might be a good thing for safety. 60 | e.consume(this); 61 | } 62 | 63 | 64 | void MenuOverlay::onAction(const ActionEvent& e) { 65 | requestDelete(); 66 | } 67 | 68 | 69 | } // namespace ui 70 | } // namespace rack 71 | -------------------------------------------------------------------------------- /src/ui/MenuSeparator.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | namespace rack { 5 | namespace ui { 6 | 7 | 8 | MenuSeparator::MenuSeparator() { 9 | box.size.y = BND_WIDGET_HEIGHT / 2; 10 | } 11 | 12 | void MenuSeparator::draw(const DrawArgs& args) { 13 | nvgBeginPath(args.vg); 14 | const float margin = 8.0; 15 | nvgMoveTo(args.vg, margin, box.size.y / 2.0); 16 | nvgLineTo(args.vg, box.size.x - margin, box.size.y / 2.0); 17 | nvgStrokeWidth(args.vg, 1.0); 18 | nvgStrokeColor(args.vg, color::alpha(bndGetTheme()->menuTheme.textColor, 0.25)); 19 | nvgStroke(args.vg); 20 | } 21 | 22 | 23 | } // namespace ui 24 | } // namespace rack 25 | -------------------------------------------------------------------------------- /src/ui/OptionButton.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | namespace rack { 5 | namespace ui { 6 | 7 | 8 | void OptionButton::draw(const DrawArgs& args) { 9 | BNDwidgetState state = BND_DEFAULT; 10 | if (quantity) { 11 | if (quantity->isMax()) 12 | state = BND_ACTIVE; 13 | } 14 | 15 | std::string text = this->text; 16 | if (text.empty() && quantity) 17 | text = quantity->getLabel(); 18 | bndOptionButton(args.vg, 0.0, 0.0, INFINITY, box.size.y, state, text.c_str()); 19 | } 20 | 21 | 22 | } // namespace ui 23 | } // namespace rack 24 | -------------------------------------------------------------------------------- /src/ui/ProgressBar.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | namespace rack { 5 | namespace ui { 6 | 7 | 8 | ProgressBar::ProgressBar() { 9 | box.size.y = BND_WIDGET_HEIGHT; 10 | } 11 | 12 | void ProgressBar::draw(const DrawArgs& args) { 13 | float progress = quantity ? quantity->getScaledValue() : 0.f; 14 | std::string text = quantity ? quantity->getString() : ""; 15 | bndSlider(args.vg, 0.0, 0.0, box.size.x, box.size.y, BND_CORNER_ALL, BND_DEFAULT, progress, text.c_str(), NULL); 16 | } 17 | 18 | 19 | } // namespace ui 20 | } // namespace rack 21 | -------------------------------------------------------------------------------- /src/ui/RadioButton.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | namespace rack { 6 | namespace ui { 7 | 8 | 9 | void RadioButton::draw(const DrawArgs& args) { 10 | BNDwidgetState state = BND_DEFAULT; 11 | if (APP->event->getHoveredWidget() == this) 12 | state = BND_HOVER; 13 | 14 | if (quantity) { 15 | if (quantity->isMax()) 16 | state = BND_ACTIVE; 17 | } 18 | 19 | std::string text = this->text; 20 | if (text.empty() && quantity) 21 | text = quantity->getLabel(); 22 | bndRadioButton(args.vg, 0.0, 0.0, box.size.x, box.size.y, BND_CORNER_NONE, state, -1, text.c_str()); 23 | } 24 | 25 | 26 | void RadioButton::onDragStart(const DragStartEvent& e) { 27 | OpaqueWidget::onDragStart(e); 28 | } 29 | 30 | 31 | void RadioButton::onDragEnd(const DragEndEvent& e) { 32 | OpaqueWidget::onDragEnd(e); 33 | } 34 | 35 | 36 | void RadioButton::onDragDrop(const DragDropEvent& e) { 37 | if (e.origin == this) { 38 | if (quantity) 39 | quantity->toggle(); 40 | 41 | ActionEvent eAction; 42 | onAction(eAction); 43 | } 44 | } 45 | 46 | 47 | } // namespace ui 48 | } // namespace rack 49 | -------------------------------------------------------------------------------- /src/ui/Slider.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | namespace rack { 6 | namespace ui { 7 | 8 | 9 | static const float SENSITIVITY = 0.001f; 10 | 11 | 12 | Slider::Slider() { 13 | box.size.y = BND_WIDGET_HEIGHT; 14 | } 15 | 16 | void Slider::draw(const DrawArgs& args) { 17 | BNDwidgetState state = BND_DEFAULT; 18 | if (APP->event->hoveredWidget == this) 19 | state = BND_HOVER; 20 | if (APP->event->draggedWidget == this) 21 | state = BND_ACTIVE; 22 | 23 | float progress = quantity ? quantity->getScaledValue() : 0.f; 24 | std::string text = quantity ? quantity->getString() : ""; 25 | 26 | // If parent is a Menu, make corners sharp 27 | ui::Menu* parentMenu = dynamic_cast(getParent()); 28 | int flags = parentMenu ? BND_CORNER_ALL : BND_CORNER_NONE; 29 | bndSlider(args.vg, 0.0, 0.0, box.size.x, box.size.y, flags, state, progress, text.c_str(), NULL); 30 | } 31 | 32 | void Slider::onDragStart(const DragStartEvent& e) { 33 | if (e.button != GLFW_MOUSE_BUTTON_LEFT) 34 | return; 35 | 36 | APP->window->cursorLock(); 37 | } 38 | 39 | void Slider::onDragMove(const DragMoveEvent& e) { 40 | if (quantity) { 41 | quantity->moveScaledValue(SENSITIVITY * e.mouseDelta.x); 42 | } 43 | } 44 | 45 | void Slider::onDragEnd(const DragEndEvent& e) { 46 | APP->window->cursorUnlock(); 47 | } 48 | 49 | void Slider::onDoubleClick(const DoubleClickEvent& e) { 50 | if (quantity) 51 | quantity->reset(); 52 | } 53 | 54 | 55 | } // namespace ui 56 | } // namespace rack 57 | -------------------------------------------------------------------------------- /src/ui/Tooltip.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | 6 | namespace rack { 7 | namespace ui { 8 | 9 | 10 | void Tooltip::step() { 11 | // Wrap size to contents 12 | nvgSave(APP->window->vg); 13 | nvgTextLineHeight(APP->window->vg, 1.2); 14 | box.size.x = bndLabelWidth(APP->window->vg, -1, text.c_str()); 15 | box.size.y = bndLabelHeight(APP->window->vg, -1, text.c_str(), INFINITY); 16 | // Position near cursor. This assumes that the Tooltip is added to the root widget. 17 | box.pos = APP->scene->mousePos.plus(math::Vec(15, 15)); 18 | // Fit inside parent 19 | assert(parent); 20 | box = box.nudge(parent->box.zeroPos()); 21 | nvgRestore(APP->window->vg); 22 | 23 | Widget::step(); 24 | } 25 | 26 | void Tooltip::draw(const DrawArgs& args) { 27 | bndTooltipBackground(args.vg, 0.0, 0.0, box.size.x, box.size.y); 28 | nvgTextLineHeight(args.vg, 1.2); 29 | 30 | // Because there is no bndThemeLabel() function, temporarily replace the menu text color with tooltip text color and draw a menu label 31 | BNDtheme* theme = (BNDtheme*) bndGetTheme(); 32 | NVGcolor menuTextColor = theme->menuTheme.textColor; 33 | theme->menuTheme.textColor = theme->tooltipTheme.textColor; 34 | bndMenuLabel(args.vg, 0.0, 0.0, INFINITY, box.size.y, -1, text.c_str()); 35 | theme->menuTheme.textColor = menuTextColor; 36 | 37 | Widget::draw(args); 38 | } 39 | 40 | 41 | } // namespace ui 42 | } // namespace rack 43 | -------------------------------------------------------------------------------- /src/widget/OpenGlWidget.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | namespace rack { 6 | namespace widget { 7 | 8 | 9 | void OpenGlWidget::step() { 10 | // Render every frame 11 | dirty = true; 12 | FramebufferWidget::step(); 13 | } 14 | 15 | 16 | void OpenGlWidget::drawFramebuffer() { 17 | math::Vec fbSize = getFramebufferSize(); 18 | glViewport(0.0, 0.0, fbSize.x, fbSize.y); 19 | glClearColor(0.0, 0.0, 0.0, 1.0); 20 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); 21 | 22 | glMatrixMode(GL_PROJECTION); 23 | glLoadIdentity(); 24 | glOrtho(0.0, fbSize.x, 0.0, fbSize.y, -1.0, 1.0); 25 | 26 | glBegin(GL_TRIANGLES); 27 | glColor3f(1, 0, 0); 28 | glVertex3f(0, 0, 0); 29 | glColor3f(0, 1, 0); 30 | glVertex3f(fbSize.x, 0, 0); 31 | glColor3f(0, 0, 1); 32 | glVertex3f(0, fbSize.y, 0); 33 | glEnd(); 34 | } 35 | 36 | 37 | } // namespace widget 38 | } // namespace rack 39 | -------------------------------------------------------------------------------- /src/widget/SvgWidget.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | namespace rack { 6 | namespace widget { 7 | 8 | 9 | SvgWidget::SvgWidget() { 10 | box.size = math::Vec(); 11 | } 12 | 13 | 14 | void SvgWidget::wrap() { 15 | if (svg) { 16 | box.size = svg->getSize(); 17 | } 18 | else { 19 | box.size = math::Vec(); 20 | } 21 | } 22 | 23 | 24 | void SvgWidget::setSvg(std::shared_ptr svg) { 25 | this->svg = svg; 26 | wrap(); 27 | } 28 | 29 | 30 | void SvgWidget::draw(const DrawArgs& args) { 31 | if (!svg) 32 | return; 33 | 34 | window::svgDraw(args.vg, svg->handle); 35 | } 36 | 37 | 38 | } // namespace widget 39 | } // namespace rack 40 | -------------------------------------------------------------------------------- /src/widget/ZoomWidget.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | namespace rack { 5 | namespace widget { 6 | 7 | 8 | math::Vec ZoomWidget::getRelativeOffset(math::Vec v, Widget* ancestor) { 9 | // Transform `v` (which is in child coordinates) to local coordinates. 10 | v = v.mult(zoom); 11 | return Widget::getRelativeOffset(v, ancestor); 12 | } 13 | 14 | 15 | float ZoomWidget::getRelativeZoom(Widget* ancestor) { 16 | return zoom * Widget::getRelativeZoom(ancestor); 17 | } 18 | 19 | 20 | math::Rect ZoomWidget::getViewport(math::Rect r) { 21 | r.pos = r.pos.mult(zoom); 22 | r.size = r.size.mult(zoom); 23 | r = Widget::getViewport(r); 24 | r.pos = r.pos.div(zoom); 25 | r.size = r.size.div(zoom); 26 | return r; 27 | } 28 | 29 | 30 | float ZoomWidget::getZoom() { 31 | return zoom; 32 | } 33 | 34 | 35 | void ZoomWidget::setZoom(float zoom) { 36 | if (zoom == this->zoom) 37 | return; 38 | this->zoom = zoom; 39 | 40 | // Dispatch Dirty event 41 | widget::EventContext cDirty; 42 | DirtyEvent eDirty; 43 | eDirty.context = &cDirty; 44 | Widget::onDirty(eDirty); 45 | } 46 | 47 | 48 | void ZoomWidget::draw(const DrawArgs& args) { 49 | DrawArgs zoomCtx = args; 50 | zoomCtx.clipBox.pos = zoomCtx.clipBox.pos.div(zoom); 51 | zoomCtx.clipBox.size = zoomCtx.clipBox.size.div(zoom); 52 | // No need to save the state because that is done in the parent 53 | nvgScale(args.vg, zoom, zoom); 54 | Widget::draw(zoomCtx); 55 | } 56 | 57 | 58 | void ZoomWidget::drawLayer(const DrawArgs& args, int layer) { 59 | DrawArgs zoomCtx = args; 60 | zoomCtx.clipBox.pos = zoomCtx.clipBox.pos.div(zoom); 61 | zoomCtx.clipBox.size = zoomCtx.clipBox.size.div(zoom); 62 | // No need to save the state because that is done in the parent 63 | nvgScale(args.vg, zoom, zoom); 64 | Widget::drawLayer(zoomCtx, layer); 65 | } 66 | 67 | 68 | } // namespace widget 69 | } // namespace rack 70 | -------------------------------------------------------------------------------- /template.vcv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VCVRack/Rack/768d859187d64aed4d3d3db1f9c3aef596676116/template.vcv -------------------------------------------------------------------------------- /valgrind.supp: -------------------------------------------------------------------------------- 1 | { 2 | <> 3 | Memcheck:Cond 4 | ... 5 | fun:pa_mainloop_run 6 | } 7 | { 8 | <> 9 | Memcheck:Cond 10 | ... 11 | obj:/usr/lib/libgallium* 12 | ... 13 | } 14 | { 15 | <> 16 | Memcheck:Cond 17 | ... 18 | obj:/usr/lib/libGLX_mesa* 19 | ... 20 | } 21 | { 22 | <> 23 | Memcheck:Leak 24 | ... 25 | obj:/usr/lib/libgallium* 26 | ... 27 | } 28 | { 29 | <> 30 | Memcheck:Leak 31 | ... 32 | fun:snd_seq_open 33 | ... 34 | } 35 | { 36 | <> 37 | Memcheck:Leak 38 | ... 39 | fun:snd_config_update_r 40 | ... 41 | } 42 | { 43 | <> 44 | Memcheck:Leak 45 | ... 46 | fun:_snd_config_load_with_include 47 | ... 48 | } 49 | { 50 | 51 | Memcheck:Leak 52 | ... 53 | fun:pa_pdispatch_run 54 | ... 55 | } --------------------------------------------------------------------------------