Browse Source

Update dpf and plugins to it

tags/v1.5
falkTX 3 years ago
parent
commit
b55108b1ed
99 changed files with 4905 additions and 2746 deletions
  1. +24
    -3
      dpf/Makefile.base.mk
  2. +101
    -38
      dpf/Makefile.plugins.mk
  3. +9
    -7
      dpf/cmake/DPF-plugin.cmake
  4. +9
    -0
      dpf/dgl/Application.hpp
  5. +17
    -0
      dpf/dgl/Base.hpp
  6. +1
    -1
      dpf/dgl/ImageBase.hpp
  7. +48
    -3
      dpf/dgl/ImageBaseWidgets.hpp
  8. +6
    -0
      dpf/dgl/Makefile
  9. +14
    -1
      dpf/dgl/NanoVG.hpp
  10. +7
    -1
      dpf/dgl/TopLevelWidget.hpp
  11. +42
    -49
      dpf/dgl/Window.hpp
  12. +5
    -0
      dpf/dgl/src/Application.cpp
  13. +7
    -0
      dpf/dgl/src/ApplicationPrivateData.cpp
  14. +9
    -0
      dpf/dgl/src/ApplicationPrivateData.hpp
  15. +4
    -4
      dpf/dgl/src/ImageBaseWidgets.cpp
  16. +17
    -11
      dpf/dgl/src/NanoVG.cpp
  17. +14
    -5
      dpf/dgl/src/SubWidget.cpp
  18. +38
    -12
      dpf/dgl/src/TopLevelWidget.cpp
  19. +0
    -20
      dpf/dgl/src/TopLevelWidgetPrivateData.cpp
  20. +1
    -1
      dpf/dgl/src/TopLevelWidgetPrivateData.hpp
  21. +12
    -21
      dpf/dgl/src/WidgetPrivateData.cpp
  22. +56
    -13
      dpf/dgl/src/Window.cpp
  23. +68
    -206
      dpf/dgl/src/WindowPrivateData.cpp
  24. +11
    -128
      dpf/dgl/src/WindowPrivateData.hpp
  25. +4
    -0
      dpf/dgl/src/nanovg/fontstash.h
  26. +21
    -4
      dpf/dgl/src/nanovg/nanovg.c
  27. +0
    -3
      dpf/dgl/src/nanovg/nanovg_gl.h
  28. +9
    -7
      dpf/dgl/src/pugl-upstream/include/pugl/pugl.h
  29. +20
    -6
      dpf/dgl/src/pugl-upstream/src/mac.m
  30. +9
    -7
      dpf/dgl/src/pugl-upstream/src/win.c
  31. +38
    -26
      dpf/dgl/src/pugl-upstream/src/x11.c
  32. +1
    -1
      dpf/dgl/src/pugl-upstream/src/x11.h
  33. +27
    -164
      dpf/dgl/src/pugl.cpp
  34. +1
    -21
      dpf/dgl/src/pugl.hpp
  35. +101
    -27
      dpf/distrho/DistrhoInfo.hpp
  36. +28
    -5
      dpf/distrho/DistrhoPlugin.hpp
  37. +10
    -0
      dpf/distrho/DistrhoPluginMain.cpp
  38. +57
    -1
      dpf/distrho/DistrhoPluginUtils.hpp
  39. +35
    -4
      dpf/distrho/DistrhoUI.hpp
  40. +11
    -0
      dpf/distrho/DistrhoUIMain.cpp
  41. +20
    -15
      dpf/distrho/DistrhoUI_macOS.mm
  42. +72
    -47
      dpf/distrho/DistrhoUtils.hpp
  43. +592
    -0
      dpf/distrho/extra/FileBrowserDialog.cpp
  44. +134
    -0
      dpf/distrho/extra/FileBrowserDialog.hpp
  45. +0
    -0
      dpf/distrho/extra/sofd/libsofd.c
  46. +0
    -0
      dpf/distrho/extra/sofd/libsofd.h
  47. +1
    -0
      dpf/distrho/src/DistrhoDefines.h
  48. +15
    -3
      dpf/distrho/src/DistrhoPlugin.cpp
  49. +1
    -1
      dpf/distrho/src/DistrhoPluginCarla.cpp
  50. +26
    -15
      dpf/distrho/src/DistrhoPluginInternal.hpp
  51. +185
    -9
      dpf/distrho/src/DistrhoPluginJACK.cpp
  52. +9
    -7
      dpf/distrho/src/DistrhoPluginLADSPA+DSSI.cpp
  53. +9
    -12
      dpf/distrho/src/DistrhoPluginLV2.cpp
  54. +13
    -6
      dpf/distrho/src/DistrhoPluginLV2export.cpp
  55. +44
    -15
      dpf/distrho/src/DistrhoPluginVST2.cpp
  56. +1609
    -1244
      dpf/distrho/src/DistrhoPluginVST3.cpp
  57. +288
    -0
      dpf/distrho/src/DistrhoPluginVST3.hpp
  58. +75
    -12
      dpf/distrho/src/DistrhoUI.cpp
  59. +22
    -9
      dpf/distrho/src/DistrhoUIInternal.hpp
  60. +29
    -9
      dpf/distrho/src/DistrhoUIPrivateData.hpp
  61. +291
    -220
      dpf/distrho/src/DistrhoUIVST3.cpp
  62. +138
    -0
      dpf/distrho/src/DistrhoUtils.cpp
  63. +1
    -1
      dpf/distrho/src/jackbridge/JackBridge.cpp
  64. +0
    -257
      dpf/distrho/src/jackbridge/Makefile
  65. +11
    -3
      dpf/distrho/src/jackbridge/RtAudioBridge.hpp
  66. +2
    -2
      dpf/distrho/src/lv2/lv2_kxstudio_properties.h
  67. +2
    -1
      dpf/distrho/src/lv2/state.h
  68. +1
    -0
      dpf/distrho/src/travesty/base.h
  69. +3
    -3
      dpf/distrho/src/travesty/edit_controller.h
  70. +1
    -1
      dpf/distrho/src/travesty/view.h
  71. +1
    -0
      dpf/dpf.doxygen
  72. +1
    -0
      dpf/tests/FileBrowserDialog.cpp
  73. +3
    -0
      dpf/utils/generate-vst-bundles.sh
  74. +4
    -3
      dpf/utils/package-osx-bundles.sh
  75. +0
    -1
      dpf/utils/plugin.vst/Contents/MacOS/deleteme
  76. +2
    -0
      dpf/utils/symbols/shared.def
  77. +1
    -0
      dpf/utils/symbols/shared.exp
  78. +4
    -0
      dpf/utils/symbols/shared.version
  79. +6
    -6
      plugins/3BandEQ/DistrhoPlugin3BandEQ.cpp
  80. +6
    -6
      plugins/3BandSplitter/DistrhoPlugin3BandSplitter.cpp
  81. +1
    -1
      plugins/AmplitudeImposer/DistrhoPluginAmplitudeImposer.cpp
  82. +1
    -1
      plugins/CycleShifter/DistrhoPluginCycleShifter.cpp
  83. +3
    -3
      plugins/Kars/DistrhoPluginKars.cpp
  84. +9
    -9
      plugins/MVerb/DistrhoPluginMVerb.cpp
  85. +1
    -1
      plugins/Nekobi/DistrhoPluginInfo.h
  86. +8
    -8
      plugins/Nekobi/DistrhoPluginNekobi.cpp
  87. +3
    -2
      plugins/Nekobi/Makefile
  88. +2
    -2
      plugins/PingPongPan/DistrhoPluginPingPongPan.cpp
  89. +1
    -1
      plugins/SoulForce/DistrhoPluginSoulForce.cpp
  90. +0
    -1
      plugins/bitcrush/DistrhoPluginMaxGen.cpp
  91. +89
    -0
      plugins/bitcrush/DistrhoPluginMaxGen.cpp
  92. +1
    -1
      plugins/common/DistrhoPluginMaxGen.cpp
  93. +0
    -1
      plugins/freeverb/DistrhoPluginMaxGen.cpp
  94. +89
    -0
      plugins/freeverb/DistrhoPluginMaxGen.cpp
  95. +0
    -1
      plugins/gigaverb/DistrhoPluginMaxGen.cpp
  96. +89
    -0
      plugins/gigaverb/DistrhoPluginMaxGen.cpp
  97. +5
    -5
      plugins/glBars/DistrhoPluginGLBars.cpp
  98. +0
    -1
      plugins/pitchshift/DistrhoPluginMaxGen.cpp
  99. +89
    -0
      plugins/pitchshift/DistrhoPluginMaxGen.cpp

+ 24
- 3
dpf/Makefile.base.mk View File

@@ -163,14 +163,20 @@ LINK_OPTS += -Wl,--strip-all
endif
endif

ifeq ($(SKIP_STRIPPING),true)
BASE_FLAGS += -g
endif

ifeq ($(NOOPT),true)
# Non-CPU-specific optimization flags
BASE_OPTS = -O2 -ffast-math -fdata-sections -ffunction-sections
endif

ifeq ($(WINDOWS),true)
# Assume we want posix
BASE_FLAGS += -posix -D__STDC_FORMAT_MACROS
# Needed for windows, see https://github.com/falkTX/Carla/issues/855
BASE_OPTS += -mstackrealign
BASE_FLAGS += -mstackrealign
else
# Not needed for Windows
BASE_FLAGS += -fPIC -DPIC
@@ -184,6 +190,11 @@ BASE_FLAGS += -DNDEBUG $(BASE_OPTS) -fvisibility=hidden
CXXFLAGS += -fvisibility-inlines-hidden
endif

ifeq ($(WITH_LTO),true)
BASE_FLAGS += -fno-strict-aliasing -flto
LINK_FLAGS += -fno-strict-aliasing -flto -Werror=odr -Werror=lto-type-mismatch
endif

BUILD_C_FLAGS = $(BASE_FLAGS) -std=gnu99 $(CFLAGS)
BUILD_CXX_FLAGS = $(BASE_FLAGS) -std=gnu++11 $(CXXFLAGS)
LINK_FLAGS = $(LINK_OPTS) $(LDFLAGS)
@@ -238,6 +249,7 @@ HAVE_OPENGL = true
else
HAVE_OPENGL = $(shell $(PKG_CONFIG) --exists gl && echo true)
ifneq ($(HAIKU),true)
HAVE_DBUS = $(shell $(PKG_CONFIG) --exists dbus-1 && echo true)
HAVE_X11 = $(shell $(PKG_CONFIG) --exists x11 && echo true)
HAVE_XCURSOR = $(shell $(PKG_CONFIG) --exists xcursor && echo true)
HAVE_XEXT = $(shell $(PKG_CONFIG) --exists xext && echo true)
@@ -250,6 +262,9 @@ endif

HAVE_LIBLO = $(shell $(PKG_CONFIG) --exists liblo && echo true)

ifeq ($(SKIP_RTAUDIO_FALLBACK),true)
CXXFLAGS += -DDPF_JACK_STANDALONE_SKIP_RTAUDIO_FALLBACK
else
ifeq ($(MACOS),true)
HAVE_RTAUDIO = true
else ifeq ($(WINDOWS),true)
@@ -263,6 +278,7 @@ else ifeq ($(HAVE_PULSEAUDIO),true)
HAVE_RTAUDIO = true
endif
endif
endif

# backwards compat
HAVE_JACK = true
@@ -280,15 +296,19 @@ endif

ifeq ($(WINDOWS),true)
DGL_SYSTEM_LIBS += -lgdi32 -lcomdlg32
# -lole32
endif

ifneq ($(HAIKU_OR_MACOS_OR_WINDOWS),true)
ifeq ($(HAVE_DBUS),true)
DGL_FLAGS += $(shell $(PKG_CONFIG) --cflags dbus-1) -DHAVE_DBUS
DGL_SYSTEM_LIBS += $(shell $(PKG_CONFIG) --libs dbus-1)
endif
ifeq ($(HAVE_X11),true)
DGL_FLAGS += $(shell $(PKG_CONFIG) --cflags x11) -DHAVE_X11
DGL_SYSTEM_LIBS += $(shell $(PKG_CONFIG) --libs x11)
ifeq ($(HAVE_XCURSOR),true)
# TODO -DHAVE_XCURSOR
DGL_FLAGS += $(shell $(PKG_CONFIG) --cflags xcursor)
DGL_FLAGS += $(shell $(PKG_CONFIG) --cflags xcursor) -DHAVE_XCURSOR
DGL_SYSTEM_LIBS += $(shell $(PKG_CONFIG) --libs xcursor)
endif
ifeq ($(HAVE_XEXT),true)
@@ -475,6 +495,7 @@ features:
$(call print_available,UNIX)
@echo === Detected features
$(call print_available,HAVE_ALSA)
$(call print_available,HAVE_DBUS)
$(call print_available,HAVE_CAIRO)
$(call print_available,HAVE_DGL)
$(call print_available,HAVE_LIBLO)


+ 101
- 38
dpf/Makefile.plugins.mk View File

@@ -49,9 +49,12 @@ endif
ifeq ($(MACOS),true)
JACK_LIBS += -framework CoreAudio -framework CoreFoundation
else ifeq ($(WINDOWS),true)
JACK_LIBS += -lksuser -lmfplat -lmfuuid -lole32 -lwinmm -lwmcodecdspuuid
JACK_LIBS += -lole32 -lwinmm
# DirectSound
JACK_LIBS += -ldsound
# WASAPI
# JACK_LIBS += -lksuser -lmfplat -lmfuuid -lwmcodecdspuuid
else ifneq ($(HAIKU),true)
JACK_LIBS = -ldl
ifeq ($(HAVE_ALSA),true)
JACK_FLAGS += $(ALSA_FLAGS)
JACK_LIBS += $(ALSA_LIBS)
@@ -68,19 +71,9 @@ endif
# backwards compat
BASE_FLAGS += -DHAVE_JACK

# ---------------------------------------------------------------------------------------------------------------------
# Set VST3 filename, see https://vst3sdk-doc.diatonic.jp/doc/vstinterfaces/vst3loc.html

ifeq ($(LINUX),true)
VST3_FILENAME = $(TARGET_PROCESSOR)-linux/$(NAME).so
endif
ifeq ($(MACOS),true)
ifneq ($(MACOS_OLD),true)
VST3_FILENAME = MacOS/$(NAME)
endif
endif
ifeq ($(WINDOWS),true)
VST3_FILENAME = $(TARGET_PROCESSOR)-win/$(NAME).vst3
# always needed
ifneq ($(HAIKU_OR_MACOS_OR_WINDOWS),true)
LINK_FLAGS += -ldl
endif

# ---------------------------------------------------------------------------------------------------------------------
@@ -93,6 +86,32 @@ ifeq ($(MACOS),true)
OBJS_UI += $(BUILD_DIR)/DistrhoUI_macOS_$(NAME).mm.o
endif

# ---------------------------------------------------------------------------------------------------------------------
# Set VST2 filename, either single binary or inside a bundle

ifeq ($(MACOS),true)
VST2_CONTENTS = $(NAME).vst/Contents
VST2_FILENAME = $(VST2_CONTENTS)/MacOS/$(NAME)
else ifeq ($(USE_VST2_BUNDLE),true)
VST2_FILENAME = $(NAME).vst/$(NAME)$(LIB_EXT)
else
VST2_FILENAME = $(NAME)-vst$(LIB_EXT)
endif

# ---------------------------------------------------------------------------------------------------------------------
# Set VST3 filename, see https://vst3sdk-doc.diatonic.jp/doc/vstinterfaces/vst3loc.html

ifeq ($(LINUX),true)
VST3_FILENAME = $(NAME).vst3/Contents/$(TARGET_PROCESSOR)-linux/$(NAME).so
endif
ifeq ($(MACOS),true)
VST3_CONTENTS = $(NAME).vst3/Contents
VST3_FILENAME = $(VST3_CONTENTS)/MacOS/$(NAME)
endif
ifeq ($(WINDOWS),true)
VST3_FILENAME = $(NAME).vst3/Contents/$(TARGET_PROCESSOR)-win/$(NAME).vst3
endif

# ---------------------------------------------------------------------------------------------------------------------
# Set plugin binary file targets

@@ -103,9 +122,19 @@ dssi_ui = $(TARGET_DIR)/$(NAME)-dssi/$(NAME)_ui$(APP_EXT)
lv2 = $(TARGET_DIR)/$(NAME).lv2/$(NAME)$(LIB_EXT)
lv2_dsp = $(TARGET_DIR)/$(NAME).lv2/$(NAME)_dsp$(LIB_EXT)
lv2_ui = $(TARGET_DIR)/$(NAME).lv2/$(NAME)_ui$(LIB_EXT)
vst2 = $(TARGET_DIR)/$(NAME)-vst$(LIB_EXT)
vst2 = $(TARGET_DIR)/$(VST2_FILENAME)
ifneq ($(VST3_FILENAME),)
vst3 = $(TARGET_DIR)/$(NAME).vst3/Contents/$(VST3_FILENAME)
vst3 = $(TARGET_DIR)/$(VST3_FILENAME)
endif
shared = $(TARGET_DIR)/$(NAME)$(LIB_EXT)

ifeq ($(MACOS),true)
vst2files += $(TARGET_DIR)/$(VST2_CONTENTS)/Info.plist
vst2files += $(TARGET_DIR)/$(VST2_CONTENTS)/PkgInfo
vst2files += $(TARGET_DIR)/$(VST2_CONTENTS)/Resources/empty.lproj
vst3files += $(TARGET_DIR)/$(VST3_CONTENTS)/Info.plist
vst3files += $(TARGET_DIR)/$(VST3_CONTENTS)/PkgInfo
vst3files += $(TARGET_DIR)/$(VST3_CONTENTS)/Resources/empty.lproj
endif

# ---------------------------------------------------------------------------------------------------------------------
@@ -119,6 +148,7 @@ SYMBOLS_LV2UI = -Wl,-exported_symbols_list,$(DPF_PATH)/utils/symbols/lv2-ui.exp
SYMBOLS_LV2 = -Wl,-exported_symbols_list,$(DPF_PATH)/utils/symbols/lv2.exp
SYMBOLS_VST2 = -Wl,-exported_symbols_list,$(DPF_PATH)/utils/symbols/vst2.exp
SYMBOLS_VST3 = -Wl,-exported_symbols_list,$(DPF_PATH)/utils/symbols/vst3.exp
SYMBOLS_SHARED = -Wl,-exported_symbols_list,$(DPF_PATH)/utils/symbols/shared.exp
else ifeq ($(WINDOWS),true)
SYMBOLS_LADSPA = $(DPF_PATH)/utils/symbols/ladspa.def
SYMBOLS_DSSI = $(DPF_PATH)/utils/symbols/dssi.def
@@ -127,6 +157,7 @@ SYMBOLS_LV2UI = $(DPF_PATH)/utils/symbols/lv2-ui.def
SYMBOLS_LV2 = $(DPF_PATH)/utils/symbols/lv2.def
SYMBOLS_VST2 = $(DPF_PATH)/utils/symbols/vst2.def
SYMBOLS_VST3 = $(DPF_PATH)/utils/symbols/vst3.def
SYMBOLS_SHARED = $(DPF_PATH)/utils/symbols/shared.def
else ifneq ($(DEBUG),true)
SYMBOLS_LADSPA = -Wl,--version-script=$(DPF_PATH)/utils/symbols/ladspa.version
SYMBOLS_DSSI = -Wl,--version-script=$(DPF_PATH)/utils/symbols/dssi.version
@@ -135,6 +166,7 @@ SYMBOLS_LV2UI = -Wl,--version-script=$(DPF_PATH)/utils/symbols/lv2-ui.version
SYMBOLS_LV2 = -Wl,--version-script=$(DPF_PATH)/utils/symbols/lv2.version
SYMBOLS_VST2 = -Wl,--version-script=$(DPF_PATH)/utils/symbols/vst2.version
SYMBOLS_VST3 = -Wl,--version-script=$(DPF_PATH)/utils/symbols/vst3.version
SYMBOLS_SHARED = -Wl,--version-script=$(DPF_PATH)/utils/symbols/shared.version
endif

# ---------------------------------------------------------------------------------------------------------------------
@@ -238,32 +270,32 @@ all:
# ---------------------------------------------------------------------------------------------------------------------
# Common

$(BUILD_DIR)/%.S.o: %.S $(EXTRA_LIBS)
$(BUILD_DIR)/%.S.o: %.S
-@mkdir -p "$(shell dirname $(BUILD_DIR)/$<)"
@echo "Compiling $<"
@$(CC) $< $(BUILD_C_FLAGS) -c -o $@

$(BUILD_DIR)/%.c.o: %.c $(EXTRA_LIBS)
$(BUILD_DIR)/%.c.o: %.c
-@mkdir -p "$(shell dirname $(BUILD_DIR)/$<)"
@echo "Compiling $<"
$(SILENT)$(CC) $< $(BUILD_C_FLAGS) -c -o $@

$(BUILD_DIR)/%.cc.o: %.cc $(EXTRA_LIBS)
$(BUILD_DIR)/%.cc.o: %.cc
-@mkdir -p "$(shell dirname $(BUILD_DIR)/$<)"
@echo "Compiling $<"
$(SILENT)$(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@

$(BUILD_DIR)/%.cpp.o: %.cpp $(EXTRA_LIBS)
$(BUILD_DIR)/%.cpp.o: %.cpp
-@mkdir -p "$(shell dirname $(BUILD_DIR)/$<)"
@echo "Compiling $<"
$(SILENT)$(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@

$(BUILD_DIR)/%.m.o: %.m $(EXTRA_LIBS)
$(BUILD_DIR)/%.m.o: %.m
-@mkdir -p "$(shell dirname $(BUILD_DIR)/$<)"
@echo "Compiling $<"
$(SILENT)$(CC) $< $(BUILD_C_FLAGS) -ObjC -c -o $@

$(BUILD_DIR)/%.mm.o: %.mm $(EXTRA_LIBS)
$(BUILD_DIR)/%.mm.o: %.mm
-@mkdir -p "$(shell dirname $(BUILD_DIR)/$<)"
@echo "Compiling $<"
$(SILENT)$(CC) $< $(BUILD_CXX_FLAGS) -ObjC++ -c -o $@
@@ -291,27 +323,27 @@ $(DPF_PATH)/build/libdgl-vulkan.a:

AS_PUGL_NAMESPACE = $(subst -,_,$(1))

$(BUILD_DIR)/DistrhoPluginMain_%.cpp.o: $(DPF_PATH)/distrho/DistrhoPluginMain.cpp
$(BUILD_DIR)/DistrhoPluginMain_%.cpp.o: $(DPF_PATH)/distrho/DistrhoPluginMain.cpp $(EXTRA_DEPENDENCIES)
-@mkdir -p $(BUILD_DIR)
@echo "Compiling DistrhoPluginMain.cpp ($*)"
$(SILENT)$(CXX) $< $(BUILD_CXX_FLAGS) -DDISTRHO_PLUGIN_TARGET_$* -c -o $@

$(BUILD_DIR)/DistrhoUIMain_%.cpp.o: $(DPF_PATH)/distrho/DistrhoUIMain.cpp
$(BUILD_DIR)/DistrhoUIMain_%.cpp.o: $(DPF_PATH)/distrho/DistrhoUIMain.cpp $(EXTRA_DEPENDENCIES)
-@mkdir -p $(BUILD_DIR)
@echo "Compiling DistrhoUIMain.cpp ($*)"
$(SILENT)$(CXX) $< $(BUILD_CXX_FLAGS) -DDISTRHO_PLUGIN_TARGET_$* -c -o $@

$(BUILD_DIR)/DistrhoUI_macOS_%.mm.o: $(DPF_PATH)/distrho/DistrhoUI_macOS.mm
$(BUILD_DIR)/DistrhoUI_macOS_%.mm.o: $(DPF_PATH)/distrho/DistrhoUI_macOS.mm $(EXTRA_DEPENDENCIES)
-@mkdir -p $(BUILD_DIR)
@echo "Compiling DistrhoUI_macOS.mm ($*)"
$(SILENT)$(CXX) $< $(BUILD_CXX_FLAGS) -DPUGL_NAMESPACE=$(call AS_PUGL_NAMESPACE,$*) -DGL_SILENCE_DEPRECATION -Wno-deprecated-declarations -I$(DPF_PATH)/dgl/src -I$(DPF_PATH)/dgl/src/pugl-upstream/include -ObjC++ -c -o $@

$(BUILD_DIR)/DistrhoPluginMain_JACK.cpp.o: $(DPF_PATH)/distrho/DistrhoPluginMain.cpp
$(BUILD_DIR)/DistrhoPluginMain_JACK.cpp.o: $(DPF_PATH)/distrho/DistrhoPluginMain.cpp $(EXTRA_DEPENDENCIES)
-@mkdir -p $(BUILD_DIR)
@echo "Compiling DistrhoPluginMain.cpp (JACK)"
$(SILENT)$(CXX) $< $(BUILD_CXX_FLAGS) -DDISTRHO_PLUGIN_TARGET_JACK $(JACK_FLAGS) -c -o $@

$(BUILD_DIR)/DistrhoUIMain_DSSI.cpp.o: $(DPF_PATH)/distrho/DistrhoUIMain.cpp
$(BUILD_DIR)/DistrhoUIMain_DSSI.cpp.o: $(DPF_PATH)/distrho/DistrhoUIMain.cpp $(EXTRA_DEPENDENCIES)
-@mkdir -p $(BUILD_DIR)
@echo "Compiling DistrhoUIMain.cpp (DSSI)"
$(SILENT)$(CXX) $< $(BUILD_CXX_FLAGS) $(LIBLO_FLAGS) -DDISTRHO_PLUGIN_TARGET_DSSI -c -o $@
@@ -322,13 +354,13 @@ $(BUILD_DIR)/DistrhoUIMain_DSSI.cpp.o: $(DPF_PATH)/distrho/DistrhoUIMain.cpp
jack: $(jack)

ifeq ($(HAVE_DGL),true)
$(jack): $(OBJS_DSP) $(OBJS_UI) $(BUILD_DIR)/DistrhoPluginMain_JACK.cpp.o $(BUILD_DIR)/DistrhoUIMain_JACK.cpp.o $(DGL_LIB) $(EXTRA_LIBS)
$(jack): $(OBJS_DSP) $(OBJS_UI) $(BUILD_DIR)/DistrhoPluginMain_JACK.cpp.o $(BUILD_DIR)/DistrhoUIMain_JACK.cpp.o $(DGL_LIB)
else
$(jack): $(OBJS_DSP) $(BUILD_DIR)/DistrhoPluginMain_JACK.cpp.o
endif
-@mkdir -p $(shell dirname $@)
@echo "Creating JACK standalone for $(NAME)"
$(SILENT)$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(DGL_LIBS) $(JACK_LIBS) -o $@
$(SILENT)$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(EXTRA_LIBS) $(DGL_LIBS) $(JACK_LIBS) -o $@

# ---------------------------------------------------------------------------------------------------------------------
# LADSPA
@@ -365,13 +397,13 @@ lv2_dsp: $(lv2_dsp)
lv2_sep: $(lv2_dsp) $(lv2_ui)

ifeq ($(HAVE_DGL),true)
$(lv2): $(OBJS_DSP) $(OBJS_UI) $(BUILD_DIR)/DistrhoPluginMain_LV2.cpp.o $(BUILD_DIR)/DistrhoUIMain_LV2.cpp.o $(DGL_LIB) $(EXTRA_LIBS)
$(lv2): $(OBJS_DSP) $(OBJS_UI) $(BUILD_DIR)/DistrhoPluginMain_LV2.cpp.o $(BUILD_DIR)/DistrhoUIMain_LV2.cpp.o $(DGL_LIB)
else
$(lv2): $(OBJS_DSP) $(OBJS_UI) $(BUILD_DIR)/DistrhoPluginMain_LV2.cpp.o
endif
-@mkdir -p $(shell dirname $@)
@echo "Creating LV2 plugin for $(NAME)"
$(SILENT)$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(DGL_LIBS) $(SHARED) $(SYMBOLS_LV2) -o $@
$(SILENT)$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(EXTRA_LIBS) $(DGL_LIBS) $(SHARED) $(SYMBOLS_LV2) -o $@

$(lv2_dsp): $(OBJS_DSP) $(BUILD_DIR)/DistrhoPluginMain_LV2.cpp.o
-@mkdir -p $(shell dirname $@)
@@ -386,30 +418,59 @@ $(lv2_ui): $(OBJS_UI) $(BUILD_DIR)/DistrhoUIMain_LV2.cpp.o $(DGL_LIB)
# ---------------------------------------------------------------------------------------------------------------------
# VST2

vst2 vst: $(vst2)
vst2 vst: $(vst2) $(vst2files)

ifeq ($(HAVE_DGL),true)
$(vst2): $(OBJS_DSP) $(OBJS_UI) $(BUILD_DIR)/DistrhoPluginMain_VST2.cpp.o $(BUILD_DIR)/DistrhoUIMain_VST2.cpp.o $(DGL_LIB) $(EXTRA_LIBS)
$(vst2): $(OBJS_DSP) $(OBJS_UI) $(BUILD_DIR)/DistrhoPluginMain_VST2.cpp.o $(BUILD_DIR)/DistrhoUIMain_VST2.cpp.o $(DGL_LIB)
else
$(vst2): $(OBJS_DSP) $(BUILD_DIR)/DistrhoPluginMain_VST2.cpp.o
endif
-@mkdir -p $(shell dirname $@)
@echo "Creating VST2 plugin for $(NAME)"
$(SILENT)$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(DGL_LIBS) $(SHARED) $(SYMBOLS_VST2) -o $@
$(SILENT)$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(EXTRA_LIBS) $(DGL_LIBS) $(SHARED) $(SYMBOLS_VST2) -o $@

# ---------------------------------------------------------------------------------------------------------------------
# VST3

vst3: $(vst3)
vst3: $(vst3) $(vst3files)

ifeq ($(HAVE_DGL),true)
$(vst3): $(OBJS_DSP) $(OBJS_UI) $(BUILD_DIR)/DistrhoPluginMain_VST3.cpp.o $(BUILD_DIR)/DistrhoUIMain_VST3.cpp.o $(DGL_LIB) $(EXTRA_LIBS)
$(vst3): $(OBJS_DSP) $(OBJS_UI) $(BUILD_DIR)/DistrhoPluginMain_VST3.cpp.o $(BUILD_DIR)/DistrhoUIMain_VST3.cpp.o $(DGL_LIB)
else
$(vst3): $(OBJS_DSP) $(BUILD_DIR)/DistrhoPluginMain_VST3.cpp.o
endif
-@mkdir -p $(shell dirname $@)
@echo "Creating VST3 plugin for $(NAME)"
$(SILENT)$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(DGL_LIBS) $(SHARED) $(SYMBOLS_VST3) -o $@
$(SILENT)$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(EXTRA_LIBS) $(DGL_LIBS) $(SHARED) $(SYMBOLS_VST3) -o $@

# ---------------------------------------------------------------------------------------------------------------------
# Shared

shared: $(shared)

ifeq ($(HAVE_DGL),true)
$(shared): $(OBJS_DSP) $(OBJS_UI) $(BUILD_DIR)/DistrhoPluginMain_SHARED.cpp.o $(BUILD_DIR)/DistrhoUIMain_SHARED.cpp.o $(DGL_LIB)
else
$(shared): $(OBJS_DSP) $(BUILD_DIR)/DistrhoPluginMain_SHARED.cpp.o
endif
-@mkdir -p $(shell dirname $@)
@echo "Creating shared library for $(NAME)"
$(SILENT)$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(EXTRA_LIBS) $(DGL_LIBS) $(SHARED) $(SYMBOLS_SHARED) -o $@

# ---------------------------------------------------------------------------------------------------------------------
# macOS files

$(TARGET_DIR)/%/Contents/Info.plist: $(DPF_PATH)/utils/plugin.vst/Contents/Info.plist
-@mkdir -p $(shell dirname $@)
$(SILENT)sed -e "s/@INFO_PLIST_PROJECT_NAME@/$(NAME)/" $< > $@

$(TARGET_DIR)/%/Contents/PkgInfo: $(DPF_PATH)/utils/plugin.vst/Contents/PkgInfo
-@mkdir -p $(shell dirname $@)
$(SILENT)cp $< $@

$(TARGET_DIR)/%/Resources/empty.lproj: $(DPF_PATH)/utils/plugin.vst/Contents/Resources/empty.lproj
-@mkdir -p $(shell dirname $@)
$(SILENT)cp $< $@

# ---------------------------------------------------------------------------------------------------------------------

@@ -424,11 +485,13 @@ endif
-include $(BUILD_DIR)/DistrhoPluginMain_LV2.cpp.d
-include $(BUILD_DIR)/DistrhoPluginMain_VST2.cpp.d
-include $(BUILD_DIR)/DistrhoPluginMain_VST3.cpp.d
-include $(BUILD_DIR)/DistrhoPluginMain_SHARED.cpp.d

-include $(BUILD_DIR)/DistrhoUIMain_JACK.cpp.d
-include $(BUILD_DIR)/DistrhoUIMain_DSSI.cpp.d
-include $(BUILD_DIR)/DistrhoUIMain_LV2.cpp.d
-include $(BUILD_DIR)/DistrhoUIMain_VST2.cpp.d
-include $(BUILD_DIR)/DistrhoUIMain_VST3.cpp.d
-include $(BUILD_DIR)/DistrhoUIMain_SHARED.cpp.d

# ---------------------------------------------------------------------------------------------------------------------

+ 9
- 7
dpf/cmake/DPF-plugin.cmake View File

@@ -122,6 +122,10 @@ function(dpf_add_plugin NAME)
target_include_directories("${NAME}" PUBLIC
"${DPF_ROOT_DIR}/distrho")

if((NOT WIN32) AND (NOT APPLE) AND (NOT HAIKU))
target_link_libraries("${NAME}" PRIVATE "dl")
endif()

if(_dgl_library)
# make sure that all code will see DGL_* definitions
target_link_libraries("${NAME}" PUBLIC
@@ -135,6 +139,9 @@ function(dpf_add_plugin NAME)
if(_dgl_library)
dpf__add_static_library("${NAME}-ui" ${_dpf_plugin_FILES_UI})
target_link_libraries("${NAME}-ui" PUBLIC "${NAME}" ${_dgl_library})
if((NOT WIN32) AND (NOT APPLE) AND (NOT HAIKU))
target_link_libraries("${NAME}-ui" PRIVATE "dl")
endif()
# add the files containing Objective-C classes, recompiled under namespace
dpf__add_plugin_specific_ui_sources("${NAME}-ui")
else()
@@ -185,11 +192,6 @@ function(dpf__build_jack NAME DGL_LIBRARY)
RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin/$<0:>"
OUTPUT_NAME "${NAME}")

# Note: libjack will be linked at runtime
if((NOT WIN32) AND (NOT APPLE) AND (NOT HAIKU))
target_link_libraries("${NAME}-jack" PRIVATE "dl")
endif()

# for RtAudio native fallback
if(APPLE)
find_library(APPLE_COREAUDIO_FRAMEWORK "CoreAudio")
@@ -303,7 +305,7 @@ function(dpf__build_lv2 NAME DGL_LIBRARY MONOLITHIC)
add_dependencies("${NAME}-lv2" lv2_ttl_generator)

add_custom_command(TARGET "${NAME}-lv2" POST_BUILD
COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR}
COMMAND
"$<TARGET_FILE:lv2_ttl_generator>"
"$<TARGET_FILE:${NAME}-lv2>"
WORKING_DIRECTORY "${PROJECT_BINARY_DIR}/bin/${NAME}.lv2"
@@ -414,7 +416,7 @@ function(dpf__build_vst3 NAME DGL_LIBRARY)
SUFFIX "")
elseif(WIN32)
set_target_properties("${NAME}-vst3" PROPERTIES
LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin/${NAME}.vst3/Contents/${vst3_arch}-win/$<0:>")
LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin/${NAME}.vst3/Contents/${vst3_arch}-win/$<0:>" SUFFIX ".vst3")
else()
set_target_properties("${NAME}-vst3" PROPERTIES
LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin/${NAME}.vst3/Contents/${vst3_arch}-linux/$<0:>")


+ 9
- 0
dpf/dgl/Application.hpp View File

@@ -80,6 +80,15 @@ public:
*/
bool isStandalone() const noexcept;

/**
Return the time in seconds.

This is a monotonically increasing clock with high resolution.@n
The returned time is only useful to compare against other times returned by this function,
its absolute value has no meaning.
*/
double getTime() const;

/**
Add a callback function to be triggered on every idle cycle.
You can add more than one, and remove them at anytime with removeIdleCallback().


+ 17
- 0
dpf/dgl/Base.hpp View File

@@ -130,6 +130,23 @@ enum CrossingMode {
kCrossingUngrab ///< Crossing due to a grab release
};

/**
A mouse cursor type.

This is a portable subset of mouse cursors that exist on X11, MacOS, and Windows.
*/
enum MouseCursor {
kMouseCursorArrow, ///< Default pointing arrow
kMouseCursorCaret, ///< Caret (I-Beam) for text entry
kMouseCursorCrosshair, ///< Cross-hair
kMouseCursorHand, ///< Hand with a pointing finger
kMouseCursorNotAllowed, ///< Operation not allowed
kMouseCursorLeftRight, ///< Left/right arrow for horizontal resize
kMouseCursorUpDown, ///< Up/down arrow for vertical resize
kMouseCursorDiagonal, ///< Top-left to bottom-right arrow for diagonal resize
kMouseCursorAntiDiagonal ///< Bottom-left to top-right arrow for diagonal resize
};

/**
Scroll direction.



+ 1
- 1
dpf/dgl/ImageBase.hpp View File

@@ -39,7 +39,7 @@ enum ImageFormat {
It is an abstract class that provides the common methods to build on top.
Cairo and OpenGL Image classes are based upon this one.

@see Image
@see CairoImage, OpenGLImage
*/
class ImageBase
{


+ 48
- 3
dpf/dgl/ImageBaseWidgets.hpp View File

@@ -25,13 +25,36 @@ START_NAMESPACE_DGL

// --------------------------------------------------------------------------------------------------------------------

/**
DGL Image About Window class.

This is a Window attached (transient) to another Window that simply shows an Image as its content.
It is typically used for "about this project" style pop-up Windows.

Pressing 'Esc' or clicking anywhere on the window will automatically close it.

@see CairoImageAboutWindow, OpenGLImageAboutWindow, Window::runAsModal(bool)
*/
template <class ImageType>
class ImageBaseAboutWindow : public StandaloneWindow
{
public:
explicit ImageBaseAboutWindow(Window& parentWindow, const ImageType& image = ImageType());
explicit ImageBaseAboutWindow(TopLevelWidget* parentTopLevelWidget, const ImageType& image = ImageType());

/**
Constructor taking an existing Window as the parent transient window and an optional image.
If @a image is valid, the about window size will match the image size.
*/
explicit ImageBaseAboutWindow(Window& transientParentWindow, const ImageType& image = ImageType());

/**
Constructor taking a top-level-widget's Window as the parent transient window and an optional image.
If @a image is valid, the about window size will match the image size.
*/
explicit ImageBaseAboutWindow(TopLevelWidget* topLevelWidget, const ImageType& image = ImageType());

/**
Set a new image to use as background for this window.
Window size will adjust to match the image size.
*/
void setImage(const ImageType& image);

protected:
@@ -47,6 +70,16 @@ private:

// --------------------------------------------------------------------------------------------------------------------

/**
DGL Image Button class.

This is a typical button, where the drawing comes from a pregenerated set of images.
The button can be under "normal", "hover" and "down" states, with one separate image possible for each.

The event logic for this button comes from the ButtonEventHandler class.

@see CairoImageButton, OpenGLImageButton
*/
template <class ImageType>
class ImageBaseButton : public SubWidget,
public ButtonEventHandler
@@ -81,6 +114,18 @@ private:

// --------------------------------------------------------------------------------------------------------------------

/**
DGL Image Knob class.

This is a typical knob/dial, where the drawing comes from a pregenerated image "filmstrip".
The knob's "filmstrip" image can be either horizontal or vertical,
with the number of steps automatically based on the largest value (ie, horizontal if width>height, vertical if height>width).
There are no different images for "hover" or "down" states.

The event logic for this knob comes from the KnobEventHandler class.

@see CairoImageKnob, OpenGLImageKnob
*/
template <class ImageType>
class ImageBaseKnob : public SubWidget,
public KnobEventHandler


+ 6
- 0
dpf/dgl/Makefile View File

@@ -13,6 +13,12 @@ BUILD_CXX_FLAGS += $(DGL_FLAGS) -I. -Isrc -DDONT_SET_USING_DGL_NAMESPACE -Wno-un
BUILD_CXX_FLAGS += -Isrc/pugl-upstream/include
LINK_FLAGS += $(DGL_LIBS)

ifeq ($(NVG_DISABLE_SKIPPING_WHITESPACE),true)
BUILD_CXX_FLAGS += -DNVG_DISABLE_SKIPPING_WHITESPACE
endif
ifneq ($(NVG_FONT_TEXTURE_FLAGS),)
BUILD_CXX_FLAGS += -DNVG_FONT_TEXTURE_FLAGS=$(NVG_FONT_TEXTURE_FLAGS)
endif
ifeq ($(USE_OPENGL3),true)
BUILD_CXX_FLAGS += -DDGL_USE_OPENGL3
endif


+ 14
- 1
dpf/dgl/NanoVG.hpp View File

@@ -42,6 +42,15 @@ START_NAMESPACE_DGL

class NanoVG;

// -----------------------------------------------------------------------
// Helper methods

/**
Create a NanoVG context using the DPF-provided NanoVG library.
On Windows this will load a few extra OpenGL functions required for NanoVG to work.
*/
NVGcontext* nvgCreateGL(int flags);

// -----------------------------------------------------------------------
// NanoImage

@@ -444,6 +453,11 @@ public:
*/
void globalAlpha(float alpha);

/**
Sets the color tint applied to all rendered shapes.
*/
void globalTint(Color tint);

/* --------------------------------------------------------------------
* Transforms */

@@ -943,7 +957,6 @@ private:
inline void onDisplay() override
{
// NOTE maybe should use BaseWidget::getWindow().getScaleFactor() as 3rd arg ?
NanoVG::reset();
NanoVG::beginFrame(BaseWidget::getWidth(), BaseWidget::getHeight());
onNanoDisplay();
NanoVG::endFrame();


+ 7
- 1
dpf/dgl/TopLevelWidget.hpp View File

@@ -101,13 +101,17 @@ public:
void repaint(const Rectangle<uint>& rect) noexcept;

// TODO group stuff after here, convenience functions present in Window class
bool setClipboard(const char* mimeType, const void* data, size_t dataSize);
const void* getClipboard(const char*& mimeType, size_t& dataSize);
bool setCursor(MouseCursor cursor);
bool addIdleCallback(IdleCallback* callback, uint timerFrequencyInMs = 0);
bool removeIdleCallback(IdleCallback* callback);
double getScaleFactor() const noexcept;
void setGeometryConstraints(uint minimumWidth,
uint minimumHeight,
bool keepAspectRatio = false,
bool automaticallyScale = false);
bool automaticallyScale = false,
bool resizeNowIfAutoScaling = true);

DISTRHO_DEPRECATED_BY("getApp()")
Application& getParentApp() const noexcept { return getApp(); }
@@ -129,6 +133,8 @@ private:
#ifdef DISTRHO_DEFINES_H_INCLUDED
friend class DISTRHO_NAMESPACE::UI;
#endif
/** @internal */
virtual void requestSizeChange(uint width, uint height);

DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(TopLevelWidget)
};


+ 42
- 49
dpf/dgl/Window.hpp View File

@@ -19,9 +19,14 @@

#include "Geometry.hpp"

#ifndef DGL_FILE_BROWSER_DISABLED
# include "../distrho/extra/FileBrowserDialog.hpp"
#endif

START_NAMESPACE_DGL

class Application;
class PluginWindow;
class TopLevelWidget;

// -----------------------------------------------------------------------
@@ -53,53 +58,9 @@ class Window

public:
#ifndef DGL_FILE_BROWSER_DISABLED
/**
File browser options.
@see Window::openFileBrowser
*/
struct FileBrowserOptions {
/**
File browser button state.
This allows to customize the behaviour of the file browse dialog buttons.
Note these are merely hints, not all systems support them.
*/
enum ButtonState {
kButtonInvisible,
kButtonVisibleUnchecked,
kButtonVisibleChecked,
};

/** Start directory, uses current working directory if null */
const char* startDir;
/** File browser dialog window title, uses "FileBrowser" if null */
const char* title;
// TODO file filter

/**
File browser buttons.
*/
struct Buttons {
/** Whether to list all files vs only those with matching file extension */
ButtonState listAllFiles;
/** Whether to show hidden files */
ButtonState showHidden;
/** Whether to show list of places (bookmarks) */
ButtonState showPlaces;

/** Constructor for default values */
Buttons()
: listAllFiles(kButtonVisibleChecked),
showHidden(kButtonVisibleUnchecked),
showPlaces(kButtonVisibleChecked) {}
} buttons;

/** Constructor for default values */
FileBrowserOptions()
: startDir(nullptr),
title(nullptr),
buttons() {}
};
#endif // DGL_FILE_BROWSER_DISABLED
typedef DISTRHO_NAMESPACE::FileBrowserHandle FileBrowserHandle;
typedef DISTRHO_NAMESPACE::FileBrowserOptions FileBrowserOptions;
#endif

/**
Window graphics context as a scoped struct.
@@ -302,6 +263,36 @@ public:
*/
void setIgnoringKeyRepeat(bool ignore) noexcept;

/**
Set the clipboard contents.

This sets the system clipboard contents,
which can be retrieved with getClipboard() or pasted into other applications.

If using a string, the use of a null terminator is required (and must be part of dataSize).@n
The MIME type of the data "text/plain" is assumed if null is used.
*/
bool setClipboard(const char* mimeType, const void* data, size_t dataSize);

/**
Get the clipboard contents.

This gets the system clipboard contents,
which may have been set with setClipboard() or copied from another application.

returns the clipboard contents, or null.
*/
const void* getClipboard(const char*& mimeType, size_t& dataSize);

/**
Set the mouse cursor.

This changes the system cursor that is displayed when the pointer is inside the window.
May fail if setting the cursor is not supported on this system,
for example if compiled on X11 without Xcursor support.
*/
bool setCursor(MouseCursor cursor);

/**
Add a callback function to be triggered on every idle cycle or on a specific timer frequency.
You can add more than one, and remove them at anytime with removeIdleCallback().
@@ -361,7 +352,7 @@ public:

#ifndef DGL_FILE_BROWSER_DISABLED
/**
Open a file browser dialog with this window as parent.
Open a file browser dialog with this window as transient parent.
A few options can be specified to setup the dialog.

If a path is selected, onFileSelected() will be called with the user chosen path.
@@ -408,7 +399,8 @@ public:
void setGeometryConstraints(uint minimumWidth,
uint minimumHeight,
bool keepAspectRatio = false,
bool automaticallyScale = false);
bool automaticallyScale = false,
bool resizeNowIfAutoScaling = true);

/** DEPRECATED Use isIgnoringKeyRepeat(). */
DISTRHO_DEPRECATED_BY("isIgnoringKeyRepeat()")
@@ -482,6 +474,7 @@ private:
uint height,
double scaleFactor,
bool resizable,
bool isVST3,
bool doPostInit);

DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(Window);


+ 5
- 0
dpf/dgl/src/Application.cpp View File

@@ -56,6 +56,11 @@ bool Application::isStandalone() const noexcept
return pData->isStandalone;
}

double Application::getTime() const
{
return pData->getTime();
}

void Application::addIdleCallback(IdleCallback* const callback)
{
DISTRHO_SAFE_ASSERT_RETURN(callback != nullptr,)


+ 7
- 0
dpf/dgl/src/ApplicationPrivateData.cpp View File

@@ -152,6 +152,13 @@ void Application::PrivateData::quit()
#endif
}

double Application::PrivateData::getTime() const
{
DISTRHO_SAFE_ASSERT_RETURN(world != nullptr, 0.0);

return puglGetTime(world);
}

void Application::PrivateData::setClassName(const char* const name)
{
DISTRHO_SAFE_ASSERT_RETURN(world != nullptr,);


+ 9
- 0
dpf/dgl/src/ApplicationPrivateData.hpp View File

@@ -30,12 +30,18 @@ typedef HANDLE d_ThreadHandle;
typedef pthread_t d_ThreadHandle;
#endif

#ifdef DISTRHO_OS_MAC
typedef struct PuglWorldImpl PuglWorld;
#endif

START_NAMESPACE_DGL

class Window;

#ifndef DISTRHO_OS_MAC
typedef struct PuglWorldImpl PuglWorld;
#endif

// --------------------------------------------------------------------------------------------------------------------

struct Application::PrivateData {
@@ -91,6 +97,9 @@ struct Application::PrivateData {
For standalone mode only. */
void quit();

/** Get time via pugl */
double getTime() const;

/** Set pugl world class name. */
void setClassName(const char* name);



+ 4
- 4
dpf/dgl/src/ImageBaseWidgets.cpp View File

@@ -22,8 +22,8 @@ START_NAMESPACE_DGL
// --------------------------------------------------------------------------------------------------------------------

template <class ImageType>
ImageBaseAboutWindow<ImageType>::ImageBaseAboutWindow(Window& parentWindow, const ImageType& image)
: StandaloneWindow(parentWindow.getApp(), parentWindow),
ImageBaseAboutWindow<ImageType>::ImageBaseAboutWindow(Window& transientParentWindow, const ImageType& image)
: StandaloneWindow(transientParentWindow.getApp(), transientParentWindow),
img(image)
{
setResizable(false);
@@ -39,8 +39,8 @@ ImageBaseAboutWindow<ImageType>::ImageBaseAboutWindow(Window& parentWindow, cons
}

template <class ImageType>
ImageBaseAboutWindow<ImageType>::ImageBaseAboutWindow(TopLevelWidget* const parentTopLevelWidget, const ImageType& image)
: StandaloneWindow(parentTopLevelWidget->getApp(), parentTopLevelWidget->getWindow()),
ImageBaseAboutWindow<ImageType>::ImageBaseAboutWindow(TopLevelWidget* const topLevelWidget, const ImageType& image)
: StandaloneWindow(topLevelWidget->getApp(), topLevelWidget->getWindow()),
img(image)
{
setResizable(false);


+ 17
- 11
dpf/dgl/src/NanoVG.cpp View File

@@ -102,28 +102,32 @@ DGL_EXT(PFNGLUNIFORMBLOCKBINDINGPROC, glUniformBlockBinding)
#endif

#if defined(NANOVG_GL2)
# define nvgCreateGL nvgCreateGL2
# define nvgCreateGLfn nvgCreateGL2
# define nvgDeleteGL nvgDeleteGL2
# define nvglCreateImageFromHandle nvglCreateImageFromHandleGL2
# define nvglImageHandle nvglImageHandleGL2
#elif defined(NANOVG_GL3)
# define nvgCreateGL nvgCreateGL3
# define nvgCreateGLfn nvgCreateGL3
# define nvgDeleteGL nvgDeleteGL3
# define nvglCreateImageFromHandle nvglCreateImageFromHandleGL3
# define nvglImageHandle nvglImageHandleGL3
#elif defined(NANOVG_GLES2)
# define nvgCreateGL nvgCreateGLES2
# define nvgCreateGLfn nvgCreateGLES2
# define nvgDeleteGL nvgDeleteGLES2
# define nvglCreateImageFromHandle nvglCreateImageFromHandleGLES2
# define nvglImageHandle nvglImageHandleGLES2
#elif defined(NANOVG_GLES3)
# define nvgCreateGL nvgCreateGLES3
# define nvgCreateGLfn nvgCreateGLES3
# define nvgDeleteGL nvgDeleteGLES3
# define nvglCreateImageFromHandle nvglCreateImageFromHandleGLES3
# define nvglImageHandle nvglImageHandleGLES3
#endif

static NVGcontext* nvgCreateGL_helper(int flags)
// -----------------------------------------------------------------------

START_NAMESPACE_DGL

NVGcontext* nvgCreateGL(int flags)
{
#if defined(DISTRHO_OS_WINDOWS)
# if defined(__GNUC__) && (__GNUC__ >= 9)
@@ -189,13 +193,9 @@ DGL_EXT(PFNGLUNIFORMBLOCKBINDINGPROC, glUniformBlockBinding)
# pragma GCC diagnostic pop
# endif
#endif
return nvgCreateGL(flags);
return nvgCreateGLfn(flags);
}

// -----------------------------------------------------------------------

START_NAMESPACE_DGL

// -----------------------------------------------------------------------
// DGL Color class conversion

@@ -312,7 +312,7 @@ NanoVG::Paint::operator NVGpaint() const noexcept
// NanoVG

NanoVG::NanoVG(int flags)
: fContext(nvgCreateGL_helper(flags)),
: fContext(nvgCreateGL(flags)),
fInFrame(false),
fIsSubWidget(false) {}

@@ -513,6 +513,12 @@ void NanoVG::globalAlpha(float alpha)
nvgGlobalAlpha(fContext, alpha);
}

void NanoVG::globalTint(Color tint)
{
if (fContext != nullptr)
nvgGlobalTint(fContext, tint);
}

// -----------------------------------------------------------------------
// Transforms



+ 14
- 5
dpf/dgl/src/SubWidget.cpp View File

@@ -35,8 +35,8 @@ template<typename T>
bool SubWidget::contains(const T x, const T y) const noexcept
{
return Rectangle<double>(0, 0,
static_cast<double>(getWidth()) - pData->margin.getX(),
static_cast<double>(getHeight()) - pData->margin.getY()).contains(x, y);
static_cast<double>(getWidth()),
static_cast<double>(getHeight())).contains(x, y);
}

template<typename T>
@@ -67,9 +67,18 @@ Rectangle<int> SubWidget::getAbsoluteArea() const noexcept

Rectangle<uint> SubWidget::getConstrainedAbsoluteArea() const noexcept
{
return Rectangle<uint>(static_cast<uint>(std::max(0, getAbsoluteX())),
static_cast<uint>(std::max(0, getAbsoluteY())),
getSize());
const int x = getAbsoluteX();
const int y = getAbsoluteY();

if (x >= 0 && y >= 0)
return Rectangle<uint>(x, y, getSize());

const int xOffset = std::min(0, x);
const int yOffset = std::min(0, y);
const int width = std::max(0, static_cast<int>(getWidth()) + xOffset);
const int height = std::max(0, static_cast<int>(getHeight()) + yOffset);

return Rectangle<uint>(0, 0, static_cast<uint>(width), static_cast<uint>(height));
}

void SubWidget::setAbsoluteX(const int x) noexcept


+ 38
- 12
dpf/dgl/src/TopLevelWidget.cpp View File

@@ -60,6 +60,21 @@ void TopLevelWidget::setSize(const Size<uint>& size)
pData->window.setSize(size);
}

bool TopLevelWidget::setClipboard(const char* const mimeType, const void* const data, const size_t dataSize)
{
return pData->window.setClipboard(mimeType, data, dataSize);
}

const void* TopLevelWidget::getClipboard(const char*& mimeType, size_t& dataSize)
{
return pData->window.getClipboard(mimeType, dataSize);
}

bool TopLevelWidget::setCursor(const MouseCursor cursor)
{
return pData->window.setCursor(cursor);
}

bool TopLevelWidget::addIdleCallback(IdleCallback* const callback, const uint timerFrequencyInMs)
{
return pData->window.addIdleCallback(callback, timerFrequencyInMs);
@@ -88,36 +103,47 @@ void TopLevelWidget::repaint(const Rectangle<uint>& rect) noexcept
void TopLevelWidget::setGeometryConstraints(const uint minimumWidth,
const uint minimumHeight,
const bool keepAspectRatio,
const bool automaticallyScale)
const bool automaticallyScale,
const bool resizeNowIfAutoScaling)
{
pData->window.setGeometryConstraints(minimumWidth, minimumHeight, keepAspectRatio, automaticallyScale);
pData->window.setGeometryConstraints(minimumWidth,
minimumHeight,
keepAspectRatio,
automaticallyScale,
resizeNowIfAutoScaling);
}

// --------------------------------------------------------------------------------------------------------------------

bool TopLevelWidget::onKeyboard(const KeyboardEvent&)
bool TopLevelWidget::onKeyboard(const KeyboardEvent& ev)
{
return false;
return pData->keyboardEvent(ev);
}

bool TopLevelWidget::onCharacterInput(const CharacterInputEvent&)
bool TopLevelWidget::onCharacterInput(const CharacterInputEvent& ev)
{
return false;
return pData->characterInputEvent(ev);
}

bool TopLevelWidget::onMouse(const MouseEvent&)
bool TopLevelWidget::onMouse(const MouseEvent& ev)
{
return false;
return pData->mouseEvent(ev);
}

bool TopLevelWidget::onMotion(const MotionEvent&)
bool TopLevelWidget::onMotion(const MotionEvent& ev)
{
return false;
return pData->motionEvent(ev);
}

bool TopLevelWidget::onScroll(const ScrollEvent&)
bool TopLevelWidget::onScroll(const ScrollEvent& ev)
{
return pData->scrollEvent(ev);
}

// --------------------------------------------------------------------------------------------------------------------

void TopLevelWidget::requestSizeChange(uint, uint)
{
return false;
}

// --------------------------------------------------------------------------------------------------------------------


+ 0
- 20
dpf/dgl/src/TopLevelWidgetPrivateData.cpp View File

@@ -42,10 +42,6 @@ bool TopLevelWidget::PrivateData::keyboardEvent(const KeyboardEvent& ev)
if (! selfw->pData->visible)
return false;

// give top-level widget chance to catch this event first
if (self->onKeyboard(ev))
return true;

// propagate event to all subwidgets recursively
return selfw->pData->giveKeyboardEventForSubWidgets(ev);
}
@@ -56,10 +52,6 @@ bool TopLevelWidget::PrivateData::characterInputEvent(const CharacterInputEvent&
if (! selfw->pData->visible)
return false;

// give top-level widget chance to catch this event first
if (self->onCharacterInput(ev))
return true;

// propagate event to all subwidgets recursively
return selfw->pData->giveCharacterInputEventForSubWidgets(ev);
}
@@ -82,10 +74,6 @@ bool TopLevelWidget::PrivateData::mouseEvent(const MouseEvent& ev)
rev.absolutePos.setY(ev.absolutePos.getY() / autoScaleFactor);
}

// give top-level widget chance to catch this event first
if (self->onMouse(ev))
return true;

// propagate event to all subwidgets recursively
return selfw->pData->giveMouseEventForSubWidgets(rev);
}
@@ -108,10 +96,6 @@ bool TopLevelWidget::PrivateData::motionEvent(const MotionEvent& ev)
rev.absolutePos.setY(ev.absolutePos.getY() / autoScaleFactor);
}

// give top-level widget chance to catch this event first
if (self->onMotion(ev))
return true;

// propagate event to all subwidgets recursively
return selfw->pData->giveMotionEventForSubWidgets(rev);
}
@@ -136,10 +120,6 @@ bool TopLevelWidget::PrivateData::scrollEvent(const ScrollEvent& ev)
rev.delta.setY(ev.delta.getY() / autoScaleFactor);
}

// give top-level widget chance to catch this event first
if (self->onScroll(ev))
return true;

// propagate event to all subwidgets recursively
return selfw->pData->giveScrollEventForSubWidgets(rev);
}


+ 1
- 1
dpf/dgl/src/TopLevelWidgetPrivateData.hpp View File

@@ -30,7 +30,7 @@ struct TopLevelWidget::PrivateData {
Widget* const selfw;
Window& window;

explicit PrivateData(TopLevelWidget* const s, Window& w);
explicit PrivateData(TopLevelWidget* self, Window& window);
~PrivateData();
void display();
bool keyboardEvent(const KeyboardEvent& ev);


+ 12
- 21
dpf/dgl/src/WidgetPrivateData.cpp View File

@@ -112,18 +112,15 @@ bool Widget::PrivateData::giveMouseEventForSubWidgets(MouseEvent& ev)
if (subWidgets.size() == 0)
return false;

double x = ev.absolutePos.getX();
double y = ev.absolutePos.getY();
const double x = ev.absolutePos.getX();
const double y = ev.absolutePos.getY();

if (SubWidget* const selfw = dynamic_cast<SubWidget*>(self))
{
if (selfw->pData->needsViewportScaling)
{
x -= selfw->getAbsoluteX();
y -= selfw->getAbsoluteY();

ev.absolutePos.setX(x);
ev.absolutePos.setY(y);
ev.absolutePos.setX(x - selfw->getAbsoluteX() + selfw->getMargin().getX());
ev.absolutePos.setY(y - selfw->getAbsoluteY() + selfw->getMargin().getY());
}
}

@@ -151,18 +148,15 @@ bool Widget::PrivateData::giveMotionEventForSubWidgets(MotionEvent& ev)
if (subWidgets.size() == 0)
return false;

double x = ev.absolutePos.getX();
double y = ev.absolutePos.getY();
const double x = ev.absolutePos.getX();
const double y = ev.absolutePos.getY();

if (SubWidget* const selfw = dynamic_cast<SubWidget*>(self))
{
if (selfw->pData->needsViewportScaling)
{
x -= selfw->getAbsoluteX();
y -= selfw->getAbsoluteY();

ev.absolutePos.setX(x);
ev.absolutePos.setY(y);
ev.absolutePos.setX(x - selfw->getAbsoluteX() + selfw->getMargin().getX());
ev.absolutePos.setY(y - selfw->getAbsoluteY() + selfw->getMargin().getY());
}
}

@@ -190,18 +184,15 @@ bool Widget::PrivateData::giveScrollEventForSubWidgets(ScrollEvent& ev)
if (subWidgets.size() == 0)
return false;

double x = ev.absolutePos.getX();
double y = ev.absolutePos.getY();
const double x = ev.absolutePos.getX();
const double y = ev.absolutePos.getY();

if (SubWidget* const selfw = dynamic_cast<SubWidget*>(self))
{
if (selfw->pData->needsViewportScaling)
{
x -= selfw->getAbsoluteX();
y -= selfw->getAbsoluteY();

ev.absolutePos.setX(x);
ev.absolutePos.setY(y);
ev.absolutePos.setX(x - selfw->getAbsoluteX() + selfw->getMargin().getX());
ev.absolutePos.setY(y - selfw->getAbsoluteY() + selfw->getMargin().getY());
}
}



+ 56
- 13
dpf/dgl/src/Window.cpp View File

@@ -15,6 +15,7 @@
*/

#include "WindowPrivateData.hpp"
#include "../TopLevelWidget.hpp"

#include "pugl.hpp"

@@ -87,7 +88,7 @@ Window::Window(Application& app,
const uint height,
const double scaleFactor,
const bool resizable)
: pData(new PrivateData(app, this, parentWindowHandle, width, height, scaleFactor, resizable))
: pData(new PrivateData(app, this, parentWindowHandle, width, height, scaleFactor, resizable, false))
{
pData->initPost();
}
@@ -98,8 +99,9 @@ Window::Window(Application& app,
const uint height,
const double scaleFactor,
const bool resizable,
const bool isVST3,
const bool doPostInit)
: pData(new PrivateData(app, this, parentWindowHandle, width, height, scaleFactor, resizable))
: pData(new PrivateData(app, this, parentWindowHandle, width, height, scaleFactor, resizable, isVST3))
{
if (doPostInit)
pData->initPost();
@@ -199,8 +201,14 @@ void Window::setSize(uint width, uint height)
if (pData->isEmbed)
{
const double scaleFactor = pData->scaleFactor;
const uint minWidth = static_cast<uint>(pData->minWidth * scaleFactor + 0.5);
const uint minHeight = static_cast<uint>(pData->minHeight * scaleFactor + 0.5);
uint minWidth = pData->minWidth;
uint minHeight = pData->minHeight;

if (pData->autoScaling && scaleFactor != 1.0)
{
minWidth *= scaleFactor;
minHeight *= scaleFactor;
}

// handle geometry constraints here
if (width < minWidth)
@@ -228,7 +236,19 @@ void Window::setSize(uint width, uint height)
}
}

puglSetWindowSize(pData->view, width, height);
if (pData->usesSizeRequest)
{
DISTRHO_SAFE_ASSERT_RETURN(pData->topLevelWidgets.size() != 0,);

TopLevelWidget* const topLevelWidget = pData->topLevelWidgets.front();
DISTRHO_SAFE_ASSERT_RETURN(topLevelWidget != nullptr,);

topLevelWidget->requestSizeChange(width, height);
}
else
{
puglSetWindowSize(pData->view, width, height);
}
}

void Window::setSize(const Size<uint>& size)
@@ -257,6 +277,25 @@ void Window::setIgnoringKeyRepeat(const bool ignore) noexcept
puglSetViewHint(pData->view, PUGL_IGNORE_KEY_REPEAT, ignore);
}

bool Window::setClipboard(const char* const mimeType, const void* const data, const size_t dataSize)
{
return puglSetClipboard(pData->view, mimeType, data, dataSize) == PUGL_SUCCESS;
}

const void* Window::getClipboard(const char*& mimeType, size_t& dataSize)
{
DISTRHO_SAFE_ASSERT_RETURN(!pData->ignoreEvents, nullptr);
pData->ignoreEvents = true;
const void* const clipboard = puglGetClipboard(pData->view, &mimeType, &dataSize);
pData->ignoreEvents = false;
return clipboard;
}

bool Window::setCursor(const MouseCursor cursor)
{
return puglSetCursor(pData->view, static_cast<PuglCursor>(cursor)) == PUGL_SUCCESS;
}

bool Window::addIdleCallback(IdleCallback* const callback, const uint timerFrequencyInMs)
{
DISTRHO_SAFE_ASSERT_RETURN(callback != nullptr, false)
@@ -352,10 +391,11 @@ Size<uint> Window::getGeometryConstraints(bool& keepAspectRatio)
return Size<uint>(pData->minWidth, pData->minHeight);
}

void Window::setGeometryConstraints(const uint minimumWidth,
const uint minimumHeight,
void Window::setGeometryConstraints(uint minimumWidth,
uint minimumHeight,
const bool keepAspectRatio,
const bool automaticallyScale)
const bool automaticallyScale,
const bool resizeNowIfAutoScaling)
{
DISTRHO_SAFE_ASSERT_RETURN(minimumWidth > 0,);
DISTRHO_SAFE_ASSERT_RETURN(minimumHeight > 0,);
@@ -370,12 +410,15 @@ void Window::setGeometryConstraints(const uint minimumWidth,

const double scaleFactor = pData->scaleFactor;

puglSetGeometryConstraints(pData->view,
static_cast<uint>(minimumWidth * scaleFactor + 0.5),
static_cast<uint>(minimumHeight * scaleFactor + 0.5),
keepAspectRatio);
if (automaticallyScale && scaleFactor != 1.0)
{
minimumWidth *= scaleFactor;
minimumHeight *= scaleFactor;
}

puglSetGeometryConstraints(pData->view, minimumWidth, minimumHeight, keepAspectRatio);

if (scaleFactor != 1.0)
if (scaleFactor != 1.0 && automaticallyScale && resizeNowIfAutoScaling)
{
const Size<uint> size(getSize());



+ 68
- 206
dpf/dgl/src/WindowPrivateData.cpp View File

@@ -19,18 +19,7 @@

#include "pugl.hpp"

#include "../../distrho/extra/String.hpp"

#ifdef DISTRHO_OS_WINDOWS
# include <direct.h>
# include <winsock2.h>
# include <windows.h>
# include <vector>
#else
# include <unistd.h>
#endif

#define DGL_DEBUG_EVENTS
// #define DGL_DEBUG_EVENTS

#if defined(DEBUG) && defined(DGL_DEBUG_EVENTS)
# ifdef DISTRHO_PROPER_CPP11_SUPPORT
@@ -63,11 +52,6 @@ START_NAMESPACE_DGL

// -----------------------------------------------------------------------

#ifdef DISTRHO_OS_WINDOWS
// static pointer used for direct comparisons
static const char* const kWin32SelectedFileCancelled = "__dpf_cancelled__";
#endif

static double getDesktopScaleFactor(const PuglView* const view)
{
// allow custom scale for testing
@@ -92,6 +76,7 @@ Window::PrivateData::PrivateData(Application& a, Window* const s)
isClosed(true),
isVisible(false),
isEmbed(false),
usesSizeRequest(false),
scaleFactor(getDesktopScaleFactor(view)),
autoScaling(false),
autoScaleFactor(1.0),
@@ -99,9 +84,10 @@ Window::PrivateData::PrivateData(Application& a, Window* const s)
minHeight(0),
keepAspectRatio(false),
ignoreIdleCallbacks(false),
ignoreEvents(false),
filenameToRenderInto(nullptr),
#ifdef DISTRHO_OS_WINDOWS
win32SelectedFile(nullptr),
#ifndef DGL_FILE_BROWSER_DISABLED
fileBrowserHandle(nullptr),
#endif
modal()
{
@@ -118,6 +104,7 @@ Window::PrivateData::PrivateData(Application& a, Window* const s, PrivateData* c
isClosed(true),
isVisible(false),
isEmbed(false),
usesSizeRequest(false),
scaleFactor(ppData->scaleFactor),
autoScaling(false),
autoScaleFactor(1.0),
@@ -125,9 +112,10 @@ Window::PrivateData::PrivateData(Application& a, Window* const s, PrivateData* c
minHeight(0),
keepAspectRatio(false),
ignoreIdleCallbacks(false),
ignoreEvents(false),
filenameToRenderInto(nullptr),
#ifdef DISTRHO_OS_WINDOWS
win32SelectedFile(nullptr),
#ifndef DGL_FILE_BROWSER_DISABLED
fileBrowserHandle(nullptr),
#endif
modal(ppData)
{
@@ -148,6 +136,7 @@ Window::PrivateData::PrivateData(Application& a, Window* const s,
isClosed(parentWindowHandle == 0),
isVisible(parentWindowHandle != 0),
isEmbed(parentWindowHandle != 0),
usesSizeRequest(false),
scaleFactor(scale != 0.0 ? scale : getDesktopScaleFactor(view)),
autoScaling(false),
autoScaleFactor(1.0),
@@ -155,9 +144,10 @@ Window::PrivateData::PrivateData(Application& a, Window* const s,
minHeight(0),
keepAspectRatio(false),
ignoreIdleCallbacks(false),
ignoreEvents(false),
filenameToRenderInto(nullptr),
#ifdef DISTRHO_OS_WINDOWS
win32SelectedFile(nullptr),
#ifndef DGL_FILE_BROWSER_DISABLED
fileBrowserHandle(nullptr),
#endif
modal()
{
@@ -170,7 +160,7 @@ Window::PrivateData::PrivateData(Application& a, Window* const s,
Window::PrivateData::PrivateData(Application& a, Window* const s,
const uintptr_t parentWindowHandle,
const uint width, const uint height,
const double scale, const bool resizable)
const double scale, const bool resizable, const bool isVST3)
: app(a),
appData(a.pData),
self(s),
@@ -180,6 +170,7 @@ Window::PrivateData::PrivateData(Application& a, Window* const s,
isClosed(parentWindowHandle == 0),
isVisible(parentWindowHandle != 0 && view != nullptr),
isEmbed(parentWindowHandle != 0),
usesSizeRequest(isVST3),
scaleFactor(scale != 0.0 ? scale : getDesktopScaleFactor(view)),
autoScaling(false),
autoScaleFactor(1.0),
@@ -187,9 +178,10 @@ Window::PrivateData::PrivateData(Application& a, Window* const s,
minHeight(0),
keepAspectRatio(false),
ignoreIdleCallbacks(false),
ignoreEvents(false),
filenameToRenderInto(nullptr),
#ifdef DISTRHO_OS_WINDOWS
win32SelectedFile(nullptr),
#ifndef DGL_FILE_BROWSER_DISABLED
fileBrowserHandle(nullptr),
#endif
modal()
{
@@ -210,8 +202,9 @@ Window::PrivateData::~PrivateData()

if (isEmbed)
{
#ifdef HAVE_X11
sofdFileDialogClose();
#ifndef DGL_FILE_BROWSER_DISABLED
if (fileBrowserHandle != nullptr)
fileBrowserClose(fileBrowserHandle);
#endif
puglHide(view);
appData->oneWindowClosed();
@@ -219,11 +212,6 @@ Window::PrivateData::~PrivateData()
isVisible = false;
}

#ifdef DISTRHO_OS_WINDOWS
if (win32SelectedFile != nullptr && win32SelectedFile != kWin32SelectedFileCancelled)
std::free(const_cast<char*>(win32SelectedFile));
#endif

puglFreeView(view);
}

@@ -367,9 +355,14 @@ void Window::PrivateData::hide()
if (modal.enabled)
stopModal();

#ifdef HAVE_X11
sofdFileDialogClose();
#ifndef DGL_FILE_BROWSER_DISABLED
if (fileBrowserHandle != nullptr)
{
fileBrowserClose(fileBrowserHandle);
fileBrowserHandle = nullptr;
}
#endif

puglHide(view);

isVisible = false;
@@ -411,20 +404,12 @@ void Window::PrivateData::setResizable(const bool resizable)
void Window::PrivateData::idleCallback()
{
#ifndef DGL_FILE_BROWSER_DISABLED
# ifdef DISTRHO_OS_WINDOWS
if (const char* path = win32SelectedFile)
if (fileBrowserHandle != nullptr && fileBrowserIdle(fileBrowserHandle))
{
win32SelectedFile = nullptr;
if (path == kWin32SelectedFileCancelled)
path = nullptr;
self->onFileSelected(path);
std::free(const_cast<char*>(path));
self->onFileSelected(fileBrowserGetPath(fileBrowserHandle));
fileBrowserClose(fileBrowserHandle);
fileBrowserHandle = nullptr;
}
# endif
# ifdef HAVE_X11
if (sofdFileDialogIdle(view))
self->onFileSelected(sofdFileDialogGetPath());
# endif
#endif
}

@@ -464,164 +449,23 @@ bool Window::PrivateData::removeIdleCallback(IdleCallback* const callback)
// -----------------------------------------------------------------------
// file handling

bool Window::PrivateData::openFileBrowser(const Window::FileBrowserOptions& options)
bool Window::PrivateData::openFileBrowser(const FileBrowserOptions& options)
{
using DISTRHO_NAMESPACE::String;

// --------------------------------------------------------------------------
// configure start dir

// TODO: get abspath if needed
// TODO: cross-platform

String startDir(options.startDir);

if (startDir.isEmpty())
{
// TESTING verify this whole thing...
# ifdef DISTRHO_OS_WINDOWS
if (char* const cwd = _getcwd(nullptr, 0))
{
startDir = cwd;
std::free(cwd);
}
# else
if (char* const cwd = getcwd(nullptr, 0))
{
startDir = cwd;
std::free(cwd);
}
# endif
}
if (fileBrowserHandle != nullptr)
fileBrowserClose(fileBrowserHandle);

DISTRHO_SAFE_ASSERT_RETURN(startDir.isNotEmpty(), false);
FileBrowserOptions options2 = options;

if (! startDir.endsWith(DISTRHO_OS_SEP))
startDir += DISTRHO_OS_SEP_STR;
if (options2.title == nullptr)
options2.title = puglGetWindowTitle(view);

// --------------------------------------------------------------------------
// configure title
fileBrowserHandle = fileBrowserCreate(isEmbed,
puglGetNativeWindow(view),
autoScaling ? autoScaleFactor : scaleFactor,
options2);

String title(options.title);

if (title.isEmpty())
{
title = puglGetWindowTitle(view);

if (title.isEmpty())
title = "FileBrowser";
}

// --------------------------------------------------------------------------
// show

# ifdef DISTRHO_OS_MAC
uint flags = 0x0;

if (options.buttons.listAllFiles == FileBrowserOptions::kButtonVisibleChecked)
flags |= 0x001;
else if (options.buttons.listAllFiles == FileBrowserOptions::kButtonVisibleUnchecked)
flags |= 0x002;

if (options.buttons.showHidden == FileBrowserOptions::kButtonVisibleChecked)
flags |= 0x010;
else if (options.buttons.showHidden == FileBrowserOptions::kButtonVisibleUnchecked)
flags |= 0x020;

if (options.buttons.showPlaces == FileBrowserOptions::kButtonVisibleChecked)
flags |= 0x100;
else if (options.buttons.showPlaces == FileBrowserOptions::kButtonVisibleUnchecked)
flags |= 0x200;

return puglMacOSFilePanelOpen(view, startDir, title, flags, openPanelCallback);
# endif

# ifdef DISTRHO_OS_WINDOWS
// the old and compatible dialog API
OPENFILENAMEW ofn;
memset(&ofn, 0, sizeof(ofn));
if (win32SelectedFile != nullptr && win32SelectedFile != kWin32SelectedFileCancelled)
std::free(const_cast<char*>(win32SelectedFile));
win32SelectedFile = nullptr;

ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = (HWND)puglGetNativeWindow(view);

// set start directory in UTF-16 encoding
std::vector<WCHAR> startDirW;
startDirW.resize(startDir.length() + 1);
if (MultiByteToWideChar(CP_UTF8, 0, startDir.buffer(), -1, startDirW.data(), static_cast<int>(startDirW.size())))
ofn.lpstrInitialDir = startDirW.data();

// set title in UTF-16 encoding
std::vector<WCHAR> titleW;
titleW.resize(title.length() + 1);
if (MultiByteToWideChar(CP_UTF8, 0, title.buffer(), -1, titleW.data(), static_cast<int>(titleW.size())))
ofn.lpstrTitle = titleW.data();

// prepare a buffer to receive the result
std::vector<WCHAR> fileNameW(32768); // the Unicode maximum
ofn.lpstrFile = fileNameW.data();
ofn.nMaxFile = (DWORD)fileNameW.size();

// flags
ofn.Flags = OFN_PATHMUSTEXIST;
if (options.buttons.showHidden == FileBrowserOptions::kButtonVisibleChecked)
ofn.Flags |= OFN_FORCESHOWHIDDEN;
if (options.buttons.showPlaces == FileBrowserOptions::kButtonInvisible)
ofn.FlagsEx |= OFN_EX_NOPLACESBAR;

// TODO synchronous only, can't do better with WinAPI native dialogs.
// threading might work, if someone is motivated to risk it.
if (GetOpenFileNameW(&ofn))
{
// back to UTF-8
std::vector<char> fileNameA(4 * 32768);
if (WideCharToMultiByte(CP_UTF8, 0, fileNameW.data(), -1,
fileNameA.data(), (int)fileNameA.size(),
nullptr, nullptr))
{
// handle it during the next idle cycle (fake async)
win32SelectedFile = strdup(fileNameA.data());
}
}

if (win32SelectedFile == nullptr)
win32SelectedFile = kWin32SelectedFileCancelled;

return true;
# endif

# ifdef HAVE_X11
uint flags = 0x0;

if (options.buttons.listAllFiles == FileBrowserOptions::kButtonVisibleChecked)
flags |= 0x001;
else if (options.buttons.listAllFiles == FileBrowserOptions::kButtonVisibleUnchecked)
flags |= 0x002;

if (options.buttons.showHidden == FileBrowserOptions::kButtonVisibleChecked)
flags |= 0x010;
else if (options.buttons.showHidden == FileBrowserOptions::kButtonVisibleUnchecked)
flags |= 0x020;

if (options.buttons.showPlaces == FileBrowserOptions::kButtonVisibleChecked)
flags |= 0x100;
else if (options.buttons.showPlaces == FileBrowserOptions::kButtonVisibleUnchecked)
flags |= 0x200;

return sofdFileDialogShow(view, startDir, title, flags, autoScaling ? autoScaleFactor : scaleFactor);
# endif

return false;
}

# ifdef DISTRHO_OS_MAC
void Window::PrivateData::openPanelCallback(PuglView* const view, const char* const path)
{
((Window::PrivateData*)puglGetHandle(view))->self->onFileSelected(path);
return fileBrowserHandle != nullptr;
}
# endif
#endif // ! DGL_FILE_BROWSER_DISABLED

// -----------------------------------------------------------------------
@@ -822,7 +666,7 @@ void Window::PrivateData::onPuglKey(const Widget::KeyboardEvent& ev)
{
TopLevelWidget* const widget(*rit);

if (widget->isVisible() && widget->pData->keyboardEvent(ev))
if (widget->isVisible() && widget->onKeyboard(ev))
break;
}
#endif
@@ -840,7 +684,7 @@ void Window::PrivateData::onPuglText(const Widget::CharacterInputEvent& ev)
{
TopLevelWidget* const widget(*rit);

if (widget->isVisible() && widget->pData->characterInputEvent(ev))
if (widget->isVisible() && widget->onCharacterInput(ev))
break;
}
#endif
@@ -858,7 +702,7 @@ void Window::PrivateData::onPuglMouse(const Widget::MouseEvent& ev)
{
TopLevelWidget* const widget(*rit);

if (widget->isVisible() && widget->pData->mouseEvent(ev))
if (widget->isVisible() && widget->onMouse(ev))
break;
}
#endif
@@ -876,7 +720,7 @@ void Window::PrivateData::onPuglMotion(const Widget::MotionEvent& ev)
{
TopLevelWidget* const widget(*rit);

if (widget->isVisible() && widget->pData->motionEvent(ev))
if (widget->isVisible() && widget->onMotion(ev))
break;
}
#endif
@@ -894,7 +738,7 @@ void Window::PrivateData::onPuglScroll(const Widget::ScrollEvent& ev)
{
TopLevelWidget* const widget(*rit);

if (widget->isVisible() && widget->pData->scrollEvent(ev))
if (widget->isVisible() && widget->onScroll(ev))
break;
}
#endif
@@ -908,7 +752,9 @@ PuglStatus Window::PrivateData::puglEventCallback(PuglView* const view, const Pu
{
Window::PrivateData* const pData = (Window::PrivateData*)puglGetHandle(view);
#if defined(DEBUG) && defined(DGL_DEBUG_EVENTS)
printEvent(event, "pugl event: ", true);
if (event->type != PUGL_TIMER) {
printEvent(event, "pugl event: ", true);
}
#endif

switch (event->type)
@@ -921,7 +767,7 @@ PuglStatus Window::PrivateData::puglEventCallback(PuglView* const view, const Pu
case PUGL_CREATE:
#ifdef HAVE_X11
if (! pData->isEmbed)
puglX11SetWindowTypeAndPID(view);
puglX11SetWindowTypeAndPID(view, pData->appData->isStandalone);
#endif
break;

@@ -949,6 +795,8 @@ PuglStatus Window::PrivateData::puglEventCallback(PuglView* const view, const Pu

///< View must be drawn, a #PuglEventExpose
case PUGL_EXPOSE:
if (pData->ignoreEvents)
break;
// unused x, y, width, height (double)
pData->onPuglExpose();
break;
@@ -962,6 +810,8 @@ PuglStatus Window::PrivateData::puglEventCallback(PuglView* const view, const Pu
case PUGL_FOCUS_IN:
///< Keyboard focus left view, a #PuglEventFocus
case PUGL_FOCUS_OUT:
if (pData->ignoreEvents)
break;
pData->onPuglFocus(event->type == PUGL_FOCUS_IN,
static_cast<CrossingMode>(event->focus.mode));
break;
@@ -971,6 +821,8 @@ PuglStatus Window::PrivateData::puglEventCallback(PuglView* const view, const Pu
///< Key released, a #PuglEventKey
case PUGL_KEY_RELEASE:
{
if (pData->ignoreEvents)
break;
// unused x, y, xRoot, yRoot (double)
Widget::KeyboardEvent ev;
ev.mod = event->key.state;
@@ -994,6 +846,8 @@ PuglStatus Window::PrivateData::puglEventCallback(PuglView* const view, const Pu
///< Character entered, a #PuglEventText
case PUGL_TEXT:
{
if (pData->ignoreEvents)
break;
// unused x, y, xRoot, yRoot (double)
Widget::CharacterInputEvent ev;
ev.mod = event->text.state;
@@ -1018,6 +872,8 @@ PuglStatus Window::PrivateData::puglEventCallback(PuglView* const view, const Pu
///< Mouse button released, a #PuglEventButton
case PUGL_BUTTON_RELEASE:
{
if (pData->ignoreEvents)
break;
Widget::MouseEvent ev;
ev.mod = event->button.state;
ev.flags = event->button.flags;
@@ -1033,6 +889,8 @@ PuglStatus Window::PrivateData::puglEventCallback(PuglView* const view, const Pu
///< Pointer moved, a #PuglEventMotion
case PUGL_MOTION:
{
if (pData->ignoreEvents)
break;
Widget::MotionEvent ev;
ev.mod = event->motion.state;
ev.flags = event->motion.flags;
@@ -1046,6 +904,8 @@ PuglStatus Window::PrivateData::puglEventCallback(PuglView* const view, const Pu
///< Scrolled, a #PuglEventScroll
case PUGL_SCROLL:
{
if (pData->ignoreEvents)
break;
Widget::ScrollEvent ev;
ev.mod = event->scroll.state;
ev.flags = event->scroll.flags;
@@ -1064,6 +924,8 @@ PuglStatus Window::PrivateData::puglEventCallback(PuglView* const view, const Pu

///< Timer triggered, a #PuglEventTimer
case PUGL_TIMER:
if (pData->ignoreEvents)
break;
if (IdleCallback* const idleCallback = reinterpret_cast<IdleCallback*>(event->timer.id))
idleCallback->idleCallback();
break;


+ 11
- 128
dpf/dgl/src/WindowPrivateData.hpp View File

@@ -63,6 +63,9 @@ struct Window::PrivateData : IdleCallback {
/** Whether this Window is embed into another (usually not DGL-controlled) Window. */
const bool isEmbed;

/** Whether to ignore resize requests and feed them into the host instead. used for VST3 */
const bool usesSizeRequest;

/** Scale factor to report to widgets on request, purely informational. */
double scaleFactor;

@@ -77,12 +80,15 @@ struct Window::PrivateData : IdleCallback {
/** Whether to ignore idle callback requests, useful for temporary windows. */
bool ignoreIdleCallbacks;

/** Whether to ignore pugl events (except create and destroy), used for puglGetClipboard. */
bool ignoreEvents;

/** Render to a picture file when non-null, automatically free+unset after saving. */
char* filenameToRenderInto;

#ifdef DISTRHO_OS_WINDOWS
/** Selected file for openFileBrowser on windows, stored for fake async operation. */
const char* win32SelectedFile;
#ifndef DGL_FILE_BROWSER_DISABLED
/** Handle for file browser dialog operations. */
FileBrowserHandle fileBrowserHandle;
#endif

/** Modal window setup. */
@@ -124,7 +130,7 @@ struct Window::PrivateData : IdleCallback {

/** Constructor for an embed Window, with a few extra hints from the host side. */
explicit PrivateData(Application& app, Window* self, uintptr_t parentWindowHandle,
uint width, uint height, double scaling, bool resizable);
uint width, uint height, double scaling, bool resizable, bool isVST3);

/** Destructor. */
~PrivateData() override;
@@ -159,10 +165,7 @@ struct Window::PrivateData : IdleCallback {

#ifndef DGL_FILE_BROWSER_DISABLED
// file handling
bool openFileBrowser(const Window::FileBrowserOptions& options);
# ifdef DISTRHO_OS_MAC
static void openPanelCallback(PuglView* view, const char* path);
# endif
bool openFileBrowser(const FileBrowserOptions& options);
#endif

static void renderToPicture(const char* filename, const GraphicsContext& context, uint width, uint height);
@@ -193,124 +196,4 @@ struct Window::PrivateData : IdleCallback {

END_NAMESPACE_DGL

#if 0
// #if defined(DISTRHO_OS_HAIKU)
// BApplication* bApplication;
// BView* bView;
// BWindow* bWindow;
#if defined(DISTRHO_OS_MAC)
// NSView<PuglGenericView>* mView;
// id mWindow;
// id mParentWindow;
# ifndef DGL_FILE_BROWSER_DISABLED
NSOpenPanel* fOpenFilePanel;
id fFilePanelDelegate;
# endif
#elif defined(DISTRHO_OS_WINDOWS)
// HWND hwnd;
// HWND hwndParent;
# ifndef DGL_FILE_BROWSER_DISABLED
String fSelectedFile;
# endif
#endif
#endif

#if 0
// -----------------------------------------------------------------------
// Window Private

struct Window::PrivateData {
// -------------------------------------------------------------------

bool handlePluginSpecial(const bool press, const Key key)
{
DBGp("PUGL: handlePluginSpecial : %i %i\n", press, key);

if (fModal.childFocus != nullptr)
{
fModal.childFocus->focus();
return true;
}

int mods = 0x0;

switch (key)
{
case kKeyShift:
mods |= kModifierShift;
break;
case kKeyControl:
mods |= kModifierControl;
break;
case kKeyAlt:
mods |= kModifierAlt;
break;
default:
break;
}

if (mods != 0x0)
{
if (press)
fView->mods |= mods;
else
fView->mods &= ~(mods);
}

Widget::SpecialEvent ev;
ev.press = press;
ev.key = key;
ev.mod = static_cast<Modifier>(fView->mods);
ev.time = 0;

FOR_EACH_WIDGET_INV(rit)
{
Widget* const widget(*rit);

if (widget->isVisible() && widget->onSpecial(ev))
return true;
}

return false;
}

#if defined(DISTRHO_OS_MAC) && !defined(DGL_FILE_BROWSER_DISABLED)
static void openPanelDidEnd(NSOpenPanel* panel, int returnCode, void *userData)
{
PrivateData* pData = (PrivateData*)userData;

if (returnCode == NSOKButton)
{
NSArray* urls = [panel URLs];
NSURL* fileUrl = nullptr;

for (NSUInteger i = 0, n = [urls count]; i < n && !fileUrl; ++i)
{
NSURL* url = (NSURL*)[urls objectAtIndex:i];
if ([url isFileURL])
fileUrl = url;
}

if (fileUrl)
{
PuglView* view = pData->fView;
if (view->fileSelectedFunc)
{
const char* fileName = [fileUrl.path UTF8String];
view->fileSelectedFunc(view, fileName);
}
}
}

[pData->fOpenFilePanel release];
pData->fOpenFilePanel = nullptr;
}
#endif

// -------------------------------------------------------------------

DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PrivateData)
};
#endif

#endif // DGL_WINDOW_PRIVATE_DATA_HPP_INCLUDED

+ 4
- 0
dpf/dgl/src/nanovg/fontstash.h View File

@@ -907,6 +907,8 @@ static int fons__allocFont(FONScontext* stash)
stash->fonts = (FONSfont**)realloc(stash->fonts, sizeof(FONSfont*) * stash->cfonts);
if (stash->fonts == NULL)
return -1;
for (int i=stash->nfonts; i<stash->cfonts; ++i)
stash->fonts[i] = NULL;
}
font = (FONSfont*)malloc(sizeof(FONSfont));
if (font == NULL) goto error;
@@ -1015,6 +1017,8 @@ static FONSglyph* fons__allocGlyph(FONSfont* font)
font->cglyphs = font->cglyphs == 0 ? 8 : font->cglyphs * 2;
font->glyphs = (FONSglyph*)realloc(font->glyphs, sizeof(FONSglyph) * font->cglyphs);
if (font->glyphs == NULL) return NULL;
for (int i=font->nglyphs; i<font->cglyphs; ++i)
memset(&font->glyphs[i], 0, sizeof(*font->glyphs));
}
font->nglyphs++;
return &font->glyphs[font->nglyphs-1];


+ 21
- 4
dpf/dgl/src/nanovg/nanovg.c View File

@@ -30,6 +30,16 @@
#include "stb_image.h"
#endif

#ifdef NVG_DISABLE_SKIPPING_WHITESPACE
#define NVG_SKIPPED_CHAR NVG_SPACE
#else
#define NVG_SKIPPED_CHAR NVG_CHAR
#endif

#ifndef NVG_FONT_TEXTURE_FLAGS
#define NVG_FONT_TEXTURE_FLAGS 0
#endif

#ifdef _MSC_VER
#pragma warning(disable: 4100) // unreferenced formal parameter
#pragma warning(disable: 4127) // conditional expression is constant
@@ -342,7 +352,12 @@ NVGcontext* nvgCreateInternal(NVGparams* params, NVGcontext* other) // Share th
if (ctx->fontContext->fs == NULL) goto error;

// Create font texture
ctx->fontContext->fontImages[0] = ctx->params.renderCreateTexture(ctx->params.userPtr, NVG_TEXTURE_ALPHA, fontParams.width, fontParams.height, 0, NULL);
ctx->fontContext->fontImages[0] = ctx->params.renderCreateTexture(ctx->params.userPtr,
NVG_TEXTURE_ALPHA,
fontParams.width,
fontParams.height,
NVG_FONT_TEXTURE_FLAGS,
NULL);
if (ctx->fontContext->fontImages[0] == 0) goto error;
ctx->fontContext->fontImageIdx = 0;
}
@@ -2484,7 +2499,9 @@ static int nvg__allocTextAtlas(NVGcontext* ctx)
iw *= 2;
if (iw > NVG_MAX_FONTIMAGE_SIZE || ih > NVG_MAX_FONTIMAGE_SIZE)
iw = ih = NVG_MAX_FONTIMAGE_SIZE;
ctx->fontContext->fontImages[ctx->fontContext->fontImageIdx+1] = ctx->params.renderCreateTexture(ctx->params.userPtr, NVG_TEXTURE_ALPHA, iw, ih, 0, NULL);
ctx->fontContext->fontImages[ctx->fontContext->fontImageIdx+1]
= ctx->params.renderCreateTexture(ctx->params.userPtr,
NVG_TEXTURE_ALPHA, iw, ih, NVG_FONT_TEXTURE_FLAGS, NULL);
}
++ctx->fontContext->fontImageIdx;
fonsResetAtlas(ctx->fontContext->fs, iw, ih);
@@ -2775,7 +2792,7 @@ int nvgTextBreakLines(NVGcontext* ctx, const char* string, const char* end, floa
} else {
if (rowStart == NULL) {
// Skip white space until the beginning of the line
if (type == NVG_CHAR || type == NVG_CJK_CHAR) {
if (type == NVG_CHAR || type == NVG_CJK_CHAR || type == NVG_SKIPPED_CHAR) {
// The current char is the row so far
rowStartX = iter.x;
rowStart = iter.str;
@@ -2795,7 +2812,7 @@ int nvgTextBreakLines(NVGcontext* ctx, const char* string, const char* end, floa
float nextWidth = iter.nextx - rowStartX;

// track last non-white space character
if (type == NVG_CHAR || type == NVG_CJK_CHAR) {
if (type == NVG_CHAR || type == NVG_CJK_CHAR || type == NVG_SKIPPED_CHAR) {
rowEnd = iter.next;
rowWidth = iter.nextx - rowStartX;
rowMaxX = q.x1 - rowStartX;


+ 0
- 3
dpf/dgl/src/nanovg/nanovg_gl.h View File

@@ -245,9 +245,6 @@ struct GLNVGcontext {
GLNVGshader shader;
GLNVGtextureContext* textureContext;
float view[2];
int ntextures;
int ctextures;
int textureId;
GLuint vertBuf;
#if defined NANOVG_GL3
GLuint vertArr;


+ 9
- 7
dpf/dgl/src/pugl-upstream/include/pugl/pugl.h View File

@@ -1128,13 +1128,15 @@ puglPostRedisplayRect(PuglView* view, PuglRect rect);
Windows.
*/
typedef enum {
PUGL_CURSOR_ARROW, ///< Default pointing arrow
PUGL_CURSOR_CARET, ///< Caret (I-Beam) for text entry
PUGL_CURSOR_CROSSHAIR, ///< Cross-hair
PUGL_CURSOR_HAND, ///< Hand with a pointing finger
PUGL_CURSOR_NO, ///< Operation not allowed
PUGL_CURSOR_LEFT_RIGHT, ///< Left/right arrow for horizontal resize
PUGL_CURSOR_UP_DOWN, ///< Up/down arrow for vertical resize
PUGL_CURSOR_ARROW, ///< Default pointing arrow
PUGL_CURSOR_CARET, ///< Caret (I-Beam) for text entry
PUGL_CURSOR_CROSSHAIR, ///< Cross-hair
PUGL_CURSOR_HAND, ///< Hand with a pointing finger
PUGL_CURSOR_NO, ///< Operation not allowed
PUGL_CURSOR_LEFT_RIGHT, ///< Left/right arrow for horizontal resize
PUGL_CURSOR_UP_DOWN, ///< Up/down arrow for vertical resize
PUGL_CURSOR_DIAGONAL, ///< Top-left to bottom-right arrow for diagonal resize
PUGL_CURSOR_ANTI_DIAGONAL, ///< Bottom-left to top-right arrow for diagonal resize
} PuglCursor;

/// Grab the keyboard input focus


+ 20
- 6
dpf/dgl/src/pugl-upstream/src/mac.m View File

@@ -1039,12 +1039,6 @@ puglRealize(PuglView* view)
[window setContentView:impl->wrapperView];
[window makeFirstResponder:impl->wrapperView];
[window setIsVisible:NO];

if (! view->transientParent)
{
[window makeKeyAndOrderFront:window];
[view->world->impl->app activateIgnoringOtherApps:YES];
}
}

[impl->wrapperView updateTrackingAreas];
@@ -1070,6 +1064,11 @@ puglShow(PuglView* view)
updateViewRect(view);
}

if (! view->transientParent) {
[view->impl->window makeKeyAndOrderFront:view->impl->window];
[view->world->impl->app activateIgnoringOtherApps:YES];
}

return PUGL_SUCCESS;
}

@@ -1421,6 +1420,8 @@ puglGetClipboard(PuglView* const view,
static NSCursor*
puglGetNsCursor(const PuglCursor cursor)
{
SEL cursorSelector = nil;

switch (cursor) {
case PUGL_CURSOR_ARROW:
return [NSCursor arrowCursor];
@@ -1436,6 +1437,19 @@ puglGetNsCursor(const PuglCursor cursor)
return [NSCursor resizeLeftRightCursor];
case PUGL_CURSOR_UP_DOWN:
return [NSCursor resizeUpDownCursor];
case PUGL_CURSOR_DIAGONAL:
cursorSelector = @selector(_windowResizeNorthWestSouthEastCursor);
break;
case PUGL_CURSOR_ANTI_DIAGONAL:
cursorSelector = @selector(_windowResizeNorthEastSouthWestCursor);
break;
}

if (cursorSelector && [NSCursor respondsToSelector:cursorSelector])
{
id object = [NSCursor performSelector:cursorSelector];
if ([object isKindOfClass:[NSCursor class]])
return (NSCursor*)object;
}

return NULL;


+ 9
- 7
dpf/dgl/src/pugl-upstream/src/win.c View File

@@ -1125,13 +1125,15 @@ puglSetClipboard(PuglView* const view,
}

static const char* const cursor_ids[] = {
IDC_ARROW, // ARROW
IDC_IBEAM, // CARET
IDC_CROSS, // CROSSHAIR
IDC_HAND, // HAND
IDC_NO, // NO
IDC_SIZEWE, // LEFT_RIGHT
IDC_SIZENS, // UP_DOWN
IDC_ARROW, // ARROW
IDC_IBEAM, // CARET
IDC_CROSS, // CROSSHAIR
IDC_HAND, // HAND
IDC_NO, // NO
IDC_SIZEWE, // LEFT_RIGHT
IDC_SIZENS, // UP_DOWN
IDC_SIZENWSE, // DIAGONAL
IDC_SIZENESW, // ANTI_DIAGONAL
};

PuglStatus


+ 38
- 26
dpf/dgl/src/pugl-upstream/src/x11.c View File

@@ -82,6 +82,34 @@ enum WmClientStateMessageAction {
WM_STATE_TOGGLE
};

#ifdef HAVE_XCURSOR
static const char* cursor_names_x11[] = {
"left_ptr", // ARROW
"xterm", // CARET
"crosshair", // CROSSHAIR
"hand2", // HAND
"forbidden", // NO
"sb_h_double_arrow", // LEFT_RIGHT
"sb_v_double_arrow", // UP_DOWN
"size_fdiag", // DIAGONAL
"size_bdiag", // ANTI_DIAGONAL
};

/*
static const char* cursor_names_xdg[] = {
"default", // ARROW
"text", // CARET
"crosshair", // CROSSHAIR
"pointer", // HAND
"not-allowed", // NO
"ew-resize", // LEFT_RIGHT
"ns-resize", // UP_DOWN
"nwse-resize", // DIAGONAL
"nesw-resize", // ANTI_DIAGONAL
};
*/
#endif

static bool
initXSync(PuglWorldInternals* const impl)
{
@@ -167,7 +195,7 @@ puglInitViewInternals(void)
PuglInternals* impl = (PuglInternals*)calloc(1, sizeof(PuglInternals));

#ifdef HAVE_XCURSOR
impl->cursorShape = XC_arrow;
impl->cursorName = cursor_names_x11[0];
#endif

return impl;
@@ -263,12 +291,12 @@ updateSizeHints(const PuglView* const view)

#ifdef HAVE_XCURSOR
static PuglStatus
defineCursorShape(PuglView* const view, const unsigned shape)
defineCursorName(PuglView* const view, const char* const name)
{
PuglInternals* const impl = view->impl;
PuglWorld* const world = view->world;
Display* const display = world->impl->display;
const Cursor cur = XcursorShapeLoadCursor(display, shape);
const Cursor cur = XcursorLibraryLoadCursor(display, name);

if (cur) {
XDefineCursor(display, impl->win, cur);
@@ -404,10 +432,6 @@ puglRealize(PuglView* const view)
impl->win,
(XIM)0);

#ifdef HAVE_XCURSOR
defineCursorShape(view, impl->cursorShape);
#endif

puglDispatchSimpleEvent(view, PUGL_CREATE);

return PUGL_SUCCESS;
@@ -1401,8 +1425,8 @@ puglGetClipboard(PuglView* const view,
impl->win,
CurrentTime);

// Run event loop until data is received
while (!view->clipboard.data) {
// Run event loop until data is received, within limits
for (int i=500; !view->clipboard.data && --i >= 0;) {
puglUpdate(view->world, -1.0);
}
}
@@ -1427,37 +1451,25 @@ puglSetClipboard(PuglView* const view,
return st;
}

#ifdef HAVE_XCURSOR
static const unsigned cursor_nums[] = {
XC_arrow, // ARROW
XC_xterm, // CARET
XC_crosshair, // CROSSHAIR
XC_hand2, // HAND
XC_pirate, // NO
XC_sb_h_double_arrow, // LEFT_RIGHT
XC_sb_v_double_arrow, // UP_DOWN
};
#endif

PuglStatus
puglSetCursor(PuglView* const view, const PuglCursor cursor)
{
#ifdef HAVE_XCURSOR
PuglInternals* const impl = view->impl;
const unsigned index = (unsigned)cursor;
const unsigned count = sizeof(cursor_nums) / sizeof(cursor_nums[0]);
const unsigned count = sizeof(cursor_names_x11) / sizeof(cursor_names_x11[0]);
if (index >= count) {
return PUGL_BAD_PARAMETER;
}

const unsigned shape = cursor_nums[index];
if (!impl->win || impl->cursorShape == shape) {
const char* name = cursor_names_x11[index];
if (!impl->win || impl->cursorName == name) {
return PUGL_SUCCESS;
}

impl->cursorShape = cursor_nums[index];
impl->cursorName = cursor_names_x11[index];

return defineCursorShape(view, impl->cursorShape);
return defineCursorName(view, impl->cursorName);
#else
(void)view;
(void)cursor;


+ 1
- 1
dpf/dgl/src/pugl-upstream/src/x11.h View File

@@ -69,7 +69,7 @@ struct PuglInternalsImpl {
PuglEvent pendingExpose;
int screen;
#ifdef HAVE_XCURSOR
unsigned cursorShape;
const char* cursorName;
#endif
};



+ 27
- 164
dpf/dgl/src/pugl.cpp View File

@@ -42,6 +42,7 @@
# endif
#elif defined(DISTRHO_OS_WINDOWS)
# include <wctype.h>
# include <winsock2.h>
# include <windows.h>
# include <windowsx.h>
# ifdef DGL_CAIRO
@@ -57,6 +58,7 @@
# endif
#else
# include <dlfcn.h>
# include <unistd.h>
# include <sys/select.h>
# include <sys/time.h>
# include <X11/X.h>
@@ -90,10 +92,12 @@
# endif
#endif

#ifdef HAVE_X11
# define DBLCLKTME 400
# include "sofd/libsofd.h"
# include "sofd/libsofd.c"
#ifndef DGL_FILE_BROWSER_DISABLED
# ifdef DISTRHO_OS_MAC
# import "../../distrho/extra/FileBrowserDialog.cpp"
# else
# include "../../distrho/extra/FileBrowserDialog.cpp"
# endif
#endif

#ifndef DISTRHO_OS_MAC
@@ -321,20 +325,12 @@ PuglStatus puglSetGeometryConstraints(PuglView* const view, const uint width, co
view->maxAspectY = (int)height;
}

#if defined(DISTRHO_OS_HAIKU)
// nothing?
#elif defined(DISTRHO_OS_MAC)
/*
if (view->impl->window)
{
[view->impl->window setContentMinSize:sizePoints(view, view->minWidth, view->minHeight)];
#if defined(DISTRHO_OS_HAIKU) || defined(DISTRHO_OS_MAC)
puglSetMinSize(view, width, height);

if (aspect)
[view->impl->window setContentAspectRatio:sizePoints(view, view->minAspectX, view->minAspectY)];
if (aspect) {
puglSetAspectRatio(view, width, height, width, height);
}
*/
puglSetMinSize(view, width, height);
puglSetAspectRatio(view, width, height, width, height);
#elif defined(DISTRHO_OS_WINDOWS)
// nothing
#else
@@ -354,17 +350,18 @@ PuglStatus puglSetWindowSize(PuglView* const view, const uint width, const uint
{
view->defaultWidth = width;
view->defaultHeight = height;
view->frame.width = width;
view->frame.height = height;

#if defined(DISTRHO_OS_HAIKU) || defined(DISTRHO_OS_MAC)
// replace the 2 views setFrame with setFrameSize
const PuglRect frame = { view->frame.x, view->frame.y, (double)width, (double)height };
#if defined(DISTRHO_OS_HAIKU)
#elif defined(DISTRHO_OS_MAC)
// replace setFrame with setFrameSize
PuglInternals* const impl = view->impl;

// Update view frame to exactly the requested frame in Pugl coordinates
view->frame = frame;

const PuglRect frame = view->frame;
const NSRect framePx = rectToNsRect(frame);
const NSRect framePt = nsRectToPoints(view, framePx);

if (impl->window)
{
// Resize window to fit new content rect
@@ -418,8 +415,6 @@ PuglStatus puglSetWindowSize(PuglView* const view, const uint width, const uint
}
#endif

view->frame.width = width;
view->frame.height = height;
return PUGL_SUCCESS;
}

@@ -529,50 +524,6 @@ void puglMacOSShowCentered(PuglView* const view)
}

// --------------------------------------------------------------------------------------------------------------------
// macOS specific, setup file browser dialog

bool puglMacOSFilePanelOpen(PuglView* const view,
const char* const startDir, const char* const title, const uint flags,
openPanelCallback callback)
{
PuglInternals* impl = view->impl;

NSOpenPanel* const panel = [NSOpenPanel openPanel];

[panel setAllowsMultipleSelection:NO];
[panel setCanChooseFiles:YES];
[panel setCanChooseDirectories:NO];
[panel setDirectoryURL:[NSURL fileURLWithPath:[NSString stringWithUTF8String:startDir]]];

// TODO file filter using allowedContentTypes: [UTType]

if (flags & 0x001)
[panel setAllowsOtherFileTypes:YES];
if (flags & 0x010)
[panel setShowsHiddenFiles:YES];

NSString* titleString = [[NSString alloc]
initWithBytes:title
length:strlen(title)
encoding:NSUTF8StringEncoding];
[panel setTitle:titleString];

[panel beginSheetModalForWindow:(impl->window ? impl->window : [view->impl->wrapperView window])
completionHandler:^(NSInteger result)
{
if (result == NSModalResponseOK && [[panel URL] isFileURL])
{
NSString* const path = [[panel URL] path];
callback(view, [path UTF8String]);
}
else
{
callback(view, nullptr);
}
}];

return true;
}
#endif

#ifdef DISTRHO_OS_WINDOWS
@@ -657,7 +608,7 @@ PuglStatus puglX11GrabFocus(const PuglView* const view)
// --------------------------------------------------------------------------------------------------------------------
// X11 specific, set dialog window type and pid hints

void puglX11SetWindowTypeAndPID(const PuglView* const view)
void puglX11SetWindowTypeAndPID(const PuglView* const view, const bool isStandalone)
{
const PuglInternals* const impl = view->impl;

@@ -667,107 +618,19 @@ void puglX11SetWindowTypeAndPID(const PuglView* const view)

const Atom _wt = XInternAtom(impl->display, "_NET_WM_WINDOW_TYPE", False);

// Setting the window to both dialog and normal will produce a decorated floating dialog
// Order is important: DIALOG needs to come before NORMAL
const Atom _wts[2] = {
XInternAtom(impl->display, "_NET_WM_WINDOW_TYPE_DIALOG", False),
XInternAtom(impl->display, "_NET_WM_WINDOW_TYPE_NORMAL", False)
};

XChangeProperty(impl->display, impl->win, _wt, XA_ATOM, 32, PropModeReplace, (const uchar*)&_wts, 2);
}

// --------------------------------------------------------------------------------------------------------------------
// X11 specific stuff for sofd
Atom _wts[2];
int numAtoms = 0;

static Display* sofd_display;
static char* sofd_filename;
if (! isStandalone)
_wts[numAtoms++] = XInternAtom(impl->display, "_NET_WM_WINDOW_TYPE_DIALOG", False);

// --------------------------------------------------------------------------------------------------------------------
// X11 specific, show file dialog via sofd
_wts[numAtoms++] = XInternAtom(impl->display, "_NET_WM_WINDOW_TYPE_NORMAL", False);

bool sofdFileDialogShow(PuglView* const view,
const char* const startDir, const char* const title,
const uint flags, const double scaleFactor)
{
// only one possible at a time
DISTRHO_SAFE_ASSERT_RETURN(sofd_display == nullptr, false);

sofd_display = XOpenDisplay(nullptr);
DISTRHO_SAFE_ASSERT_RETURN(sofd_display != nullptr, false);

DISTRHO_SAFE_ASSERT_RETURN(x_fib_configure(0, startDir) == 0, false);
DISTRHO_SAFE_ASSERT_RETURN(x_fib_configure(1, title) == 0, false);

x_fib_cfg_buttons(3, flags & 0x001 ? 1 : flags & 0x002 ? 0 : -1);
x_fib_cfg_buttons(1, flags & 0x010 ? 1 : flags & 0x020 ? 0 : -1);
x_fib_cfg_buttons(2, flags & 0x100 ? 1 : flags & 0x200 ? 0 : -1);

return (x_fib_show(sofd_display, view->impl->win, 0, 0, scaleFactor + 0.5) == 0);
}

// --------------------------------------------------------------------------------------------------------------------
// X11 specific, idle sofd file dialog, returns true if dialog was closed (with or without a file selection)

bool sofdFileDialogIdle(PuglView* const view)
{
if (sofd_display == nullptr)
return false;

XEvent event;
while (XPending(sofd_display) > 0)
{
XNextEvent(sofd_display, &event);

if (x_fib_handle_events(sofd_display, &event) == 0)
continue;

if (sofd_filename != nullptr)
std::free(sofd_filename);

if (x_fib_status() > 0)
sofd_filename = x_fib_filename();
else
sofd_filename = nullptr;

x_fib_close(sofd_display);
XCloseDisplay(sofd_display);
sofd_display = nullptr;
return true;
}

return false;
XChangeProperty(impl->display, impl->win, _wt, XA_ATOM, 32, PropModeReplace, (const uchar*)&_wts, numAtoms);
}

// --------------------------------------------------------------------------------------------------------------------
// X11 specific, close sofd file dialog

void sofdFileDialogClose()
{
if (sofd_display != nullptr)
{
x_fib_close(sofd_display);
XCloseDisplay(sofd_display);
sofd_display = nullptr;
}

if (sofd_filename != nullptr)
{
std::free(sofd_filename);
sofd_filename = nullptr;
}
}

// --------------------------------------------------------------------------------------------------------------------
// X11 specific, get path chosen via sofd file dialog

const char* sofdFileDialogGetPath()
{
return sofd_filename;
}
#endif

// --------------------------------------------------------------------------------------------------------------------
#endif // HAVE_X11

#ifndef DISTRHO_OS_MAC
END_NAMESPACE_DGL


+ 1
- 21
dpf/dgl/src/pugl.hpp View File

@@ -111,10 +111,6 @@ puglMacOSRemoveChildWindow(PuglView* view, PuglView* child);
// macOS specific, center view based on parent coordinates (if there is one)
PUGL_API void
puglMacOSShowCentered(PuglView* view);

// macOS specific, setup file browser dialog
typedef void (*openPanelCallback)(PuglView* view, const char* path);
bool puglMacOSFilePanelOpen(PuglView* view, const char* startDir, const char* title, uint flags, openPanelCallback callback);
#endif

#ifdef DISTRHO_OS_WINDOWS
@@ -138,23 +134,7 @@ puglX11GrabFocus(const PuglView* view);

// X11 specific, set dialog window type and pid hints
PUGL_API void
puglX11SetWindowTypeAndPID(const PuglView* view);

// X11 specific, show file dialog via sofd
PUGL_API bool
sofdFileDialogShow(PuglView* view, const char* startDir, const char* title, uint flags, double scaleFactor);

// X11 specific, idle sofd file dialog, returns true if dialog was closed (with or without a file selection)
PUGL_API bool
sofdFileDialogIdle(PuglView* const view);

// X11 specific, close sofd file dialog
PUGL_API void
sofdFileDialogClose();

// X11 specific, get path chosen via sofd file dialog
PUGL_API const char*
sofdFileDialogGetPath();
puglX11SetWindowTypeAndPID(const PuglView* view, bool isStandalone);
#endif

PUGL_END_DECLS


+ 101
- 27
dpf/distrho/DistrhoInfo.hpp View File

@@ -31,23 +31,39 @@ START_NAMESPACE_DISTRHO
It allows developers to create plugins with custom UIs using a simple C++ API.@n
The framework facilitates exporting various different plugin formats from the same code-base.

DPF can build for LADSPA, DSSI, LV2 and VST2 formats.@n
DPF can build for LADSPA, DSSI, LV2, VST2 and VST3 formats.@n
A JACK/Standalone mode is also available, allowing you to quickly test plugins.

@section Macros
You start by creating a "DistrhoPluginInfo.h" file describing the plugin via macros, see @ref PluginMacros.@n
This file is included in the main DPF code to select which features to activate for each plugin format.
This file is included during compilation of the main DPF code to select which features to activate for each plugin format.

For example, a plugin (with %UI) that use states will require LV2 hosts to support Atom and Worker extensions for
message passing from the %UI to the plugin.@n
message passing from the %UI to the (DSP) plugin.@n
If your plugin does not make use of states, the Worker extension is not set as a required feature.

@section Plugin
The next step is to create your plugin code by subclassing DPF's Plugin class.@n
You need to pass the number of parameters in the constructor and also the number of programs and states, if any.

Here's an example of an audio plugin that simply mutes the host output:
Do note all of DPF code is within its own C++ namespace (@b DISTRHO for DSP/plugin stuff, @b DGL for UI stuff).@n
You can use @ref START_NAMESPACE_DISTRHO / @ref END_NAMESPACE_DISTRHO combo around your code, or globally set @ref USE_NAMESPACE_DISTRHO.@n
These are defined as compiler macros so that you can override the namespace name during build. When in doubt, just follow the examples.

@section Examples
Let's begin with some examples.@n
Here is one of a stereo audio plugin that simply mutes the host output:
@code
/* Make DPF related classes available for us to use without any extra namespace references */
USE_NAMESPACE_DISTRHO;

/**
Our custom plugin class.
Subclassing `Plugin` from DPF is how this all works.

By default, only information-related functions and `run` are pure virtual (that is, must be reimplemented).
When enabling certain features (such as programs or states, more on that below), a few extra functions also need to be reimplemented.
*/
class MutePlugin : public Plugin
{
public:
@@ -111,7 +127,6 @@ START_NAMESPACE_DISTRHO

/**
Run/process function for plugins without MIDI input.
NOTE: Some parameters might be null if there are no audio inputs or outputs.
*/
void run(const float**, float** outputs, uint32_t frames) override
{
@@ -123,11 +138,20 @@ START_NAMESPACE_DISTRHO
std::memset(outL, 0, sizeof(float)*frames);
std::memset(outR, 0, sizeof(float)*frames);
}

};

/**
Create an instance of the Plugin class.
This is the entry point for DPF plugins.
DPF will call this to either create an instance of your plugin for the host or to fetch some initial information for internal caching.
*/
Plugin* createPlugin()
{
return new MutePlugin();
}
@endcode

See the Plugin class for more information and to understand what each function does.
See the Plugin class for more information.

@section Parameters
A plugin is nothing without parameters.@n
@@ -135,12 +159,12 @@ START_NAMESPACE_DISTRHO
They have hints to describe how they behave plus a name and a symbol identifying them.@n
Parameters also have 'ranges' – a minimum, maximum and default value.

Input parameters are "read-only": the plugin can read them but not change them.
(the exception being when changing programs, more on that below)@n
Input parameters are by default "read-only": the plugin can read them but not change them.
(there are exceptions and possibly a request to the host to change values, more on that below)@n
It's the host responsibility to save, restore and set input parameters.

Output parameters can be changed at anytime by the plugin.@n
The host will simply read their values and not change them.
The host will simply read their values and never change them.

Here's an example of an audio plugin that has 1 input parameter:
@code
@@ -197,7 +221,7 @@ START_NAMESPACE_DISTRHO
{
// we only have one parameter so we can skip checking the index

parameter.hints = kParameterIsAutomable;
parameter.hints = kParameterIsAutomatable;
parameter.name = "Gain";
parameter.symbol = "gain";
parameter.ranges.min = 0.0f;
@@ -250,8 +274,8 @@ START_NAMESPACE_DISTRHO
See the Parameter struct for more information about parameters.

@section Programs
Programs in DPF refer to plugin-side presets (usually called "factory presets"),
an initial set of presets provided by plugin authors included in the actual plugin.
Programs in DPF refer to plugin-side presets (usually called "factory presets").@n
This is meant as an initial set of presets provided by plugin authors included in the actual plugin.

To use programs you must first enable them by setting @ref DISTRHO_PLUGIN_WANT_PROGRAMS to 1 in your DistrhoPluginInfo.h file.@n
When enabled you'll need to override 2 new function in your plugin code,
@@ -307,7 +331,7 @@ START_NAMESPACE_DISTRHO
*/
void initParameter(uint32_t index, Parameter& parameter) override
{
parameter.hints = kParameterIsAutomable;
parameter.hints = kParameterIsAutomatable;
parameter.ranges.min = 0.0f;
parameter.ranges.max = 2.0f;
parameter.ranges.def = 1.0f;
@@ -331,12 +355,9 @@ START_NAMESPACE_DISTRHO
*/
void initProgramName(uint32_t index, String& programName)
{
switch(index)
{
case 0:
programName = "Default";
break;
}
// we only have one program so we can skip checking the index

programName = "Default";
}

/* ----------------------------------------------------------------------------------------
@@ -377,13 +398,10 @@ START_NAMESPACE_DISTRHO
*/
void loadProgram(uint32_t index)
{
switch(index)
{
case 0:
fGainL = 1.0f;
fGainR = 1.0f;
break;
}
// same as before, ignore index check

fGainL = 1.0f;
fGainR = 1.0f;
}

/* ----------------------------------------------------------------------------------------
@@ -774,6 +792,62 @@ START_NAMESPACE_DISTRHO

/** @} */

/* ------------------------------------------------------------------------------------------------------------
* Namespace Macros */

/**
@defgroup NamespaceMacros Namespace Macros

C Macros to use and customize DPF namespaces.

These are macros that serve as helpers around C++ namespaces, and also as a way to set custom namespaces during a build.
@{
*/

/**
Compiler macro that sets the C++ namespace for DPF plugins.@n
If unset during build, it will use the name @b DISTRHO by default.

Unless you know exactly what you are doing, you do need to modify this value.@n
The only probable useful case for customizing it is if you are building a big collection of very similar DPF-based plugins in your application.@n
For example, having 2 different versions of the same plugin that should behave differently but still exist within the same binary.

On macOS (where due to Objective-C restrictions all code that interacts with Cocoa needs to be in a flat namespace),
DPF will automatically use the plugin name as prefix to flat namespace functions in order to avoid conflicts.

So, basically, it is DPF's job to make sure plugin binaries are 100% usable as-is.@n
You typically do not need to care about this at all.
*/
#define DISTRHO_NAMESPACE DISTRHO

/**
Compiler macro that begins the C++ namespace for @b DISTRHO, as needed for (the DSP side of) plugins.@n
All classes in DPF are within this namespace except for UI/graphics stuff.
@see END_NAMESPACE_DISTRHO
*/
#define START_NAMESPACE_DISTRHO namespace DISTRHO_NAMESPACE {

/**
Close the namespace previously started by @ref START_NAMESPACE_DISTRHO.@n
This doesn't really need to be a macro, it is just prettier/more consistent that way.
*/
#define END_NAMESPACE_DISTRHO }

/**
Make the @b DISTRHO namespace available in the current function scope.@n
This is not set by default in order to avoid conflicts with commonly used names such as "Parameter" and "Plugin".
*/
#define USE_NAMESPACE_DISTRHO using namespace DISTRHO_NAMESPACE;

/* TODO
*
* DISTRHO_MACRO_AS_STRING_VALUE
* DISTRHO_MACRO_AS_STRING
* DISTRHO_PROPER_CPP11_SUPPORT
* DONT_SET_USING_DISTRHO_NAMESPACE
*
*/

// -----------------------------------------------------------------------------------------------------------

END_NAMESPACE_DISTRHO


+ 28
- 5
dpf/distrho/DistrhoPlugin.hpp View File

@@ -86,10 +86,14 @@ static const uint32_t kCVPortHasScaledRange = 0x80;
*/

/**
Parameter is automable (real-time safe).
Parameter is automatable (real-time safe).
@see Plugin::setParameterValue(uint32_t, float)
*/
static const uint32_t kParameterIsAutomable = 0x01;
static const uint32_t kParameterIsAutomatable = 0x01;

/** It was a typo, sorry.. */
DISTRHO_DEPRECATED_BY("kParameterIsAutomatable")
static const uint32_t kParameterIsAutomable = kParameterIsAutomatable;

/**
Parameter value is boolean.@n
@@ -563,7 +567,7 @@ struct Parameter {
case kParameterDesignationNull:
break;
case kParameterDesignationBypass:
hints = kParameterIsAutomable|kParameterIsBoolean|kParameterIsInteger;
hints = kParameterIsAutomatable|kParameterIsBoolean|kParameterIsInteger;
name = "Bypass";
shortName = "Bypass";
symbol = "dpf_bypass";
@@ -837,6 +841,22 @@ public:
*/
double getSampleRate() const noexcept;

/**
Get the bundle path where the plugin resides.
Can return null if the plugin is not available in a bundle (if it is a single binary).
@see getBinaryFilename
@see getResourcePath
*/
const char* getBundlePath() const noexcept;

/**
Check if this plugin instance is a "dummy" one used for plugin meta-data/information export.@n
When true no processing will be done, the plugin is created only to extract information.@n
In DPF, LADSPA/DSSI, VST2 and VST3 formats create one global instance per plugin binary
while LV2 creates one when generating turtle meta-data.
*/
bool isDummyInstance() const noexcept;

#if DISTRHO_PLUGIN_WANT_TIMEPOS
/**
Get the current host transport time position.@n
@@ -994,7 +1014,7 @@ protected:
/**
Change a parameter value.@n
The host may call this function from any context, including realtime processing.@n
When a parameter is marked as automable, you must ensure no non-realtime operations are performed.
When a parameter is marked as automatable, you must ensure no non-realtime operations are performed.
@note This function will only be called for parameter inputs.
*/
virtual void setParameterValue(uint32_t index, float value);
@@ -1094,7 +1114,10 @@ private:
*/

/**
TODO.
Create an instance of the Plugin class.@n
This is the entry point for DPF plugins.@n
DPF will call this to either create an instance of your plugin for the host
or to fetch some initial information for internal caching.
*/
extern Plugin* createPlugin();



+ 10
- 0
dpf/distrho/DistrhoPluginMain.cpp View File

@@ -29,6 +29,16 @@
# include "src/DistrhoPluginVST2.cpp"
#elif defined(DISTRHO_PLUGIN_TARGET_VST3)
# include "src/DistrhoPluginVST3.cpp"
#elif defined(DISTRHO_PLUGIN_TARGET_SHARED)
DISTRHO_PLUGIN_EXPORT DISTRHO_NAMESPACE::Plugin* createSharedPlugin();
DISTRHO_PLUGIN_EXPORT DISTRHO_NAMESPACE::Plugin* createSharedPlugin() { return DISTRHO_NAMESPACE::createPlugin(); }
#else
# error unsupported format
#endif

#if defined(DISTRHO_PLUGIN_TARGET_JACK)
# define DISTRHO_IS_STANDALONE 1
#else
# define DISTRHO_IS_STANDALONE 0
#endif
#include "src/DistrhoUtils.cpp"

+ 57
- 1
dpf/distrho/DistrhoPluginUtils.hpp View File

@@ -21,8 +21,61 @@

START_NAMESPACE_DISTRHO

// -----------------------------------------------------------------------------------------------------------
/* ------------------------------------------------------------------------------------------------------------
* Plugin related utilities */

/**
@defgroup PluginRelatedUtilities Plugin related utilities

@{
*/

/**
Get the absolute filename of the plugin DSP/UI binary.@n
Under certain systems or plugin formats the binary will be inside the plugin bundle.@n
Also, in some formats or setups, the DSP and UI binaries are in different files.
*/
const char* getBinaryFilename();

/**
Get a string representation of the current plugin format we are building against.@n
This can be "JACK/Standalone", "LADSPA", "DSSI", "LV2", "VST2" or "VST3".@n
This string is purely informational and must not be used to tweak plugin behaviour.

@note DO NOT CHANGE PLUGIN BEHAVIOUR BASED ON PLUGIN FORMAT.
*/
const char* getPluginFormatName() noexcept;

/**
Get the path to where resources are stored within the plugin bundle.@n
Requires a valid plugin bundle path.

Returns a path inside the bundle where the plugin is meant to store its resources in.@n
This path varies between systems and plugin formats, like so:

- LV2: <bundle>/resources (can be stored anywhere inside the bundle really, DPF just uses this one)
- VST2 macOS: <bundle>/Contents/Resources
- VST2 non-macOS: <bundle>/resources (see note)

The other non-mentioned formats do not support bundles.@n

@note For VST2 on non-macOS systems, this assumes you have your plugin inside a dedicated directory
rather than only shipping with the binary (e.g. <myplugin.vst>/myplugin.dll)
*/
const char* getResourcePath(const char* bundlePath) noexcept;

/** @} */

/* ------------------------------------------------------------------------------------------------------------
* Plugin helper classes */

/**
@defgroup PluginHelperClasses Plugin helper classes

@{
*/

#if DISTRHO_PLUGIN_NUM_OUTPUTS > 0
/**
Handy class to help keep audio buffer in sync with incoming MIDI events.
To use it, create a local variable (on the stack) and call nextEvent() until it returns false.
@@ -151,6 +204,9 @@ private:
uint32_t remainingMidiEventCount;
uint32_t totalFramesUsed;
};
#endif

/** @} */

// -----------------------------------------------------------------------------------------------------------



+ 35
- 4
dpf/distrho/DistrhoUI.hpp View File

@@ -48,6 +48,10 @@ typedef DGL_NAMESPACE::NanoTopLevelWidget UIWidget;
typedef DGL_NAMESPACE::TopLevelWidget UIWidget;
#endif

#ifndef DGL_FILE_BROWSER_DISABLED
# include "extra/FileBrowserDialog.hpp"
#endif

START_NAMESPACE_DGL
class PluginWindow;
END_NAMESPACE_DGL
@@ -80,7 +84,7 @@ public:
It assumes aspect ratio is meant to be kept.
Manually call setGeometryConstraints instead if keeping UI aspect ratio is not required.
*/
UI(uint width = 0, uint height = 0, bool automaticallyScale = false);
UI(uint width = 0, uint height = 0, bool automaticallyScaleAndSetAsMinimumSize = false);

/**
Destructor.
@@ -131,6 +135,13 @@ public:
*/
double getSampleRate() const noexcept;

/**
Get the bundle path where the UI resides.@n
Can return null if the UI is not available in a bundle (if it is a single binary).
@see getBinaryFilename
*/
const char* getBundlePath() const noexcept;

/**
editParameter.

@@ -176,6 +187,22 @@ public:
void sendNote(uint8_t channel, uint8_t note, uint8_t velocity);
#endif

#ifndef DGL_FILE_BROWSER_DISABLED
/**
Open a file browser dialog with this window as transient parent.@n
A few options can be specified to setup the dialog.

If a path is selected, onFileSelected() will be called with the user chosen path.
If the user cancels or does not pick a file, onFileSelected() will be called with nullptr as filename.

This function does not block the event loop.

@note This is exactly the same API as provided by the Window class,
but redeclared here so that non-embed/DGL based UIs can still use file browser related functions.
*/
bool openFileBrowser(const FileBrowserOptions& options = FileBrowserOptions());
#endif

#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
/* --------------------------------------------------------------------------------------------------------
* Direct DSP access - DO NOT USE THIS UNLESS STRICTLY NECESSARY!! */
@@ -290,8 +317,9 @@ protected:
The most common exception is custom OpenGL setup, but only really needed for custom OpenGL drawing code.
*/
virtual void uiReshape(uint width, uint height);
#endif // !DISTRHO_PLUGIN_HAS_EXTERNAL_UI

# ifndef DGL_FILE_BROWSER_DISABLED
#ifndef DGL_FILE_BROWSER_DISABLED
/**
Window file selected function, called when a path is selected by the user, as triggered by openFileBrowser().
This function is for plugin UIs to be able to override Window::onFileSelected(const char*).
@@ -302,8 +330,7 @@ protected:
If you need to use files as plugin state, please setup and use DISTRHO_PLUGIN_WANT_STATEFILES instead.
*/
virtual void uiFileBrowserSelected(const char* filename);
# endif
#endif // !DISTRHO_PLUGIN_HAS_EXTERNAL_UI
#endif

/* --------------------------------------------------------------------------------------------------------
* UI Resize Handling, internal */
@@ -331,6 +358,10 @@ private:
PrivateData* const uiData;
friend class DGL_NAMESPACE::PluginWindow;
friend class UIExporter;
#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI
/** @internal */
void requestSizeChange(uint width, uint height) override;
#endif

DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(UI)
};


+ 11
- 0
dpf/distrho/DistrhoUIMain.cpp View File

@@ -28,6 +28,17 @@
// nothing
#elif defined(DISTRHO_PLUGIN_TARGET_VST3)
# include "src/DistrhoUIVST3.cpp"
#elif defined(DISTRHO_PLUGIN_TARGET_SHARED)
// nothing
#else
# error unsupported format
#endif

#if !DISTRHO_PLUGIN_WANT_DIRECT_ACCESS && !DISTRHO_PLUGIN_TARGET_JACK && !DISTRHO_PLUGIN_TARGET_VST2 && !DISTRHO_PLUGIN_TARGET_VST3
# ifdef DISTRHO_PLUGIN_TARGET_DSSI
# define DISTRHO_IS_STANDALONE 1
# else
# define DISTRHO_IS_STANDALONE 0
# endif
# include "src/DistrhoUtils.cpp"
#endif

+ 20
- 15
dpf/distrho/DistrhoUI_macOS.mm View File

@@ -22,10 +22,15 @@
#include "src/DistrhoDefines.h"

#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI
#import <Cocoa/Cocoa.h>
#include <algorithm>
#include <cmath>

# import <Cocoa/Cocoa.h>
# include <algorithm>
# include <cmath>
# ifndef DGL_FILE_BROWSER_DISABLED
# import "extra/FileBrowserDialog.cpp"
# endif

// Declared in DistrhoUI.cpp but defined here because it uses Obj-C
START_NAMESPACE_DISTRHO
double getDesktopScaleFactor(const uintptr_t parentWindowHandle)
{
@@ -40,19 +45,19 @@ double getDesktopScaleFactor(const uintptr_t parentWindowHandle)
return [NSScreen mainScreen].backingScaleFactor;
}
END_NAMESPACE_DISTRHO
#else // DISTRHO_PLUGIN_HAS_EXTERNAL_UI
#include "../dgl/Base.hpp"

#define DISTRHO_MACOS_NAMESPACE_MACRO_HELPER(DGL_NS, SEP, PUGL_NS, INTERFACE) DGL_NS ## SEP ## PUGL_NS ## SEP ## INTERFACE
#define DISTRHO_MACOS_NAMESPACE_MACRO(DGL_NS, PUGL_NS, INTERFACE) DISTRHO_MACOS_NAMESPACE_MACRO_HELPER(DGL_NS, _, PUGL_NS, INTERFACE)
#else // DISTRHO_PLUGIN_HAS_EXTERNAL_UI

#define PuglCairoView DISTRHO_MACOS_NAMESPACE_MACRO(DGL_NAMESPACE, PUGL_NAMESPACE, CairoView)
#define PuglOpenGLView DISTRHO_MACOS_NAMESPACE_MACRO(DGL_NAMESPACE, PUGL_NAMESPACE, OpenGLView)
#define PuglStubView DISTRHO_MACOS_NAMESPACE_MACRO(DGL_NAMESPACE, PUGL_NAMESPACE, StubView)
#define PuglVulkanView DISTRHO_MACOS_NAMESPACE_MACRO(DGL_NAMESPACE, PUGL_NAMESPACE, VulkanView)
#define PuglWindow DISTRHO_MACOS_NAMESPACE_MACRO(DGL_NAMESPACE, PUGL_NAMESPACE, Window)
#define PuglWindowDelegate DISTRHO_MACOS_NAMESPACE_MACRO(DGL_NAMESPACE, PUGL_NAMESPACE, WindowDelegate)
#define PuglWrapperView DISTRHO_MACOS_NAMESPACE_MACRO(DGL_NAMESPACE, PUGL_NAMESPACE, WrapperView)
# include "../dgl/Base.hpp"
# define DISTRHO_MACOS_NAMESPACE_MACRO_HELPER(DGL_NS, SEP, PUGL_NS, INTERFACE) DGL_NS ## SEP ## PUGL_NS ## SEP ## INTERFACE
# define DISTRHO_MACOS_NAMESPACE_MACRO(DGL_NS, PUGL_NS, INTERFACE) DISTRHO_MACOS_NAMESPACE_MACRO_HELPER(DGL_NS, _, PUGL_NS, INTERFACE)
# define PuglCairoView DISTRHO_MACOS_NAMESPACE_MACRO(DGL_NAMESPACE, PUGL_NAMESPACE, CairoView)
# define PuglOpenGLView DISTRHO_MACOS_NAMESPACE_MACRO(DGL_NAMESPACE, PUGL_NAMESPACE, OpenGLView)
# define PuglStubView DISTRHO_MACOS_NAMESPACE_MACRO(DGL_NAMESPACE, PUGL_NAMESPACE, StubView)
# define PuglVulkanView DISTRHO_MACOS_NAMESPACE_MACRO(DGL_NAMESPACE, PUGL_NAMESPACE, VulkanView)
# define PuglWindow DISTRHO_MACOS_NAMESPACE_MACRO(DGL_NAMESPACE, PUGL_NAMESPACE, Window)
# define PuglWindowDelegate DISTRHO_MACOS_NAMESPACE_MACRO(DGL_NAMESPACE, PUGL_NAMESPACE, WindowDelegate)
# define PuglWrapperView DISTRHO_MACOS_NAMESPACE_MACRO(DGL_NAMESPACE, PUGL_NAMESPACE, WrapperView)
# import "src/pugl.mm"

#import "src/pugl.mm"
#endif // DISTRHO_PLUGIN_HAS_EXTERNAL_UI

+ 72
- 47
dpf/distrho/DistrhoUtils.hpp View File

@@ -58,11 +58,18 @@ inline float round(float __x)
#define DISTRHO_MACRO_AS_STRING_VALUE(MACRO) #MACRO
#define DISTRHO_MACRO_AS_STRING(MACRO) DISTRHO_MACRO_AS_STRING_VALUE(MACRO)

// -----------------------------------------------------------------------
// misc functions
/* ------------------------------------------------------------------------------------------------------------
* misc functions */

/*
* Return a 64-bit number from 4 8-bit numbers.
/**
@defgroup MiscellaneousFunctions Miscellaneous functions

@{
*/

/**
Return a 32-bit number from 4 8-bit numbers.@n
The return type is a int64_t for better compatibility with plugin formats that use such numbers.
*/
static inline constexpr
int64_t d_cconst(const uint8_t a, const uint8_t b, const uint8_t c, const uint8_t d) noexcept
@@ -70,8 +77,8 @@ int64_t d_cconst(const uint8_t a, const uint8_t b, const uint8_t c, const uint8_
return (a << 24) | (b << 16) | (c << 8) | (d << 0);
}

/*
* Return an hexadecimal representation of a MAJ.MIN.MICRO version number.
/**
Return an hexadecimal representation of a MAJ.MIN.MICRO version number.
*/
static inline constexpr
uint32_t d_version(const uint8_t major, const uint8_t minor, const uint8_t micro) noexcept
@@ -79,18 +86,26 @@ uint32_t d_version(const uint8_t major, const uint8_t minor, const uint8_t micro
return uint32_t(major << 16) | uint32_t(minor << 8) | (micro << 0);
}

/*
* Dummy function.
/**
Dummy, no-op function.
*/
static inline
void d_pass() noexcept {}

// -----------------------------------------------------------------------
// string print functions
/** @} */

/*
* Print a string to stdout with newline (gray color).
* Does nothing if DEBUG is not defined.
/* ------------------------------------------------------------------------------------------------------------
* string print functions */

/**
@defgroup StringPrintFunctions String print functions

@{
*/

/**
Print a string to stdout with newline (gray color).
Does nothing if DEBUG is not defined.
*/
#ifndef DEBUG
# define d_debug(...)
@@ -109,8 +124,8 @@ void d_debug(const char* const fmt, ...) noexcept
}
#endif

/*
* Print a string to stdout with newline.
/**
Print a string to stdout with newline.
*/
static inline
void d_stdout(const char* const fmt, ...) noexcept
@@ -124,8 +139,8 @@ void d_stdout(const char* const fmt, ...) noexcept
} catch (...) {}
}

/*
* Print a string to stderr with newline.
/**
Print a string to stderr with newline.
*/
static inline
void d_stderr(const char* const fmt, ...) noexcept
@@ -139,8 +154,8 @@ void d_stderr(const char* const fmt, ...) noexcept
} catch (...) {}
}

/*
* Print a string to stderr with newline (red color).
/**
Print a string to stderr with newline (red color).
*/
static inline
void d_stderr2(const char* const fmt, ...) noexcept
@@ -155,8 +170,8 @@ void d_stderr2(const char* const fmt, ...) noexcept
} catch (...) {}
}

/*
* Print a safe assertion error message.
/**
Print a safe assertion error message.
*/
static inline
void d_safe_assert(const char* const assertion, const char* const file, const int line) noexcept
@@ -164,8 +179,8 @@ void d_safe_assert(const char* const assertion, const char* const file, const in
d_stderr2("assertion failure: \"%s\" in file %s, line %i", assertion, file, line);
}

/*
* Print a safe assertion error message, with 1 extra signed integer value.
/**
Print a safe assertion error message, with 1 extra signed integer value.
*/
static inline
void d_safe_assert_int(const char* const assertion, const char* const file,
@@ -174,8 +189,8 @@ void d_safe_assert_int(const char* const assertion, const char* const file,
d_stderr2("assertion failure: \"%s\" in file %s, line %i, value %i", assertion, file, line, value);
}

/*
* Print a safe assertion error message, with 1 extra unsigned integer value.
/**
Print a safe assertion error message, with 1 extra unsigned integer value.
*/
static inline
void d_safe_assert_uint(const char* const assertion, const char* const file,
@@ -184,8 +199,8 @@ void d_safe_assert_uint(const char* const assertion, const char* const file,
d_stderr2("assertion failure: \"%s\" in file %s, line %i, value %u", assertion, file, line, value);
}

/*
* Print a safe assertion error message, with 2 extra signed integer values.
/**
Print a safe assertion error message, with 2 extra signed integer values.
*/
static inline
void d_safe_assert_int2(const char* const assertion, const char* const file,
@@ -194,8 +209,8 @@ void d_safe_assert_int2(const char* const assertion, const char* const file,
d_stderr2("assertion failure: \"%s\" in file %s, line %i, v1 %i, v2 %i", assertion, file, line, v1, v2);
}

/*
* Print a safe assertion error message, with 2 extra unsigned integer values.
/**
Print a safe assertion error message, with 2 extra unsigned integer values.
*/
static inline
void d_safe_assert_uint2(const char* const assertion, const char* const file,
@@ -204,8 +219,8 @@ void d_safe_assert_uint2(const char* const assertion, const char* const file,
d_stderr2("assertion failure: \"%s\" in file %s, line %i, v1 %u, v2 %u", assertion, file, line, v1, v2);
}

/*
* Print a safe assertion error message, with a custom error message.
/**
Print a safe assertion error message, with a custom error message.
*/
static inline
void d_custom_safe_assert(const char* const message, const char* const assertion, const char* const file,
@@ -214,8 +229,8 @@ void d_custom_safe_assert(const char* const message, const char* const assertion
d_stderr2("assertion failure: %s, condition \"%s\" in file %s, line %i", message, assertion, file, line);
}

/*
* Print a safe exception error message.
/**
Print a safe exception error message.
*/
static inline
void d_safe_exception(const char* const exception, const char* const file, const int line) noexcept
@@ -223,12 +238,20 @@ void d_safe_exception(const char* const exception, const char* const file, const
d_stderr2("exception caught: \"%s\" in file %s, line %i", exception, file, line);
}

// -----------------------------------------------------------------------
// math functions
/** @} */

/*
* Safely compare two floating point numbers.
* Returns true if they match.
/* ------------------------------------------------------------------------------------------------------------
* math functions */

/**
@defgroup MathFunctions Math related functions

@{
*/

/**
Safely compare two floating point numbers.
Returns true if they match.
*/
template<typename T>
static inline
@@ -237,9 +260,9 @@ bool d_isEqual(const T& v1, const T& v2)
return std::abs(v1-v2) < std::numeric_limits<T>::epsilon();
}

/*
* Safely compare two floating point numbers.
* Returns true if they don't match.
/**
Safely compare two floating point numbers.
Returns true if they don't match.
*/
template<typename T>
static inline
@@ -248,8 +271,8 @@ bool d_isNotEqual(const T& v1, const T& v2)
return std::abs(v1-v2) >= std::numeric_limits<T>::epsilon();
}

/*
* Safely check if a floating point number is zero.
/**
Safely check if a floating point number is zero.
*/
template<typename T>
static inline
@@ -258,8 +281,8 @@ bool d_isZero(const T& value)
return std::abs(value) < std::numeric_limits<T>::epsilon();
}

/*
* Safely check if a floating point number is not zero.
/**
Safely check if a floating point number is not zero.
*/
template<typename T>
static inline
@@ -268,8 +291,8 @@ bool d_isNotZero(const T& value)
return std::abs(value) >= std::numeric_limits<T>::epsilon();
}

/*
* Get next power of 2.
/**
Get next power of 2.
*/
static inline
uint32_t d_nextPowerOf2(uint32_t size) noexcept
@@ -286,6 +309,8 @@ uint32_t d_nextPowerOf2(uint32_t size) noexcept
return ++size;
}

/** @} */

// -----------------------------------------------------------------------

#ifndef DONT_SET_USING_DISTRHO_NAMESPACE


+ 592
- 0
dpf/distrho/extra/FileBrowserDialog.cpp View File

@@ -0,0 +1,592 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2021 Filipe Coelho <falktx@falktx.com>
*
* Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this
* permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
* TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

#include "FileBrowserDialog.hpp"
#include "ScopedPointer.hpp"
#include "String.hpp"

#ifdef DISTRHO_OS_MAC
# import <Cocoa/Cocoa.h>
#endif
#ifdef DISTRHO_OS_WINDOWS
# include <direct.h>
# include <process.h>
# include <winsock2.h>
# include <windows.h>
# include <commdlg.h>
# include <vector>
#else
# include <unistd.h>
#endif
#ifdef HAVE_DBUS
# include <dbus/dbus.h>
#endif
#ifdef HAVE_X11
# define DBLCLKTME 400
# include "sofd/libsofd.h"
# include "sofd/libsofd.c"
#endif

START_NAMESPACE_DISTRHO

// --------------------------------------------------------------------------------------------------------------------

// static pointer used for signal null/none action taken
static const char* const kSelectedFileCancelled = "__dpf_cancelled__";

struct FileBrowserData {
const char* selectedFile;

#ifdef DISTRHO_OS_MAC
NSSavePanel* nsBasePanel;
NSOpenPanel* nsOpenPanel;
#endif
#ifdef HAVE_DBUS
DBusConnection* dbuscon;
#endif
#ifdef HAVE_X11
Display* x11display;
#endif

#ifdef DISTRHO_OS_WINDOWS
OPENFILENAMEW ofn;
volatile bool threadCancelled;
uintptr_t threadHandle;
std::vector<WCHAR> fileNameW;
std::vector<WCHAR> startDirW;
std::vector<WCHAR> titleW;
const bool saving;
bool isEmbed;

FileBrowserData(const bool save)
: selectedFile(nullptr),
threadCancelled(false),
threadHandle(0),
fileNameW(32768),
saving(save),
isEmbed(false)
{
std::memset(&ofn, 0, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.lpstrFile = fileNameW.data();
ofn.nMaxFile = (DWORD)fileNameW.size();
}

~FileBrowserData()
{
if (cancelAndStop() && selectedFile != nullptr && selectedFile != kSelectedFileCancelled)
std::free(const_cast<char*>(selectedFile));
}

void setupAndStart(const bool embed,
const char* const startDir,
const char* const windowTitle,
const uintptr_t winId,
const FileBrowserOptions options)
{
isEmbed = embed;

ofn.hwndOwner = (HWND)winId;

ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR;
if (options.buttons.showHidden == FileBrowserOptions::kButtonVisibleChecked)
ofn.Flags |= OFN_FORCESHOWHIDDEN;

ofn.FlagsEx = 0x0;
if (options.buttons.showPlaces == FileBrowserOptions::kButtonInvisible)
ofn.FlagsEx |= OFN_EX_NOPLACESBAR;

startDirW.resize(std::strlen(startDir) + 1);
if (MultiByteToWideChar(CP_UTF8, 0, startDir, -1, startDirW.data(), static_cast<int>(startDirW.size())))
ofn.lpstrInitialDir = startDirW.data();

titleW.resize(std::strlen(windowTitle) + 1);
if (MultiByteToWideChar(CP_UTF8, 0, windowTitle, -1, titleW.data(), static_cast<int>(titleW.size())))
ofn.lpstrTitle = titleW.data();

uint threadId;
threadCancelled = false;
threadHandle = _beginthreadex(nullptr, 0, _run, this, 0, &threadId);
}

bool cancelAndStop()
{
threadCancelled = true;

if (threadHandle == 0)
return true;

// if previous dialog running, carefully close its window
const HWND owner = isEmbed ? GetParent(ofn.hwndOwner) : ofn.hwndOwner;

if (owner != nullptr && owner != INVALID_HANDLE_VALUE)
{
const HWND window = GetWindow(owner, GW_HWNDFIRST);

if (window != nullptr && window != INVALID_HANDLE_VALUE)
{
SendMessage(window, WM_SYSCOMMAND, SC_CLOSE, 0);
SendMessage(window, WM_CLOSE, 0, 0);
WaitForSingleObject((HANDLE)threadHandle, 5000);
}
}

if (threadHandle == 0)
return true;

// not good if thread still running, but let's close the handle anyway
CloseHandle((HANDLE)threadHandle);
threadHandle = 0;
return false;
}

void run()
{
const char* nextFile = nullptr;

if (saving ? GetSaveFileNameW(&ofn) : GetOpenFileNameW(&ofn))
{
if (threadCancelled)
{
threadHandle = 0;
return;
}

// back to UTF-8
std::vector<char> fileNameA(4 * 32768);
if (WideCharToMultiByte(CP_UTF8, 0, fileNameW.data(), -1,
fileNameA.data(), (int)fileNameA.size(),
nullptr, nullptr))
{
nextFile = strdup(fileNameA.data());
}
}

if (threadCancelled)
{
threadHandle = 0;
return;
}

if (nextFile == nullptr)
nextFile = kSelectedFileCancelled;

selectedFile = nextFile;
threadHandle = 0;
}

static unsigned __stdcall _run(void* const arg)
{
// CoInitializeEx(nullptr, COINIT_MULTITHREADED);
static_cast<FileBrowserData*>(arg)->run();
// CoUninitialize();
_endthreadex(0);
return 0;
}
#else // DISTRHO_OS_WINDOWS
FileBrowserData(const bool saving)
: selectedFile(nullptr)
{
#ifdef DISTRHO_OS_MAC
if (saving)
{
nsOpenPanel = nullptr;
nsBasePanel = [[NSSavePanel savePanel]retain];
}
else
{
nsOpenPanel = [[NSOpenPanel openPanel]retain];
nsBasePanel = nsOpenPanel;
}
#endif
#ifdef HAVE_DBUS
if ((dbuscon = dbus_bus_get(DBUS_BUS_SESSION, nullptr)) != nullptr)
dbus_connection_set_exit_on_disconnect(dbuscon, false);
#endif
#ifdef HAVE_X11
x11display = XOpenDisplay(nullptr);
#endif

// maybe unused
return; (void)saving;
}

~FileBrowserData()
{
#ifdef DISTRHO_OS_MAC
[nsBasePanel release];
#endif
#ifdef HAVE_DBUS
if (dbuscon != nullptr)
dbus_connection_unref(dbuscon);
#endif
#ifdef HAVE_X11
if (x11display != nullptr)
XCloseDisplay(x11display);
#endif

if (selectedFile != nullptr && selectedFile != kSelectedFileCancelled)
std::free(const_cast<char*>(selectedFile));
}
#endif
};

// --------------------------------------------------------------------------------------------------------------------

#ifdef DISTRHO_FILE_BROWSER_DIALOG_EXTRA_NAMESPACE
namespace DISTRHO_FILE_BROWSER_DIALOG_EXTRA_NAMESPACE {
#endif

// --------------------------------------------------------------------------------------------------------------------

FileBrowserHandle fileBrowserCreate(const bool isEmbed,
const uintptr_t windowId,
const double scaleFactor,
const FileBrowserOptions& options)
{
String startDir(options.startDir);

if (startDir.isEmpty())
{
#ifdef DISTRHO_OS_WINDOWS
if (char* const cwd = _getcwd(nullptr, 0))
{
startDir = cwd;
std::free(cwd);
}
#else
if (char* const cwd = getcwd(nullptr, 0))
{
startDir = cwd;
std::free(cwd);
}
#endif
}

DISTRHO_SAFE_ASSERT_RETURN(startDir.isNotEmpty(), nullptr);

if (! startDir.endsWith(DISTRHO_OS_SEP))
startDir += DISTRHO_OS_SEP_STR;

String windowTitle(options.title);

if (windowTitle.isEmpty())
windowTitle = "FileBrowser";

ScopedPointer<FileBrowserData> handle(new FileBrowserData(options.saving));

#ifdef DISTRHO_OS_MAC
NSSavePanel* const nsBasePanel = handle->nsBasePanel;
DISTRHO_SAFE_ASSERT_RETURN(nsBasePanel != nullptr, nullptr);

if (! options.saving)
{
NSOpenPanel* const nsOpenPanel = handle->nsOpenPanel;
DISTRHO_SAFE_ASSERT_RETURN(nsOpenPanel != nullptr, nullptr);

[nsOpenPanel setAllowsMultipleSelection:NO];
[nsOpenPanel setCanChooseDirectories:NO];
[nsOpenPanel setCanChooseFiles:YES];
}

[nsBasePanel setDirectoryURL:[NSURL fileURLWithPath:[NSString stringWithUTF8String:startDir]]];

// TODO file filter using allowedContentTypes: [UTType]

if (options.buttons.listAllFiles == FileBrowserOptions::kButtonVisibleChecked)
[nsBasePanel setAllowsOtherFileTypes:YES];
if (options.buttons.showHidden == FileBrowserOptions::kButtonVisibleChecked)
[nsBasePanel setShowsHiddenFiles:YES];

NSString* const titleString = [[NSString alloc]
initWithBytes:windowTitle
length:strlen(windowTitle)
encoding:NSUTF8StringEncoding];
[nsBasePanel setTitle:titleString];

FileBrowserData* const handleptr = handle.get();

dispatch_async(dispatch_get_main_queue(), ^
{
[nsBasePanel beginSheetModalForWindow:[(NSView*)windowId window]
completionHandler:^(NSModalResponse result)
{
if (result == NSModalResponseOK && [[nsBasePanel URL] isFileURL])
{
NSString* const path = [[nsBasePanel URL] path];
handleptr->selectedFile = strdup([path UTF8String]);
}
else
{
handleptr->selectedFile = kSelectedFileCancelled;
}
}];
});
#endif

#ifdef DISTRHO_OS_WINDOWS
handle->setupAndStart(isEmbed, startDir, windowTitle, windowId, options);
#endif

#ifdef HAVE_DBUS
// optional, can be null
DBusConnection* const dbuscon = handle->dbuscon;

if (dbuscon != nullptr && dbus_bus_name_has_owner(dbuscon, "org.freedesktop.portal.Desktop", nullptr))
{
// https://flatpak.github.io/xdg-desktop-portal/portal-docs.html#gdbus-org.freedesktop.portal.FileChooser
if (DBusMessage* const message = dbus_message_new_method_call("org.freedesktop.portal.Desktop",
"/org/freedesktop/portal/desktop",
"org.freedesktop.portal.FileChooser",
options.saving ? "SaveFile" : "OpenFile"))
{
char windowIdStr[32];
memset(windowIdStr, 0, sizeof(windowIdStr));
# ifdef HAVE_X11
snprintf(windowIdStr, sizeof(windowIdStr)-1, "x11:%llx", (ulonglong)windowId);
# endif
const char* windowIdStrPtr = windowIdStr;

dbus_message_append_args(message,
DBUS_TYPE_STRING, &windowIdStrPtr,
DBUS_TYPE_STRING, &windowTitle,
DBUS_TYPE_INVALID);

DBusMessageIter iter, array;
dbus_message_iter_init_append(message, &iter);
dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &array);

{
DBusMessageIter dict, variant, variantArray;
const char* const current_folder_key = "current_folder";
const char* const current_folder_val = startDir.buffer();

dbus_message_iter_open_container(&array, DBUS_TYPE_DICT_ENTRY, nullptr, &dict);
dbus_message_iter_append_basic(&dict, DBUS_TYPE_STRING, &current_folder_key);
dbus_message_iter_open_container(&dict, DBUS_TYPE_VARIANT, "ay", &variant);
dbus_message_iter_open_container(&variant, DBUS_TYPE_ARRAY, "y", &variantArray);
dbus_message_iter_append_fixed_array(&variantArray, DBUS_TYPE_BYTE,
&current_folder_val, startDir.length()+1);
dbus_message_iter_close_container(&variant, &variantArray);
dbus_message_iter_close_container(&dict, &variant);
dbus_message_iter_close_container(&array, &dict);
}

dbus_message_iter_close_container(&iter, &array);

dbus_connection_send(dbuscon, message, nullptr);

dbus_message_unref(message);
return handle.release();
}
}
#endif

#ifdef HAVE_X11
Display* const x11display = handle->x11display;
DISTRHO_SAFE_ASSERT_RETURN(x11display != nullptr, nullptr);

// unsupported at the moment
if (options.saving)
return nullptr;

DISTRHO_SAFE_ASSERT_RETURN(x_fib_configure(0, startDir) == 0, nullptr);
DISTRHO_SAFE_ASSERT_RETURN(x_fib_configure(1, windowTitle) == 0, nullptr);

const int button1 = options.buttons.showHidden == FileBrowserOptions::kButtonVisibleChecked ? 1
: options.buttons.showHidden == FileBrowserOptions::kButtonVisibleUnchecked ? 0 : -1;
const int button2 = options.buttons.showPlaces == FileBrowserOptions::kButtonVisibleChecked ? 1
: options.buttons.showPlaces == FileBrowserOptions::kButtonVisibleUnchecked ? 0 : -1;
const int button3 = options.buttons.listAllFiles == FileBrowserOptions::kButtonVisibleChecked ? 1
: options.buttons.listAllFiles == FileBrowserOptions::kButtonVisibleUnchecked ? 0 : -1;

x_fib_cfg_buttons(1, button1);
x_fib_cfg_buttons(2, button2);
x_fib_cfg_buttons(3, button3);

if (x_fib_show(x11display, windowId, 0, 0, scaleFactor + 0.5) != 0)
return nullptr;
#endif

return handle.release();

// might be unused
(void)isEmbed;
(void)windowId;
(void)scaleFactor;
}

// --------------------------------------------------------------------------------------------------------------------
// returns true if dialog was closed (with or without a file selection)

bool fileBrowserIdle(const FileBrowserHandle handle)
{
#ifdef HAVE_DBUS
if (DBusConnection* dbuscon = handle->dbuscon)
{
while (dbus_connection_dispatch(dbuscon) == DBUS_DISPATCH_DATA_REMAINS) {}
dbus_connection_read_write_dispatch(dbuscon, 0);

if (DBusMessage* const message = dbus_connection_pop_message(dbuscon))
{
const char* const interface = dbus_message_get_interface(message);
const char* const member = dbus_message_get_member(message);

if (interface != nullptr && std::strcmp(interface, "org.freedesktop.portal.Request") == 0
&& member != nullptr && std::strcmp(member, "Response") == 0)
{
do {
DBusMessageIter iter;
dbus_message_iter_init(message, &iter);

// starts with uint32 for return/exit code
DISTRHO_SAFE_ASSERT_BREAK(dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_UINT32);

uint32_t ret = 1;
dbus_message_iter_get_basic(&iter, &ret);

if (ret != 0)
break;

// next must be array
dbus_message_iter_next(&iter);
DISTRHO_SAFE_ASSERT_BREAK(dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_ARRAY);

// open dict array
DBusMessageIter dictArray;
dbus_message_iter_recurse(&iter, &dictArray);
DISTRHO_SAFE_ASSERT_BREAK(dbus_message_iter_get_arg_type(&dictArray) == DBUS_TYPE_DICT_ENTRY);

// open containing dict
DBusMessageIter dict;
dbus_message_iter_recurse(&dictArray, &dict);

// look for dict with string "uris"
DISTRHO_SAFE_ASSERT_BREAK(dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_STRING);

const char* key = nullptr;
dbus_message_iter_get_basic(&dict, &key);
DISTRHO_SAFE_ASSERT_BREAK(key != nullptr);

// keep going until we find it
while (std::strcmp(key, "uris") != 0)
{
key = nullptr;
dbus_message_iter_next(&dictArray);
DISTRHO_SAFE_ASSERT_BREAK(dbus_message_iter_get_arg_type(&dictArray) == DBUS_TYPE_DICT_ENTRY);

dbus_message_iter_recurse(&dictArray, &dict);
DISTRHO_SAFE_ASSERT_BREAK(dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_STRING);

dbus_message_iter_get_basic(&dict, &key);
DISTRHO_SAFE_ASSERT_BREAK(key != nullptr);
}

if (key == nullptr)
break;

// then comes variant
dbus_message_iter_next(&dict);
DISTRHO_SAFE_ASSERT_BREAK(dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_VARIANT);

DBusMessageIter variant;
dbus_message_iter_recurse(&dict, &variant);
DISTRHO_SAFE_ASSERT_BREAK(dbus_message_iter_get_arg_type(&variant) == DBUS_TYPE_ARRAY);

// open variant array (variant type is string)
DBusMessageIter variantArray;
dbus_message_iter_recurse(&variant, &variantArray);
DISTRHO_SAFE_ASSERT_BREAK(dbus_message_iter_get_arg_type(&variantArray) == DBUS_TYPE_STRING);

const char* value = nullptr;
dbus_message_iter_get_basic(&variantArray, &value);

// and finally we have our dear value, just make sure it is local
DISTRHO_SAFE_ASSERT_BREAK(value != nullptr);

if (const char* const localvalue = std::strstr(value, "file:///"))
handle->selectedFile = strdup(localvalue + 7);

} while(false);

if (handle->selectedFile == nullptr)
handle->selectedFile = kSelectedFileCancelled;
}
}
}
#endif

#ifdef HAVE_X11
Display* const x11display = handle->x11display;

if (x11display == nullptr)
return false;

XEvent event;
while (XPending(x11display) > 0)
{
XNextEvent(x11display, &event);

if (x_fib_handle_events(x11display, &event) == 0)
continue;

if (x_fib_status() > 0)
handle->selectedFile = x_fib_filename();
else
handle->selectedFile = kSelectedFileCancelled;

x_fib_close(x11display);
XCloseDisplay(x11display);
handle->x11display = nullptr;
break;
}
#endif

return handle->selectedFile != nullptr;
}

// --------------------------------------------------------------------------------------------------------------------
// close sofd file dialog

void fileBrowserClose(const FileBrowserHandle handle)
{
#ifdef HAVE_X11
if (Display* const x11display = handle->x11display)
x_fib_close(x11display);
#endif

delete handle;
}

// --------------------------------------------------------------------------------------------------------------------
// get path chosen via sofd file dialog

const char* fileBrowserGetPath(const FileBrowserHandle handle)
{
if (const char* const selectedFile = handle->selectedFile)
if (selectedFile != kSelectedFileCancelled && std::strcmp(selectedFile, kSelectedFileCancelled) != 0)
return selectedFile;

return nullptr;
}

// --------------------------------------------------------------------------------------------------------------------

#ifdef DISTRHO_FILE_BROWSER_DIALOG_EXTRA_NAMESPACE
}
#endif

END_NAMESPACE_DISTRHO

+ 134
- 0
dpf/distrho/extra/FileBrowserDialog.hpp View File

@@ -0,0 +1,134 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2021 Filipe Coelho <falktx@falktx.com>
*
* Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this
* permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
* TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

#ifndef DISTRHO_FILE_BROWSER_DIALOG_HPP_INCLUDED
#define DISTRHO_FILE_BROWSER_DIALOG_HPP_INCLUDED

#include "../DistrhoUtils.hpp"

START_NAMESPACE_DISTRHO

// --------------------------------------------------------------------------------------------------------------------
// File Browser Dialog stuff

struct FileBrowserData;
typedef FileBrowserData* FileBrowserHandle;

// --------------------------------------------------------------------------------------------------------------------

/**
File browser options, for customizing the file browser dialog.@n
By default the file browser dialog will be work as "open file" in the current working directory.
*/
struct FileBrowserOptions {
/** Whether we are saving, opening files otherwise (default) */
bool saving;

/** Start directory, uses current working directory if null */
const char* startDir;

/** File browser dialog window title, uses "FileBrowser" if null */
const char* title;

// TODO file filter

/**
File browser button state.
This allows to customize the behaviour of the file browse dialog buttons.
Note these are merely hints, not all systems support them.
*/
enum ButtonState {
kButtonInvisible,
kButtonVisibleUnchecked,
kButtonVisibleChecked,
};

/**
File browser buttons.
*/
struct Buttons {
/** Whether to list all files vs only those with matching file extension */
ButtonState listAllFiles;
/** Whether to show hidden files */
ButtonState showHidden;
/** Whether to show list of places (bookmarks) */
ButtonState showPlaces;

/** Constructor for default values */
Buttons()
: listAllFiles(kButtonVisibleChecked),
showHidden(kButtonVisibleUnchecked),
showPlaces(kButtonVisibleChecked) {}
} buttons;

/** Constructor for default values */
FileBrowserOptions()
: saving(false),
startDir(nullptr),
title(nullptr),
buttons() {}
};

// --------------------------------------------------------------------------------------------------------------------

#ifdef DISTRHO_FILE_BROWSER_DIALOG_EXTRA_NAMESPACE
namespace DISTRHO_FILE_BROWSER_DIALOG_EXTRA_NAMESPACE {
#endif

/**
Create a new file browser dialog.

@p isEmbed: Whether the window this dialog belongs to is an embed/child window (needed to close dialog on Windows)
@p windowId: The native window id to attach this dialog to as transient parent (X11 Window, HWND or NSView*)
@p scaleFactor: Scale factor to use (only used on X11)
@p options: Extra options, optional
By default the file browser dialog will be work as "open file" in the current working directory.
*/
FileBrowserHandle fileBrowserCreate(bool isEmbed,
uintptr_t windowId,
double scaleFactor,
const FileBrowserOptions& options = FileBrowserOptions());

/**
Idle the file browser dialog handle.@n
Returns true if dialog was closed (with or without a file selection),
in which case the handle must not be used afterwards.
You can then call fileBrowserGetPath to know the selected file (or null if cancelled).
*/
bool fileBrowserIdle(const FileBrowserHandle handle);

/**
Close the file browser dialog, handle must not be used afterwards.
*/
void fileBrowserClose(const FileBrowserHandle handle);

/**
Get the path chosen by the user or null.@n
Should only be called after fileBrowserIdle returns true.
*/
const char* fileBrowserGetPath(const FileBrowserHandle handle);

// --------------------------------------------------------------------------------------------------------------------

#ifdef DISTRHO_FILE_BROWSER_DIALOG_EXTRA_NAMESPACE
}
#endif

// --------------------------------------------------------------------------------------------------------------------

END_NAMESPACE_DISTRHO

#endif // DISTRHO_FILE_BROWSER_DIALOG_HPP_INCLUDED

dpf/dgl/src/sofd/libsofd.c → dpf/distrho/extra/sofd/libsofd.c View File


dpf/dgl/src/sofd/libsofd.h → dpf/distrho/extra/sofd/libsofd.h View File


+ 1
- 0
dpf/distrho/src/DistrhoDefines.h View File

@@ -207,6 +207,7 @@ typedef unsigned char uchar;
typedef unsigned short int ushort;
typedef unsigned int uint;
typedef unsigned long int ulong;
typedef unsigned long long int ulonglong;

/* Deprecated macros */
#define DISTRHO_DECLARE_NON_COPY_CLASS(ClassName) DISTRHO_DECLARE_NON_COPYABLE(ClassName)


+ 15
- 3
dpf/distrho/src/DistrhoPlugin.cpp View File

@@ -21,9 +21,11 @@ START_NAMESPACE_DISTRHO
/* ------------------------------------------------------------------------------------------------------------
* Static data, see DistrhoPluginInternal.hpp */

uint32_t d_lastBufferSize = 0;
double d_lastSampleRate = 0.0;
bool d_lastCanRequestParameterValueChanges = false;
uint32_t d_nextBufferSize = 0;
double d_nextSampleRate = 0.0;
const char* d_nextBundlePath = nullptr;
bool d_nextPluginIsDummy = false;
bool d_nextCanRequestParameterValueChanges = false;

/* ------------------------------------------------------------------------------------------------------------
* Static fallback data, see DistrhoPluginInternal.hpp */
@@ -100,6 +102,16 @@ double Plugin::getSampleRate() const noexcept
return pData->sampleRate;
}

const char* Plugin::getBundlePath() const noexcept
{
return pData->bundlePath;
}

bool Plugin::isDummyInstance() const noexcept
{
return pData->isDummy;
}

#if DISTRHO_PLUGIN_WANT_TIMEPOS
const TimePosition& Plugin::getTimePosition() const noexcept
{


+ 1
- 1
dpf/distrho/src/DistrhoPluginCarla.cpp View File

@@ -238,7 +238,7 @@ protected:
int nativeParamHints = ::NATIVE_PARAMETER_IS_ENABLED;
const uint32_t paramHints = fPlugin.getParameterHints(index);

if (paramHints & kParameterIsAutomable)
if (paramHints & kParameterIsAutomatable)
nativeParamHints |= ::NATIVE_PARAMETER_IS_AUTOMABLE;
if (paramHints & kParameterIsBoolean)
nativeParamHints |= ::NATIVE_PARAMETER_IS_BOOLEAN;


+ 26
- 15
dpf/distrho/src/DistrhoPluginInternal.hpp View File

@@ -19,6 +19,10 @@

#include "../DistrhoPlugin.hpp"

#ifdef DISTRHO_PLUGIN_TARGET_VST3
# include "DistrhoPluginVST3.hpp"
#endif

#include <set>

START_NAMESPACE_DISTRHO
@@ -31,9 +35,11 @@ static const uint32_t kMaxMidiEvents = 512;
// -----------------------------------------------------------------------
// Static data, see DistrhoPlugin.cpp

extern uint32_t d_lastBufferSize;
extern double d_lastSampleRate;
extern bool d_lastCanRequestParameterValueChanges;
extern uint32_t d_nextBufferSize;
extern double d_nextSampleRate;
extern const char* d_nextBundlePath;
extern bool d_nextPluginIsDummy;
extern bool d_nextCanRequestParameterValueChanges;

// -----------------------------------------------------------------------
// DSP callbacks
@@ -83,6 +89,8 @@ static void fillInPredefinedPortGroupData(const uint32_t groupId, PortGroup& por
// Plugin private data

struct Plugin::PrivateData {
const bool canRequestParameterValueChanges;
const bool isDummy;
bool isProcessing;

#if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0
@@ -122,10 +130,12 @@ struct Plugin::PrivateData {

uint32_t bufferSize;
double sampleRate;
bool canRequestParameterValueChanges;
char* bundlePath;

PrivateData() noexcept
: isProcessing(false),
: canRequestParameterValueChanges(d_nextCanRequestParameterValueChanges),
isDummy(d_nextPluginIsDummy),
isProcessing(false),
#if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0
audioPorts(nullptr),
#endif
@@ -149,9 +159,9 @@ struct Plugin::PrivateData {
callbacksPtr(nullptr),
writeMidiCallbackFunc(nullptr),
requestParameterValueChangeCallbackFunc(nullptr),
bufferSize(d_lastBufferSize),
sampleRate(d_lastSampleRate),
canRequestParameterValueChanges(d_lastCanRequestParameterValueChanges)
bufferSize(d_nextBufferSize),
sampleRate(d_nextSampleRate),
bundlePath(d_nextBundlePath != nullptr ? strdup(d_nextBundlePath) : nullptr)
{
DISTRHO_SAFE_ASSERT(bufferSize != 0);
DISTRHO_SAFE_ASSERT(d_isNotZero(sampleRate));
@@ -164,7 +174,7 @@ struct Plugin::PrivateData {
#endif

#ifdef DISTRHO_PLUGIN_TARGET_LV2
# if (DISTRHO_PLUGIN_WANT_MIDI_INPUT || DISTRHO_PLUGIN_WANT_TIMEPOS || DISTRHO_PLUGIN_WANT_STATE)
# if (DISTRHO_PLUGIN_WANT_MIDI_INPUT || DISTRHO_PLUGIN_WANT_STATE || DISTRHO_PLUGIN_WANT_TIMEPOS)
parameterOffset += 1;
# endif
# if (DISTRHO_PLUGIN_WANT_MIDI_OUTPUT || DISTRHO_PLUGIN_WANT_STATE)
@@ -173,12 +183,7 @@ struct Plugin::PrivateData {
#endif

#ifdef DISTRHO_PLUGIN_TARGET_VST3
# if DISTRHO_PLUGIN_WANT_MIDI_INPUT
parameterOffset += 130 * 16; // all MIDI CCs plus aftertouch and pitchbend
# endif
# if DISTRHO_PLUGIN_WANT_PROGRAMS
parameterOffset += 1;
# endif
parameterOffset += kVst3InternalParameterCount;
#endif
}

@@ -225,6 +230,12 @@ struct Plugin::PrivateData {
stateDefValues = nullptr;
}
#endif

if (bundlePath != nullptr)
{
std::free(bundlePath);
bundlePath = nullptr;
}
}

#if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT


+ 185
- 9
dpf/distrho/src/DistrhoPluginJACK.cpp View File

@@ -15,6 +15,7 @@
*/

#include "DistrhoPluginInternal.hpp"
#include "../DistrhoPluginUtils.hpp"

#if DISTRHO_PLUGIN_HAS_UI
# include "DistrhoUIInternal.hpp"
@@ -23,11 +24,16 @@
# include "../extra/Sleep.hpp"
#endif

#ifdef DPF_RUNTIME_TESTING
# include "../extra/Thread.hpp"
#endif

#include "jackbridge/JackBridge.cpp"
#include "lv2/lv2.h"

#ifndef DISTRHO_OS_WINDOWS
# include <signal.h>
# include <unistd.h>
#endif

#ifndef JACK_METADATA_ORDER
@@ -115,7 +121,7 @@ public:
#if DISTRHO_PLUGIN_HAS_UI
fUI(this,
0, // winId
d_lastSampleRate,
d_nextSampleRate,
nullptr, // edit param
setParameterValueCallback,
setStateCallback,
@@ -422,7 +428,7 @@ protected:

for (uint32_t i=0; i < eventCount; ++i)
{
if (jackbridge_midi_event_get(&jevent, midiInBuf, i) != 0)
if (! jackbridge_midi_event_get(&jevent, midiInBuf, i))
break;

// Check if message is control change on channel 1
@@ -735,7 +741,7 @@ private:
return jackbridge_midi_event_write(fPortMidiOutBuffer,
midiEvent.frame,
midiEvent.size > MidiEvent::kDataSize ? midiEvent.dataExt : midiEvent.data,
midiEvent.size) == 0;
midiEvent.size);
}

static bool writeMidiCallback(void* ptr, const MidiEvent& midiEvent)
@@ -747,14 +753,153 @@ private:
#undef thisPtr
};

// -----------------------------------------------------------------------

#ifdef DPF_RUNTIME_TESTING
class PluginProcessTestingThread : public Thread
{
PluginExporter& plugin;

public:
PluginProcessTestingThread(PluginExporter& p) : plugin(p) {}

protected:
void run() override
{
plugin.setBufferSize(256);
plugin.activate();

float buffer[256];
const float* inputs[DISTRHO_PLUGIN_NUM_INPUTS > 0 ? DISTRHO_PLUGIN_NUM_INPUTS : 1];
float* outputs[DISTRHO_PLUGIN_NUM_OUTPUTS > 0 ? DISTRHO_PLUGIN_NUM_OUTPUTS : 1];
for (int i=0; i<DISTRHO_PLUGIN_NUM_INPUTS; ++i)
inputs[i] = buffer;
for (int i=0; i<DISTRHO_PLUGIN_NUM_OUTPUTS; ++i)
outputs[i] = buffer;

while (! shouldThreadExit())
{
#if DISTRHO_PLUGIN_WANT_MIDI_INPUT
plugin.run(inputs, outputs, 128, nullptr, 0);
#else
plugin.run(inputs, outputs, 128);
#endif
d_msleep(100);
}

plugin.deactivate();
}
};

bool runSelfTests()
{
// simple plugin creation first
{
d_nextBufferSize = 512;
d_nextSampleRate = 44100.0;
PluginExporter plugin(nullptr, nullptr, nullptr);
d_nextBufferSize = 0;
d_nextSampleRate = 0.0;
}

// keep values for all tests now
d_nextBufferSize = 512;
d_nextSampleRate = 44100.0;

// simple processing
{
PluginExporter plugin(nullptr, nullptr, nullptr);
plugin.activate();
plugin.deactivate();
plugin.setBufferSize(128);
plugin.setSampleRate(48000);
plugin.activate();

float buffer[128];
const float* inputs[DISTRHO_PLUGIN_NUM_INPUTS > 0 ? DISTRHO_PLUGIN_NUM_INPUTS : 1];
float* outputs[DISTRHO_PLUGIN_NUM_OUTPUTS > 0 ? DISTRHO_PLUGIN_NUM_OUTPUTS : 1];
for (int i=0; i<DISTRHO_PLUGIN_NUM_INPUTS; ++i)
inputs[i] = buffer;
for (int i=0; i<DISTRHO_PLUGIN_NUM_OUTPUTS; ++i)
outputs[i] = buffer;

#if DISTRHO_PLUGIN_WANT_MIDI_INPUT
plugin.run(inputs, outputs, 128, nullptr, 0);
#else
plugin.run(inputs, outputs, 128);
#endif

plugin.deactivate();
}

// multi-threaded processing with UI
{
PluginExporter pluginA(nullptr, nullptr, nullptr);
PluginExporter pluginB(nullptr, nullptr, nullptr);
PluginExporter pluginC(nullptr, nullptr, nullptr);
PluginProcessTestingThread procTestA(pluginA);
PluginProcessTestingThread procTestB(pluginB);
PluginProcessTestingThread procTestC(pluginC);
procTestA.startThread();
procTestB.startThread();
procTestC.startThread();

// wait 2s
d_sleep(2);

// stop the 2nd instance now
procTestB.stopThread(5000);

#if DISTRHO_PLUGIN_HAS_UI
// start UI in the middle of this
{
UIExporter uiA(nullptr, 0, pluginA.getSampleRate(),
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
pluginA.getInstancePointer(), 0.0);
UIExporter uiB(nullptr, 0, pluginA.getSampleRate(),
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
pluginB.getInstancePointer(), 0.0);
UIExporter uiC(nullptr, 0, pluginA.getSampleRate(),
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
pluginC.getInstancePointer(), 0.0);

// show UIs
uiB.showAndFocus();
uiA.showAndFocus();
uiC.showAndFocus();

// idle for 3s
for (int i=0; i<30; i++)
{
uiC.plugin_idle();
uiB.plugin_idle();
uiA.plugin_idle();
d_msleep(100);
}
}
#endif

procTestA.stopThread(5000);
procTestC.stopThread(5000);
}

return true;
}
#endif // DPF_RUNTIME_TESTING

END_NAMESPACE_DISTRHO

// -----------------------------------------------------------------------

int main()
int main(int argc, char* argv[])
{
USE_NAMESPACE_DISTRHO;

#ifdef DPF_RUNTIME_TESTING
if (argc == 2 && std::strcmp(argv[1], "selftest") == 0)
return runSelfTests() ? 0 : 1;
#endif

jack_status_t status = jack_status_t(0x0);
jack_client_t* client = jackbridge_client_open(DISTRHO_PLUGIN_NAME, JackNoStartServer, &status);

@@ -800,17 +945,48 @@ int main()
return 1;
}

USE_NAMESPACE_DISTRHO;

initSignalHandler();

d_lastBufferSize = jackbridge_get_buffer_size(client);
d_lastSampleRate = jackbridge_get_sample_rate(client);
d_lastCanRequestParameterValueChanges = true;
d_nextBufferSize = jackbridge_get_buffer_size(client);
d_nextSampleRate = jackbridge_get_sample_rate(client);
d_nextCanRequestParameterValueChanges = true;

#ifndef DISTRHO_OS_WINDOWS
// find plugin bundle
static String bundlePath;
if (bundlePath.isEmpty())
{
String tmpPath(getBinaryFilename());
tmpPath.truncate(tmpPath.rfind(DISTRHO_OS_SEP));
#ifdef DISTRHO_OS_MAC
if (tmpPath.endsWith("/MacOS"))
{
tmpPath.truncate(tmpPath.rfind('/'));
if (tmpPath.endsWith("/Contents"))
{
tmpPath.truncate(tmpPath.rfind('/'));
bundlePath = tmpPath;
d_nextBundlePath = bundlePath.buffer();
}
}
#else
if (access(tmpPath + DISTRHO_OS_SEP_STR "resources", F_OK) == 0)
{
bundlePath = tmpPath;
d_nextBundlePath = bundlePath.buffer();
}
#endif
}
#endif

const PluginJack p(client);

return 0;

#ifndef DPF_RUNTIME_TESTING
// unused
(void)argc; (void)argv;
#endif
}

// -----------------------------------------------------------------------

+ 9
- 7
dpf/distrho/src/DistrhoPluginLADSPA+DSSI.cpp View File

@@ -418,9 +418,9 @@ private:

static LADSPA_Handle ladspa_instantiate(const LADSPA_Descriptor*, ulong sampleRate)
{
if (d_lastBufferSize == 0)
d_lastBufferSize = 2048;
d_lastSampleRate = sampleRate;
if (d_nextBufferSize == 0)
d_nextBufferSize = 2048;
d_nextSampleRate = sampleRate;

return new PluginLadspaDssi();
}
@@ -551,11 +551,13 @@ static const struct DescriptorInitializer
DescriptorInitializer()
{
// Create dummy plugin to get data from
d_lastBufferSize = 512;
d_lastSampleRate = 44100.0;
d_nextBufferSize = 512;
d_nextSampleRate = 44100.0;
d_nextPluginIsDummy = true;
const PluginExporter plugin(nullptr, nullptr, nullptr);
d_lastBufferSize = 0;
d_lastSampleRate = 0.0;
d_nextBufferSize = 0;
d_nextSampleRate = 0.0;
d_nextPluginIsDummy = false;

// Get port count, init
ulong port = 0;


+ 9
- 12
dpf/distrho/src/DistrhoPluginLV2.cpp View File

@@ -37,10 +37,6 @@
# include "libmodla.h"
#endif

#ifdef noexcept
# undef noexcept
#endif

#include <map>

#ifndef DISTRHO_PLUGIN_URI
@@ -1296,7 +1292,7 @@ private:

// -----------------------------------------------------------------------

static LV2_Handle lv2_instantiate(const LV2_Descriptor*, double sampleRate, const char*, const LV2_Feature* const* features)
static LV2_Handle lv2_instantiate(const LV2_Descriptor*, double sampleRate, const char* bundlePath, const LV2_Feature* const* features)
{
const LV2_Options_Option* options = nullptr;
const LV2_URID_Map* uridMap = nullptr;
@@ -1339,7 +1335,7 @@ static LV2_Handle lv2_instantiate(const LV2_Descriptor*, double sampleRate, cons
mod_license_check(features, DISTRHO_PLUGIN_URI);
#endif

d_lastBufferSize = 0;
d_nextBufferSize = 0;
bool usingNominal = false;

for (int i=0; options[i].key != 0; ++i)
@@ -1348,7 +1344,7 @@ static LV2_Handle lv2_instantiate(const LV2_Descriptor*, double sampleRate, cons
{
if (options[i].type == uridMap->map(uridMap->handle, LV2_ATOM__Int))
{
d_lastBufferSize = *(const int*)options[i].value;
d_nextBufferSize = *(const int*)options[i].value;
usingNominal = true;
}
else
@@ -1361,7 +1357,7 @@ static LV2_Handle lv2_instantiate(const LV2_Descriptor*, double sampleRate, cons
if (options[i].key == uridMap->map(uridMap->handle, LV2_BUF_SIZE__maxBlockLength))
{
if (options[i].type == uridMap->map(uridMap->handle, LV2_ATOM__Int))
d_lastBufferSize = *(const int*)options[i].value;
d_nextBufferSize = *(const int*)options[i].value;
else
d_stderr("Host provides maxBlockLength but has wrong value type");

@@ -1369,14 +1365,15 @@ static LV2_Handle lv2_instantiate(const LV2_Descriptor*, double sampleRate, cons
}
}

if (d_lastBufferSize == 0)
if (d_nextBufferSize == 0)
{
d_stderr("Host does not provide nominalBlockLength or maxBlockLength options");
d_lastBufferSize = 2048;
d_nextBufferSize = 2048;
}

d_lastSampleRate = sampleRate;
d_lastCanRequestParameterValueChanges = ctrlInPortChangeReq != nullptr;
d_nextSampleRate = sampleRate;
d_nextBundlePath = bundlePath;
d_nextCanRequestParameterValueChanges = ctrlInPortChangeReq != nullptr;

return new PluginLv2(sampleRate, uridMap, worker, ctrlInPortChangeReq, usingNominal);
}


+ 13
- 6
dpf/distrho/src/DistrhoPluginLV2export.cpp View File

@@ -15,6 +15,7 @@
*/

#include "DistrhoPluginInternal.hpp"
#include "../DistrhoPluginUtils.hpp"

#include "lv2/atom.h"
#include "lv2/buf-size.h"
@@ -223,12 +224,18 @@ void lv2_generate_ttl(const char* const basename)
{
USE_NAMESPACE_DISTRHO

String bundlePath(getBinaryFilename());
bundlePath.truncate(bundlePath.rfind(DISTRHO_OS_SEP));
d_nextBundlePath = bundlePath.buffer();

// Dummy plugin to get data from
d_lastBufferSize = 512;
d_lastSampleRate = 44100.0;
d_nextBufferSize = 512;
d_nextSampleRate = 44100.0;
d_nextPluginIsDummy = true;
PluginExporter plugin(nullptr, nullptr, nullptr);
d_lastBufferSize = 0;
d_lastSampleRate = 0.0;
d_nextBufferSize = 0;
d_nextSampleRate = 0.0;
d_nextPluginIsDummy = false;

const String pluginDLL(basename);
const String pluginTTL(pluginDLL + ".ttl");
@@ -844,10 +851,10 @@ void lv2_generate_ttl(const char* const basename)
pluginString += " lv2:portProperty lv2:integer ;\n";
if (hints & kParameterIsLogarithmic)
pluginString += " lv2:portProperty <" LV2_PORT_PROPS__logarithmic "> ;\n";
if ((hints & kParameterIsAutomable) == 0 && plugin.isParameterInput(i))
if ((hints & kParameterIsAutomatable) == 0 && plugin.isParameterInput(i))
{
pluginString += " lv2:portProperty <" LV2_PORT_PROPS__expensive "> ,\n";
pluginString += " <" LV2_KXSTUDIO_PROPERTIES__NonAutomable "> ;\n";
pluginString += " <" LV2_KXSTUDIO_PROPERTIES__NonAutomatable "> ;\n";
}

// group


+ 44
- 15
dpf/distrho/src/DistrhoPluginVST2.cpp View File

@@ -15,6 +15,7 @@
*/

#include "DistrhoPluginInternal.hpp"
#include "../DistrhoPluginUtils.hpp"
#include "../extra/ScopedSafeLocale.hpp"

#if DISTRHO_PLUGIN_HAS_UI && ! DISTRHO_PLUGIN_HAS_EMBED_UI
@@ -991,8 +992,8 @@ public:
{
const uint32_t hints(fPlugin.getParameterHints(index));

// must be automable, and not output
if ((hints & kParameterIsAutomable) != 0 && (hints & kParameterIsOutput) == 0)
// must be automatable, and not output
if ((hints & kParameterIsAutomatable) != 0 && (hints & kParameterIsOutput) == 0)
return 1;
}
break;
@@ -1403,9 +1404,10 @@ static intptr_t vst_dispatcherCallback(AEffect* effect, int32_t opcode, int32_t
if (doInternalInit)
{
// set valid but dummy values
d_lastBufferSize = 512;
d_lastSampleRate = 44100.0;
d_lastCanRequestParameterValueChanges = true;
d_nextBufferSize = 512;
d_nextSampleRate = 44100.0;
d_nextPluginIsDummy = true;
d_nextCanRequestParameterValueChanges = true;
}

// Create dummy plugin to get data from
@@ -1414,9 +1416,10 @@ static intptr_t vst_dispatcherCallback(AEffect* effect, int32_t opcode, int32_t
if (doInternalInit)
{
// unset
d_lastBufferSize = 0;
d_lastSampleRate = 0.0;
d_lastCanRequestParameterValueChanges = false;
d_nextBufferSize = 0;
d_nextSampleRate = 0.0;
d_nextPluginIsDummy = false;
d_nextCanRequestParameterValueChanges = false;

*(PluginExporter**)ptr = &plugin;
return 0;
@@ -1437,15 +1440,15 @@ static intptr_t vst_dispatcherCallback(AEffect* effect, int32_t opcode, int32_t

audioMasterCallback audioMaster = (audioMasterCallback)obj->audioMaster;

d_lastBufferSize = audioMaster(effect, audioMasterGetBlockSize, 0, 0, nullptr, 0.0f);
d_lastSampleRate = audioMaster(effect, audioMasterGetSampleRate, 0, 0, nullptr, 0.0f);
d_lastCanRequestParameterValueChanges = true;
d_nextBufferSize = audioMaster(effect, audioMasterGetBlockSize, 0, 0, nullptr, 0.0f);
d_nextSampleRate = audioMaster(effect, audioMasterGetSampleRate, 0, 0, nullptr, 0.0f);
d_nextCanRequestParameterValueChanges = true;

// some hosts are not ready at this point or return 0 buffersize/samplerate
if (d_lastBufferSize == 0)
d_lastBufferSize = 2048;
if (d_lastSampleRate <= 0.0)
d_lastSampleRate = 44100.0;
if (d_nextBufferSize == 0)
d_nextBufferSize = 2048;
if (d_nextSampleRate <= 0.0)
d_nextSampleRate = 44100.0;

obj->plugin = new PluginVst(audioMaster, effect);
return 1;
@@ -1680,6 +1683,32 @@ const AEffect* VSTPluginMain(audioMasterCallback audioMaster)
if (audioMaster(nullptr, audioMasterVersion, 0, 0, nullptr, 0.0f) == 0)
return nullptr;

// find plugin bundle
static String bundlePath;
if (bundlePath.isEmpty())
{
String tmpPath(getBinaryFilename());
tmpPath.truncate(tmpPath.rfind(DISTRHO_OS_SEP));
#ifdef DISTRHO_OS_MAC
if (tmpPath.endsWith("/MacOS"))
{
tmpPath.truncate(tmpPath.rfind('/'));
if (tmpPath.endsWith("/Contents"))
{
tmpPath.truncate(tmpPath.rfind('/'));
bundlePath = tmpPath;
d_nextBundlePath = bundlePath.buffer();
}
}
#else
if (tmpPath.endsWith(".vst"))
{
bundlePath = tmpPath;
d_nextBundlePath = bundlePath.buffer();
}
#endif
}

// first internal init
PluginExporter* plugin = nullptr;
vst_dispatcherCallback(nullptr, -1729, 0xdead, 0xf00d, &plugin, 0.0f);


+ 1609
- 1244
dpf/distrho/src/DistrhoPluginVST3.cpp
File diff suppressed because it is too large
View File


+ 288
- 0
dpf/distrho/src/DistrhoPluginVST3.hpp View File

@@ -0,0 +1,288 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2021 Filipe Coelho <falktx@falktx.com>
*
* Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this
* permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
* TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

#ifndef DISTRHO_PLUGIN_VST3_HPP_INCLUDED
#define DISTRHO_PLUGIN_VST3_HPP_INCLUDED

#include "DistrhoPluginChecks.h"
#include "../DistrhoUtils.hpp"

#include <algorithm>
#include <cmath>

#if DISTRHO_PLUGIN_HAS_UI && ! DISTRHO_PLUGIN_HAS_EMBED_UI
# undef DISTRHO_PLUGIN_HAS_UI
# define DISTRHO_PLUGIN_HAS_UI 0
#endif

#if DISTRHO_PLUGIN_HAS_UI && ! defined(HAVE_DGL) && ! DISTRHO_PLUGIN_HAS_EXTERNAL_UI
# undef DISTRHO_PLUGIN_HAS_UI
# define DISTRHO_PLUGIN_HAS_UI 0
#endif

#if DISTRHO_PLUGIN_HAS_UI == 1 && DISTRHO_PLUGIN_WANT_DIRECT_ACCESS == 0
# define DPF_VST3_USES_SEPARATE_CONTROLLER 1
#else
# define DPF_VST3_USES_SEPARATE_CONTROLLER 0
#endif

// --------------------------------------------------------------------------------------------------------------------

#ifdef DISTRHO_PROPER_CPP11_SUPPORT
# include <atomic>
#else
// quick and dirty std::atomic replacement for the things we need
namespace std {
struct atomic_int {
volatile int value;
explicit atomic_int(volatile int v) noexcept : value(v) {}
int operator++() volatile noexcept { return __atomic_add_fetch(&value, 1, __ATOMIC_RELAXED); }
int operator--() volatile noexcept { return __atomic_sub_fetch(&value, 1, __ATOMIC_RELAXED); }
operator int() volatile noexcept { return __atomic_load_n(&value, __ATOMIC_RELAXED); }
};
};
#endif

// --------------------------------------------------------------------------------------------------------------------

START_NAMESPACE_DISTRHO

// --------------------------------------------------------------------------------------------------------------------

enum Vst3InternalParameters {
#if DPF_VST3_USES_SEPARATE_CONTROLLER
kVst3InternalParameterBufferSize,
kVst3InternalParameterSampleRate,
#endif
#if DISTRHO_PLUGIN_WANT_LATENCY
kVst3InternalParameterLatency,
#endif
#if DISTRHO_PLUGIN_WANT_PROGRAMS
kVst3InternalParameterProgram,
#endif
kVst3InternalParameterBaseCount,
#if DISTRHO_PLUGIN_WANT_MIDI_INPUT
kVst3InternalParameterMidiCC_start = kVst3InternalParameterBaseCount,
kVst3InternalParameterMidiCC_end = kVst3InternalParameterMidiCC_start + 130*16,
kVst3InternalParameterCount = kVst3InternalParameterMidiCC_end
#else
kVst3InternalParameterCount = kVst3InternalParameterBaseCount
#endif
};

#if DPF_VST3_USES_SEPARATE_CONTROLLER || DISTRHO_PLUGIN_WANT_LATENCY || DISTRHO_PLUGIN_WANT_PROGRAMS || DISTRHO_PLUGIN_WANT_MIDI_INPUT
# define DPF_VST3_HAS_INTERNAL_PARAMETERS 1
#else
# define DPF_VST3_HAS_INTERNAL_PARAMETERS 0
#endif

#if DPF_VST3_HAS_INTERNAL_PARAMETERS && DISTRHO_PLUGIN_WANT_MIDI_INPUT && \
!(DPF_VST3_USES_SEPARATE_CONTROLLER || DISTRHO_PLUGIN_WANT_LATENCY || DISTRHO_PLUGIN_WANT_PROGRAMS)
# define DPF_VST3_PURE_MIDI_INTERNAL_PARAMETERS 1
#else
# define DPF_VST3_PURE_MIDI_INTERNAL_PARAMETERS 0
#endif

// --------------------------------------------------------------------------------------------------------------------

static inline
bool strcmp_utf16(const int16_t* const str16, const char* const str8)
{
size_t i = 0;
for (; str8[i] != '\0'; ++i)
{
const uint8_t char8 = static_cast<uint8_t>(str8[i]);

// skip non-ascii chars, unsupported
if (char8 >= 0x80)
return false;

if (str16[i] != char8)
return false;
}

return str16[i] == str8[i];
}

// --------------------------------------------------------------------------------------------------------------------

static inline
size_t strlen_utf16(const int16_t* const str)
{
size_t i = 0;

while (str[i] != 0)
++i;

return i;
}

// --------------------------------------------------------------------------------------------------------------------

static inline
void strncpy(char* const dst, const char* const src, const size_t length)
{
DISTRHO_SAFE_ASSERT_RETURN(length > 0,);

if (const size_t len = std::min(std::strlen(src), length-1U))
{
std::memcpy(dst, src, len);
dst[len] = '\0';
}
else
{
dst[0] = '\0';
}
}

static inline
void strncpy_utf8(char* const dst, const int16_t* const src, const size_t length)
{
DISTRHO_SAFE_ASSERT_RETURN(length > 0,);

if (const size_t len = std::min(strlen_utf16(src), length-1U))
{
for (size_t i=0; i<len; ++i)
{
// skip non-ascii chars, unsupported
if (src[i] >= 0x80)
continue;

dst[i] = src[i];
}
dst[len] = 0;
}
else
{
dst[0] = 0;
}
}

static inline
void strncpy_utf16(int16_t* const dst, const char* const src, const size_t length)
{
DISTRHO_SAFE_ASSERT_RETURN(length > 0,);

if (const size_t len = std::min(std::strlen(src), length-1U))
{
for (size_t i=0; i<len; ++i)
{
// skip non-ascii chars, unsupported
if ((uint8_t)src[i] >= 0x80)
continue;

dst[i] = src[i];
}
dst[len] = 0;
}
else
{
dst[0] = 0;
}
}

// --------------------------------------------------------------------------------------------------------------------

template<typename T>
static void snprintf_t(char* const dst, const T value, const char* const format, const size_t size)
{
DISTRHO_SAFE_ASSERT_RETURN(size > 0,);
std::snprintf(dst, size-1, format, value);
dst[size-1] = '\0';
}

template<typename T>
static void snprintf_utf16_t(int16_t* const dst, const T value, const char* const format, const size_t size)
{
DISTRHO_SAFE_ASSERT_RETURN(size > 0,);

char* const tmpbuf = (char*)std::malloc(size);
DISTRHO_SAFE_ASSERT_RETURN(tmpbuf != nullptr,);

std::snprintf(tmpbuf, size-1, format, value);
tmpbuf[size-1] = '\0';

strncpy_utf16(dst, tmpbuf, size);
std::free(tmpbuf);
}

static inline
void snprintf_u32(char* const dst, const uint32_t value, const size_t size)
{
return snprintf_t<uint32_t>(dst, value, "%u", size);
}

static inline
void snprintf_f32_utf16(int16_t* const dst, const float value, const size_t size)
{
return snprintf_utf16_t<float>(dst, value, "%f", size);
}

static inline
void snprintf_i32_utf16(int16_t* const dst, const int value, const size_t size)
{
return snprintf_utf16_t<int>(dst, value, "%d", size);
}

// --------------------------------------------------------------------------------------------------------------------
// handy way to create a utf16 string from a utf8 one on the current function scope, used for message strings

struct ScopedUTF16String {
int16_t* str;
ScopedUTF16String(const char* const s) noexcept
: str(nullptr)
{
const size_t len = std::strlen(s);
str = static_cast<int16_t*>(std::malloc(sizeof(int16_t) * (len + 1)));
DISTRHO_SAFE_ASSERT_RETURN(str != nullptr,);
strncpy_utf16(str, s, len + 1);
}

~ScopedUTF16String() noexcept
{
std::free(str);
}

operator const int16_t*() const noexcept
{
return str;
}
};

// --------------------------------------------------------------------------------------------------------------------
// handy way to create a utf8 string from a utf16 one on the current function scope (limited to 128 chars)

struct ScopedUTF8String {
char str[128];

ScopedUTF8String(const int16_t* const s) noexcept
{
strncpy_utf8(str, s, 128);
}

operator const char*() const noexcept
{
return str;
}
};

// --------------------------------------------------------------------------------------------------------------------

END_NAMESPACE_DISTRHO

// --------------------------------------------------------------------------------------------------------------------

#endif // DISTRHO_PLUGIN_VST3_HPP_INCLUDED

+ 75
- 12
dpf/distrho/src/DistrhoUI.cpp View File

@@ -15,10 +15,33 @@
*/

#include "src/DistrhoPluginChecks.h"
#include "src/DistrhoDefines.h"

#if !defined(DGL_FILE_BROWSER_DISABLED) && !defined(DISTRHO_OS_MAC)
# define DISTRHO_PUGL_NAMESPACE_MACRO_HELPER(NS, SEP, FUNCTION) NS ## SEP ## FUNCTION
# define DISTRHO_PUGL_NAMESPACE_MACRO(NS, FUNCTION) DISTRHO_PUGL_NAMESPACE_MACRO_HELPER(NS, _, FUNCTION)
# define DISTRHO_FILE_BROWSER_DIALOG_EXTRA_NAMESPACE Plugin
# define x_fib_add_recent DISTRHO_PUGL_NAMESPACE_MACRO(Plugin, x_fib_add_recent)
# define x_fib_cfg_buttons DISTRHO_PUGL_NAMESPACE_MACRO(Plugin, x_fib_cfg_buttons)
# define x_fib_cfg_filter_callback DISTRHO_PUGL_NAMESPACE_MACRO(Plugin, x_fib_cfg_filter_callback)
# define x_fib_close DISTRHO_PUGL_NAMESPACE_MACRO(Plugin, x_fib_close)
# define x_fib_configure DISTRHO_PUGL_NAMESPACE_MACRO(Plugin, x_fib_configure)
# define x_fib_filename DISTRHO_PUGL_NAMESPACE_MACRO(Plugin, x_fib_filename)
# define x_fib_free_recent DISTRHO_PUGL_NAMESPACE_MACRO(Plugin, x_fib_free_recent)
# define x_fib_handle_events DISTRHO_PUGL_NAMESPACE_MACRO(Plugin, x_fib_handle_events)
# define x_fib_load_recent DISTRHO_PUGL_NAMESPACE_MACRO(Plugin, x_fib_load_recent)
# define x_fib_recent_at DISTRHO_PUGL_NAMESPACE_MACRO(Plugin, x_fib_recent_at)
# define x_fib_recent_count DISTRHO_PUGL_NAMESPACE_MACRO(Plugin, x_fib_recent_count)
# define x_fib_recent_file DISTRHO_PUGL_NAMESPACE_MACRO(Plugin, x_fib_recent_file)
# define x_fib_save_recent DISTRHO_PUGL_NAMESPACE_MACRO(Plugin, x_fib_save_recent)
# define x_fib_show DISTRHO_PUGL_NAMESPACE_MACRO(Plugin, x_fib_show)
# define x_fib_status DISTRHO_PUGL_NAMESPACE_MACRO(Plugin, x_fib_status)
# include "../extra/FileBrowserDialog.cpp"
#endif

#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI
# if defined(DISTRHO_OS_WINDOWS)
# define WIN32_LEAN_AND_MEAN
# include <winsock2.h>
# include <windows.h>
# elif defined(HAVE_X11)
# include <X11/Xresource.h>
@@ -32,14 +55,16 @@

START_NAMESPACE_DISTRHO

#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI
/* ------------------------------------------------------------------------------------------------------------
* Static data, see DistrhoUIInternal.hpp */

const char* g_nextBundlePath = nullptr;
#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI
uintptr_t g_nextWindowId = 0;
double g_nextScaleFactor = 1.0;
const char* g_nextBundlePath = nullptr;
#endif

#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI
/* ------------------------------------------------------------------------------------------------------------
* get global scale factor */

@@ -164,21 +189,21 @@ UI::PrivateData::createNextWindow(UI* const ui, const uint width, const uint hei
/* ------------------------------------------------------------------------------------------------------------
* UI */

UI::UI(const uint width, const uint height, const bool automaticallyScale)
UI::UI(const uint width, const uint height, const bool automaticallyScaleAndSetAsMinimumSize)
: UIWidget(UI::PrivateData::createNextWindow(this, width, height)),
uiData(UI::PrivateData::s_nextPrivateData)
{
#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI
if (width > 0 && height > 0)
if (width != 0 && height != 0)
{
Widget::setSize(width, height);

if (automaticallyScale)
setGeometryConstraints(width, height, true, true);
if (automaticallyScaleAndSetAsMinimumSize)
setGeometryConstraints(width, height, true, true, true);
}
#else
// unused
return; (void)automaticallyScale;
(void)automaticallyScaleAndSetAsMinimumSize;
#endif
}

@@ -217,6 +242,11 @@ double UI::getSampleRate() const noexcept
return uiData->sampleRate;
}

const char* UI::getBundlePath() const noexcept
{
return uiData->bundlePath;
}

void UI::editParameter(uint32_t index, bool started)
{
uiData->editParamCallback(index + uiData->parameterOffset, started);
@@ -248,6 +278,19 @@ void UI::sendNote(uint8_t channel, uint8_t note, uint8_t velocity)
}
#endif

#ifndef DGL_FILE_BROWSER_DISABLED
bool UI::openFileBrowser(const FileBrowserOptions& options)
{
# if DISTRHO_PLUGIN_HAS_EXTERNAL_UI
// TODO
return false;
(void)options;
# else
return getWindow().openFileBrowser(options);
# endif
}
#endif

#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
/* ------------------------------------------------------------------------------------------------------------
* Direct DSP access */
@@ -260,7 +303,7 @@ void* UI::getPluginInstancePointer() const noexcept

#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI
/* ------------------------------------------------------------------------------------------------------------
* External UI helpers */
* External UI helpers (static calls) */

const char* UI::getNextBundlePath() noexcept
{
@@ -304,13 +347,13 @@ void UI::uiReshape(uint, uint)
// NOTE this must be the same as Window::onReshape
pData->fallbackOnResize();
}
#endif // !DISTRHO_PLUGIN_HAS_EXTERNAL_UI

# ifndef DGL_FILE_BROWSER_DISABLED
#ifndef DGL_FILE_BROWSER_DISABLED
void UI::uiFileBrowserSelected(const char*)
{
}
# endif
#endif // !DISTRHO_PLUGIN_HAS_EXTERNAL_UI
#endif

/* ------------------------------------------------------------------------------------------------------------
* UI Resize Handling, internal */
@@ -327,9 +370,29 @@ void UI::onResize(const ResizeEvent& ev)
{
UIWidget::onResize(ev);

#ifndef DISTRHO_PLUGIN_TARGET_VST3
if (uiData->initializing)
return;

const uint width = ev.size.getWidth();
const uint height = ev.size.getHeight();
uiData->setSizeCallback(width, height);
#endif
}

// NOTE: only used for VST3
void UI::requestSizeChange(const uint width, const uint height)
{
# ifdef DISTRHO_PLUGIN_TARGET_VST3
if (uiData->initializing)
uiData->window->setSizeForVST3(width, height);
else
uiData->setSizeCallback(width, height);
# else
// unused
(void)width;
(void)height;
# endif
}
#endif



+ 22
- 9
dpf/distrho/src/DistrhoUIInternal.hpp View File

@@ -24,10 +24,10 @@ START_NAMESPACE_DISTRHO
// -----------------------------------------------------------------------
// Static data, see DistrhoUI.cpp

extern const char* g_nextBundlePath;
#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI
extern uintptr_t g_nextWindowId;
extern double g_nextScaleFactor;
extern const char* g_nextBundlePath;
#endif

// -----------------------------------------------------------------------
@@ -77,19 +77,19 @@ public:
uiData->setSizeCallbackFunc = setSizeCall;
uiData->fileRequestCallbackFunc = fileRequestCall;

g_nextBundlePath = bundlePath;
#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI
g_nextWindowId = winId;
g_nextScaleFactor = scaleFactor;
g_nextBundlePath = bundlePath;
#endif
UI::PrivateData::s_nextPrivateData = uiData;

UI* const uiPtr = createUI();

g_nextBundlePath = nullptr;
#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI
g_nextWindowId = 0;
g_nextScaleFactor = 0.0;
g_nextBundlePath = nullptr;
#else
// enter context called in the PluginWindow constructor, see DistrhoUIPrivateData.hpp
uiData->window->leaveContext();
@@ -98,6 +98,7 @@ public:

DISTRHO_SAFE_ASSERT_RETURN(uiPtr != nullptr,);
ui = uiPtr;
uiData->initializing = false;

#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI
// unused
@@ -230,7 +231,14 @@ public:

ui->uiIdle();
}
#else

void showAndFocus()
{
uiData->window->show();
uiData->window->focus();
}
#endif

bool plugin_idle()
{
DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr, false);
@@ -239,7 +247,6 @@ public:
ui->uiIdle();
return ! uiData->app.isQuitting();
}
#endif

void focus()
{
@@ -254,7 +261,7 @@ public:

// -------------------------------------------------------------------

#if defined(DISTRHO_PLUGIN_TARGET_VST3) && (defined(DISTRHO_OS_MAC) || defined(DISTRHO_OS_WINDOWS))
#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI && defined(DISTRHO_PLUGIN_TARGET_VST3) && (defined(DISTRHO_OS_MAC) || defined(DISTRHO_OS_WINDOWS))
void addIdleCallbackForVST3(IdleCallback* const cb, const uint timerFrequencyInMs)
{
uiData->window->addIdleCallback(cb, timerFrequencyInMs);
@@ -279,10 +286,10 @@ public:
#ifdef DISTRHO_PLUGIN_TARGET_VST3
void setWindowSizeForVST3(const uint width, const uint height)
{
# if DISTRHO_PLUGIN_HAS_EXTERNAL_UI
ui->setSize(width, height);
# if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI
uiData->window->setSize(width, height);
// uiData->app.idle();
# else
uiData->window->setSizeForVST3(width, height);
# endif
}
#endif
@@ -320,6 +327,9 @@ public:

const bool ret = ui->onKeyboard(ev);

if (! press)
return ret;

DGL_NAMESPACE::Widget::CharacterInputEvent cev;
cev.mod = mods;
cev.character = key;
@@ -342,6 +352,9 @@ public:

const bool ret = ui->onKeyboard(ev);

if (! press)
return ret;

DGL_NAMESPACE::Widget::CharacterInputEvent cev;
cev.mod = mods;
cev.keycode = keycode;


+ 29
- 9
dpf/distrho/src/DistrhoUIPrivateData.hpp View File

@@ -19,6 +19,10 @@

#include "../DistrhoUI.hpp"

#ifdef DISTRHO_PLUGIN_TARGET_VST3
# include "DistrhoPluginVST3.hpp"
#endif

#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI
# include "../extra/Sleep.hpp"
#else
@@ -33,7 +37,13 @@
# define DISTRHO_UI_IS_STANDALONE 0
#endif

#if defined(DISTRHO_PLUGIN_TARGET_VST2)
#ifdef DISTRHO_PLUGIN_TARGET_VST3
# define DISTRHO_UI_IS_VST3 1
#else
# define DISTRHO_UI_IS_VST3 0
#endif

#ifdef DISTRHO_PLUGIN_TARGET_VST2
# undef DISTRHO_UI_USER_RESIZABLE
# define DISTRHO_UI_USER_RESIZABLE 0
#endif
@@ -175,7 +185,8 @@ public:
const uint width,
const uint height,
const double scaleFactor)
: Window(app, parentWindowHandle, width, height, scaleFactor, DISTRHO_UI_USER_RESIZABLE, false),
: Window(app, parentWindowHandle, width, height, scaleFactor,
DISTRHO_UI_USER_RESIZABLE, DISTRHO_UI_IS_VST3, false),
ui(uiPtr),
initializing(true),
receivedReshapeDuringInit(false)
@@ -220,6 +231,13 @@ public:
puglBackendEnter(pData->view);
}

#ifdef DISTRHO_PLUGIN_TARGET_VST3
void setSizeForVST3(const uint width, const uint height)
{
puglSetWindowSize(pData->view, width, height);
}
#endif

protected:
void onFocus(const bool focus, const DGL_NAMESPACE::CrossingMode mode) override
{
@@ -308,6 +326,10 @@ struct UI::PrivateData {
#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI && !defined(DGL_FILE_BROWSER_DISABLED)
char* uiStateFileKeyRequest;
#endif
char* bundlePath;

// Ignore initial resize events while initializing
bool initializing;

// Callbacks
void* callbacksPtr;
@@ -331,6 +353,8 @@ struct UI::PrivateData {
#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI && !defined(DGL_FILE_BROWSER_DISABLED)
uiStateFileKeyRequest(nullptr),
#endif
bundlePath(nullptr),
initializing(true),
callbacksPtr(nullptr),
editParamCallbackFunc(nullptr),
setParamCallbackFunc(nullptr),
@@ -356,12 +380,7 @@ struct UI::PrivateData {
#endif

#ifdef DISTRHO_PLUGIN_TARGET_VST3
# if DISTRHO_PLUGIN_WANT_MIDI_INPUT
parameterOffset += 130 * 16; // all MIDI CCs plus aftertouch and pitchbend
# endif
# if DISTRHO_PLUGIN_WANT_PROGRAMS
parameterOffset += 1;
# endif
parameterOffset += kVst3InternalParameterCount;
#endif
}

@@ -370,6 +389,7 @@ struct UI::PrivateData {
#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI && !defined(DGL_FILE_BROWSER_DISABLED)
std::free(uiStateFileKeyRequest);
#endif
std::free(bundlePath);
}

void editParamCallback(const uint32_t rindex, const bool started)
@@ -430,7 +450,7 @@ inline bool UI::PrivateData::fileRequestCallback(const char* const key)
snprintf(title, sizeof(title)-1u, DISTRHO_PLUGIN_NAME ": %s", key);
title[sizeof(title)-1u] = '\0';

DGL_NAMESPACE::Window::FileBrowserOptions opts;
FileBrowserOptions opts;
opts.title = title;
return window->openFileBrowser(opts);
#endif


+ 291
- 220
dpf/distrho/src/DistrhoUIVST3.cpp
File diff suppressed because it is too large
View File


+ 138
- 0
dpf/distrho/src/DistrhoUtils.cpp View File

@@ -0,0 +1,138 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2021 Filipe Coelho <falktx@falktx.com>
*
* Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this
* permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
* TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

#ifndef DISTRHO_IS_STANDALONE
# error Wrong build configuration
#endif

#include "../extra/String.hpp"

#ifdef DISTRHO_OS_WINDOWS
# include <windows.h>
#else
# include <dlfcn.h>
# include <limits.h>
# include <stdlib.h>
#endif

#if defined(DISTRHO_OS_WINDOWS) && !DISTRHO_IS_STANDALONE
static HINSTANCE hInstance = nullptr;

DISTRHO_PLUGIN_EXPORT
BOOL WINAPI DllMain(HINSTANCE hInst, DWORD reason, LPVOID)
{
if (reason == DLL_PROCESS_ATTACH)
hInstance = hInst;
return 1;
}
#endif

START_NAMESPACE_DISTRHO

// -----------------------------------------------------------------------

const char* getBinaryFilename()
{
static String filename;

if (filename.isNotEmpty())
return filename;

#ifdef DISTRHO_OS_WINDOWS
# if DISTRHO_IS_STANDALONE
constexpr const HINSTANCE hInstance = nullptr;
# endif
CHAR filenameBuf[MAX_PATH];
filenameBuf[0] = '\0';
GetModuleFileName(hInstance, filenameBuf, sizeof(filenameBuf));
filename = filenameBuf;
#else
Dl_info info;
dladdr((void*)getBinaryFilename, &info);
char filenameBuf[PATH_MAX];
filename = realpath(info.dli_fname, filenameBuf);
#endif

return filename;
}

const char* getPluginFormatName() noexcept
{
#if defined(DISTRHO_PLUGIN_TARGET_CARLA)
return "Carla";
#elif defined(DISTRHO_PLUGIN_TARGET_JACK)
return "JACK/Standalone";
#elif defined(DISTRHO_PLUGIN_TARGET_LADSPA)
return "LADSPA";
#elif defined(DISTRHO_PLUGIN_TARGET_DSSI)
return "DSSI";
#elif defined(DISTRHO_PLUGIN_TARGET_LV2)
return "LV2";
#elif defined(DISTRHO_PLUGIN_TARGET_VST2)
return "VST2";
#elif defined(DISTRHO_PLUGIN_TARGET_VST3)
return "VST3";
#else
return "Unknown";
#endif
}

const char* getResourcePath(const char* const bundlePath) noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(bundlePath != nullptr, nullptr);

#if defined(DISTRHO_PLUGIN_TARGET_JACK) || defined(DISTRHO_PLUGIN_TARGET_VST2)
static String resourcePath;

if (resourcePath.isEmpty())
{
resourcePath = bundlePath;
# ifdef DISTRHO_OS_MAC
resourcePath += "/Contents/Resources";
# else
resourcePath += DISTRHO_OS_SEP_STR "resources";
# endif
}

return resourcePath.buffer();
#elif defined(DISTRHO_PLUGIN_TARGET_LV2)
static String resourcePath;

if (resourcePath.isEmpty())
{
resourcePath = bundlePath;
resourcePath += DISTRHO_OS_SEP_STR "resources";
}

return resourcePath.buffer();
#elif defined(DISTRHO_PLUGIN_TARGET_VST3)
static String resourcePath;

if (resourcePath.isEmpty())
{
resourcePath = bundlePath;
resourcePath += "/Contents/Resources";
}

return resourcePath.buffer();
#endif

return nullptr;
}

// -----------------------------------------------------------------------

END_NAMESPACE_DISTRHO

+ 1
- 1
dpf/distrho/src/jackbridge/JackBridge.cpp View File

@@ -36,7 +36,7 @@
#include "../../extra/LibraryUtils.hpp"

// in case JACK fails, we fallback to RtAudio's native API
#ifdef DISTRHO_PROPER_CPP11_SUPPORT
#if defined(DISTRHO_PROPER_CPP11_SUPPORT) && !defined(DPF_JACK_STANDALONE_SKIP_RTAUDIO_FALLBACK)
# include "RtAudioBridge.hpp"
# ifdef RTAUDIO_API_TYPE
# include "rtaudio/RtAudio.cpp"


+ 0
- 257
dpf/distrho/src/jackbridge/Makefile View File

@@ -1,257 +0,0 @@
#!/usr/bin/make -f
# Makefile for jackbridge #
# ----------------------- #
# Created by falkTX
#

CWD=..
MODULENAME=jackbridge
include ../modules/Makefile.mk

# ---------------------------------------------------------------------------------------------------------------------

BUILD_CXX_FLAGS += $(JACKBRIDGE_FLAGS)
LINK_FLAGS += $(JACKBRIDGE_LIBS)

WINE_32BIT_FLAGS = $(32BIT_FLAGS) -fpermissive
WINE_64BIT_FLAGS = $(64BIT_FLAGS) -fpermissive
WINE_LINK_FLAGS = $(LINK_FLAGS) $(LIBDL_LIBS) -lpthread -lstdc++

ifeq ($(JACKBRIDGE_DIRECT),true)
BUILD_CXX_FLAGS += $(JACK_FLAGS) -DJACKBRIDGE_DIRECT
LINK_FLAGS += $(JACK_LIBS)
endif

ifneq ($(MACOS),true)
WINE_32BIT_FLAGS += -I/usr/include/wine/wine/windows
WINE_32BIT_FLAGS += -I/usr/include/wine-development/windows
WINE_32BIT_FLAGS += -I/opt/wine-devel/include/wine/windows
WINE_32BIT_FLAGS += -L/usr/lib32/wine
WINE_32BIT_FLAGS += -L/usr/lib/wine
WINE_32BIT_FLAGS += -L/usr/lib/i386-linux-gnu/wine
WINE_32BIT_FLAGS += -L/usr/lib/i386-linux-gnu/wine-development
WINE_32BIT_FLAGS += -L/opt/wine-stable/lib
WINE_32BIT_FLAGS += -L/opt/wine-stable/lib/wine
WINE_32BIT_FLAGS += -L/opt/wine-staging/lib
WINE_32BIT_FLAGS += -L/opt/wine-staging/lib/wine

WINE_64BIT_FLAGS += -I/usr/include/wine/wine/windows
WINE_64BIT_FLAGS += -I/usr/include/wine-development/windows
WINE_64BIT_FLAGS += -I/opt/wine-devel/include/wine/windows
WINE_64BIT_FLAGS += -L/usr/lib64/wine
WINE_64BIT_FLAGS += -L/usr/lib/x86_64-linux-gnu/wine
WINE_64BIT_FLAGS += -L/usr/lib/x86_64-linux-gnu/wine-development
WINE_64BIT_FLAGS += -L/opt/wine-stable/lib64
WINE_64BIT_FLAGS += -L/opt/wine-stable/lib64/wine
WINE_64BIT_FLAGS += -L/opt/wine-staging/lib64
WINE_64BIT_FLAGS += -L/opt/wine-staging/lib64/wine

WINE_LINK_FLAGS += -lrt
endif

# ---------------------------------------------------------------------------------------------------------------------

OBJS = $(OBJDIR)/JackBridge1.cpp.o $(OBJDIR)/JackBridge2.cpp.o
OBJS_arm32 = $(OBJDIR)/JackBridge1.cpp.arm32.o $(OBJDIR)/JackBridge2.cpp.arm32.o
OBJS_posix32 = $(OBJDIR)/JackBridge1.cpp.posix32.o $(OBJDIR)/JackBridge2.cpp.posix32.o
OBJS_posix64 = $(OBJDIR)/JackBridge1.cpp.posix64.o $(OBJDIR)/JackBridge2.cpp.posix64.o
OBJS_win32 = $(OBJDIR)/JackBridge1.cpp.win32.o $(OBJDIR)/JackBridge2.cpp.win32.o
OBJS_win64 = $(OBJDIR)/JackBridge1.cpp.win64.o $(OBJDIR)/JackBridge2.cpp.win64.o
OBJS_wine32 = $(OBJDIR)/JackBridge1.cpp.wine32.o $(OBJDIR)/JackBridge2.cpp.wine32.o $(OBJDIR)/JackBridge3.cpp.wine32.o
OBJS_wine64 = $(OBJDIR)/JackBridge1.cpp.wine64.o $(OBJDIR)/JackBridge2.cpp.wine64.o $(OBJDIR)/JackBridge3.cpp.wine64.o

OBJS_posix32e = $(OBJDIR)/JackBridgeExport.cpp.posix32e.o
OBJS_posix64e = $(OBJDIR)/JackBridgeExport.cpp.posix64e.o
OBJS_win64e = $(OBJDIR)/JackBridgeExport.cpp.win64e.o
OBJS_win32e = $(OBJDIR)/JackBridgeExport.cpp.win32e.o

# ---------------------------------------------------------------------------------------------------------------------

all: $(MODULEDIR)/$(MODULENAME).a

ifeq ($(WIN32),true)
posix32:
posix64:
posix32e:
posix64e:
win32: $(MODULEDIR)/$(MODULENAME).win32.a
win64: $(MODULEDIR)/$(MODULENAME).win64.a
win32e: $(MODULEDIR)/$(MODULENAME).win32e.a
win64e: $(MODULEDIR)/$(MODULENAME).win64e.a
wine32:
wine64:
else
arm32: $(MODULEDIR)/$(MODULENAME).arm32.a
posix32: $(MODULEDIR)/$(MODULENAME).posix32.a
posix64: $(MODULEDIR)/$(MODULENAME).posix64.a
posix32e: $(MODULEDIR)/$(MODULENAME).posix32e.a
posix64e: $(MODULEDIR)/$(MODULENAME).posix64e.a
win32:
win64:
win32e:
win64e:
wine32: $(MODULEDIR)/$(MODULENAME)-wine32.dll$(LIB_EXT)
wine64: $(MODULEDIR)/$(MODULENAME)-wine64.dll$(LIB_EXT)
endif

# ---------------------------------------------------------------------------------------------------------------------

clean:
rm -f $(OBJDIR)/*.o $(MODULEDIR)/$(MODULENAME)*.*

debug:
$(MAKE) DEBUG=true

# ---------------------------------------------------------------------------------------------------------------------

$(MODULEDIR)/$(MODULENAME).a: $(OBJS)
-@mkdir -p $(MODULEDIR)
@echo "Creating $(MODULENAME).a"
@rm -f $@
@$(AR) crs $@ $^

$(MODULEDIR)/$(MODULENAME).arm32.a: $(OBJS_arm32)
-@mkdir -p $(MODULEDIR)
@echo "Creating $(MODULENAME).arm32.a"
@rm -f $@
@$(AR) crs $@ $^

$(MODULEDIR)/$(MODULENAME).posix32.a: $(OBJS_posix32)
-@mkdir -p $(MODULEDIR)
@echo "Creating $(MODULENAME).posix32.a"
@rm -f $@
@$(AR) crs $@ $^

$(MODULEDIR)/$(MODULENAME).posix64.a: $(OBJS_posix64)
-@mkdir -p $(MODULEDIR)
@echo "Creating $(MODULENAME).posix64.a"
@rm -f $@
@$(AR) crs $@ $^

$(MODULEDIR)/$(MODULENAME).win32.a: $(OBJS_win32)
-@mkdir -p $(MODULEDIR)
@echo "Creating $(MODULENAME).win32.a"
@rm -f $@
@$(AR) crs $@ $^

$(MODULEDIR)/$(MODULENAME).win64.a: $(OBJS_win64)
-@mkdir -p $(MODULEDIR)
@echo "Creating $(MODULENAME).win64.a"
@rm -f $@
@$(AR) crs $@ $^

# ---------------------------------------------------------------------------------------------------------------------

$(MODULEDIR)/$(MODULENAME).posix32e.a: $(OBJS_posix32e)
-@mkdir -p $(MODULEDIR)
@echo "Creating $(MODULENAME).posix32e.a"
@rm -f $@
@$(AR) crs $@ $^

$(MODULEDIR)/$(MODULENAME).posix64e.a: $(OBJS_posix64e)
-@mkdir -p $(MODULEDIR)
@echo "Creating $(MODULENAME).posix64e.a"
@rm -f $@
@$(AR) crs $@ $^

$(MODULEDIR)/$(MODULENAME).win32e.a: $(OBJS_win32e)
-@mkdir -p $(MODULEDIR)
@echo "Creating $(MODULENAME).win32e.a"
@rm -f $@
@$(AR) crs $@ $^

$(MODULEDIR)/$(MODULENAME).win64e.a: $(OBJS_win64e)
-@mkdir -p $(MODULEDIR)
@echo "Creating $(MODULENAME).win64e.a"
@rm -f $@
@$(AR) crs $@ $^

# ---------------------------------------------------------------------------------------------------------------------

$(MODULEDIR)/$(MODULENAME)-wine32.dll$(LIB_EXT): $(OBJS_wine32) JackBridgeExport.def
-@mkdir -p $(MODULEDIR)
@echo "Linking $(MODULENAME)-wine32.dll$(LIB_EXT)"
@$(WINECC) $^ $(WINE_32BIT_FLAGS) $(WINE_LINK_FLAGS) $(SHARED) -o $@

$(MODULEDIR)/$(MODULENAME)-wine64.dll$(LIB_EXT): $(OBJS_wine64) JackBridgeExport.def
-@mkdir -p $(MODULEDIR)
@echo "Linking $(MODULENAME)-wine64.dll$(LIB_EXT)"
@$(WINECC) $^ $(WINE_64BIT_FLAGS) $(WINE_LINK_FLAGS) $(SHARED) -o $@

# ---------------------------------------------------------------------------------------------------------------------

$(OBJDIR)/JackBridge1.cpp.o: JackBridge1.cpp
-@mkdir -p $(OBJDIR)
@echo "Compiling JackBridge1.cpp"
@$(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@

$(OBJDIR)/JackBridge2.cpp.o: JackBridge2.cpp
-@mkdir -p $(OBJDIR)
@echo "Compiling JackBridge2.cpp"
@$(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@

# ---------------------------------------------------------------------------------------------------------------------

$(OBJDIR)/JackBridgeExport.cpp.%32e.o: JackBridgeExport.cpp
-@mkdir -p $(OBJDIR)
@echo "Compiling $<"
@$(CXX) $< $(BUILD_CXX_FLAGS) $(32BIT_FLAGS) -fpermissive -c -o $@

$(OBJDIR)/JackBridgeExport.cpp.%64e.o: JackBridgeExport.cpp
-@mkdir -p $(OBJDIR)
@echo "Compiling $<"
@$(CXX) $< $(BUILD_CXX_FLAGS) $(64BIT_FLAGS) -fpermissive -c -o $@

# ---------------------------------------------------------------------------------------------------------------------

$(OBJDIR)/%.cpp.arm32.o: %.cpp
-@mkdir -p $(OBJDIR)
@echo "Compiling $< (arm32)"
@$(CXX) $< $(BUILD_CXX_FLAGS) $(ARM32_FLAGS) -c -o $@

$(OBJDIR)/%.cpp.posix32.o: %.cpp
-@mkdir -p $(OBJDIR)
@echo "Compiling $< (posix32)"
@$(CXX) $< $(BUILD_CXX_FLAGS) $(32BIT_FLAGS) -c -o $@

$(OBJDIR)/%.cpp.posix64.o: %.cpp
-@mkdir -p $(OBJDIR)
@echo "Compiling $< (posix64)"
@$(CXX) $< $(BUILD_CXX_FLAGS) $(64BIT_FLAGS) -c -o $@

$(OBJDIR)/%.cpp.win32.o: %.cpp
-@mkdir -p $(OBJDIR)
@echo "Compiling $< (win32)"
@$(CXX) $< $(BUILD_CXX_FLAGS) $(32BIT_FLAGS) -c -o $@

$(OBJDIR)/%.cpp.win64.o: %.cpp
-@mkdir -p $(OBJDIR)
@echo "Compiling $< (win64)"
@$(CXX) $< $(BUILD_CXX_FLAGS) $(64BIT_FLAGS) -c -o $@

$(OBJDIR)/%.cpp.wine32.o: %.cpp
-@mkdir -p $(OBJDIR)
@echo "Compiling $< (wine32)"
@$(WINECC) $< $(BUILD_CXX_FLAGS) $(WINE_32BIT_FLAGS) -c -o $@

$(OBJDIR)/%.cpp.wine64.o: %.cpp
-@mkdir -p $(OBJDIR)
@echo "Compiling $< (wine64)"
@$(WINECC) $< $(BUILD_CXX_FLAGS) $(WINE_64BIT_FLAGS) -c -o $@

# ---------------------------------------------------------------------------------------------------------------------

-include $(OBJS:%.o=%.d)
-include $(OBJS_arm32:%.o=%.d)
-include $(OBJS_posix32:%.o=%.d)
-include $(OBJS_posix32e:%.o=%.d)
-include $(OBJS_posix64:%.o=%.d)
-include $(OBJS_posix64e:%.o=%.d)
-include $(OBJS_win32:%.o=%.d)
-include $(OBJS_win32e:%.o=%.d)
-include $(OBJS_win64:%.o=%.d)
-include $(OBJS_win64e:%.o=%.d)
-include $(OBJS_wine32:%.o=%.d)
-include $(OBJS_wine64:%.o=%.d)

# ---------------------------------------------------------------------------------------------------------------------

+ 11
- 3
dpf/distrho/src/jackbridge/RtAudioBridge.hpp View File

@@ -23,8 +23,8 @@
# define __MACOSX_CORE__
# define RTAUDIO_API_TYPE MACOSX_CORE
#elif defined(DISTRHO_OS_WINDOWS) && !defined(_MSC_VER)
# define __WINDOWS_WASAPI__
# define RTAUDIO_API_TYPE WINDOWS_WASAPI
# define __WINDOWS_DS__
# define RTAUDIO_API_TYPE WINDOWS_DS
#elif defined(HAVE_PULSEAUDIO)
# define __LINUX_PULSE__
# define RTAUDIO_API_TYPE LINUX_PULSE
@@ -90,9 +90,14 @@ struct RtAudioBridge {

uint rtAudioBufferFrames = 512;

#if DISTRHO_PLUGIN_NUM_INPUTS > 0
RtAudio::StreamParameters inParams;
RtAudio::StreamParameters* const inParamsPtr = &inParams;
inParams.deviceId = rtAudio->getDefaultInputDevice();
inParams.nChannels = DISTRHO_PLUGIN_NUM_INPUTS;
#else
RtAudio::StreamParameters* const inParamsPtr = nullptr;
#endif

RtAudio::StreamParameters outParams;
outParams.deviceId = rtAudio->getDefaultOutputDevice();
@@ -102,7 +107,10 @@ struct RtAudioBridge {
opts.flags = RTAUDIO_NONINTERLEAVED | RTAUDIO_MINIMIZE_LATENCY | RTAUDIO_ALSA_USE_DEFAULT;

try {
rtAudio->openStream(&outParams, &inParams, RTAUDIO_FLOAT32, 48000, &rtAudioBufferFrames, RtAudioCallback, this, &opts, nullptr);
rtAudio->openStream(&outParams, inParamsPtr, RTAUDIO_FLOAT32, 48000, &rtAudioBufferFrames, RtAudioCallback, this, &opts, nullptr);
} catch (const RtAudioError& err) {
d_safe_exception(err.getMessage().c_str(), __FILE__, __LINE__);
return false;
} DISTRHO_SAFE_EXCEPTION_RETURN("rtAudio->openStream()", false);

handle = rtAudio;


+ 2
- 2
dpf/distrho/src/lv2/lv2_kxstudio_properties.h View File

@@ -1,6 +1,6 @@
/*
LV2 KXStudio Properties Extension
Copyright 2014 Filipe Coelho <falktx@falktx.com>
Copyright 2014-2021 Filipe Coelho <falktx@falktx.com>

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@@ -26,7 +26,7 @@
#define LV2_KXSTUDIO_PROPERTIES_URI "http://kxstudio.sf.net/ns/lv2ext/props"
#define LV2_KXSTUDIO_PROPERTIES_PREFIX LV2_KXSTUDIO_PROPERTIES_URI "#"

#define LV2_KXSTUDIO_PROPERTIES__NonAutomable LV2_KXSTUDIO_PROPERTIES_PREFIX "NonAutomable"
#define LV2_KXSTUDIO_PROPERTIES__NonAutomatable LV2_KXSTUDIO_PROPERTIES_PREFIX "NonAutomatable"
#define LV2_KXSTUDIO_PROPERTIES__TimePositionTicksPerBeat LV2_KXSTUDIO_PROPERTIES_PREFIX "TimePositionTicksPerBeat"
#define LV2_KXSTUDIO_PROPERTIES__TransientWindowId LV2_KXSTUDIO_PROPERTIES_PREFIX "TransientWindowId"



+ 2
- 1
dpf/distrho/src/lv2/state.h View File

@@ -99,7 +99,8 @@ typedef enum {
LV2_STATE_ERR_BAD_TYPE = 2, /**< Failed due to unsupported type. */
LV2_STATE_ERR_BAD_FLAGS = 3, /**< Failed due to unsupported flags. */
LV2_STATE_ERR_NO_FEATURE = 4, /**< Failed due to missing features. */
LV2_STATE_ERR_NO_PROPERTY = 5 /**< Failed due to missing property. */
LV2_STATE_ERR_NO_PROPERTY = 5, /**< Failed due to missing property. */
LV2_STATE_ERR_NO_SPACE = 6 /**< Failed due to insufficient space. */
} LV2_State_Status;

/**


+ 1
- 0
dpf/distrho/src/travesty/base.h View File

@@ -29,6 +29,7 @@
/**
* cast object into its proper C++ type.
* this is needed because `struct v3_funknown;` on a C++ class does not inherit `v3_funknown`'s fields.
*
* we can use this as a little helper for keeping both C and C++ compatiblity.
* specialized templated calls are defined where required
* (that is, object inherits from something other than `v3_funknown`)


+ 3
- 3
dpf/distrho/src/travesty/edit_controller.h View File

@@ -79,9 +79,9 @@ struct v3_param_info {
struct v3_edit_controller {
struct v3_plugin_base;

v3_result (V3_API* set_component_state)(void* self, struct v3_bstream*);
v3_result (V3_API* set_state)(void* self, struct v3_bstream*);
v3_result (V3_API* get_state)(void* self, struct v3_bstream*);
v3_result (V3_API* set_component_state)(void* self, struct v3_bstream**);
v3_result (V3_API* set_state)(void* self, struct v3_bstream**);
v3_result (V3_API* get_state)(void* self, struct v3_bstream**);
int32_t (V3_API* get_parameter_count)(void* self);
v3_result (V3_API* get_parameter_info)(void* self, int32_t param_idx, struct v3_param_info*);
v3_result (V3_API* get_parameter_string_for_value)(void* self, v3_param_id, double normalised, v3_str_128 output);


+ 1
- 1
dpf/distrho/src/travesty/view.h View File

@@ -176,7 +176,7 @@ struct v3_event_handler_cpp : v3_funknown {
};

struct v3_timer_handler_cpp : v3_funknown {
v3_timer_handler handler;
v3_timer_handler timer;
};

struct v3_run_loop_cpp : v3_funknown {


+ 1
- 0
dpf/dpf.doxygen View File

@@ -242,6 +242,7 @@ SEARCH_INCLUDES = YES
INCLUDE_PATH =
INCLUDE_FILE_PATTERNS =
PREDEFINED = DOXYGEN \
DEBUG \
HAVE_CAIRO=1 \
HAVE_OPENGL=1 \
DISTRHO_PLUGIN_NAME="Plugin Name" \


+ 1
- 0
dpf/tests/FileBrowserDialog.cpp View File

@@ -125,6 +125,7 @@ protected:
repaint();

FileBrowserOptions opts;
// opts.saving = true;
opts.title = "Look at me";
if (! openFileBrowser(opts))
{


+ 3
- 0
dpf/utils/generate-vst-bundles.sh View File

@@ -1,5 +1,8 @@
#!/bin/bash

echo "WARNING: generate-vst-bundles.sh script is no longer used"
exit 0

set -e

if [ -d bin ]; then


+ 4
- 3
dpf/utils/package-osx-bundles.sh View File

@@ -17,9 +17,10 @@ rm -rf vst2
rm -rf vst3

mkdir lv2 vst2 vst3
mv *.lv2 lv2/
mv *.vst vst2/
mv *.vst3 vst3/
cp -RL *.lv2 lv2/
cp -RL *.vst vst2/
cp -RL *.vst3 vst3/
rm -rf *.lv2 *.vst *.vst3

pkgbuild \
--identifier "studio.kx.distrho.plugins.${SNAME}.lv2bundles" \


+ 0
- 1
dpf/utils/plugin.vst/Contents/MacOS/deleteme View File

@@ -1 +0,0 @@

+ 2
- 0
dpf/utils/symbols/shared.def View File

@@ -0,0 +1,2 @@
EXPORTS
createSharedPlugin

+ 1
- 0
dpf/utils/symbols/shared.exp View File

@@ -0,0 +1 @@
_createSharedPlugin

+ 4
- 0
dpf/utils/symbols/shared.version View File

@@ -0,0 +1,4 @@
{
global: createSharedPlugin;
local: *;
};

+ 6
- 6
plugins/3BandEQ/DistrhoPlugin3BandEQ.cpp View File

@@ -45,7 +45,7 @@ void DistrhoPlugin3BandEQ::initParameter(uint32_t index, Parameter& parameter)
switch (index)
{
case paramLow:
parameter.hints = kParameterIsAutomable;
parameter.hints = kParameterIsAutomatable;
parameter.name = "Low";
parameter.symbol = "low";
parameter.unit = "dB";
@@ -55,7 +55,7 @@ void DistrhoPlugin3BandEQ::initParameter(uint32_t index, Parameter& parameter)
break;
case paramMid:
parameter.hints = kParameterIsAutomable;
parameter.hints = kParameterIsAutomatable;
parameter.name = "Mid";
parameter.symbol = "mid";
parameter.unit = "dB";
@@ -65,7 +65,7 @@ void DistrhoPlugin3BandEQ::initParameter(uint32_t index, Parameter& parameter)
break;
case paramHigh:
parameter.hints = kParameterIsAutomable;
parameter.hints = kParameterIsAutomatable;
parameter.name = "High";
parameter.symbol = "high";
parameter.unit = "dB";
@@ -75,7 +75,7 @@ void DistrhoPlugin3BandEQ::initParameter(uint32_t index, Parameter& parameter)
break;
case paramMaster:
parameter.hints = kParameterIsAutomable;
parameter.hints = kParameterIsAutomatable;
parameter.name = "Master";
parameter.symbol = "master";
parameter.unit = "dB";
@@ -85,7 +85,7 @@ void DistrhoPlugin3BandEQ::initParameter(uint32_t index, Parameter& parameter)
break;
case paramLowMidFreq:
parameter.hints = kParameterIsAutomable;
parameter.hints = kParameterIsAutomatable;
parameter.name = "Low-Mid Freq";
parameter.symbol = "low_mid";
parameter.unit = "Hz";
@@ -95,7 +95,7 @@ void DistrhoPlugin3BandEQ::initParameter(uint32_t index, Parameter& parameter)
break;
case paramMidHighFreq:
parameter.hints = kParameterIsAutomable;
parameter.hints = kParameterIsAutomatable;
parameter.name = "Mid-High Freq";
parameter.symbol = "mid_high";
parameter.unit = "Hz";


+ 6
- 6
plugins/3BandSplitter/DistrhoPlugin3BandSplitter.cpp View File

@@ -45,7 +45,7 @@ void DistrhoPlugin3BandSplitter::initParameter(uint32_t index, Parameter& parame
switch (index)
{
case paramLow:
parameter.hints = kParameterIsAutomable;
parameter.hints = kParameterIsAutomatable;
parameter.name = "Low";
parameter.symbol = "low";
parameter.unit = "dB";
@@ -55,7 +55,7 @@ void DistrhoPlugin3BandSplitter::initParameter(uint32_t index, Parameter& parame
break;
case paramMid:
parameter.hints = kParameterIsAutomable;
parameter.hints = kParameterIsAutomatable;
parameter.name = "Mid";
parameter.symbol = "mid";
parameter.unit = "dB";
@@ -65,7 +65,7 @@ void DistrhoPlugin3BandSplitter::initParameter(uint32_t index, Parameter& parame
break;
case paramHigh:
parameter.hints = kParameterIsAutomable;
parameter.hints = kParameterIsAutomatable;
parameter.name = "High";
parameter.symbol = "high";
parameter.unit = "dB";
@@ -75,7 +75,7 @@ void DistrhoPlugin3BandSplitter::initParameter(uint32_t index, Parameter& parame
break;
case paramMaster:
parameter.hints = kParameterIsAutomable;
parameter.hints = kParameterIsAutomatable;
parameter.name = "Master";
parameter.symbol = "master";
parameter.unit = "dB";
@@ -85,7 +85,7 @@ void DistrhoPlugin3BandSplitter::initParameter(uint32_t index, Parameter& parame
break;
case paramLowMidFreq:
parameter.hints = kParameterIsAutomable;
parameter.hints = kParameterIsAutomatable;
parameter.name = "Low-Mid Freq";
parameter.symbol = "low_mid";
parameter.unit = "Hz";
@@ -95,7 +95,7 @@ void DistrhoPlugin3BandSplitter::initParameter(uint32_t index, Parameter& parame
break;
case paramMidHighFreq:
parameter.hints = kParameterIsAutomable;
parameter.hints = kParameterIsAutomatable;
parameter.name = "Mid-High Freq";
parameter.symbol = "mid_high";
parameter.unit = "Hz";


+ 1
- 1
plugins/AmplitudeImposer/DistrhoPluginAmplitudeImposer.cpp View File

@@ -92,7 +92,7 @@ void DistrhoPluginAmplitudeImposer::initAudioPort(bool input, uint32_t index, Au
void DistrhoPluginAmplitudeImposer::initParameter(uint32_t index, Parameter& parameter)
{
parameter.hints = kParameterIsAutomable;
parameter.hints = kParameterIsAutomatable;
parameter.ranges.min = 0.0f;
parameter.ranges.max = 1.0f;


+ 1
- 1
plugins/CycleShifter/DistrhoPluginCycleShifter.cpp View File

@@ -45,7 +45,7 @@ DistrhoPluginCycleShifter::DistrhoPluginCycleShifter()
void DistrhoPluginCycleShifter::initParameter(uint32_t index, Parameter& parameter)
{
parameter.hints = kParameterIsAutomable;
parameter.hints = kParameterIsAutomatable;
parameter.ranges.min = 0.0f;
parameter.ranges.max = 1.0f;


+ 3
- 3
plugins/Kars/DistrhoPluginKars.cpp View File

@@ -44,7 +44,7 @@ void DistrhoPluginKars::initParameter(uint32_t index, Parameter& parameter)
switch (index)
{
case paramSustain:
parameter.hints = kParameterIsAutomable|kParameterIsBoolean;
parameter.hints = kParameterIsAutomatable|kParameterIsBoolean;
parameter.name = "Sustain";
parameter.symbol = "sustain";
parameter.ranges.def = 0.0f;
@@ -52,7 +52,7 @@ void DistrhoPluginKars::initParameter(uint32_t index, Parameter& parameter)
parameter.ranges.max = 1.0f;
break;
case paramRelease:
parameter.hints = kParameterIsAutomable;
parameter.hints = kParameterIsAutomatable;
parameter.name = "Release";
parameter.symbol = "release";
parameter.unit = "s";
@@ -61,7 +61,7 @@ void DistrhoPluginKars::initParameter(uint32_t index, Parameter& parameter)
parameter.ranges.max = 5.0f;
break;
case paramVolume:
parameter.hints = kParameterIsAutomable;
parameter.hints = kParameterIsAutomatable;
parameter.name = "Volume";
parameter.symbol = "volume";
parameter.unit = "%";


+ 9
- 9
plugins/MVerb/DistrhoPluginMVerb.cpp View File

@@ -44,56 +44,56 @@ void DistrhoPluginMVerb::initParameter(uint32_t index, Parameter& parameter)
switch (index)
{
case MVerb<float>::DAMPINGFREQ:
parameter.hints = kParameterIsAutomable;
parameter.hints = kParameterIsAutomatable;
parameter.name = "Damping";
parameter.symbol = "damping";
parameter.ranges.def = 0.5f * 100.0f;
break;
case MVerb<float>::DENSITY:
parameter.hints = kParameterIsAutomable;
parameter.hints = kParameterIsAutomatable;
parameter.name = "Density";
parameter.symbol = "density";
parameter.ranges.def = 0.5f * 100.0f;
break;
case MVerb<float>::BANDWIDTHFREQ:
parameter.hints = kParameterIsAutomable;
parameter.hints = kParameterIsAutomatable;
parameter.name = "Bandwidth";
parameter.symbol = "bandwidth";
parameter.ranges.def = 0.5f * 100.0f;
break;
case MVerb<float>::DECAY:
parameter.hints = kParameterIsAutomable;
parameter.hints = kParameterIsAutomatable;
parameter.name = "Decay";
parameter.symbol = "decay";
parameter.ranges.def = 0.5f * 100.0f;
break;
case MVerb<float>::PREDELAY:
parameter.hints = kParameterIsAutomable;
parameter.hints = kParameterIsAutomatable;
parameter.name = "Predelay";
parameter.symbol = "predelay";
parameter.ranges.def = 0.5f * 100.0f;
break;
case MVerb<float>::SIZE:
parameter.hints = kParameterIsAutomable;
parameter.hints = kParameterIsAutomatable;
parameter.name = "Size";
parameter.symbol = "size";
parameter.ranges.def = 0.75f * 100.0f;
parameter.ranges.min = 0.05f * 100.0f;
break;
case MVerb<float>::GAIN:
parameter.hints = kParameterIsAutomable;
parameter.hints = kParameterIsAutomatable;
parameter.name = "Gain";
parameter.symbol = "gain";
parameter.ranges.def = 1.0f * 100.0f;
break;
case MVerb<float>::MIX:
parameter.hints = kParameterIsAutomable;
parameter.hints = kParameterIsAutomatable;
parameter.name = "Mix";
parameter.symbol = "mix";
parameter.ranges.def = 0.5f * 100.0f;
break;
case MVerb<float>::EARLYMIX:
parameter.hints = kParameterIsAutomable;
parameter.hints = kParameterIsAutomatable;
parameter.name = "Early/Late Mix";
parameter.symbol = "earlymix";
parameter.ranges.def = 0.5f * 100.0f;


+ 1
- 1
plugins/Nekobi/DistrhoPluginInfo.h View File

@@ -22,7 +22,7 @@
#define DISTRHO_PLUGIN_NAME "Nekobi"
#define DISTRHO_PLUGIN_URI "http://distrho.sf.net/plugins/Nekobi"

#define DISTRHO_PLUGIN_HAS_UI 1
#define DISTRHO_PLUGIN_HAS_UI 0
#define DISTRHO_PLUGIN_IS_RT_SAFE 1
#define DISTRHO_PLUGIN_IS_SYNTH 1
#define DISTRHO_PLUGIN_NUM_INPUTS 0


+ 8
- 8
plugins/Nekobi/DistrhoPluginNekobi.cpp View File

@@ -163,7 +163,7 @@ void DistrhoPluginNekobi::initParameter(uint32_t index, Parameter& parameter)
switch (index)
{
case paramWaveform:
parameter.hints = kParameterIsAutomable|kParameterIsInteger;
parameter.hints = kParameterIsAutomatable|kParameterIsInteger;
parameter.name = "Waveform";
parameter.symbol = "waveform";
parameter.ranges.def = 0.0f;
@@ -182,7 +182,7 @@ void DistrhoPluginNekobi::initParameter(uint32_t index, Parameter& parameter)
}
break;
case paramTuning:
parameter.hints = kParameterIsAutomable; // was 0.5 <-> 2.0, log
parameter.hints = kParameterIsAutomatable; // was 0.5 <-> 2.0, log
parameter.name = "Tuning";
parameter.symbol = "tuning";
parameter.ranges.def = 0.0f;
@@ -191,7 +191,7 @@ void DistrhoPluginNekobi::initParameter(uint32_t index, Parameter& parameter)
parameter.midiCC = 75;
break;
case paramCutoff:
parameter.hints = kParameterIsAutomable; // modified x2.5
parameter.hints = kParameterIsAutomatable; // modified x2.5
parameter.name = "Cutoff";
parameter.symbol = "cutoff";
parameter.unit = "%";
@@ -201,7 +201,7 @@ void DistrhoPluginNekobi::initParameter(uint32_t index, Parameter& parameter)
parameter.midiCC = 74;
break;
case paramResonance:
parameter.hints = kParameterIsAutomable; // modified x100
parameter.hints = kParameterIsAutomatable; // modified x100
parameter.name = "VCF Resonance";
parameter.symbol = "resonance";
parameter.unit = "%";
@@ -211,7 +211,7 @@ void DistrhoPluginNekobi::initParameter(uint32_t index, Parameter& parameter)
parameter.midiCC = 71;
break;
case paramEnvMod:
parameter.hints = kParameterIsAutomable; // modified x100
parameter.hints = kParameterIsAutomatable; // modified x100
parameter.name = "Env Mod";
parameter.symbol = "env_mod";
parameter.unit = "%";
@@ -221,7 +221,7 @@ void DistrhoPluginNekobi::initParameter(uint32_t index, Parameter& parameter)
parameter.midiCC = 1; //Mod Wheel
break;
case paramDecay:
parameter.hints = kParameterIsAutomable; // was 0.000009 <-> 0.0005, log
parameter.hints = kParameterIsAutomatable; // was 0.000009 <-> 0.0005, log
parameter.name = "Decay";
parameter.symbol = "decay";
parameter.unit = "%";
@@ -231,7 +231,7 @@ void DistrhoPluginNekobi::initParameter(uint32_t index, Parameter& parameter)
parameter.midiCC = 72;
break;
case paramAccent:
parameter.hints = kParameterIsAutomable; // modified x100
parameter.hints = kParameterIsAutomatable; // modified x100
parameter.name = "Accent";
parameter.symbol = "accent";
parameter.unit = "%";
@@ -241,7 +241,7 @@ void DistrhoPluginNekobi::initParameter(uint32_t index, Parameter& parameter)
parameter.midiCC = 76;
break;
case paramVolume:
parameter.hints = kParameterIsAutomable; // modified x100
parameter.hints = kParameterIsAutomatable; // modified x100
parameter.name = "Volume";
parameter.symbol = "volume";
parameter.unit = "%";


+ 3
- 2
plugins/Nekobi/Makefile View File

@@ -15,7 +15,7 @@ NAME = Nekobi
FILES_DSP = \
DistrhoPluginNekobi.cpp

FILES_UI = \
FILES_UIxx = \
DistrhoArtworkNekobi.cpp \
DistrhoUINekobi.cpp

@@ -28,7 +28,8 @@ include ../../dpf/Makefile.plugins.mk
# --------------------------------------------------------------
# Extra flags

LINK_FLAGS += -lpthread
BASE_FLAGS += -pthread
LINK_FLAGS += -pthread

# --------------------------------------------------------------
# Enable all possible plugin types


+ 2
- 2
plugins/PingPongPan/DistrhoPluginPingPongPan.cpp View File

@@ -43,7 +43,7 @@ void DistrhoPluginPingPongPan::initParameter(uint32_t index, Parameter& paramete
switch (index)
{
case paramFreq:
parameter.hints = kParameterIsAutomable;
parameter.hints = kParameterIsAutomatable;
parameter.name = "Frequency";
parameter.symbol = "freq";
parameter.ranges.def = 50.0f;
@@ -52,7 +52,7 @@ void DistrhoPluginPingPongPan::initParameter(uint32_t index, Parameter& paramete
break;
case paramWidth:
parameter.hints = kParameterIsAutomable;
parameter.hints = kParameterIsAutomatable;
parameter.name = "Width";
parameter.symbol = "width";
parameter.unit = "%";


+ 1
- 1
plugins/SoulForce/DistrhoPluginSoulForce.cpp View File

@@ -44,7 +44,7 @@ DistrhoPluginSoulForce::DistrhoPluginSoulForce()
void DistrhoPluginSoulForce::initParameter(uint32_t index, Parameter& parameter)
{
parameter.hints = kParameterIsAutomable;
parameter.hints = kParameterIsAutomatable;
parameter.ranges.min = 0.0f;
parameter.ranges.max = 1.0f;


+ 0
- 1
plugins/bitcrush/DistrhoPluginMaxGen.cpp View File

@@ -1 +0,0 @@
../common/DistrhoPluginMaxGen.cpp

+ 89
- 0
plugins/bitcrush/DistrhoPluginMaxGen.cpp View File

@@ -0,0 +1,89 @@
/*
* DPF Max Gen
* Copyright (C) 2015 Filipe Coelho <falktx@falktx.com>
*
* Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this
* permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
* TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "DistrhoPluginMaxGen.hpp"
#include "gen_exported.cpp"
namespace gen = gen_exported;
START_NAMESPACE_DISTRHO
// -----------------------------------------------------------------------
DistrhoPluginMaxGen::DistrhoPluginMaxGen()
: Plugin(gen::num_params(), 0, 0), // 0 programs, 0 states
fGenState((CommonState*)gen::create(getSampleRate(), getBufferSize()))
{
gen::reset(fGenState);
}
DistrhoPluginMaxGen::~DistrhoPluginMaxGen()
{
gen::destroy(fGenState);
}
// -----------------------------------------------------------------------
// Init
void DistrhoPluginMaxGen::initParameter(uint32_t index, Parameter& parameter)
{
ParamInfo& info(fGenState->params[index]);
parameter.hints = kParameterIsAutomatable;
parameter.name = info.name;
parameter.symbol = info.name;
parameter.unit = info.units;
parameter.ranges.def = info.defaultvalue;
parameter.ranges.min = info.outputmin;
parameter.ranges.max = info.outputmax;
}
// -----------------------------------------------------------------------
// Internal data
float DistrhoPluginMaxGen::getParameterValue(uint32_t index) const
{
t_param value = 0.0f;
gen::getparameter(fGenState, index, &value);
return value;
}
void DistrhoPluginMaxGen::setParameterValue(uint32_t index, float value)
{
gen::setparameter(fGenState, index, value, nullptr);
}
// -----------------------------------------------------------------------
// Process
void DistrhoPluginMaxGen::run(const float** inputs, float** outputs, uint32_t frames)
{
gen::perform(fGenState, (float**)inputs, gen::gen_kernel_numins, outputs, gen::gen_kernel_numouts, frames);
}
// -----------------------------------------------------------------------
Plugin* createPlugin()
{
return new DistrhoPluginMaxGen();
}
// -----------------------------------------------------------------------
END_NAMESPACE_DISTRHO
#include "gen_dsp/genlib.cpp"

+ 1
- 1
plugins/common/DistrhoPluginMaxGen.cpp View File

@@ -43,7 +43,7 @@ void DistrhoPluginMaxGen::initParameter(uint32_t index, Parameter& parameter)
{
ParamInfo& info(fGenState->params[index]);
parameter.hints = kParameterIsAutomable;
parameter.hints = kParameterIsAutomatable;
parameter.name = info.name;
parameter.symbol = info.name;
parameter.unit = info.units;


+ 0
- 1
plugins/freeverb/DistrhoPluginMaxGen.cpp View File

@@ -1 +0,0 @@
../common/DistrhoPluginMaxGen.cpp

+ 89
- 0
plugins/freeverb/DistrhoPluginMaxGen.cpp View File

@@ -0,0 +1,89 @@
/*
* DPF Max Gen
* Copyright (C) 2015 Filipe Coelho <falktx@falktx.com>
*
* Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this
* permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
* TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "DistrhoPluginMaxGen.hpp"
#include "gen_exported.cpp"
namespace gen = gen_exported;
START_NAMESPACE_DISTRHO
// -----------------------------------------------------------------------
DistrhoPluginMaxGen::DistrhoPluginMaxGen()
: Plugin(gen::num_params(), 0, 0), // 0 programs, 0 states
fGenState((CommonState*)gen::create(getSampleRate(), getBufferSize()))
{
gen::reset(fGenState);
}
DistrhoPluginMaxGen::~DistrhoPluginMaxGen()
{
gen::destroy(fGenState);
}
// -----------------------------------------------------------------------
// Init
void DistrhoPluginMaxGen::initParameter(uint32_t index, Parameter& parameter)
{
ParamInfo& info(fGenState->params[index]);
parameter.hints = kParameterIsAutomatable;
parameter.name = info.name;
parameter.symbol = info.name;
parameter.unit = info.units;
parameter.ranges.def = info.defaultvalue;
parameter.ranges.min = info.outputmin;
parameter.ranges.max = info.outputmax;
}
// -----------------------------------------------------------------------
// Internal data
float DistrhoPluginMaxGen::getParameterValue(uint32_t index) const
{
t_param value = 0.0f;
gen::getparameter(fGenState, index, &value);
return value;
}
void DistrhoPluginMaxGen::setParameterValue(uint32_t index, float value)
{
gen::setparameter(fGenState, index, value, nullptr);
}
// -----------------------------------------------------------------------
// Process
void DistrhoPluginMaxGen::run(const float** inputs, float** outputs, uint32_t frames)
{
gen::perform(fGenState, (float**)inputs, gen::gen_kernel_numins, outputs, gen::gen_kernel_numouts, frames);
}
// -----------------------------------------------------------------------
Plugin* createPlugin()
{
return new DistrhoPluginMaxGen();
}
// -----------------------------------------------------------------------
END_NAMESPACE_DISTRHO
#include "gen_dsp/genlib.cpp"

+ 0
- 1
plugins/gigaverb/DistrhoPluginMaxGen.cpp View File

@@ -1 +0,0 @@
../common/DistrhoPluginMaxGen.cpp

+ 89
- 0
plugins/gigaverb/DistrhoPluginMaxGen.cpp View File

@@ -0,0 +1,89 @@
/*
* DPF Max Gen
* Copyright (C) 2015 Filipe Coelho <falktx@falktx.com>
*
* Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this
* permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
* TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "DistrhoPluginMaxGen.hpp"
#include "gen_exported.cpp"
namespace gen = gen_exported;
START_NAMESPACE_DISTRHO
// -----------------------------------------------------------------------
DistrhoPluginMaxGen::DistrhoPluginMaxGen()
: Plugin(gen::num_params(), 0, 0), // 0 programs, 0 states
fGenState((CommonState*)gen::create(getSampleRate(), getBufferSize()))
{
gen::reset(fGenState);
}
DistrhoPluginMaxGen::~DistrhoPluginMaxGen()
{
gen::destroy(fGenState);
}
// -----------------------------------------------------------------------
// Init
void DistrhoPluginMaxGen::initParameter(uint32_t index, Parameter& parameter)
{
ParamInfo& info(fGenState->params[index]);
parameter.hints = kParameterIsAutomatable;
parameter.name = info.name;
parameter.symbol = info.name;
parameter.unit = info.units;
parameter.ranges.def = info.defaultvalue;
parameter.ranges.min = info.outputmin;
parameter.ranges.max = info.outputmax;
}
// -----------------------------------------------------------------------
// Internal data
float DistrhoPluginMaxGen::getParameterValue(uint32_t index) const
{
t_param value = 0.0f;
gen::getparameter(fGenState, index, &value);
return value;
}
void DistrhoPluginMaxGen::setParameterValue(uint32_t index, float value)
{
gen::setparameter(fGenState, index, value, nullptr);
}
// -----------------------------------------------------------------------
// Process
void DistrhoPluginMaxGen::run(const float** inputs, float** outputs, uint32_t frames)
{
gen::perform(fGenState, (float**)inputs, gen::gen_kernel_numins, outputs, gen::gen_kernel_numouts, frames);
}
// -----------------------------------------------------------------------
Plugin* createPlugin()
{
return new DistrhoPluginMaxGen();
}
// -----------------------------------------------------------------------
END_NAMESPACE_DISTRHO
#include "gen_dsp/genlib.cpp"

+ 5
- 5
plugins/glBars/DistrhoPluginGLBars.cpp View File

@@ -50,7 +50,7 @@ void DistrhoPluginGLBars::initParameter(uint32_t index, Parameter& parameter)
switch (index)
{
case kParameterScale:
parameter.hints = kParameterIsAutomable|kParameterIsLogarithmic;
parameter.hints = kParameterIsAutomatable|kParameterIsLogarithmic;
parameter.name = "Scale";
parameter.symbol = "scale";
parameter.unit = "";
@@ -60,7 +60,7 @@ void DistrhoPluginGLBars::initParameter(uint32_t index, Parameter& parameter)
break;
case kParameterSpeed:
parameter.hints = kParameterIsAutomable|kParameterIsLogarithmic;
parameter.hints = kParameterIsAutomatable|kParameterIsLogarithmic;
parameter.name = "Speed";
parameter.symbol = "speed";
parameter.unit = "";
@@ -70,7 +70,7 @@ void DistrhoPluginGLBars::initParameter(uint32_t index, Parameter& parameter)
break;
case kParameterX:
parameter.hints = kParameterIsAutomable;
parameter.hints = kParameterIsAutomatable;
parameter.name = "X";
parameter.symbol = "x";
parameter.unit = "";
@@ -80,7 +80,7 @@ void DistrhoPluginGLBars::initParameter(uint32_t index, Parameter& parameter)
break;
case kParameterY:
parameter.hints = kParameterIsAutomable;
parameter.hints = kParameterIsAutomatable;
parameter.name = "Y";
parameter.symbol = "y";
parameter.unit = "";
@@ -90,7 +90,7 @@ void DistrhoPluginGLBars::initParameter(uint32_t index, Parameter& parameter)
break;
case kParameterZ:
parameter.hints = kParameterIsAutomable;
parameter.hints = kParameterIsAutomatable;
parameter.name = "Z";
parameter.symbol = "z";
parameter.unit = "";


+ 0
- 1
plugins/pitchshift/DistrhoPluginMaxGen.cpp View File

@@ -1 +0,0 @@
../common/DistrhoPluginMaxGen.cpp

+ 89
- 0
plugins/pitchshift/DistrhoPluginMaxGen.cpp View File

@@ -0,0 +1,89 @@
/*
* DPF Max Gen
* Copyright (C) 2015 Filipe Coelho <falktx@falktx.com>
*
* Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this
* permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
* TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "DistrhoPluginMaxGen.hpp"
#include "gen_exported.cpp"
namespace gen = gen_exported;
START_NAMESPACE_DISTRHO
// -----------------------------------------------------------------------
DistrhoPluginMaxGen::DistrhoPluginMaxGen()
: Plugin(gen::num_params(), 0, 0), // 0 programs, 0 states
fGenState((CommonState*)gen::create(getSampleRate(), getBufferSize()))
{
gen::reset(fGenState);
}
DistrhoPluginMaxGen::~DistrhoPluginMaxGen()
{
gen::destroy(fGenState);
}
// -----------------------------------------------------------------------
// Init
void DistrhoPluginMaxGen::initParameter(uint32_t index, Parameter& parameter)
{
ParamInfo& info(fGenState->params[index]);
parameter.hints = kParameterIsAutomatable;
parameter.name = info.name;
parameter.symbol = info.name;
parameter.unit = info.units;
parameter.ranges.def = info.defaultvalue;
parameter.ranges.min = info.outputmin;
parameter.ranges.max = info.outputmax;
}
// -----------------------------------------------------------------------
// Internal data
float DistrhoPluginMaxGen::getParameterValue(uint32_t index) const
{
t_param value = 0.0f;
gen::getparameter(fGenState, index, &value);
return value;
}
void DistrhoPluginMaxGen::setParameterValue(uint32_t index, float value)
{
gen::setparameter(fGenState, index, value, nullptr);
}
// -----------------------------------------------------------------------
// Process
void DistrhoPluginMaxGen::run(const float** inputs, float** outputs, uint32_t frames)
{
gen::perform(fGenState, (float**)inputs, gen::gen_kernel_numins, outputs, gen::gen_kernel_numouts, frames);
}
// -----------------------------------------------------------------------
Plugin* createPlugin()
{
return new DistrhoPluginMaxGen();
}
// -----------------------------------------------------------------------
END_NAMESPACE_DISTRHO
#include "gen_dsp/genlib.cpp"

Loading…
Cancel
Save