Browse Source

Update dpf and plugins to it

tags/v1.5
falkTX 2 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