Browse Source

Update DPF and plugins

Fixes #14
tags/v1.3
falkTX 5 years ago
parent
commit
0530b4309b
56 changed files with 2116 additions and 768 deletions
  1. +7
    -7
      Makefile
  2. +84
    -29
      dpf/Makefile.base.mk
  3. +56
    -16
      dpf/Makefile.plugins.mk
  4. +1
    -1
      dpf/README.md
  5. +6
    -84
      dpf/dgl/Base.hpp
  6. +40
    -0
      dpf/dgl/Cairo.hpp
  7. +1
    -1
      dpf/dgl/Color.hpp
  8. +13
    -10
      dpf/dgl/Geometry.hpp
  9. +30
    -52
      dpf/dgl/Image.hpp
  10. +125
    -0
      dpf/dgl/ImageBase.hpp
  11. +87
    -19
      dpf/dgl/Makefile
  12. +2
    -1
      dpf/dgl/NanoVG.hpp
  13. +121
    -0
      dpf/dgl/OpenGL.hpp
  14. +1
    -1
      dpf/dgl/Widget.hpp
  15. +6
    -2
      dpf/dgl/Window.hpp
  16. +27
    -0
      dpf/dgl/src/Cairo.cpp
  17. +29
    -19
      dpf/dgl/src/Color.cpp
  18. +13
    -89
      dpf/dgl/src/Geometry.cpp
  19. +29
    -73
      dpf/dgl/src/Image.cpp
  20. +106
    -0
      dpf/dgl/src/ImageBase.cpp
  21. +5
    -1
      dpf/dgl/src/ImageWidgets.cpp
  22. +20
    -1
      dpf/dgl/src/NanoVG.cpp
  23. +157
    -0
      dpf/dgl/src/OpenGL.cpp
  24. +1
    -1
      dpf/dgl/src/Widget.cpp
  25. +107
    -0
      dpf/dgl/src/WidgetPrivateData.cpp
  26. +3
    -56
      dpf/dgl/src/WidgetPrivateData.hpp
  27. +54
    -25
      dpf/dgl/src/Window.cpp
  28. +43
    -40
      dpf/dgl/src/pugl/pugl.h
  29. +3
    -0
      dpf/dgl/src/pugl/pugl_internal.h
  30. +497
    -129
      dpf/dgl/src/pugl/pugl_osx.m
  31. +104
    -19
      dpf/dgl/src/pugl/pugl_win.cpp
  32. +133
    -8
      dpf/dgl/src/pugl/pugl_x11.c
  33. +15
    -1
      dpf/distrho/DistrhoInfo.hpp
  34. +1
    -1
      dpf/distrho/DistrhoPlugin.hpp
  35. +21
    -3
      dpf/distrho/DistrhoUI.hpp
  36. +2
    -2
      dpf/distrho/src/DistrhoPluginChecks.h
  37. +11
    -1
      dpf/distrho/src/DistrhoPluginJack.cpp
  38. +1
    -1
      dpf/distrho/src/DistrhoPluginLV2.cpp
  39. +1
    -1
      dpf/distrho/src/DistrhoPluginLV2export.cpp
  40. +10
    -4
      dpf/distrho/src/DistrhoPluginVST.cpp
  41. +21
    -3
      dpf/distrho/src/DistrhoUI.cpp
  42. +21
    -16
      dpf/distrho/src/DistrhoUIInternal.hpp
  43. +16
    -8
      dpf/distrho/src/DistrhoUILV2.cpp
  44. +1
    -0
      dpf/distrho/src/lv2/ui.h
  45. +2
    -1
      dpf/dpf.doxygen
  46. +1
    -1
      dpf/utils/lv2-ttl-generator/GNUmakefile
  47. +15
    -15
      dpf/utils/res2c.py
  48. +56
    -19
      plugins/Kars/DistrhoPluginKars.cpp
  49. +2
    -2
      plugins/Kars/DistrhoPluginKars.hpp
  50. +1
    -0
      plugins/bitcrush/Makefile
  51. +1
    -0
      plugins/freeverb/Makefile
  52. +1
    -0
      plugins/gigaverb/Makefile
  53. +1
    -1
      plugins/glBars/DistrhoUIGLBars.cpp
  54. +1
    -2
      plugins/glBars/DistrhoUIGLBars.hpp
  55. +2
    -2
      plugins/glBars/glBars.hpp
  56. +1
    -0
      plugins/pitchshift/Makefile

+ 7
- 7
Makefile View File

@@ -20,7 +20,7 @@ HAVE_PROJM = $(shell pkg-config --exists libprojectM && echo true)
# --------------------------------------------------------------

dgl:
ifeq ($(HAVE_DGL),true)
ifeq ($(HAVE_CAIRO_OR_OPENGL),true)
$(MAKE) -C dpf/dgl
endif

@@ -50,7 +50,7 @@ plugins: dgl
$(MAKE) all -C plugins/gigaverb
$(MAKE) all -C plugins/pitchshift

ifeq ($(HAVE_DGL),true)
ifeq ($(HAVE_CAIRO_OR_OPENGL),true)
# glBars (needs OpenGL)
$(MAKE) all -C plugins/glBars

@@ -58,7 +58,7 @@ ifeq ($(HAVE_PROJM),true)
# ProM (needs OpenGL + ProjectM)
$(MAKE) all -C plugins/ProM
endif # HAVE_PROJM
endif # HAVE_DGL
endif # HAVE_CAIRO_OR_OPENGL

ifneq ($(CROSS_COMPILING),true)
gen: plugins dpf/utils/lv2_ttl_generator
@@ -123,9 +123,9 @@ install:
install -m 644 bin/*-dssi.* $(DESTDIR)$(PREFIX)/lib/dssi/
install -m 644 bin/*-vst.* $(DESTDIR)$(PREFIX)/lib/vst/

ifeq ($(HAVE_DGL),true)
ifeq ($(HAVE_CAIRO_OR_OPENGL),true)
cp -r bin/*-dssi $(DESTDIR)$(PREFIX)/lib/dssi/
endif # HAVE_DGL
endif # HAVE_CAIRO_OR_OPENGL
cp -r bin/*.lv2 $(DESTDIR)$(PREFIX)/lib/lv2/

ifeq ($(HAVE_JACK),true)
@@ -142,12 +142,12 @@ ifeq ($(HAVE_JACK),true)
install -m 755 bin/MaFreeverb $(DESTDIR)$(PREFIX)/bin/
install -m 755 bin/MaGigaverb $(DESTDIR)$(PREFIX)/bin/
install -m 755 bin/MaPitchshift $(DESTDIR)$(PREFIX)/bin/
ifeq ($(HAVE_DGL),true)
ifeq ($(HAVE_CAIRO_OR_OPENGL),true)
install -m 755 bin/glBars $(DESTDIR)$(PREFIX)/bin/
ifeq ($(HAVE_PROJM),true)
install -m 755 bin/ProM $(DESTDIR)$(PREFIX)/bin/
endif # HAVE_PROJM
endif # HAVE_DGL
endif # HAVE_CAIRO_OR_OPENGL
endif # HAVE_JACK

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


+ 84
- 29
dpf/Makefile.base.mk View File

@@ -16,7 +16,7 @@ ifneq ($(HAIKU),true)
ifneq ($(HURD),true)
ifneq ($(LINUX),true)
ifneq ($(MACOS),true)
ifneq ($(WIN32),true)
ifneq ($(WINDOWS),true)

TARGET_MACHINE := $(shell $(CC) -dumpmachine)
ifneq (,$(findstring bsd,$(TARGET_MACHINE)))
@@ -35,7 +35,7 @@ ifneq (,$(findstring apple,$(TARGET_MACHINE)))
MACOS=true
endif
ifneq (,$(findstring mingw,$(TARGET_MACHINE)))
WIN32=true
WINDOWS=true
endif

endif
@@ -45,6 +45,16 @@ endif
endif
endif

# ---------------------------------------------------------------------------------------------------------------------
# Set PKG_CONFIG (can be overridden by environment variable)

ifeq ($(WINDOWS),true)
# Build statically on Windows by default
PKG_CONFIG ?= pkg-config --static
else
PKG_CONFIG ?= pkg-config
endif

# ---------------------------------------------------------------------------------------------------------------------
# Set LINUX_OR_MACOS

@@ -57,14 +67,20 @@ LINUX_OR_MACOS=true
endif

# ---------------------------------------------------------------------------------------------------------------------
# Set MACOS_OR_WIN32
# Set MACOS_OR_WINDOWS and HAIKU_OR_MACOS_OR_WINDOWS

ifeq ($(HAIKU),true)
HAIKU_OR_MACOS_OR_WINDOWS=true
endif

ifeq ($(MACOS),true)
MACOS_OR_WIN32=true
MACOS_OR_WINDOWS=true
HAIKU_OR_MACOS_OR_WINDOWS=true
endif

ifeq ($(WIN32),true)
MACOS_OR_WIN32=true
ifeq ($(WINDOWS),true)
MACOS_OR_WINDOWS=true
HAIKU_OR_MACOS_OR_WINDOWS=true
endif

# ---------------------------------------------------------------------------------------------------------------------
@@ -108,10 +124,12 @@ ifeq ($(NOOPT),true)
BASE_OPTS = -O2 -ffast-math -fdata-sections -ffunction-sections
endif

ifeq ($(WIN32),true)
ifeq ($(WINDOWS),true)
# mingw has issues with this specific optimization
# See https://github.com/falkTX/Carla/issues/696
BASE_OPTS += -fno-rerun-cse-after-loop
# See https://github.com/falkTX/Carla/issues/855
BASE_OPTS += -mstackrealign
ifeq ($(BUILDING_FOR_WINDOWS),true)
BASE_FLAGS += -DBUILDING_CARLA_FOR_WINDOWS
endif
@@ -141,7 +159,7 @@ ifeq ($(MACOS_OLD),true)
BUILD_CXX_FLAGS = $(BASE_FLAGS) $(CXXFLAGS) -DHAVE_CPP11_SUPPORT=0
endif

ifeq ($(WIN32),true)
ifeq ($(WINDOWS),true)
# Always build statically on windows
LINK_FLAGS += -static
endif
@@ -170,44 +188,81 @@ CXXFLAGS += -Weffc++ -Wnon-virtual-dtor -Woverloaded-virtual
endif

# ---------------------------------------------------------------------------------------------------------------------
# Check for optional libs
# Check for required libraries

ifeq ($(MACOS_OR_WIN32),true)
HAVE_DGL = true
HAVE_CAIRO = $(shell $(PKG_CONFIG) --exists cairo && echo true)

ifeq ($(HAIKU_OR_MACOS_OR_WINDOWS),true)
HAVE_OPENGL = true
else
HAVE_DGL = $(shell pkg-config --exists gl x11 && echo true)
HAVE_JACK = $(shell pkg-config --exists jack && echo true)
HAVE_LIBLO = $(shell pkg-config --exists liblo && echo true)
HAVE_OPENGL = $(shell $(PKG_CONFIG) --exists gl && echo true)
HAVE_X11 = $(shell $(PKG_CONFIG) --exists x11 && echo true)
endif

ifneq ($(HAVE_DGL),true)
$(error DGL missing 22)
# ---------------------------------------------------------------------------------------------------------------------
# Check for optional libraries

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

# ---------------------------------------------------------------------------------------------------------------------
# Set Generic DGL stuff

ifeq ($(MACOS),true)
DGL_SYSTEM_LIBS += -framework Cocoa
endif

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

ifneq ($(HAIKU_OR_MACOS_OR_WINDOWS),true)
DGL_FLAGS += $(shell $(PKG_CONFIG) --cflags x11)
DGL_SYSTEM_LIBS += $(shell $(PKG_CONFIG) --libs x11)
endif

# ---------------------------------------------------------------------------------------------------------------------
# Set Cairo specific stuff

ifeq ($(HAVE_CAIRO),true)

DGL_FLAGS += -DHAVE_CAIRO

CAIRO_FLAGS = $(shell $(PKG_CONFIG) --cflags cairo)
CAIRO_LIBS = $(shell $(PKG_CONFIG) --libs cairo)

HAVE_CAIRO_OR_OPENGL = true

endif

# ---------------------------------------------------------------------------------------------------------------------
# Set libs stuff
# Set OpenGL specific stuff

ifeq ($(HAVE_OPENGL),true)

ifeq ($(HAVE_DGL),true)
DGL_FLAGS += -DHAVE_OPENGL

ifeq ($(MACOS),true)
DGL_LIBS = -framework OpenGL -framework Cocoa
OPENGL_LIBS = -framework OpenGL
endif

ifeq ($(WIN32),true)
DGL_LIBS = -lopengl32 -lgdi32
ifeq ($(WINDOWS),true)
OPENGL_LIBS = -lopengl32
endif

ifneq ($(MACOS_OR_WIN32),true)
DGL_FLAGS = $(shell pkg-config --cflags gl x11)
DGL_LIBS = $(shell pkg-config --libs gl x11)
ifneq ($(MACOS_OR_WINDOWS),true)
OPENGL_FLAGS = $(shell $(PKG_CONFIG) --cflags gl x11)
OPENGL_LIBS = $(shell $(PKG_CONFIG) --libs gl x11)
endif

endif # HAVE_DGL
HAVE_CAIRO_OR_OPENGL = true

endif

# ---------------------------------------------------------------------------------------------------------------------
# Set app extension

ifeq ($(WIN32),true)
ifeq ($(WINDOWS),true)
APP_EXT = .exe
endif

@@ -220,17 +275,17 @@ ifeq ($(MACOS),true)
LIB_EXT = .dylib
endif

ifeq ($(WIN32),true)
ifeq ($(WINDOWS),true)
LIB_EXT = .dll
endif

# ---------------------------------------------------------------------------------------------------------------------
# Set shared library CLI arg

SHARED = -shared

ifeq ($(MACOS),true)
SHARED = -dynamiclib
else
SHARED = -shared
endif

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

+ 56
- 16
dpf/Makefile.plugins.mk View File

@@ -15,10 +15,6 @@ endif

include $(DPF_PATH)/Makefile.base.mk

ifeq ($(FILES_UI),)
HAVE_DGL = false
endif

# ---------------------------------------------------------------------------------------------------------------------
# Basic setup

@@ -28,8 +24,12 @@ BUILD_DIR = ../../build/$(NAME)
BUILD_C_FLAGS += -I.
BUILD_CXX_FLAGS += -I. -I$(DPF_PATH)/distrho -I$(DPF_PATH)/dgl

ifeq ($(HAVE_DGL),true)
BASE_FLAGS += -DHAVE_DGL
ifeq ($(HAVE_CAIRO),true)
DGL_FLAGS += -DHAVE_CAIRO
endif

ifeq ($(HAVE_OPENGL),true)
DGL_FLAGS += -DHAVE_OPENGL
endif

ifeq ($(HAVE_JACK),true)
@@ -59,7 +59,39 @@ lv2_ui = $(TARGET_DIR)/$(NAME).lv2/$(NAME)_ui$(LIB_EXT)
vst = $(TARGET_DIR)/$(NAME)-vst$(LIB_EXT)

# ---------------------------------------------------------------------------------------------------------------------
# Handle plugins without UI
# Handle UI stuff, disable UI support automatically

ifeq ($(FILES_UI),)
UI_TYPE = none
endif

ifeq ($(UI_TYPE),)
UI_TYPE = opengl
endif

ifeq ($(UI_TYPE),cairo)
ifeq ($(HAVE_CAIRO),true)
DGL_FLAGS += $(CAIRO_FLAGS) -DDGL_CAIRO
DGL_LIBS += $(CAIRO_LIBS)
DGL_LIB = $(DPF_PATH)/build/libdgl-cairo.a
HAVE_DGL = true
else
HAVE_DGL = false
endif
endif

ifeq ($(UI_TYPE),opengl)
ifeq ($(HAVE_OPENGL),true)
DGL_FLAGS += $(OPENGL_FLAGS) -DDGL_OPENGL
DGL_LIBS += $(OPENGL_LIBS)
DGL_LIB = $(DPF_PATH)/build/libdgl-opengl.a
HAVE_DGL = true
else
HAVE_DGL = false
endif
endif

DGL_LIBS += $(DGL_SYSTEM_LIBS)

ifneq ($(HAVE_DGL),true)
dssi_ui =
@@ -68,6 +100,9 @@ DGL_LIBS =
OBJS_UI =
endif

# TODO split dsp and ui object build flags
BASE_FLAGS += $(DGL_FLAGS)

# ---------------------------------------------------------------------------------------------------------------------
# all needs to be first

@@ -81,6 +116,11 @@ $(BUILD_DIR)/%.c.o: %.c
@echo "Compiling $<"
@$(CC) $< $(BUILD_C_FLAGS) -c -o $@

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

$(BUILD_DIR)/%.cpp.o: %.cpp
-@mkdir -p "$(shell dirname $(BUILD_DIR)/$<)"
@echo "Compiling $<"
@@ -105,12 +145,12 @@ $(BUILD_DIR)/DistrhoUIMain_%.cpp.o: $(DPF_PATH)/distrho/DistrhoUIMain.cpp
$(BUILD_DIR)/DistrhoPluginMain_JACK.cpp.o: $(DPF_PATH)/distrho/DistrhoPluginMain.cpp
-@mkdir -p $(BUILD_DIR)
@echo "Compiling DistrhoPluginMain.cpp (JACK)"
@$(CXX) $< $(BUILD_CXX_FLAGS) $(shell pkg-config --cflags jack) -DDISTRHO_PLUGIN_TARGET_JACK -c -o $@
@$(CXX) $< $(BUILD_CXX_FLAGS) $(shell $(PKG_CONFIG) --cflags jack) -DDISTRHO_PLUGIN_TARGET_JACK -c -o $@

$(BUILD_DIR)/DistrhoUIMain_DSSI.cpp.o: $(DPF_PATH)/distrho/DistrhoUIMain.cpp
-@mkdir -p $(BUILD_DIR)
@echo "Compiling DistrhoUIMain.cpp (DSSI)"
@$(CXX) $< $(BUILD_CXX_FLAGS) $(shell pkg-config --cflags liblo) -DDISTRHO_PLUGIN_TARGET_DSSI -c -o $@
@$(CXX) $< $(BUILD_CXX_FLAGS) $(shell $(PKG_CONFIG) --cflags liblo) -DDISTRHO_PLUGIN_TARGET_DSSI -c -o $@

# ---------------------------------------------------------------------------------------------------------------------
# JACK
@@ -118,13 +158,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 $(DPF_PATH)/build/libdgl.a
$(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)"
@$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(DGL_LIBS) $(shell pkg-config --libs jack) -o $@
@$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(DGL_LIBS) $(shell $(PKG_CONFIG) --libs jack) -o $@

# ---------------------------------------------------------------------------------------------------------------------
# LADSPA
@@ -148,10 +188,10 @@ $(dssi_dsp): $(OBJS_DSP) $(BUILD_DIR)/DistrhoPluginMain_DSSI.cpp.o
@echo "Creating DSSI plugin library for $(NAME)"
@$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(SHARED) -o $@

$(dssi_ui): $(OBJS_UI) $(BUILD_DIR)/DistrhoUIMain_DSSI.cpp.o $(DPF_PATH)/build/libdgl.a
$(dssi_ui): $(OBJS_UI) $(BUILD_DIR)/DistrhoUIMain_DSSI.cpp.o $(DGL_LIB)
-@mkdir -p $(shell dirname $@)
@echo "Creating DSSI UI for $(NAME)"
@$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(DGL_LIBS) $(shell pkg-config --libs liblo) -o $@
@$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(DGL_LIBS) $(shell $(PKG_CONFIG) --libs liblo) -o $@

# ---------------------------------------------------------------------------------------------------------------------
# LV2
@@ -160,7 +200,7 @@ lv2: $(lv2)
lv2_dsp: $(lv2_dsp)
lv2_sep: $(lv2_dsp) $(lv2_ui)

$(lv2): $(OBJS_DSP) $(OBJS_UI) $(BUILD_DIR)/DistrhoPluginMain_LV2.cpp.o $(BUILD_DIR)/DistrhoUIMain_LV2.cpp.o $(DPF_PATH)/build/libdgl.a
$(lv2): $(OBJS_DSP) $(OBJS_UI) $(BUILD_DIR)/DistrhoPluginMain_LV2.cpp.o $(BUILD_DIR)/DistrhoUIMain_LV2.cpp.o $(DGL_LIB)
-@mkdir -p $(shell dirname $@)
@echo "Creating LV2 plugin for $(NAME)"
@$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(DGL_LIBS) $(SHARED) -o $@
@@ -170,7 +210,7 @@ $(lv2_dsp): $(OBJS_DSP) $(BUILD_DIR)/DistrhoPluginMain_LV2.cpp.o
@echo "Creating LV2 plugin library for $(NAME)"
@$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(SHARED) -o $@

$(lv2_ui): $(OBJS_UI) $(BUILD_DIR)/DistrhoUIMain_LV2.cpp.o $(DPF_PATH)/build/libdgl.a
$(lv2_ui): $(OBJS_UI) $(BUILD_DIR)/DistrhoUIMain_LV2.cpp.o $(DGL_LIB)
-@mkdir -p $(shell dirname $@)
@echo "Creating LV2 plugin UI for $(NAME)"
@$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(DGL_LIBS) $(SHARED) -o $@
@@ -181,7 +221,7 @@ $(lv2_ui): $(OBJS_UI) $(BUILD_DIR)/DistrhoUIMain_LV2.cpp.o $(DPF_PATH)/build/lib
vst: $(vst)

ifeq ($(HAVE_DGL),true)
$(vst): $(OBJS_DSP) $(OBJS_UI) $(BUILD_DIR)/DistrhoPluginMain_VST.cpp.o $(BUILD_DIR)/DistrhoUIMain_VST.cpp.o $(DPF_PATH)/build/libdgl.a
$(vst): $(OBJS_DSP) $(OBJS_UI) $(BUILD_DIR)/DistrhoPluginMain_VST.cpp.o $(BUILD_DIR)/DistrhoUIMain_VST.cpp.o $(DGL_LIB)
else
$(vst): $(OBJS_DSP) $(BUILD_DIR)/DistrhoPluginMain_VST.cpp.o
endif


+ 1
- 1
dpf/README.md View File

@@ -28,7 +28,7 @@ List of plugins made with DPF:<br/>
- [Juice Plugins](https://github.com/DISTRHO/JuicePlugins) (work in progress)
- [ZamAudio Suite](https://github.com/zamaudio/zam-plugins)
- [DragonFly-Reverb](https://github.com/michaelwillis/dragonfly-reverb)
- [Wolf-Shaper](https://github.com/pdesaulniers/wolf-shaper)
- [Wolf-Shaper](https://github.com/pdesaulniers/wolf-shaper) and [Wolf-Spectrum](https://github.com/pdesaulniers/wolf-spectrum)
- [YK Chorus](https://github.com/SpotlightKid/ykchorus)




+ 6
- 84
dpf/dgl/Base.hpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2016 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2019 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
@@ -31,89 +31,6 @@
#define END_NAMESPACE_DGL }
#define USE_NAMESPACE_DGL using namespace DGL_NAMESPACE;

#ifdef DISTRHO_OS_WINDOWS
// -----------------------------------------------------------------------
// Fix OpenGL includes for Windows, based on glfw code

#ifndef APIENTRY
# define APIENTRY __stdcall
#endif // APIENTRY

/* We need WINGDIAPI defined */
#ifndef WINGDIAPI
# if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__POCC__)
# define WINGDIAPI __declspec(dllimport)
# elif defined(__LCC__)
# define WINGDIAPI __stdcall
# else
# define WINGDIAPI extern
# endif
# define DGL_WINGDIAPI_DEFINED
#endif // WINGDIAPI

/* Some <GL/glu.h> files also need CALLBACK defined */
#ifndef CALLBACK
# if defined(_MSC_VER)
# if (defined(_M_MRX000) || defined(_M_IX86) || defined(_M_ALPHA) || defined(_M_PPC)) && !defined(MIDL_PASS)
# define CALLBACK __stdcall
# else
# define CALLBACK
# endif
# else
# define CALLBACK __stdcall
# endif
# define DGL_CALLBACK_DEFINED
#endif // CALLBACK

/* Most GL/glu.h variants on Windows need wchar_t */
#include <cstddef>

#endif // DISTRHO_OS_WINDOWS

// -----------------------------------------------------------------------
// OpenGL includes

#ifdef DISTRHO_OS_MAC
# include <OpenGL/gl.h>
#else
# ifndef DISTRHO_OS_WINDOWS
# define GL_GLEXT_PROTOTYPES
# endif
# include <GL/gl.h>
# include <GL/glext.h>
#endif

// -----------------------------------------------------------------------
// Missing OpenGL defines

#if defined(GL_BGR_EXT) && ! defined(GL_BGR)
# define GL_BGR GL_BGR_EXT
#endif

#if defined(GL_BGRA_EXT) && ! defined(GL_BGRA)
# define GL_BGRA GL_BGRA_EXT
#endif

#ifndef GL_CLAMP_TO_BORDER
# define GL_CLAMP_TO_BORDER 0x812D
#endif

#ifdef DISTRHO_OS_WINDOWS
// -----------------------------------------------------------------------
// Fix OpenGL includes for Windows, based on glfw code

#ifdef DGL_WINGDIAPI_DEFINED
# undef WINGDIAPI
# undef DGL_WINGDIAPI_DEFINED
#endif

#ifdef DGL_CALLBACK_DEFINED
# undef CALLBACK
# undef DGL_CALLBACK_DEFINED
#endif

#endif // DISTRHO_OS_WINDOWS

START_NAMESPACE_DGL

// -----------------------------------------------------------------------
@@ -172,6 +89,11 @@ enum Key {
// -----------------------------------------------------------------------
// Base DGL classes

/**
Graphics context, definition depends on build type.
*/
struct GraphicsContext;

/**
Idle callback.
*/


+ 40
- 0
dpf/dgl/Cairo.hpp View File

@@ -0,0 +1,40 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2019 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 DGL_CAIRO_HPP_INCLUDED
#define DGL_CAIRO_HPP_INCLUDED

#include "Base.hpp"

#include <cairo/cairo.h>

START_NAMESPACE_DGL

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

/**
Graphics context.
*/
struct GraphicsContext
{
cairo_t* cairo; // FIXME proper name..
};

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

END_NAMESPACE_DGL

#endif

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

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2016 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2019 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


+ 13
- 10
dpf/dgl/Geometry.hpp View File

@@ -482,6 +482,7 @@ private:
// cached values
float fTheta, fCos, fSin;

/** @internal */
void _draw(const bool outline);
};

@@ -516,16 +517,6 @@ public:
*/
Triangle(const Triangle<T>& tri) noexcept;

/**
Draw this triangle using the current OpenGL state.
*/
void draw();

/**
Draw lines (outline of this triangle) using the current OpenGL state.
*/
void drawOutline();

/**
Return true if triangle is null (all its points are equal).
An null triangle is also invalid.
@@ -549,6 +540,16 @@ public:
*/
bool isInvalid() const noexcept;

/**
Draw this triangle using the current OpenGL state.
*/
void draw();

/**
Draw lines (outline of this triangle) using the current OpenGL state.
*/
void drawOutline();

Triangle<T>& operator=(const Triangle<T>& tri) noexcept;
bool operator==(const Triangle<T>& tri) const noexcept;
bool operator!=(const Triangle<T>& tri) const noexcept;
@@ -556,6 +557,7 @@ public:
private:
Point<T> fPos1, fPos2, fPos3;

/** @internal */
void _draw(const bool outline);
};

@@ -740,6 +742,7 @@ private:
Point<T> fPos;
Size<T> fSize;

/** @internal */
void _draw(const bool outline);
};



+ 30
- 52
dpf/dgl/Image.hpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2016 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2019 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
@@ -17,14 +17,15 @@
#ifndef DGL_IMAGE_HPP_INCLUDED
#define DGL_IMAGE_HPP_INCLUDED

#include "Geometry.hpp"
#include "ImageBase.hpp"
#include "OpenGL.hpp"

START_NAMESPACE_DGL

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

/**
Base DGL Image class.
OpenGL Image class.

This is an Image class that handles raw image data in pixels.
You can init the image data on the contructor or later on by calling loadFromMemory().
@@ -35,7 +36,7 @@ START_NAMESPACE_DGL

Images are drawn on screen via 2D textures.
*/
class Image
class Image : public ImageBase
{
public:
/**
@@ -47,13 +48,20 @@ public:
Constructor using raw image data.
@note @a rawData must remain valid for the lifetime of this Image.
*/
Image(const char* const rawData, const uint width, const uint height, const GLenum format = GL_BGRA, const GLenum type = GL_UNSIGNED_BYTE);
Image(const char* const rawData,
const uint width,
const uint height,
const GLenum format = GL_BGRA,
const GLenum type = GL_UNSIGNED_BYTE);

/**
Constructor using raw image data.
@note @a rawData must remain valid for the lifetime of this Image.
*/
Image(const char* const rawData, const Size<uint>& size, const GLenum format = GL_BGRA, const GLenum type = GL_UNSIGNED_BYTE);
Image(const char* const rawData,
const Size<uint>& size,
const GLenum format = GL_BGRA,
const GLenum type = GL_UNSIGNED_BYTE);

/**
Constructor using another image data.
@@ -63,44 +71,26 @@ public:
/**
Destructor.
*/
~Image();
~Image() override;

/**
Load image data from memory.
@note @a rawData must remain valid for the lifetime of this Image.
*/
void loadFromMemory(const char* const rawData, const uint width, const uint height, const GLenum format = GL_BGRA, const GLenum type = GL_UNSIGNED_BYTE) noexcept;
void loadFromMemory(const char* const rawData,
const uint width,
const uint height,
const GLenum format = GL_BGRA,
const GLenum type = GL_UNSIGNED_BYTE) noexcept;

/**
Load image data from memory.
@note @a rawData must remain valid for the lifetime of this Image.
*/
void loadFromMemory(const char* const rawData, const Size<uint>& size, const GLenum format = GL_BGRA, const GLenum type = GL_UNSIGNED_BYTE) noexcept;

/**
Check if this image is valid.
*/
bool isValid() const noexcept;

/**
Get width.
*/
uint getWidth() const noexcept;

/**
Get height.
*/
uint getHeight() const noexcept;

/**
Get size.
*/
const Size<uint>& getSize() const noexcept;

/**
Get the raw image data.
*/
const char* getRawData() const noexcept;
void loadFromMemory(const char* const rawData,
const Size<uint>& size,
const GLenum format = GL_BGRA,
const GLenum type = GL_UNSIGNED_BYTE) noexcept;

/**
Get the image format.
@@ -113,27 +103,15 @@ public:
GLenum getType() const noexcept;

/**
Draw this image at (0, 0) point.
*/
void draw();

/**
Draw this image at (x, y) point.
TODO document this.
*/
void drawAt(const int x, const int y);

/**
Draw this image at position @a pos.
*/
void drawAt(const Point<int>& pos);

Image& operator=(const Image& image) noexcept;
bool operator==(const Image& image) const noexcept;
bool operator!=(const Image& image) const noexcept;

protected:
/** @internal */
void _drawAt(const Point<int>& pos) override;

private:
const char* fRawData;
Size<uint> fSize;
GLenum fFormat;
GLenum fType;
GLuint fTextureId;
@@ -144,4 +122,4 @@ private:

END_NAMESPACE_DGL

#endif // DGL_IMAGE_HPP_INCLUDED
#endif

+ 125
- 0
dpf/dgl/ImageBase.hpp View File

@@ -0,0 +1,125 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2019 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 DGL_IMAGE_BASE_HPP_INCLUDED
#define DGL_IMAGE_BASE_HPP_INCLUDED

#include "Geometry.hpp"

START_NAMESPACE_DGL

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

/**
Base DGL Image class.

This is an Image class that handles raw image data in pixels.
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
*/
class ImageBase
{
protected:
/**
Constructor for a null Image.
*/
ImageBase();

/**
Constructor using raw image data.
@note @a rawData must remain valid for the lifetime of this Image.
*/
ImageBase(const char* const rawData, const uint width, const uint height);

/**
Constructor using raw image data.
@note @a rawData must remain valid for the lifetime of this Image.
*/
ImageBase(const char* const rawData, const Size<uint>& size);

/**
Constructor using another image data.
*/
ImageBase(const ImageBase& image);

public:
/**
Destructor.
*/
virtual ~ImageBase();

/**
Check if this image is valid.
*/
bool isValid() const noexcept;

/**
Get width.
*/
uint getWidth() const noexcept;

/**
Get height.
*/
uint getHeight() const noexcept;

/**
Get size.
*/
const Size<uint>& getSize() const noexcept;

/**
Get the raw image data.
*/
const char* getRawData() const noexcept;

/**
Draw this image at (0, 0) point.
*/
void draw();

/**
Draw this image at (x, y) point.
*/
void drawAt(const int x, const int y);

/**
Draw this image at position @a pos.
*/
void drawAt(const Point<int>& pos);

/**
TODO document this.
*/
ImageBase& operator=(const ImageBase& image) noexcept;
bool operator==(const ImageBase& image) const noexcept;
bool operator!=(const ImageBase& image) const noexcept;

protected:
/** @internal */
virtual void _drawAt(const Point<int>& pos) = 0;

const char* fRawData;
Size<uint> fSize;
};

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

END_NAMESPACE_DGL

#endif // DGL_IMAGE_HPP_INCLUDED

+ 87
- 19
dpf/dgl/Makefile View File

@@ -9,7 +9,7 @@ include ../Makefile.base.mk
# ---------------------------------------------------------------------------------------------------------------------

BUILD_C_FLAGS += $(DGL_FLAGS) -I. -Isrc
BUILD_CXX_FLAGS += $(DGL_FLAGS) -I. -Isrc
BUILD_CXX_FLAGS += $(DGL_FLAGS) -I. -Isrc -DDONT_SET_USING_DGL_NAMESPACE -Wno-unused-parameter
LINK_FLAGS += $(DGL_LIBS)

# ifneq ($(MACOS_OLD),true)
@@ -19,36 +19,78 @@ LINK_FLAGS += $(DGL_LIBS)

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

OBJS = \
OBJS_common = \
../build/dgl/Application.cpp.o \
../build/dgl/Color.cpp.o \
../build/dgl/Geometry.cpp.o \
../build/dgl/Image.cpp.o \
../build/dgl/ImageWidgets.cpp.o \
../build/dgl/NanoVG.cpp.o \
../build/dgl/ImageBase.cpp.o \
../build/dgl/Resources.cpp.o \
../build/dgl/Widget.cpp.o

# TODO: ImageWidgets.cpp

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

OBJS_cairo = $(OBJS_common) \
../build/dgl/Cairo.cpp.cairo.o \
../build/dgl/WidgetPrivateData.cpp.cairo.o

ifeq ($(MACOS),true)
OBJS_cairo += ../build/dgl/Window.mm.cairo.o
else
OBJS_cairo += ../build/dgl/Window.cpp.cairo.o
endif

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

OBJS_opengl = $(OBJS_common) \
../build/dgl/OpenGL.cpp.opengl.o \
../build/dgl/Image.cpp.opengl.o \
../build/dgl/ImageWidgets.cpp.opengl.o \
../build/dgl/NanoVG.cpp.opengl.o \
../build/dgl/WidgetPrivateData.cpp.opengl.o

ifeq ($(MACOS),true)
OBJS += ../build/dgl/Window.mm.o
OBJS_opengl += ../build/dgl/Window.mm.opengl.o
else
OBJS += ../build/dgl/Window.cpp.o
OBJS_opengl += ../build/dgl/Window.cpp.opengl.o
endif

TARGET = ../build/libdgl.a
# ---------------------------------------------------------------------------------------------------------------------

ifeq ($(HAVE_CAIRO),true)
TARGETS += ../build/libdgl-cairo.a
endif

ifeq ($(HAVE_OPENGL),true)
TARGETS += ../build/libdgl-opengl.a
# Compat name, to be removed soon
TARGETS += ../build/libdgl.a
endif

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

all: $(TARGET)
all: $(TARGETS)

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

../build/libdgl.a: $(OBJS)
../build/libdgl-cairo.a: $(OBJS_cairo)
-@mkdir -p ../build
@echo "Creating libdgl-cairo.a"
@rm -f $@
@$(AR) crs $@ $^

../build/libdgl-opengl.a: $(OBJS_opengl)
-@mkdir -p ../build
@echo "Creating libdgl.a"
@echo "Creating libdgl-opengl.a"
@rm -f $@
@$(AR) crs $@ $^

# Compat name, to be removed soon
../build/libdgl.a: ../build/libdgl-opengl.a
@echo "Symlinking libdgl.a"
@ln -sf $< $@

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

../build/dgl/%.c.o: src/%.c
@@ -61,26 +103,52 @@ all: $(TARGET)
@echo "Compiling $<"
@$(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@

../build/dgl/Window.cpp.o: src/Window.cpp src/sofd/* src/pugl/*
# ---------------------------------------------------------------------------------------------------------------------

../build/dgl/%.cpp.cairo.o: src/%.cpp
-@mkdir -p ../build/dgl
@echo "Compiling $<"
@$(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@
@echo "Compiling $< (Cairo variant)"
@$(CXX) $< $(BUILD_CXX_FLAGS) -DDGL_CAIRO -c -o $@

../build/dgl/Window.mm.o: src/Window.cpp src/sofd/* src/pugl/*
../build/dgl/Window.cpp.cairo.o: src/Window.cpp src/sofd/* src/pugl/*
-@mkdir -p ../build/dgl
@echo "Compiling $<"
@$(CXX) $< $(BUILD_CXX_FLAGS) -ObjC++ -c -o $@
@echo "Compiling $< (Cairo variant)"
@$(CXX) $< $(BUILD_CXX_FLAGS) -DDGL_CAIRO -c -o $@

../build/dgl/Window.mm.cairo.o: src/Window.cpp src/sofd/* src/pugl/*
-@mkdir -p ../build/dgl
@echo "Compiling $< (Cairo variant)"
@$(CXX) $< $(BUILD_CXX_FLAGS) -DDGL_CAIRO -ObjC++ -c -o $@

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

../build/dgl/%.cpp.opengl.o: src/%.cpp
-@mkdir -p ../build/dgl
@echo "Compiling $< (OpenGL variant)"
@$(CXX) $< $(BUILD_CXX_FLAGS) -DDGL_OPENGL -c -o $@

../build/dgl/Window.cpp.opengl.o: src/Window.cpp src/sofd/* src/pugl/*
-@mkdir -p ../build/dgl
@echo "Compiling $< (OpenGL variant)"
@$(CXX) $< $(BUILD_CXX_FLAGS) -DDGL_OPENGL -c -o $@

../build/dgl/Window.mm.opengl.o: src/Window.cpp src/sofd/* src/pugl/*
-@mkdir -p ../build/dgl
@echo "Compiling $< (OpenGL variant)"
@$(CXX) $< $(BUILD_CXX_FLAGS) -DDGL_OPENGL -ObjC++ -c -o $@

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

clean:
rm -rf ../build/dgl ../build/libdgl.*
rm -rf ../build/dgl ../build/libdgl*.*

debug:
$(MAKE) DEBUG=true

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

-include $(OBJS:%.o=%.d)
-include $(OBJS_common:%.o=%.d)
-include $(OBJS_cairo:%.o=%.d)
-include $(OBJS_opengl:%.o=%.d)

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

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

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2016 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2019 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
@@ -18,6 +18,7 @@
#define DGL_NANO_WIDGET_HPP_INCLUDED

#include "Color.hpp"
#include "OpenGL.hpp"
#include "Widget.hpp"

#ifndef DGL_NO_SHARED_RESOURCES


+ 121
- 0
dpf/dgl/OpenGL.hpp View File

@@ -0,0 +1,121 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2019 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 DGL_OPENGL_HPP_INCLUDED
#define DGL_OPENGL_HPP_INCLUDED

#include "ImageBase.hpp"

// -----------------------------------------------------------------------
// Fix OpenGL includes for Windows, based on glfw code (part 1)

#undef DGL_CALLBACK_DEFINED
#undef DGL_WINGDIAPI_DEFINED

#ifdef DISTRHO_OS_WINDOWS

#ifndef APIENTRY
# define APIENTRY __stdcall
#endif // APIENTRY

/* We need WINGDIAPI defined */
#ifndef WINGDIAPI
# if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__POCC__)
# define WINGDIAPI __declspec(dllimport)
# elif defined(__LCC__)
# define WINGDIAPI __stdcall
# else
# define WINGDIAPI extern
# endif
# define DGL_WINGDIAPI_DEFINED
#endif // WINGDIAPI

/* Some <GL/glu.h> files also need CALLBACK defined */
#ifndef CALLBACK
# if defined(_MSC_VER)
# if (defined(_M_MRX000) || defined(_M_IX86) || defined(_M_ALPHA) || defined(_M_PPC)) && !defined(MIDL_PASS)
# define CALLBACK __stdcall
# else
# define CALLBACK
# endif
# else
# define CALLBACK __stdcall
# endif
# define DGL_CALLBACK_DEFINED
#endif // CALLBACK

/* Most GL/glu.h variants on Windows need wchar_t */
#include <cstddef>

#endif // DISTRHO_OS_WINDOWS

// -----------------------------------------------------------------------
// OpenGL includes

#ifdef DISTRHO_OS_MAC
# include <OpenGL/gl.h>
#else
# ifndef DISTRHO_OS_WINDOWS
# define GL_GLEXT_PROTOTYPES
# endif
# include <GL/gl.h>
# include <GL/glext.h>
#endif

// -----------------------------------------------------------------------
// Missing OpenGL defines

#if defined(GL_BGR_EXT) && !defined(GL_BGR)
# define GL_BGR GL_BGR_EXT
#endif

#if defined(GL_BGRA_EXT) && !defined(GL_BGRA)
# define GL_BGRA GL_BGRA_EXT
#endif

#ifndef GL_CLAMP_TO_BORDER
# define GL_CLAMP_TO_BORDER 0x812D
#endif

// -----------------------------------------------------------------------
// Fix OpenGL includes for Windows, based on glfw code (part 2)

#ifdef DGL_CALLBACK_DEFINED
# undef CALLBACK
# undef DGL_CALLBACK_DEFINED
#endif

#ifdef DGL_WINGDIAPI_DEFINED
# undef WINGDIAPI
# undef DGL_WINGDIAPI_DEFINED
#endif

START_NAMESPACE_DGL

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

/**
Graphics context.
*/
struct GraphicsContext
{
};

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

END_NAMESPACE_DGL

#endif

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

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2016 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2019 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


+ 6
- 2
dpf/dgl/Window.hpp View File

@@ -77,7 +77,7 @@ public:

explicit Window(Application& app);
explicit Window(Application& app, Window& parent);
explicit Window(Application& app, intptr_t parentId, bool resizable);
explicit Window(Application& app, intptr_t parentId, double scaling, bool resizable);
virtual ~Window();

void show();
@@ -113,7 +113,6 @@ public:
void setTransientWinId(uintptr_t winId);

double getScaling() const noexcept;
void setScaling(double scaling) noexcept;

bool getIgnoringKeyRepeat() const noexcept;
void setIgnoringKeyRepeat(bool ignore) noexcept;
@@ -121,6 +120,8 @@ public:
Application& getApp() const noexcept;
intptr_t getWindowId() const noexcept;

const GraphicsContext& getGraphicsContext() const noexcept;

void addIdleCallback(IdleCallback* const callback);
void removeIdleCallback(IdleCallback* const callback);

@@ -134,6 +135,9 @@ protected:
virtual void fileBrowserSelected(const char* filename);
#endif

// internal
void _setAutoScaling(double scaling) noexcept;

private:
struct PrivateData;
PrivateData* const pData;


+ 27
- 0
dpf/dgl/src/Cairo.cpp View File

@@ -0,0 +1,27 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2019 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 "../Base.hpp"

START_NAMESPACE_DGL

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

// nothing here yet

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

END_NAMESPACE_DGL

+ 29
- 19
dpf/dgl/src/Color.cpp View File

@@ -16,12 +16,27 @@

#include "../Color.hpp"

#ifndef HAVE_DCAIRO
#include "nanovg/nanovg.h"
#endif

START_NAMESPACE_DGL

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

static float computeHue(float h, float m1, float m2)
{
if (h < 0) h += 1;
if (h > 1) h -= 1;
if (h < 1.0f/6.0f)
return m1 + (m2 - m1) * h * 6.0f;
if (h < 3.0f/6.0f)
return m2;
if (h < 4.0f/6.0f)
return m1 + (m2 - m1) * (2.0f/3.0f - h) * 6.0f;
return m1;
}

static void fixRange(float& value)
{
/**/ if (value < 0.0f)
@@ -105,7 +120,20 @@ Color::Color(const Color& color1, const Color& color2, float u) noexcept

Color Color::fromHSL(float hue, float saturation, float lightness, float alpha)
{
return nvgHSLA(hue, saturation, lightness, static_cast<uchar>(getFixedRange(alpha)*255.0f));
float m1, m2;
Color col;
hue = fmodf(hue, 1.0f);
if (hue < 0.0f) hue += 1.0f;
fixRange(saturation);
fixRange(lightness);
m2 = lightness <= 0.5f ? (lightness * (1 + saturation)) : (lightness + saturation - lightness * saturation);
m1 = 2 * lightness - m2;
col.red = computeHue(hue + 1.0f/3.0f, m1, m2);
col.green = computeHue(hue, m1, m2);
col.blue = computeHue(hue - 1.0f/3.0f, m1, m2);
col.alpha = alpha;
col.fixBounds();
return col;
}

Color Color::fromHTML(const char* rgb, float alpha)
@@ -224,22 +252,4 @@ void Color::fixBounds() noexcept

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

Color::Color(const NVGcolor& c) noexcept
: red(c.r), green(c.g), blue(c.b), alpha(c.a)
{
fixBounds();
}

Color::operator NVGcolor() const noexcept
{
NVGcolor nc;
nc.r = red;
nc.g = green;
nc.b = blue;
nc.a = alpha;
return nc;
}

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

END_NAMESPACE_DGL

+ 13
- 89
dpf/dgl/src/Geometry.cpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2016 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2019 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
@@ -441,21 +441,6 @@ void Line<T>::moveBy(const Point<T>& pos) noexcept
fPosEnd.moveBy(pos);
}

template<typename T>
void Line<T>::draw()
{
DISTRHO_SAFE_ASSERT_RETURN(fPosStart != fPosEnd,);

glBegin(GL_LINES);

{
glVertex2d(fPosStart.fX, fPosStart.fY);
glVertex2d(fPosEnd.fX, fPosEnd.fY);
}

glEnd();
}

template<typename T>
bool Line<T>::isNull() const noexcept
{
@@ -650,27 +635,6 @@ bool Circle<T>::operator!=(const Circle<T>& cir) const noexcept
return (fPos != cir.fPos || d_isNotEqual(fSize, cir.fSize) || fNumSegments != cir.fNumSegments);
}

template<typename T>
void Circle<T>::_draw(const bool outline)
{
DISTRHO_SAFE_ASSERT_RETURN(fNumSegments >= 3 && fSize > 0.0f,);

double t, x = fSize, y = 0.0;

glBegin(outline ? GL_LINE_LOOP : GL_POLYGON);

for (uint i=0; i<fNumSegments; ++i)
{
glVertex2d(x + fPos.fX, y + fPos.fY);

t = x;
x = fCos * x - fSin * y;
y = fSin * t + fCos * y;
}

glEnd();
}

// -----------------------------------------------------------------------
// Triangle

@@ -698,18 +662,6 @@ Triangle<T>::Triangle(const Triangle<T>& tri) noexcept
fPos2(tri.fPos2),
fPos3(tri.fPos3) {}

template<typename T>
void Triangle<T>::draw()
{
_draw(false);
}

template<typename T>
void Triangle<T>::drawOutline()
{
_draw(true);
}

template<typename T>
bool Triangle<T>::isNull() const noexcept
{
@@ -734,6 +686,18 @@ bool Triangle<T>::isInvalid() const noexcept
return fPos1 == fPos2 || fPos1 == fPos3;
}

template<typename T>
void Triangle<T>::draw()
{
_draw(false);
}

template<typename T>
void Triangle<T>::drawOutline()
{
_draw(true);
}

template<typename T>
Triangle<T>& Triangle<T>::operator=(const Triangle<T>& tri) noexcept
{
@@ -755,22 +719,6 @@ bool Triangle<T>::operator!=(const Triangle<T>& tri) const noexcept
return (fPos1 != tri.fPos1 || fPos2 != tri.fPos2 || fPos3 != tri.fPos3);
}

template<typename T>
void Triangle<T>::_draw(const bool outline)
{
DISTRHO_SAFE_ASSERT_RETURN(fPos1 != fPos2 && fPos1 != fPos3,);

glBegin(outline ? GL_LINE_LOOP : GL_TRIANGLES);

{
glVertex2d(fPos1.fX, fPos1.fY);
glVertex2d(fPos2.fX, fPos2.fY);
glVertex2d(fPos3.fX, fPos3.fY);
}

glEnd();
}

// -----------------------------------------------------------------------
// Rectangle

@@ -998,30 +946,6 @@ bool Rectangle<T>::operator!=(const Rectangle<T>& rect) const noexcept
return (fPos != rect.fPos || fSize != rect.fSize);
}

template<typename T>
void Rectangle<T>::_draw(const bool outline)
{
DISTRHO_SAFE_ASSERT_RETURN(fSize.isValid(),);

glBegin(outline ? GL_LINE_LOOP : GL_QUADS);

{
glTexCoord2f(0.0f, 0.0f);
glVertex2d(fPos.fX, fPos.fY);

glTexCoord2f(1.0f, 0.0f);
glVertex2d(fPos.fX+fSize.fWidth, fPos.fY);

glTexCoord2f(1.0f, 1.0f);
glVertex2d(fPos.fX+fSize.fWidth, fPos.fY+fSize.fHeight);

glTexCoord2f(0.0f, 1.0f);
glVertex2d(fPos.fX, fPos.fY+fSize.fHeight);
}

glEnd();
}

// -----------------------------------------------------------------------
// Possible template data types



+ 29
- 73
dpf/dgl/src/Image.cpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2016 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2019 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
@@ -21,8 +21,7 @@ START_NAMESPACE_DGL
// -----------------------------------------------------------------------

Image::Image()
: fRawData(nullptr),
fSize(0, 0),
: ImageBase(),
fFormat(0),
fType(0),
fTextureId(0),
@@ -31,20 +30,18 @@ Image::Image()
glGenTextures(1, &fTextureId);
}

Image::Image(const char* const rawData, const uint width, const uint height, const GLenum format, const GLenum type)
: fRawData(rawData),
fSize(width, height),
fFormat(format),
fType(type),
Image::Image(const Image& image)
: ImageBase(image),
fFormat(image.fFormat),
fType(image.fType),
fTextureId(0),
fIsReady(false)
{
glGenTextures(1, &fTextureId);
}

Image::Image(const char* const rawData, const Size<uint>& size, const GLenum format, const GLenum type)
: fRawData(rawData),
fSize(size),
Image::Image(const char* const rawData, const uint width, const uint height, const GLenum format, const GLenum type)
: ImageBase(rawData, width, height),
fFormat(format),
fType(type),
fTextureId(0),
@@ -53,11 +50,10 @@ Image::Image(const char* const rawData, const Size<uint>& size, const GLenum for
glGenTextures(1, &fTextureId);
}

Image::Image(const Image& image)
: fRawData(image.fRawData),
fSize(image.fSize),
fFormat(image.fFormat),
fType(image.fType),
Image::Image(const char* const rawData, const Size<uint>& size, const GLenum format, const GLenum type)
: ImageBase(rawData, size),
fFormat(format),
fType(type),
fTextureId(0),
fIsReady(false)
{
@@ -75,12 +71,19 @@ Image::~Image()
}
}

void Image::loadFromMemory(const char* const rawData, const uint width, const uint height, const GLenum format, const GLenum type) noexcept
void Image::loadFromMemory(const char* const rawData,
const uint width,
const uint height,
const GLenum format,
const GLenum type) noexcept
{
loadFromMemory(rawData, Size<uint>(width, height), format, type);
}

void Image::loadFromMemory(const char* const rawData, const Size<uint>& size, const GLenum format, const GLenum type) noexcept
void Image::loadFromMemory(const char* const rawData,
const Size<uint>& size,
const GLenum format,
const GLenum type) noexcept
{
fRawData = rawData;
fSize = size;
@@ -89,31 +92,6 @@ void Image::loadFromMemory(const char* const rawData, const Size<uint>& size, co
fIsReady = false;
}

bool Image::isValid() const noexcept
{
return (fRawData != nullptr && fSize.getWidth() > 0 && fSize.getHeight() > 0);
}

uint Image::getWidth() const noexcept
{
return fSize.getWidth();
}

uint Image::getHeight() const noexcept
{
return fSize.getHeight();
}

const Size<uint>& Image::getSize() const noexcept
{
return fSize;
}

const char* Image::getRawData() const noexcept
{
return fRawData;
}

GLenum Image::getFormat() const noexcept
{
return fFormat;
@@ -124,17 +102,17 @@ GLenum Image::getType() const noexcept
return fType;
}

void Image::draw()
{
drawAt(0, 0);
}

void Image::drawAt(const int x, const int y)
Image& Image::operator=(const Image& image) noexcept
{
drawAt(Point<int>(x, y));
fRawData = image.fRawData;
fSize = image.fSize;
fFormat = image.fFormat;
fType = image.fType;
fIsReady = false;
return *this;
}

void Image::drawAt(const Point<int>& pos)
void Image::_drawAt(const Point<int>& pos)
{
if (fTextureId == 0 || ! isValid())
return;
@@ -169,26 +147,4 @@ void Image::drawAt(const Point<int>& pos)

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

Image& Image::operator=(const Image& image) noexcept
{
fRawData = image.fRawData;
fSize = image.fSize;
fFormat = image.fFormat;
fType = image.fType;
fIsReady = false;
return *this;
}

bool Image::operator==(const Image& image) const noexcept
{
return (fRawData == image.fRawData && fSize == image.fSize);
}

bool Image::operator!=(const Image& image) const noexcept
{
return !operator==(image);
}

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

END_NAMESPACE_DGL

+ 106
- 0
dpf/dgl/src/ImageBase.cpp View File

@@ -0,0 +1,106 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2019 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 "../ImageBase.hpp"

START_NAMESPACE_DGL

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

ImageBase::ImageBase()
: fRawData(nullptr),
fSize(0, 0) {}

ImageBase::ImageBase(const char* const rawData, const uint width, const uint height)
: fRawData(rawData),
fSize(width, height) {}

ImageBase::ImageBase(const char* const rawData, const Size<uint>& size)
: fRawData(rawData),
fSize(size) {}

ImageBase::ImageBase(const ImageBase& image)
: fRawData(image.fRawData),
fSize(image.fSize) {}

ImageBase::~ImageBase() {}

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

bool ImageBase::isValid() const noexcept
{
return (fRawData != nullptr && fSize.isValid());
}

uint ImageBase::getWidth() const noexcept
{
return fSize.getWidth();
}

uint ImageBase::getHeight() const noexcept
{
return fSize.getHeight();
}

const Size<uint>& ImageBase::getSize() const noexcept
{
return fSize;
}

const char* ImageBase::getRawData() const noexcept
{
return fRawData;
}

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

void ImageBase::draw()
{
_drawAt(Point<int>());
}

void ImageBase::drawAt(const int x, const int y)
{
_drawAt(Point<int>(x, y));
}

void ImageBase::drawAt(const Point<int>& pos)
{
_drawAt(pos);
}

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

ImageBase& ImageBase::operator=(const ImageBase& image) noexcept
{
fRawData = image.fRawData;
fSize = image.fSize;
return *this;
}

bool ImageBase::operator==(const ImageBase& image) const noexcept
{
return (fRawData == image.fRawData && fSize == image.fSize);
}

bool ImageBase::operator!=(const ImageBase& image) const noexcept
{
return !operator==(image);
}

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

END_NAMESPACE_DGL

+ 5
- 1
dpf/dgl/src/ImageWidgets.cpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2016 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2019 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
@@ -14,9 +14,13 @@
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

#include "../Image.hpp"
#include "Common.hpp"
#include "WidgetPrivateData.hpp"

// FIXME make this code more generic and move GL specific bits to OpenGL.cpp
#include "../OpenGL.hpp"

START_NAMESPACE_DGL

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


+ 20
- 1
dpf/dgl/src/NanoVG.cpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2018 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2019 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
@@ -124,6 +124,25 @@ DGL_EXT(PFNGLVERTEXATTRIBPOINTERPROC, glVertexAttribPointer)

START_NAMESPACE_DGL

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

Color::Color(const NVGcolor& c) noexcept
: red(c.r), green(c.g), blue(c.b), alpha(c.a)
{
fixBounds();
}

Color::operator NVGcolor() const noexcept
{
NVGcolor nc;
nc.r = red;
nc.g = green;
nc.b = blue;
nc.a = alpha;
return nc;
}

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



+ 157
- 0
dpf/dgl/src/OpenGL.cpp View File

@@ -0,0 +1,157 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2019 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 "../Geometry.hpp"
#include "../OpenGL.hpp"

START_NAMESPACE_DGL

// -----------------------------------------------------------------------
// Line

template<typename T>
void Line<T>::draw()
{
DISTRHO_SAFE_ASSERT_RETURN(fPosStart != fPosEnd,);

glBegin(GL_LINES);

{
glVertex2d(fPosStart.fX, fPosStart.fY);
glVertex2d(fPosEnd.fX, fPosEnd.fY);
}

glEnd();
}

// -----------------------------------------------------------------------
// Circle

template<typename T>
void Circle<T>::_draw(const bool outline)
{
DISTRHO_SAFE_ASSERT_RETURN(fNumSegments >= 3 && fSize > 0.0f,);

double t, x = fSize, y = 0.0;

glBegin(outline ? GL_LINE_LOOP : GL_POLYGON);

for (uint i=0; i<fNumSegments; ++i)
{
glVertex2d(x + fPos.fX, y + fPos.fY);

t = x;
x = fCos * x - fSin * y;
y = fSin * t + fCos * y;
}

glEnd();
}

// -----------------------------------------------------------------------
// Triangle

template<typename T>
void Triangle<T>::_draw(const bool outline)
{
DISTRHO_SAFE_ASSERT_RETURN(fPos1 != fPos2 && fPos1 != fPos3,);

glBegin(outline ? GL_LINE_LOOP : GL_TRIANGLES);

{
glVertex2d(fPos1.fX, fPos1.fY);
glVertex2d(fPos2.fX, fPos2.fY);
glVertex2d(fPos3.fX, fPos3.fY);
}

glEnd();
}

// -----------------------------------------------------------------------
// Rectangle

template<typename T>
void Rectangle<T>::_draw(const bool outline)
{
DISTRHO_SAFE_ASSERT_RETURN(fSize.isValid(),);

glBegin(outline ? GL_LINE_LOOP : GL_QUADS);

{
glTexCoord2f(0.0f, 0.0f);
glVertex2d(fPos.fX, fPos.fY);

glTexCoord2f(1.0f, 0.0f);
glVertex2d(fPos.fX+fSize.fWidth, fPos.fY);

glTexCoord2f(1.0f, 1.0f);
glVertex2d(fPos.fX+fSize.fWidth, fPos.fY+fSize.fHeight);

glTexCoord2f(0.0f, 1.0f);
glVertex2d(fPos.fX, fPos.fY+fSize.fHeight);
}

glEnd();
}

// -----------------------------------------------------------------------
// Possible template data types

template class Point<double>;
template class Point<float>;
template class Point<int>;
template class Point<uint>;
template class Point<short>;
template class Point<ushort>;

template class Size<double>;
template class Size<float>;
template class Size<int>;
template class Size<uint>;
template class Size<short>;
template class Size<ushort>;

template class Line<double>;
template class Line<float>;
template class Line<int>;
template class Line<uint>;
template class Line<short>;
template class Line<ushort>;

template class Circle<double>;
template class Circle<float>;
template class Circle<int>;
template class Circle<uint>;
template class Circle<short>;
template class Circle<ushort>;

template class Triangle<double>;
template class Triangle<float>;
template class Triangle<int>;
template class Triangle<uint>;
template class Triangle<short>;
template class Triangle<ushort>;

template class Rectangle<double>;
template class Rectangle<float>;
template class Rectangle<int>;
template class Rectangle<uint>;
template class Rectangle<short>;
template class Rectangle<ushort>;

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

END_NAMESPACE_DGL

+ 1
- 1
dpf/dgl/src/Widget.cpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2016 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2019 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


+ 107
- 0
dpf/dgl/src/WidgetPrivateData.cpp View File

@@ -0,0 +1,107 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2019 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 "WidgetPrivateData.hpp"

#ifdef DGL_CAIRO
# include "../Cairo.hpp"
#endif
#ifdef DGL_OPENGL
# include "../OpenGL.hpp"
#endif

START_NAMESPACE_DGL

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

void Widget::PrivateData::display(const uint width,
const uint height,
const double scaling,
const bool renderingSubWidget)
{
if ((skipDisplay && ! renderingSubWidget) || size.isInvalid() || ! visible)
return;

#ifdef DGL_OPENGL
bool needsDisableScissor = false;

// reset color
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);

if (needsFullViewport || (absolutePos.isZero() && size == Size<uint>(width, height)))
{
// full viewport size
glViewport(0,
-(height * scaling - height),
width * scaling,
height * scaling);
}
else if (needsScaling)
{
// limit viewport to widget bounds
glViewport(absolutePos.getX(),
height - self->getHeight() - absolutePos.getY(),
self->getWidth(),
self->getHeight());
}
else
{
// only set viewport pos
glViewport(absolutePos.getX() * scaling,
-std::round((height * scaling - height) + (absolutePos.getY() * scaling)),
std::round(width * scaling),
std::round(height * scaling));

// then cut the outer bounds
glScissor(absolutePos.getX() * scaling,
height - std::round((self->getHeight() + absolutePos.getY()) * scaling),
std::round(self->getWidth() * scaling),
std::round(self->getHeight() * scaling));

glEnable(GL_SCISSOR_TEST);
needsDisableScissor = true;
}
#endif

#ifdef DGL_CAIRO
cairo_t* cr = parent.getGraphicsContext().cairo;
cairo_matrix_t matrix;
cairo_get_matrix(cr, &matrix);
cairo_translate(cr, absolutePos.getX(), absolutePos.getY());
// TODO: scaling and cropping
#endif

// display widget
self->onDisplay();

#ifdef DGL_CAIRO
cairo_set_matrix(cr, &matrix);
#endif

#ifdef DGL_OPENGL
if (needsDisableScissor)
{
glDisable(GL_SCISSOR_TEST);
needsDisableScissor = false;
}
#endif

displaySubWidgets(width, height, scaling);
}

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

END_NAMESPACE_DGL

+ 3
- 56
dpf/dgl/src/WidgetPrivateData.hpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2018 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2019 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
@@ -63,61 +63,8 @@ struct Widget::PrivateData {
subWidgets.clear();
}

void display(const uint width, const uint height, const double scaling, const bool renderingSubWidget)
{
if ((skipDisplay && ! renderingSubWidget) || size.isInvalid() || ! visible)
return;

bool needsDisableScissor = false;

// reset color
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);

if (needsFullViewport || (absolutePos.isZero() && size == Size<uint>(width, height)))
{
// full viewport size
glViewport(0,
-(height * scaling - height),
width * scaling,
height * scaling);
}
else if (needsScaling)
{
// limit viewport to widget bounds
glViewport(absolutePos.getX(),
height - self->getHeight() - absolutePos.getY(),
self->getWidth(),
self->getHeight());
}
else
{
// only set viewport pos
glViewport(absolutePos.getX() * scaling,
-std::round((height * scaling - height) + (absolutePos.getY() * scaling)),
std::round(width * scaling),
std::round(height * scaling));

// then cut the outer bounds
glScissor(absolutePos.getX() * scaling,
height - std::round((self->getHeight() + absolutePos.getY()) * scaling),
std::round(self->getWidth() * scaling),
std::round(self->getHeight() * scaling));

glEnable(GL_SCISSOR_TEST);
needsDisableScissor = true;
}

// display widget
self->onDisplay();

if (needsDisableScissor)
{
glDisable(GL_SCISSOR_TEST);
needsDisableScissor = false;
}

displaySubWidgets(width, height, scaling);
}
// display function is different depending on build type
void display(const uint width, const uint height, const double scaling, const bool renderingSubWidget);

void displaySubWidgets(const uint width, const uint height, const double scaling)
{


+ 54
- 25
dpf/dgl/src/Window.cpp View File

@@ -19,6 +19,15 @@

#include "../Base.hpp"

#ifdef DGL_CAIRO
# define PUGL_CAIRO
# include "../Cairo.hpp"
#endif
#ifdef DGL_OPENGL
# define PUGL_OPENGL
# include "../OpenGL.hpp"
#endif

#include "pugl/pugl.h"

#if defined(__GNUC__) && (__GNUC__ >= 7)
@@ -84,6 +93,7 @@ struct Window::PrivateData {
fWidth(1),
fHeight(1),
fScaling(1.0),
fAutoScaling(1.0),
fTitle(nullptr),
fWidgets(),
fModal(),
@@ -115,6 +125,7 @@ struct Window::PrivateData {
fWidth(1),
fHeight(1),
fScaling(1.0),
fAutoScaling(1.0),
fTitle(nullptr),
fWidgets(),
fModal(parent.pData),
@@ -147,7 +158,7 @@ struct Window::PrivateData {
#endif
}

PrivateData(Application& app, Window* const self, const intptr_t parentId, const bool resizable)
PrivateData(Application& app, Window* const self, const intptr_t parentId, const double scaling, const bool resizable)
: fApp(app),
fSelf(self),
fView(puglInit()),
@@ -157,7 +168,8 @@ struct Window::PrivateData {
fUsingEmbed(parentId != 0),
fWidth(1),
fHeight(1),
fScaling(1.0),
fScaling(scaling),
fAutoScaling(1.0),
fTitle(nullptr),
fWidgets(),
fModal(),
@@ -222,11 +234,12 @@ struct Window::PrivateData {
puglCreateWindow(fView, nullptr);

PuglInternals* impl = fView->impl;

#if defined(DISTRHO_OS_WINDOWS)
hwnd = impl->hwnd;
DISTRHO_SAFE_ASSERT(hwnd != 0);
#elif defined(DISTRHO_OS_MAC)
mView = impl->glview;
mView = impl->view;
mWindow = impl->window;
DISTRHO_SAFE_ASSERT(mView != nullptr);
if (fUsingEmbed) {
@@ -555,6 +568,7 @@ struct Window::PrivateData {

void setGeometryConstraints(uint width, uint height, bool aspect)
{
// Did you forget to set DISTRHO_UI_USER_RESIZABLE ?
DISTRHO_SAFE_ASSERT_RETURN(fResizable,);

fView->min_width = width;
@@ -701,11 +715,11 @@ struct Window::PrivateData {
return fScaling;
}

void setScaling(double scaling) noexcept
void setAutoScaling(const double scaling) noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(scaling > 0.0,);

fScaling = scaling;
fAutoScaling = scaling;
}

// -------------------------------------------------------------------
@@ -773,7 +787,7 @@ struct Window::PrivateData {
FOR_EACH_WIDGET(it)
{
Widget* const widget(*it);
widget->pData->display(fWidth, fHeight, fScaling, false);
widget->pData->display(fWidth, fHeight, fAutoScaling, false);
}

fSelf->onDisplayAfter();
@@ -843,8 +857,8 @@ struct Window::PrivateData {
if (fModal.childFocus != nullptr)
return fModal.childFocus->focus();

x /= fScaling;
y /= fScaling;
x /= fAutoScaling;
y /= fAutoScaling;

Widget::MouseEvent ev;
ev.button = button;
@@ -870,8 +884,8 @@ struct Window::PrivateData {
if (fModal.childFocus != nullptr)
return;

x /= fScaling;
y /= fScaling;
x /= fAutoScaling;
y /= fAutoScaling;

Widget::MotionEvent ev;
ev.mod = static_cast<Modifier>(puglGetModifiers(fView));
@@ -895,10 +909,10 @@ struct Window::PrivateData {
if (fModal.childFocus != nullptr)
return;

x /= fScaling;
y /= fScaling;
dx /= fScaling;
dy /= fScaling;
x /= fAutoScaling;
y /= fAutoScaling;
dx /= fAutoScaling;
dy /= fAutoScaling;

Widget::ScrollEvent ev;
ev.delta = Point<float>(dx, dy);
@@ -1038,9 +1052,10 @@ struct Window::PrivateData {

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

Application& fApp;
Window* fSelf;
PuglView* fView;
Application& fApp;
Window* fSelf;
GraphicsContext fContext;
PuglView* fView;

bool fFirstInit;
bool fVisible;
@@ -1049,6 +1064,7 @@ struct Window::PrivateData {
uint fWidth;
uint fHeight;
double fScaling;
double fAutoScaling;
char* fTitle;
std::list<Widget*> fWidgets;

@@ -1081,7 +1097,7 @@ struct Window::PrivateData {
HWND hwndParent;
#elif defined(DISTRHO_OS_MAC)
bool fNeedsIdle;
PuglOpenGLView* mView;
NSView<PuglGenericView>* mView;
id mWindow;
id mParentWindow;
#else
@@ -1155,8 +1171,8 @@ Window::Window(Application& app)
Window::Window(Application& app, Window& parent)
: pData(new PrivateData(app, this, parent)) {}

Window::Window(Application& app, intptr_t parentId, bool resizable)
: pData(new PrivateData(app, this, parentId, resizable)) {}
Window::Window(Application& app, intptr_t parentId, double scaling, bool resizable)
: pData(new PrivateData(app, this, parentId, scaling, resizable)) {}

Window::~Window()
{
@@ -1347,11 +1363,6 @@ double Window::getScaling() const noexcept
return pData->getScaling();
}

void Window::setScaling(double scaling) noexcept
{
pData->setScaling(scaling);
}

bool Window::getIgnoringKeyRepeat() const noexcept
{
return pData->getIgnoringKeyRepeat();
@@ -1372,6 +1383,20 @@ intptr_t Window::getWindowId() const noexcept
return puglGetNativeWindow(pData->fView);
}

const GraphicsContext& Window::getGraphicsContext() const noexcept
{
GraphicsContext& context = pData->fContext;
#ifdef DGL_CAIRO
context.cairo = (cairo_t*)puglGetContext(pData->fView);
#endif
return context;
}

void Window::_setAutoScaling(double scaling) noexcept
{
pData->setAutoScaling(scaling);
}

void Window::_addWidget(Widget* const widget)
{
pData->addWidget(widget);
@@ -1407,8 +1432,10 @@ void Window::removeIdleCallback(IdleCallback* const callback)

void Window::onDisplayBefore()
{
#ifdef DGL_OPENGL
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
#endif
}

void Window::onDisplayAfter()
@@ -1417,6 +1444,7 @@ void Window::onDisplayAfter()

void Window::onReshape(uint width, uint height)
{
#ifdef DGL_OPENGL
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glMatrixMode(GL_PROJECTION);
@@ -1425,6 +1453,7 @@ void Window::onReshape(uint width, uint height)
glViewport(0, 0, static_cast<GLsizei>(width), static_cast<GLsizei>(height));
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
#endif
}

void Window::onClose()


+ 43
- 40
dpf/dgl/src/pugl/pugl.h View File

@@ -1,5 +1,6 @@
/*
Copyright 2012-2014 David Robillard <http://drobilla.net>
Copyright 2012-2019 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
@@ -29,19 +30,13 @@
platforms so they are included here to allow for pure portable programs.
*/
#ifdef __APPLE__
# include "OpenGL/gl.h"
# include <OpenGL/gl.h>
#else
# ifdef _WIN32
# include <winsock2.h>
# include <windows.h> /* Broken Windows GL headers require this */
# endif
# include "GL/gl.h"
#endif

#ifdef _WIN32
# define PUGL_API
#else
# define PUGL_API __attribute__((visibility("hidden")))
# include <GL/gl.h>
#endif

#ifdef __cplusplus
@@ -237,31 +232,31 @@ typedef void (*PuglFileSelectedFunc)(PuglView* view, const char* filename);
To create a window, call the various puglInit* functions as necessary, then
call puglCreateWindow().
*/
PUGL_API PuglView*
PuglView*
puglInit(void);

/**
Set the parent window before creating a window (for embedding).
*/
PUGL_API void
void
puglInitWindowParent(PuglView* view, PuglNativeWindow parent);

/**
Set the window size before creating a window.
*/
PUGL_API void
void
puglInitWindowSize(PuglView* view, int width, int height);

/**
Set the minimum window size before creating a window.
*/
PUGL_API void
void
puglInitWindowMinSize(PuglView* view, int width, int height);

/**
Enable or disable resizing before creating a window.
*/
PUGL_API void
void
puglInitUserResizable(PuglView* view, bool resizable);

/**
@@ -270,7 +265,7 @@ puglInitUserResizable(PuglView* view, bool resizable);
On X11, parent_id must be a Window.
On OSX, parent_id must be an NSView*.
*/
PUGL_API void
void
puglInitTransientFor(PuglView* view, uintptr_t parent);

/**
@@ -288,7 +283,7 @@ puglInitTransientFor(PuglView* view, uintptr_t parent);

@return 1 (pugl does not currently support multiple windows).
*/
PUGL_API int
int
puglCreateWindow(PuglView* view, const char* title);

/**
@@ -299,7 +294,7 @@ puglCreateWindow(PuglView* view, const char* title);
@param height Window height in pixels.
@param resizable Whether window should be user resizable.
*/
PUGL_API PuglView*
PuglView*
puglCreate(PuglNativeWindow parent,
const char* title,
int min_width,
@@ -312,19 +307,19 @@ puglCreate(PuglNativeWindow parent,
/**
Show Window (external ui)
*/
PUGL_API void
void
puglShowWindow(PuglView* view);

/**
Hide Window (external ui)
*/
PUGL_API void
void
puglHideWindow(PuglView* view);

/**
Return the native window handle.
*/
PUGL_API PuglNativeWindow
PuglNativeWindow
puglGetNativeWindow(PuglView* view);

/**
@@ -340,19 +335,27 @@ puglGetNativeWindow(PuglView* view);
Note the lack of this facility makes GLUT unsuitable for plugins or
non-trivial programs; this mistake is largely why Pugl exists.
*/
PUGL_API void
void
puglSetHandle(PuglView* view, PuglHandle handle);

/**
Get the handle to be passed to all callbacks.
*/
PUGL_API PuglHandle
PuglHandle
puglGetHandle(PuglView* view);

/**
Get the drawing context.
For Cairo contexts, this returns a pointer to a cairo_t.
For everything else, this is unused and returns NULL.
*/
void*
puglGetContext(PuglView* view);

/**
Return the timestamp (if any) of the currently-processing event.
*/
PUGL_API uint32_t
uint32_t
puglGetEventTimestamp(PuglView* view);

/**
@@ -360,13 +363,13 @@ puglGetEventTimestamp(PuglView* view);

This should only be called from an event handler.
*/
PUGL_API int
int
puglGetModifiers(PuglView* view);

/**
Ignore synthetic repeated key events.
*/
PUGL_API void
void
puglIgnoreKeyRepeat(PuglView* view, bool ignore);

/**
@@ -378,61 +381,61 @@ puglIgnoreKeyRepeat(PuglView* view, bool ignore);
/**
Set the function to call when the window is closed.
*/
PUGL_API void
void
puglSetCloseFunc(PuglView* view, PuglCloseFunc closeFunc);

/**
Set the display function which should draw the UI using GL.
*/
PUGL_API void
void
puglSetDisplayFunc(PuglView* view, PuglDisplayFunc displayFunc);

/**
Set the function to call on keyboard events.
*/
PUGL_API void
void
puglSetKeyboardFunc(PuglView* view, PuglKeyboardFunc keyboardFunc);

/**
Set the function to call on mouse motion.
*/
PUGL_API void
void
puglSetMotionFunc(PuglView* view, PuglMotionFunc motionFunc);

/**
Set the function to call on mouse button events.
*/
PUGL_API void
void
puglSetMouseFunc(PuglView* view, PuglMouseFunc mouseFunc);

/**
Set the function to call on scroll events.
*/
PUGL_API void
void
puglSetScrollFunc(PuglView* view, PuglScrollFunc scrollFunc);

/**
Set the function to call on special events.
*/
PUGL_API void
void
puglSetSpecialFunc(PuglView* view, PuglSpecialFunc specialFunc);

/**
Set the function to call when the window size changes.
*/
PUGL_API void
void
puglSetReshapeFunc(PuglView* view, PuglReshapeFunc reshapeFunc);

/**
Set callback function to change window size.
*/
PUGL_API void
void
puglSetResizeFunc(PuglView* view, PuglResizeFunc resizeFunc);

/**
Set the function to call on file-browser selections.
*/
PUGL_API void
void
puglSetFileSelectedFunc(PuglView* view, PuglFileSelectedFunc fileSelectedFunc);

/**
@@ -442,13 +445,13 @@ puglSetFileSelectedFunc(PuglView* view, PuglFileSelectedFunc fileSelectedFunc);
/**
TODO document this.
*/
PUGL_API int
int
puglUpdateGeometryConstraints(PuglView* view, int min_width, int min_height, bool aspect);

/**
Grab the input focus.
*/
PUGL_API void
void
puglGrabFocus(PuglView* view);

/**
@@ -457,25 +460,25 @@ puglGrabFocus(PuglView* view);
This handles input events as well as rendering, so it should be called
regularly and rapidly enough to keep the UI responsive.
*/
PUGL_API PuglStatus
PuglStatus
puglProcessEvents(PuglView* view);

/**
Request a redisplay on the next call to puglProcessEvents().
*/
PUGL_API void
void
puglPostRedisplay(PuglView* view);

/**
Request a resize on the next call to puglProcessEvents().
*/
PUGL_API void
void
puglPostResize(PuglView* view);

/**
Destroy a GL window.
*/
PUGL_API void
void
puglDestroy(PuglView* view);

/**


+ 3
- 0
dpf/dgl/src/pugl/pugl_internal.h View File

@@ -1,5 +1,6 @@
/*
Copyright 2012-2014 David Robillard <http://drobilla.net>
Copyright 2012-2019 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
@@ -239,6 +240,7 @@ puglLeaveContext(PuglView* view, bool flush);
static void
puglDefaultReshape(int width, int height)
{
#ifdef PUGL_OPENGL
#ifdef ROBTK_HERE
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
@@ -257,4 +259,5 @@ puglDefaultReshape(int width, int height)
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
#endif
#endif // PUGL_OPENGL
}

+ 497
- 129
dpf/dgl/src/pugl/pugl_osx.m View File

@@ -1,5 +1,6 @@
/*
Copyright 2012 David Robillard <http://drobilla.net>
Copyright 2012-2019 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
@@ -20,6 +21,10 @@

#include <stdlib.h>

#ifdef PUGL_CAIRO
#import <cairo.h>
#import <cairo-quartz.h>
#endif
#import <Cocoa/Cocoa.h>

#include "pugl_internal.h"
@@ -93,7 +98,200 @@ puglDisplay(PuglView* view)
}
}

@interface PuglOpenGLView : NSOpenGLView
@protocol PuglGenericView
@required
- (PuglView *) puglview;
- (void) setPuglview:(PuglView *)pv;
- (NSTrackingArea *) puglTrackingArea;
- (void) setPuglTrackingArea:(NSTrackingArea *)area;
@end

static unsigned
getModifiers(PuglView* view, NSEvent* ev)
{
const unsigned modifierFlags = [ev modifierFlags];

view->event_timestamp_ms = fmod([ev timestamp] * 1000.0, UINT32_MAX);

unsigned mods = 0;
mods |= (modifierFlags & NSShiftKeyMask) ? PUGL_MOD_SHIFT : 0;
mods |= (modifierFlags & NSControlKeyMask) ? PUGL_MOD_CTRL : 0;
mods |= (modifierFlags & NSAlternateKeyMask) ? PUGL_MOD_ALT : 0;
mods |= (modifierFlags & NSCommandKeyMask) ? PUGL_MOD_SUPER : 0;
return mods;
}

static int
getFixedAppKitButton(NSInteger button)
{
switch (button) {
case 0: return 1;
case 1: return 3;
case 2: return 2;
default: return button;
}
}

static void
cursorUpdate(NSView<PuglGenericView> *self, NSEvent* event)
{
[[NSCursor arrowCursor] set];
(void)self;
(void)event;
}

static void
updateTrackingAreas(NSView<PuglGenericView> *self)
{
static const int opts = NSTrackingMouseEnteredAndExited
| NSTrackingMouseMoved
| NSTrackingEnabledDuringMouseDrag
| NSTrackingInVisibleRect
| NSTrackingActiveAlways
| NSTrackingCursorUpdate;

NSTrackingArea *trackingArea = [self puglTrackingArea];
if (trackingArea != nil) {
[self removeTrackingArea:trackingArea];
[trackingArea release];
}

trackingArea = [[NSTrackingArea alloc] initWithRect:[self bounds]
options:opts
owner:self
userInfo:nil];
[self setPuglTrackingArea:trackingArea];
[self addTrackingArea:trackingArea];
}

static void
viewWillMoveToWindow(NSView<PuglGenericView> *self, NSWindow* newWindow)
{
if (newWindow != nil) {
[newWindow setAcceptsMouseMovedEvents:YES];
[newWindow makeFirstResponder:self];
}
}

static void
reshape(NSView<PuglGenericView> *self)
{
PuglView* puglview = [self puglview];

NSRect bounds = [self bounds];
int width = bounds.size.width;
int height = bounds.size.height;

puglEnterContext(puglview);

if (puglview->reshapeFunc) {
puglview->reshapeFunc(puglview, width, height);
} else {
puglDefaultReshape(width, height);
}

puglLeaveContext(puglview, false);

puglview->width = width;
puglview->height = height;
}

static void
mouseMoved(NSView<PuglGenericView> *self, NSEvent *event)
{
PuglView* puglview = [self puglview];

if (puglview->motionFunc) {
NSPoint loc = [self convertPoint:[event locationInWindow] fromView:nil];
puglview->mods = getModifiers(puglview, event);
puglview->motionFunc(puglview, loc.x, loc.y);
}
}

static void
mouseDown(NSView<PuglGenericView> *self, NSEvent *event)
{
PuglView* puglview = [self puglview];

if (puglview->mouseFunc) {
NSPoint loc = [self convertPoint:[event locationInWindow] fromView:nil];
puglview->mods = getModifiers(puglview, event);
puglview->mouseFunc(puglview, getFixedAppKitButton([event buttonNumber]), true, loc.x, loc.y);
}
}

static void
mouseUp(NSView<PuglGenericView> *self, NSEvent *event)
{
PuglView* puglview = [self puglview];

if (puglview->mouseFunc) {
NSPoint loc = [self convertPoint:[event locationInWindow] fromView:nil];
puglview->mods = getModifiers(puglview, event);
puglview->mouseFunc(puglview, getFixedAppKitButton([event buttonNumber]), false, loc.x, loc.y);
}
}

static void
scrollWheel(NSView<PuglGenericView> *self, NSEvent *event)
{
PuglView* puglview = [self puglview];

if (puglview->scrollFunc) {
NSPoint loc = [self convertPoint:[event locationInWindow] fromView:nil];
puglview->mods = getModifiers(puglview, event);
puglview->scrollFunc(puglview,
loc.x, loc.y,
[event deltaX], [event deltaY]);
}
}

static void
keyDown(NSView<PuglGenericView> *self, NSEvent *event)
{
PuglView* puglview = [self puglview];

if (puglview->keyboardFunc && !(puglview->ignoreKeyRepeat && [event isARepeat])) {
NSString* chars = [event characters];
puglview->mods = getModifiers(puglview, event);
puglview->keyboardFunc(puglview, true, [chars characterAtIndex:0]);
}
}

static void
keyUp(NSView<PuglGenericView> *self, NSEvent *event)
{
PuglView* puglview = [self puglview];

if (puglview->keyboardFunc) {
NSString* chars = [event characters];
puglview->mods = getModifiers(puglview, event);
puglview->keyboardFunc(puglview, false, [chars characterAtIndex:0]);
}
}

static void
flagsChanged(NSView<PuglGenericView> *self, NSEvent *event)
{
PuglView* puglview = [self puglview];

if (puglview->specialFunc) {
const unsigned mods = getModifiers(puglview, event);
if ((mods & PUGL_MOD_SHIFT) != (puglview->mods & PUGL_MOD_SHIFT)) {
puglview->specialFunc(puglview, mods & PUGL_MOD_SHIFT, PUGL_KEY_SHIFT);
} else if ((mods & PUGL_MOD_CTRL) != (puglview->mods & PUGL_MOD_CTRL)) {
puglview->specialFunc(puglview, mods & PUGL_MOD_CTRL, PUGL_KEY_CTRL);
} else if ((mods & PUGL_MOD_ALT) != (puglview->mods & PUGL_MOD_ALT)) {
puglview->specialFunc(puglview, mods & PUGL_MOD_ALT, PUGL_KEY_ALT);
} else if ((mods & PUGL_MOD_SUPER) != (puglview->mods & PUGL_MOD_SUPER)) {
puglview->specialFunc(puglview, mods & PUGL_MOD_SUPER, PUGL_KEY_SUPER);
}
puglview->mods = mods;
}
}

#ifdef PUGL_OPENGL
@interface PuglOpenGLView : NSOpenGLView<PuglGenericView>
{
@public
PuglView* puglview;
@@ -101,6 +299,11 @@ puglDisplay(PuglView* view)
bool doubleBuffered;
}

- (PuglView *) puglview;
- (void) setPuglview:(PuglView *)pv;
- (NSTrackingArea *) puglTrackingArea;
- (void) setPuglTrackingArea:(NSTrackingArea *)area;

- (BOOL) acceptsFirstMouse:(NSEvent*)e;
- (BOOL) acceptsFirstResponder;
- (BOOL) isFlipped;
@@ -130,6 +333,21 @@ puglDisplay(PuglView* view)
@end

@implementation PuglOpenGLView
- (PuglView *) puglview {
return self->puglview;
}

- (void) setPuglview:(PuglView *)pv {
self->puglview = pv;
}

- (NSTrackingArea *) puglTrackingArea {
return self->trackingArea;
}

- (void) setPuglTrackingArea:(NSTrackingArea *)area {
self->trackingArea = area;
}

- (BOOL) acceptsFirstMouse:(NSEvent*)e
{
@@ -209,22 +427,7 @@ puglDisplay(PuglView* view)

[[self openGLContext] update];

NSRect bounds = [self bounds];
int width = bounds.size.width;
int height = bounds.size.height;

puglEnterContext(puglview);

if (puglview->reshapeFunc) {
puglview->reshapeFunc(puglview, width, height);
} else {
puglDefaultReshape(width, height);
}

puglLeaveContext(puglview, false);

puglview->width = width;
puglview->height = height;
reshape(self);
}

- (void) drawRect:(NSRect)r
@@ -239,182 +442,326 @@ puglDisplay(PuglView* view)

- (void) cursorUpdate:(NSEvent*)e
{
[[NSCursor arrowCursor] set];

// unused
return; (void)e;
cursorUpdate(self, e);
}

- (void) updateTrackingAreas
{
static const int opts = NSTrackingMouseEnteredAndExited
| NSTrackingMouseMoved
| NSTrackingEnabledDuringMouseDrag
| NSTrackingInVisibleRect
| NSTrackingActiveAlways
| NSTrackingCursorUpdate;

if (trackingArea != nil) {
[self removeTrackingArea:trackingArea];
[trackingArea release];
}

trackingArea = [[NSTrackingArea alloc] initWithRect:[self bounds]
options:opts
owner:self
userInfo:nil];
[self addTrackingArea:trackingArea];
updateTrackingAreas(self);
[super updateTrackingAreas];
}

- (void) viewWillMoveToWindow:(NSWindow*)newWindow
{
if (newWindow != nil) {
[newWindow setAcceptsMouseMovedEvents:YES];
[newWindow makeFirstResponder:self];
}

viewWillMoveToWindow(self, newWindow);
[super viewWillMoveToWindow:newWindow];
}

static unsigned
getModifiers(PuglView* view, NSEvent* ev)
- (void) mouseMoved:(NSEvent*)event
{
const unsigned modifierFlags = [ev modifierFlags];
mouseMoved(self, event);
}

view->event_timestamp_ms = fmod([ev timestamp] * 1000.0, UINT32_MAX);
- (void) mouseDragged:(NSEvent*)event
{
mouseMoved(self, event);
}

unsigned mods = 0;
mods |= (modifierFlags & NSShiftKeyMask) ? PUGL_MOD_SHIFT : 0;
mods |= (modifierFlags & NSControlKeyMask) ? PUGL_MOD_CTRL : 0;
mods |= (modifierFlags & NSAlternateKeyMask) ? PUGL_MOD_ALT : 0;
mods |= (modifierFlags & NSCommandKeyMask) ? PUGL_MOD_SUPER : 0;
return mods;
- (void) rightMouseDragged:(NSEvent*)event
{
mouseMoved(self, event);
}

static int
getFixedAppKitButton(NSInteger button)
- (void) otherMouseDragged:(NSEvent*)event
{
switch (button) {
case 0: return 1;
case 1: return 3;
case 2: return 2;
default: return button;
mouseMoved(self, event);
}

- (void) mouseDown:(NSEvent*)event
{
mouseDown(self, event);
}

- (void) rightMouseDown:(NSEvent*)event
{
mouseDown(self, event);
}

- (void) otherMouseDown:(NSEvent*)event
{
mouseDown(self, event);
}

- (void) mouseUp:(NSEvent*)event
{
mouseUp(self, event);
}

- (void) rightMouseUp:(NSEvent*)event
{
mouseUp(self, event);
}

- (void) otherMouseUp:(NSEvent*)event
{
mouseUp(self, event);
}

- (void) scrollWheel:(NSEvent*)event
{
scrollWheel(self, event);
}

- (void) keyDown:(NSEvent*)event
{
keyDown(self, event);
}

- (void) keyUp:(NSEvent*)event
{
keyUp(self, event);
}

- (void) flagsChanged:(NSEvent*)event
{
flagsChanged(self, event);
}

@end
#endif

#ifdef PUGL_CAIRO
@interface PuglCairoView : NSView<PuglGenericView>
{
PuglView* puglview;
cairo_t* cr;
NSTrackingArea* trackingArea;
}

- (PuglView *) puglview;
- (void) setPuglview:(PuglView *)pv;
- (NSTrackingArea *) puglTrackingArea;
- (void) setPuglTrackingArea:(NSTrackingArea *)area;

- (cairo_t *) cairoContext;

- (BOOL) acceptsFirstMouse:(NSEvent*)e;
- (BOOL) acceptsFirstResponder;
- (BOOL) isFlipped;
- (BOOL) isOpaque;
- (BOOL) preservesContentInLiveResize;
- (id) initWithFrame:(NSRect)frame;
- (void) reshape;
- (void) drawRect:(NSRect)r;
- (void) cursorUpdate:(NSEvent*)e;
- (void) updateTrackingAreas;
- (void) viewWillMoveToWindow:(NSWindow*)newWindow;
- (void) mouseMoved:(NSEvent*)event;
- (void) mouseDragged:(NSEvent*)event;
- (void) rightMouseDragged:(NSEvent*)event;
- (void) otherMouseDragged:(NSEvent*)event;
- (void) mouseDown:(NSEvent*)event;
- (void) rightMouseDown:(NSEvent*)event;
- (void) otherMouseDown:(NSEvent*)event;
- (void) mouseUp:(NSEvent*)event;
- (void) rightMouseUp:(NSEvent*)event;
- (void) otherMouseUp:(NSEvent*)event;
- (void) scrollWheel:(NSEvent*)event;
- (void) keyDown:(NSEvent*)event;
- (void) keyUp:(NSEvent*)event;
- (void) flagsChanged:(NSEvent*)event;
@end

@implementation PuglCairoView
- (PuglView *) puglview {
return self->puglview;
}

- (void) setPuglview:(PuglView *)pv {
self->puglview = pv;
}

- (NSTrackingArea *) puglTrackingArea {
return self->trackingArea;
}

- (void) setPuglTrackingArea:(NSTrackingArea *)area {
self->trackingArea = area;
}

- (cairo_t *) cairoContext {
return cr;
}

- (BOOL) acceptsFirstMouse:(NSEvent*)e
{
return YES;

// unused
(void)e;
}

- (BOOL) acceptsFirstResponder
{
return YES;
}

- (BOOL) isFlipped
{
return YES;
}

- (BOOL) isOpaque
{
return YES;
}

- (BOOL) preservesContentInLiveResize
{
return NO;
}

- (id) initWithFrame:(NSRect)frame {
puglview = nil;
cr = NULL;
trackingArea = nil;
[super initWithFrame:frame];
return self;
}

- (void) reshape
{
if (!puglview) {
/* NOTE: Apparently reshape gets called when the GC gets around to
deleting the view (?), so we must have reset puglview to NULL when
this comes around.
*/
return;
}

reshape(self);
}

- (void) drawRect:(NSRect)r {
CGContextRef ctx = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
NSRect bounds = [self bounds];
cairo_surface_t* surface;
cairo_t* cairo;

surface = cairo_quartz_surface_create_for_cg_context(ctx, bounds.size.width, bounds.size.height);
if (surface) {
cairo = cairo_create(surface);
if (cairo) {
self->cr = cairo;
puglEnterContext(puglview);
puglDisplay(puglview);
puglLeaveContext(puglview, true);
self->cr = NULL;
cairo_destroy(cairo);
}
cairo_surface_destroy(surface);
}
}

- (void) cursorUpdate:(NSEvent*)e
{
cursorUpdate(self, e);
}

- (void) updateTrackingAreas
{
updateTrackingAreas(self);
[super updateTrackingAreas];
}

- (void) viewWillMoveToWindow:(NSWindow*)newWindow
{
viewWillMoveToWindow(self, newWindow);
[super viewWillMoveToWindow:newWindow];
}

- (void) mouseMoved:(NSEvent*)event
{
if (puglview->motionFunc) {
NSPoint loc = [self convertPoint:[event locationInWindow] fromView:nil];
puglview->mods = getModifiers(puglview, event);
puglview->motionFunc(puglview, loc.x, loc.y);
}
mouseMoved(self, event);
}

- (void) mouseDragged:(NSEvent*)event
{
[self mouseMoved:event];
mouseMoved(self, event);
}

- (void) rightMouseDragged:(NSEvent*)event
{
[self mouseDragged:event];
mouseMoved(self, event);
}

- (void) otherMouseDragged:(NSEvent*)event
{
[self mouseDragged:event];
mouseMoved(self, event);
}

- (void) mouseDown:(NSEvent*)event
{
if (puglview->mouseFunc) {
NSPoint loc = [self convertPoint:[event locationInWindow] fromView:nil];
puglview->mods = getModifiers(puglview, event);
puglview->mouseFunc(puglview, getFixedAppKitButton([event buttonNumber]), true, loc.x, loc.y);
}
mouseDown(self, event);
}

- (void) rightMouseDown:(NSEvent*)event
{
[self mouseDown:event];
mouseDown(self, event);
}

- (void) otherMouseDown:(NSEvent*)event
{
[self mouseDown:event];
mouseDown(self, event);
}

- (void) mouseUp:(NSEvent*)event
{
if (puglview->mouseFunc) {
NSPoint loc = [self convertPoint:[event locationInWindow] fromView:nil];
puglview->mods = getModifiers(puglview, event);
puglview->mouseFunc(puglview, getFixedAppKitButton([event buttonNumber]), false, loc.x, loc.y);
}
mouseUp(self, event);
}

- (void) rightMouseUp:(NSEvent*)event
{
[self mouseUp:event];
mouseUp(self, event);
}

- (void) otherMouseUp:(NSEvent*)event
{
[self mouseUp:event];
mouseUp(self, event);
}

- (void) scrollWheel:(NSEvent*)event
{
if (puglview->scrollFunc) {
NSPoint loc = [self convertPoint:[event locationInWindow] fromView:nil];
puglview->mods = getModifiers(puglview, event);
puglview->scrollFunc(puglview,
loc.x, loc.y,
[event deltaX], [event deltaY]);
}
scrollWheel(self, event);
}

- (void) keyDown:(NSEvent*)event
{
if (puglview->keyboardFunc && !(puglview->ignoreKeyRepeat && [event isARepeat])) {
NSString* chars = [event characters];
puglview->mods = getModifiers(puglview, event);
puglview->keyboardFunc(puglview, true, [chars characterAtIndex:0]);
}
keyDown(self, event);
}

- (void) keyUp:(NSEvent*)event
{
if (puglview->keyboardFunc) {
NSString* chars = [event characters];
puglview->mods = getModifiers(puglview, event);
puglview->keyboardFunc(puglview, false, [chars characterAtIndex:0]);
}
keyUp(self, event);
}

- (void) flagsChanged:(NSEvent*)event
{
if (puglview->specialFunc) {
const unsigned mods = getModifiers(puglview, event);
if ((mods & PUGL_MOD_SHIFT) != (puglview->mods & PUGL_MOD_SHIFT)) {
puglview->specialFunc(puglview, mods & PUGL_MOD_SHIFT, PUGL_KEY_SHIFT);
} else if ((mods & PUGL_MOD_CTRL) != (puglview->mods & PUGL_MOD_CTRL)) {
puglview->specialFunc(puglview, mods & PUGL_MOD_CTRL, PUGL_KEY_CTRL);
} else if ((mods & PUGL_MOD_ALT) != (puglview->mods & PUGL_MOD_ALT)) {
puglview->specialFunc(puglview, mods & PUGL_MOD_ALT, PUGL_KEY_ALT);
} else if ((mods & PUGL_MOD_SUPER) != (puglview->mods & PUGL_MOD_SUPER)) {
puglview->specialFunc(puglview, mods & PUGL_MOD_SUPER, PUGL_KEY_SUPER);
}
puglview->mods = mods;
}
flagsChanged(self, event);
}

@end
#endif

struct PuglInternalsImpl {
PuglOpenGLView* glview;
union {
NSView<PuglGenericView>* view;
#ifdef PUGL_OPENGL
PuglOpenGLView* glview;
#endif
#ifdef PUGL_CAIRO
PuglCairoView* cairoview;
#endif
};
id window;
};

@@ -427,19 +774,23 @@ puglInitInternals()
void
puglEnterContext(PuglView* view)
{
#ifdef PUGL_OPENGL
[[view->impl->glview openGLContext] makeCurrentContext];
#endif
}

void
puglLeaveContext(PuglView* view, bool flush)
{
if (flush) {
#ifdef PUGL_OPENGL
if (view->impl->glview->doubleBuffered) {
[[view->impl->glview openGLContext] flushBuffer];
} else {
glFlush();
}
//[NSOpenGLContext clearCurrentContext];
#endif
}
}

@@ -451,22 +802,27 @@ puglCreateWindow(PuglView* view, const char* title)
[NSAutoreleasePool new];
[NSApplication sharedApplication];

#ifdef PUGL_OPENGL
impl->glview = [PuglOpenGLView new];
#endif
#ifdef PUGL_CAIRO
impl->cairoview = [PuglCairoView new];
#endif

if (!impl->glview) {
if (!impl->view) {
return 1;
}
impl->glview->puglview = view;
[impl->view setPuglview:view];

if (view->user_resizable) {
[impl->glview setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable];
[impl->view setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable];
}

if (view->parent) {
[impl->glview retain];
[impl->view retain];
NSView* pview = (NSView*)view->parent;
[pview addSubview:impl->glview];
[pview addSubview:impl->view];
return 0;
}

@@ -482,8 +838,8 @@ puglCreateWindow(PuglView* view, const char* title)
}

[window setPuglview:view];
[window setContentView:impl->glview];
[window makeFirstResponder:impl->glview];
[window setContentView:impl->view];
[window makeFirstResponder:impl->view];
[window makeKeyAndOrderFront:window];

// wait for first puglShowWindow
@@ -505,7 +861,7 @@ puglShowWindow(PuglView* view)
if (impl->window) {
[impl->window setIsVisible:YES];
} else {
[view->impl->glview setHidden:NO];
[view->impl->view setHidden:NO];
}
}

@@ -517,21 +873,21 @@ puglHideWindow(PuglView* view)
if (impl->window) {
[impl->window setIsVisible:NO];
} else {
[impl->glview setHidden:YES];
[impl->view setHidden:YES];
}
}

void
puglDestroy(PuglView* view)
{
view->impl->glview->puglview = NULL;
[view->impl->view setPuglview:NULL];

if (view->impl->window) {
[view->impl->window close];
[view->impl->glview release];
[view->impl->view release];
[view->impl->window release];
} else {
[view->impl->glview release];
[view->impl->view release];
}

free(view->impl);
@@ -551,13 +907,25 @@ void
puglPostRedisplay(PuglView* view)
{
view->redisplay = true;
[view->impl->glview setNeedsDisplay:YES];
[view->impl->view setNeedsDisplay:YES];
}

PuglNativeWindow
puglGetNativeWindow(PuglView* view)
{
return (PuglNativeWindow)view->impl->glview;
return (PuglNativeWindow)view->impl->view;
}

void*
puglGetContext(PuglView* view)
{
#ifdef PUGL_CAIRO
return [view->impl->cairoview cairoContext];
#endif
return NULL;

// may be unused
(void)view;
}

int


+ 104
- 19
dpf/dgl/src/pugl/pugl_win.cpp View File

@@ -1,5 +1,6 @@
/*
Copyright 2012-2014 David Robillard <http://drobilla.net>
Copyright 2012-2019 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
@@ -18,16 +19,22 @@
@file pugl_win.cpp Windows/WGL Pugl Implementation.
*/

#include <ctime>
#include <cstdio>
#include <cstdlib>

#include <winsock2.h>
#include <windows.h>
#include <windowsx.h>
#ifdef PUGL_CAIRO
#include <cairo/cairo.h>
#include <cairo/cairo-win32.h>
#endif
#ifdef PUGL_OPENGL
#include <GL/gl.h>
#endif

#include <ctime>
#include <cstdio>
#include <cstdlib>

#include "pugl/pugl_internal.h"
#include "pugl_internal.h"

#ifndef WM_MOUSEWHEEL
# define WM_MOUSEWHEEL 0x020A
@@ -48,8 +55,15 @@ HINSTANCE hInstance = NULL;

struct PuglInternalsImpl {
HWND hwnd;
#ifdef PUGL_OPENGL
HDC hdc;
HGLRC hglrc;
#endif
#ifdef PUGL_CAIRO
cairo_t* buffer_cr;
cairo_surface_t* buffer_surface;
#endif
HDC paintHdc;
WNDCLASS wc;
};

@@ -76,17 +90,21 @@ puglInitInternals()
void
puglEnterContext(PuglView* view)
{
#ifdef PUGL_OPENGL
wglMakeCurrent(view->impl->hdc, view->impl->hglrc);
#endif
}

void
puglLeaveContext(PuglView* view, bool flush)
{
#ifdef PUGL_OPENGL
if (flush) {
glFlush();
SwapBuffers(view->impl->hdc);
}
wglMakeCurrent(NULL, NULL);
#endif
}

int
@@ -124,7 +142,6 @@ puglCreateWindow(PuglView* view, const char* title)
if (!RegisterClass(&impl->wc)) {
free((void*)impl->wc.lpszClassName);
free(impl);
free(view);
return 1;
}

@@ -155,12 +172,12 @@ puglCreateWindow(PuglView* view, const char* title)
UnregisterClass(impl->wc.lpszClassName, NULL);
free((void*)impl->wc.lpszClassName);
free(impl);
free(view);
return 1;
}

SetWindowLongPtr(impl->hwnd, GWLP_USERDATA, (LONG_PTR)view);

#ifdef PUGL_OPENGL
impl->hdc = GetDC(impl->hwnd);

PIXELFORMATDESCRIPTOR pfd;
@@ -183,9 +200,9 @@ puglCreateWindow(PuglView* view, const char* title)
UnregisterClass (impl->wc.lpszClassName, NULL);
free((void*)impl->wc.lpszClassName);
free(impl);
free(view);
return 1;
}
#endif

return PUGL_SUCCESS;
}
@@ -205,13 +222,25 @@ puglHideWindow(PuglView* view)
void
puglDestroy(PuglView* view)
{
if (!view) {
return;
}

PuglInternals* const impl = view->impl;

#ifdef PUGL_OPENGL
wglMakeCurrent(NULL, NULL);
wglDeleteContext(view->impl->hglrc);
ReleaseDC(view->impl->hwnd, view->impl->hdc);
DestroyWindow(view->impl->hwnd);
UnregisterClass(view->impl->wc.lpszClassName, NULL);
free((void*)view->impl->wc.lpszClassName);
free(view->impl);
wglDeleteContext(impl->hglrc);
ReleaseDC(impl->hwnd, impl->hdc);
#endif
#ifdef PUGL_CAIRO
cairo_destroy(impl->buffer_cr);
cairo_surface_destroy(impl->buffer_surface);
#endif
DestroyWindow(impl->hwnd);
UnregisterClass(impl->wc.lpszClassName, NULL);
free((void*)impl->wc.lpszClassName);
free(impl);
free(view);
}

@@ -233,14 +262,57 @@ puglReshape(PuglView* view, int width, int height)
static void
puglDisplay(PuglView* view)
{
PuglInternals* impl = view->impl;
bool success = true;

puglEnterContext(view);

view->redisplay = false;
if (view->displayFunc) {
view->displayFunc(view);
#ifdef PUGL_CAIRO
cairo_t *wc = NULL;
cairo_t *bc = NULL;
cairo_surface_t *ws = NULL;
cairo_surface_t *bs = NULL;

HDC hdc = impl->paintHdc;
bc = impl->buffer_cr;
bs = impl->buffer_surface;
int w = view->width;
int h = view->height;
int bw = bs ? cairo_image_surface_get_width(bs) : -1;
int bh = bs ? cairo_image_surface_get_height(bs) : -1;
ws = hdc ? cairo_win32_surface_create(hdc) : NULL;
wc = ws ? cairo_create(ws) : NULL;
if (wc && (!bc || bw != w || bh != h)) {
cairo_destroy(bc);
cairo_surface_destroy(bs);
bs = cairo_surface_create_similar_image(ws, CAIRO_FORMAT_ARGB32, w, h);
bc = bs ? cairo_create(bs) : NULL;
impl->buffer_cr = bc;
impl->buffer_surface = bs;
}
success = wc != NULL && bc != NULL;
#endif

if (success) {
view->redisplay = false;
if (view->displayFunc) {
view->displayFunc(view);
}
#ifdef PUGL_CAIRO
cairo_set_source_surface(wc, bs, 0, 0);
cairo_paint(wc);
#endif
}

puglLeaveContext(view, true);
puglLeaveContext(view, success);

#ifdef PUGL_CAIRO
cairo_destroy(wc);
cairo_surface_destroy(ws);
#endif

return;
(void)impl;
}

static PuglKey
@@ -329,8 +401,9 @@ handleMessage(PuglView* view, UINT message, WPARAM wParam, LPARAM lParam)
mmi->ptMinTrackSize.y = view->min_height;
break;
case WM_PAINT:
BeginPaint(view->impl->hwnd, &ps);
view->impl->paintHdc = BeginPaint(view->impl->hwnd, &ps);
puglDisplay(view);
view->impl->paintHdc = NULL;
EndPaint(view->impl->hwnd, &ps);
break;
case WM_MOUSEMOVE:
@@ -469,6 +542,18 @@ puglGetNativeWindow(PuglView* view)
return (PuglNativeWindow)view->impl->hwnd;
}

void*
puglGetContext(PuglView* view)
{
#ifdef PUGL_CAIRO
return view->impl->buffer_cr;
#endif
return NULL;

// may be unused
(void)view;
}

int
puglUpdateGeometryConstraints(PuglView* view, int min_width, int min_height, bool aspect)
{


+ 133
- 8
dpf/dgl/src/pugl/pugl_x11.c View File

@@ -2,6 +2,7 @@
Copyright 2012-2014 David Robillard <http://drobilla.net>
Copyright 2011-2012 Ben Loftis, Harrison Consoles
Copyright 2013,2015 Robin Gareus <robin@gareus.org>
Copyright 2012-2019 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
@@ -24,8 +25,14 @@
#include <stdlib.h>
#include <string.h>

#ifdef PUGL_CAIRO
#include <cairo/cairo.h>
#include <cairo/cairo-xlib.h>
#endif
#ifdef PUGL_OPENGL
#include <GL/gl.h>
#include <GL/glx.h>
#endif
#include <X11/Xatom.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
@@ -53,10 +60,19 @@ struct PuglInternalsImpl {
Display* display;
int screen;
Window win;
#ifdef PUGL_CAIRO
cairo_t* xlib_cr;
cairo_t* buffer_cr;
cairo_surface_t* xlib_surface;
cairo_surface_t* buffer_surface;
#endif
#ifdef PUGL_OPENGL
GLXContext ctx;
Bool doubleBuffered;
#endif
};

#ifdef PUGL_OPENGL
/**
Attributes for single-buffered RGBA with at least
4 bits per color and a 16 bit depth buffer.
@@ -102,6 +118,7 @@ static int attrListDblMS[] = {
GLX_SAMPLES, 4,
None
};
#endif

PuglInternals*
puglInitInternals(void)
@@ -112,12 +129,15 @@ puglInitInternals(void)
void
puglEnterContext(PuglView* view)
{
#ifdef PUGL_OPENGL
glXMakeCurrent(view->impl->display, view->impl->win, view->impl->ctx);
#endif
}

void
puglLeaveContext(PuglView* view, bool flush)
{
#ifdef PUGL_OPENGL
if (flush) {
glFlush();
if (view->impl->doubleBuffered) {
@@ -125,12 +145,13 @@ puglLeaveContext(PuglView* view, bool flush)
}
}
glXMakeCurrent(view->impl->display, None, NULL);
#endif
}

int
puglCreateWindow(PuglView* view, const char* title)
{
PuglInternals* impl = (PuglInternals*)calloc(1, sizeof(PuglInternals));
PuglInternals* impl = view->impl;
if (!impl) {
return 1;
}
@@ -142,9 +163,12 @@ puglCreateWindow(PuglView* view, const char* title)
return 1;
}
impl->screen = DefaultScreen(impl->display);
impl->doubleBuffered = True;

XVisualInfo* vi = glXChooseVisual(impl->display, impl->screen, attrListDblMS);
XVisualInfo* vi = NULL;

#ifdef PUGL_OPENGL
impl->doubleBuffered = True;
vi = glXChooseVisual(impl->display, impl->screen, attrListDblMS);

if (!vi) {
vi = glXChooseVisual(impl->display, impl->screen, attrListDbl);
@@ -157,6 +181,13 @@ puglCreateWindow(PuglView* view, const char* title)
vi = glXChooseVisual(impl->display, impl->screen, attrListSgl);
impl->doubleBuffered = False;
}
#endif
#ifdef PUGL_CAIRO
XVisualInfo pat;
int n;
pat.screen = impl->screen;
vi = XGetVisualInfo(impl->display, VisualScreenMask, &pat, &n);
#endif

if (!vi) {
XCloseDisplay(impl->display);
@@ -165,18 +196,23 @@ puglCreateWindow(PuglView* view, const char* title)
}

#ifdef PUGL_VERBOSE
#ifdef PUGL_OPENGL
int glxMajor, glxMinor;
glXQueryVersion(impl->display, &glxMajor, &glxMinor);
printf("puGL: GLX-Version : %d.%d\n", glxMajor, glxMinor);
#endif
#endif

#ifdef PUGL_OPENGL
impl->ctx = glXCreateContext(impl->display, vi, 0, GL_TRUE);

if (!impl->ctx) {
XFree(vi);
XCloseDisplay(impl->display);
free(impl);
return 1;
}
#endif

Window xParent = view->parent
? (Window)view->parent
@@ -201,11 +237,36 @@ puglCreateWindow(PuglView* view, const char* title)
CWBorderPixel | CWColormap | CWEventMask, &attr);

if (!impl->win) {
#ifdef PUGL_OPENGL
glXDestroyContext(impl->display, impl->ctx);
#endif
XFree(vi);
XCloseDisplay(impl->display);
free(impl);
return 1;
}

#ifdef PUGL_CAIRO
impl->xlib_surface = cairo_xlib_surface_create(
impl->display, impl->win, vi->visual, view->width, view->height);
if (impl->xlib_surface == NULL || cairo_surface_status(impl->xlib_surface) != CAIRO_STATUS_SUCCESS) {
printf("puGL: failed to create cairo surface\n");
}
else {
impl->xlib_cr = cairo_create(impl->xlib_surface);
}
if (impl->xlib_cr == NULL || cairo_status(impl->xlib_cr) != CAIRO_STATUS_SUCCESS) {
cairo_destroy(impl->xlib_cr);
cairo_surface_destroy(impl->xlib_surface);
XDestroyWindow(impl->display, impl->win);
XFree(vi);
XCloseDisplay(impl->display);
free(impl);
printf("puGL: failed to create cairo context\n");
return 1;
}
#endif

if (view->width > 1 || view->height > 1) {
puglUpdateGeometryConstraints(view, view->min_width, view->min_height, view->min_width != view->width);
XResizeWindow(view->impl->display, view->impl->win, view->width, view->height);
@@ -227,11 +288,13 @@ puglCreateWindow(PuglView* view, const char* title)
}

#ifdef PUGL_VERBOSE
#ifdef PUGL_OPENGL
if (glXIsDirect(impl->display, impl->ctx)) {
printf("puGL: DRI enabled (to disable, set LIBGL_ALWAYS_INDIRECT=1\n");
} else {
printf("puGL: No DRI available\n");
}
#endif
#endif

XFree(vi);
@@ -244,14 +307,25 @@ puglDestroy(PuglView* view)
if (!view) {
return;
}

PuglInternals* const impl = view->impl;

#ifndef DGL_FILE_BROWSER_DISABLED
x_fib_close(view->impl->display);
x_fib_close(impl->display);
#endif

glXDestroyContext(view->impl->display, view->impl->ctx);
XDestroyWindow(view->impl->display, view->impl->win);
XCloseDisplay(view->impl->display);
free(view->impl);
#ifdef PUGL_OPENGL
glXDestroyContext(impl->display, impl->ctx);
#endif
#ifdef PUGL_CAIRO
cairo_destroy(impl->xlib_cr);
cairo_destroy(impl->buffer_cr);
cairo_surface_destroy(impl->xlib_surface);
cairo_surface_destroy(impl->buffer_surface);
#endif
XDestroyWindow(impl->display, impl->win);
XCloseDisplay(impl->display);
free(impl);
free(view);
}

@@ -287,14 +361,47 @@ puglReshape(PuglView* view, int width, int height)
static void
puglDisplay(PuglView* view)
{
PuglInternals* impl = view->impl;

puglEnterContext(view);

#ifdef PUGL_CAIRO
cairo_t* bc = impl->buffer_cr;
cairo_surface_t* xs = impl->xlib_surface;
cairo_surface_t* bs = impl->buffer_surface;
int w = cairo_xlib_surface_get_width(xs);
int h = cairo_xlib_surface_get_height(xs);

int bw = bs ? cairo_image_surface_get_width(bs) : -1;
int bh = bs ? cairo_image_surface_get_height(bs) : -1;
if (!bc || bw != w || bh != h) {
cairo_destroy(bc);
cairo_surface_destroy(bs);
bs = cairo_surface_create_similar_image(xs, CAIRO_FORMAT_ARGB32, w, h);
bc = bs ? cairo_create(bs) : NULL;
impl->buffer_cr = bc;
impl->buffer_surface = bs;
}

if (!bc) {
puglLeaveContext(view, false);
return;
}
#endif

view->redisplay = false;
if (view->displayFunc) {
view->displayFunc(view);
}

#ifdef PUGL_CAIRO
cairo_t* xc = impl->xlib_cr;
cairo_set_source_surface(xc, impl->buffer_surface, 0, 0);
cairo_paint(xc);
#endif

puglLeaveContext(view, true);
(void)impl;
}

static void
@@ -554,6 +661,12 @@ puglProcessEvents(PuglView* view)
}

if (conf_width != -1) {
#ifdef PUGL_CAIRO
// Resize surfaces/contexts before dispatching
view->redisplay = true;
cairo_xlib_surface_set_size(view->impl->xlib_surface,
conf_width, conf_height);
#endif
puglReshape(view, conf_width, conf_height);
}

@@ -586,6 +699,18 @@ puglGetNativeWindow(PuglView* view)
return view->impl->win;
}

void*
puglGetContext(PuglView* view)
{
#ifdef PUGL_CAIRO
return view->impl->buffer_cr;
#endif
return NULL;

// may be unused
(void)view;
}

int
puglUpdateGeometryConstraints(PuglView* view, int min_width, int min_height, bool aspect)
{


+ 15
- 1
dpf/distrho/DistrhoInfo.hpp View File

@@ -417,6 +417,10 @@ START_NAMESPACE_DISTRHO
};
@endcode

This is a work-in-progress documentation page. States, MIDI, Latency, Time-Position and UI are still TODO.
*/

#if 0
@section States
describe them

@@ -431,7 +435,7 @@ START_NAMESPACE_DISTRHO

@section UI
describe them
*/
#endif

/* ------------------------------------------------------------------------------------------------------------
* Plugin Macros */
@@ -543,6 +547,16 @@ START_NAMESPACE_DISTRHO
*/
#define DISTRHO_PLUGIN_WANT_STATE 1

/**
Wherever the plugin implements the full state API.
When this macro is enabled, the plugin must implement a new getState(const char* key) function, which the host calls when saving its session/project.
This is useful for plugins that have custom internal values not exposed to the host as key-value state pairs or parameters.
Most simple effects and synths will not need this.
@note this macro is automatically enabled if a plugin has programs and state, as the key-value state pairs need to be updated when the current program changes.
@see Plugin::getState(const char*)
*/
#define DISTRHO_PLUGIN_WANT_FULL_STATE 1

/**
Wherever the plugin wants time position information from the host.
@see Plugin::getTimePosition()


+ 1
- 1
dpf/distrho/DistrhoPlugin.hpp View File

@@ -226,7 +226,7 @@ struct ParameterRanges {
/**
Get a fixed value within range.
*/
const float& getFixedValue(const float& value) const noexcept
float getFixedValue(const float& value) const noexcept
{
if (value <= min)
return min;


+ 21
- 3
dpf/distrho/DistrhoUI.hpp View File

@@ -32,6 +32,13 @@ typedef DGL_NAMESPACE::NanoWidget UIWidget;
typedef DGL_NAMESPACE::Widget UIWidget;
#endif

#ifdef DGL_CAIRO
# include "Cairo.hpp"
#endif
#ifdef DGL_OPENGL
# include "OpenGL.hpp"
#endif

START_NAMESPACE_DISTRHO

/* ------------------------------------------------------------------------------------------------------------
@@ -62,7 +69,7 @@ public:
*/
virtual ~UI();

#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI
#if DISTRHO_UI_USER_RESIZABLE && !DISTRHO_PLUGIN_HAS_EXTERNAL_UI
/**
Set geometry constraints for the UI when resized by the user, and optionally scale UI automatically.
@see Window::setGeometryConstraints(uint,uint,bool)
@@ -82,13 +89,17 @@ public:

/**
editParameter.
@TODO Document this.

Touch/pressed-down event.
Lets the host know the user is tweaking a parameter.
Required in some hosts to record automation.
*/
void editParameter(uint32_t index, bool started);

/**
setParameterValue.
@TODO Document this.
Change a parameter value in the Plugin.
*/
void setParameterValue(uint32_t index, float value);

@@ -131,6 +142,13 @@ public:
*/
static const char* getNextBundlePath() noexcept;

/**
Get the scale factor that will be used for the next UI.
@note: This function is only valid during createUI(),
it will return 1.0 when called from anywhere else.
*/
static double getNextScaleFactor() noexcept;

# if DISTRHO_PLUGIN_HAS_EMBED_UI
/**
Get the Window Id that will be used for the next created window.


+ 2
- 2
dpf/distrho/src/DistrhoPluginChecks.h View File

@@ -97,7 +97,7 @@
// Define DISTRHO_PLUGIN_HAS_EMBED_UI if needed

#ifndef DISTRHO_PLUGIN_HAS_EMBED_UI
# ifdef HAVE_DGL
# if defined(HAVE_CAIRO) || defined(HAVE_OPENGL)
# define DISTRHO_PLUGIN_HAS_EMBED_UI 1
# else
# define DISTRHO_PLUGIN_HAS_EMBED_UI 0
@@ -139,7 +139,7 @@
// -----------------------------------------------------------------------
// Disable UI if DGL or External UI is not available

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


+ 11
- 1
dpf/distrho/src/DistrhoPluginJack.cpp View File

@@ -81,6 +81,16 @@ static void initSignalHandler()

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

#if DISTRHO_PLUGIN_HAS_UI
// TODO
static double getDesktopScaleFactor() noexcept
{
return 1.0;
}
#endif

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

#if DISTRHO_PLUGIN_HAS_UI
class PluginJack : public IdleCallback
#else
@@ -91,7 +101,7 @@ public:
PluginJack(jack_client_t* const client)
: fPlugin(this, writeMidiCallback),
#if DISTRHO_PLUGIN_HAS_UI
fUI(this, 0, nullptr, setParameterValueCallback, setStateCallback, nullptr, setSizeCallback, fPlugin.getInstancePointer()),
fUI(this, 0, nullptr, setParameterValueCallback, setStateCallback, nullptr, setSizeCallback, getDesktopScaleFactor(), fPlugin.getInstancePointer()),
#endif
fClient(client)
{


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

@@ -545,7 +545,7 @@ public:

#ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD
for (uint32_t i=0; i<DISTRHO_PLUGIN_NUM_OUTPUTS; ++i)
mod_license_run_noise(fRunCount, fPortAudioOuts[i], sampleCount, i);
mod_license_run_silence(fRunCount, fPortAudioOuts[i], sampleCount, i);
#endif

#if DISTRHO_PLUGIN_WANT_TIMEPOS


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

@@ -719,7 +719,7 @@ void lv2_generate_ttl(const char* const basename)
if (value.length() < 10)
presetString += " \"" + value + "\" ;\n";
else
presetString += "\n\"\"\"\n" + value + "\n\"\"\" ;\n";
presetString += "\n\"\"\"" + value + "\"\"\" ;\n";
}

if (numParameters > 0)


+ 10
- 4
dpf/distrho/src/DistrhoPluginVST.cpp View File

@@ -161,12 +161,12 @@ public:
class UIVst
{
public:
UIVst(const audioMasterCallback audioMaster, AEffect* const effect, ParameterCheckHelper* const uiHelper, PluginExporter* const plugin, const intptr_t winId)
UIVst(const audioMasterCallback audioMaster, AEffect* const effect, ParameterCheckHelper* const uiHelper, PluginExporter* const plugin, const intptr_t winId, const float scaleFactor)
: fAudioMaster(audioMaster),
fEffect(effect),
fUiHelper(uiHelper),
fPlugin(plugin),
fUI(this, winId, editParameterCallback, setParameterCallback, setStateCallback, sendNoteCallback, setSizeCallback, plugin->getInstancePointer()),
fUI(this, winId, editParameterCallback, setParameterCallback, setStateCallback, sendNoteCallback, setSizeCallback, scaleFactor, plugin->getInstancePointer()),
fShouldCaptureVstKeys(false)
{
// FIXME only needed for windows?
@@ -575,8 +575,11 @@ public:
else
{
d_lastUiSampleRate = fPlugin.getSampleRate();
// TODO
const float scaleFactor = 1.0f;

UIExporter tmpUI(nullptr, 0, nullptr, nullptr, nullptr, nullptr, nullptr, fPlugin.getInstancePointer());
UIExporter tmpUI(nullptr, 0, nullptr, nullptr, nullptr, nullptr, nullptr, scaleFactor, fPlugin.getInstancePointer());
fVstRect.right = tmpUI.getWidth();
fVstRect.bottom = tmpUI.getHeight();
tmpUI.quit();
@@ -595,8 +598,11 @@ public:
}
# endif
d_lastUiSampleRate = fPlugin.getSampleRate();
// TODO
const float scaleFactor = 1.0f;

fVstUI = new UIVst(fAudioMaster, fEffect, this, &fPlugin, (intptr_t)ptr);
fVstUI = new UIVst(fAudioMaster, fEffect, this, &fPlugin, (intptr_t)ptr, scaleFactor);

# if DISTRHO_PLUGIN_WANT_FULL_STATE
// Update current state from plugin side


+ 21
- 3
dpf/distrho/src/DistrhoUI.cpp View File

@@ -27,8 +27,9 @@ START_NAMESPACE_DISTRHO
double d_lastUiSampleRate = 0.0;
void* d_lastUiDspPtr = nullptr;
#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI
uintptr_t g_nextWindowId = 0;
const char* g_nextBundlePath = nullptr;
double g_nextScaleFactor = 1.0;
uintptr_t g_nextWindowId = 0;
#else
Window* d_lastUiWindow = nullptr;
#endif
@@ -57,7 +58,7 @@ UI::~UI()
delete pData;
}

#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI
#if DISTRHO_UI_USER_RESIZABLE && !DISTRHO_PLUGIN_HAS_EXTERNAL_UI
void UI::setGeometryConstraints(uint minWidth, uint minHeight, bool keepAspectRatio, bool automaticallyScale)
{
DISTRHO_SAFE_ASSERT_RETURN(minWidth > 0,);
@@ -67,7 +68,13 @@ void UI::setGeometryConstraints(uint minWidth, uint minHeight, bool keepAspectRa
pData->minWidth = minWidth;
pData->minHeight = minHeight;

getParentWindow().setGeometryConstraints(minWidth, minHeight, keepAspectRatio);
Window& window(getParentWindow());

const double uiScaleFactor = window.getScaling();
window.setGeometryConstraints(minWidth * uiScaleFactor, minHeight * uiScaleFactor, keepAspectRatio);

if (d_isNotZero(uiScaleFactor - 1.0))
setSize(getWidth() * uiScaleFactor, getHeight() * uiScaleFactor);
}
#endif

@@ -122,6 +129,11 @@ const char* UI::getNextBundlePath() noexcept
return g_nextBundlePath;
}

double UI::getNextScaleFactor() noexcept
{
return g_nextScaleFactor;
}

# if DISTRHO_PLUGIN_HAS_EMBED_UI
uintptr_t UI::getNextWindowId() noexcept
{
@@ -147,6 +159,7 @@ void UI::uiFileBrowserSelected(const char*)

void UI::uiReshape(uint width, uint height)
{
#ifdef DGL_OPENGL
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glMatrixMode(GL_PROJECTION);
@@ -155,6 +168,11 @@ void UI::uiReshape(uint width, uint height)
glViewport(0, 0, static_cast<GLsizei>(width), static_cast<GLsizei>(height));
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
#else
// unused
(void)width;
(void)height;
#endif
}

/* ------------------------------------------------------------------------------------------------------------


+ 21
- 16
dpf/distrho/src/DistrhoUIInternal.hpp View File

@@ -37,11 +37,13 @@ START_NAMESPACE_DISTRHO

extern double d_lastUiSampleRate;
extern void* d_lastUiDspPtr;
#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI
#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI
extern const char* g_nextBundlePath;
extern double g_nextScaleFactor;
extern uintptr_t g_nextWindowId;
#else
extern Window* d_lastUiWindow;
#endif
extern uintptr_t g_nextWindowId;
extern const char* g_nextBundlePath;

// -----------------------------------------------------------------------
// UI callbacks
@@ -149,15 +151,17 @@ struct UI::PrivateData {

#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI
static inline
UI* createUiWrapper(void* const dspPtr, const uintptr_t winId, const char* const bundlePath)
UI* createUiWrapper(void* const dspPtr, const uintptr_t winId, const double scaleFactor, const char* const bundlePath)
{
d_lastUiDspPtr = dspPtr;
g_nextWindowId = winId;
g_nextBundlePath = bundlePath;
UI* const ret = createUI();
d_lastUiDspPtr = nullptr;
g_nextWindowId = 0;
g_nextBundlePath = nullptr;
d_lastUiDspPtr = dspPtr;
g_nextWindowId = winId;
g_nextScaleFactor = scaleFactor;
g_nextBundlePath = bundlePath;
UI* const ret = createUI();
d_lastUiDspPtr = nullptr;
g_nextWindowId = 0;
g_nextScaleFactor = 1.0;
g_nextBundlePath = nullptr;
return ret;
}
#else // DISTRHO_PLUGIN_HAS_EXTERNAL_UI
@@ -175,8 +179,8 @@ UI* createUiWrapper(void* const dspPtr, Window* const window)
class UIExporterWindow : public Window
{
public:
UIExporterWindow(Application& app, const intptr_t winId, void* const dspPtr)
: Window(app, winId, DISTRHO_UI_USER_RESIZABLE),
UIExporterWindow(Application& app, const intptr_t winId, const double scaleFactor, void* const dspPtr)
: Window(app, winId, scaleFactor, DISTRHO_UI_USER_RESIZABLE),
fUI(createUiWrapper(dspPtr, this)),
fIsReady(false)
{
@@ -214,7 +218,7 @@ protected:
{
const double scaleHorizontal = static_cast<double>(width) / static_cast<double>(pData->minWidth);
const double scaleVertical = static_cast<double>(height) / static_cast<double>(pData->minHeight);
setScaling(scaleHorizontal < scaleVertical ? scaleHorizontal : scaleVertical);
_setAutoScaling(scaleHorizontal < scaleVertical ? scaleHorizontal : scaleVertical);
}

pData->resizeInProgress = true;
@@ -254,13 +258,14 @@ public:
const setStateFunc setStateCall,
const sendNoteFunc sendNoteCall,
const setSizeFunc setSizeCall,
const float scaleFactor = 1.0f,
void* const dspPtr = nullptr,
const char* const bundlePath = nullptr)
#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI
: fUI(createUiWrapper(dspPtr, winId, bundlePath)),
: fUI(createUiWrapper(dspPtr, winId, scaleFactor, bundlePath)),
#else
: glApp(),
glWindow(glApp, winId, dspPtr),
glWindow(glApp, winId, scaleFactor, dspPtr),
fChangingSize(false),
fUI(glWindow.getUI()),
#endif


+ 16
- 8
dpf/distrho/src/DistrhoUILV2.cpp View File

@@ -53,8 +53,8 @@ public:
UiLv2(const char* const bundlePath, const intptr_t winId,
const LV2_Options_Option* options, const LV2_URID_Map* const uridMap, const LV2UI_Resize* const uiResz, const LV2UI_Touch* uiTouch,
const LV2UI_Controller controller, const LV2UI_Write_Function writeFunc,
LV2UI_Widget* const widget, void* const dspPtr)
: fUI(this, winId, editParameterCallback, setParameterCallback, setStateCallback, sendNoteCallback, setSizeCallback, dspPtr, bundlePath),
const float scaleFactor, LV2UI_Widget* const widget, void* const dspPtr)
: fUI(this, winId, editParameterCallback, setParameterCallback, setStateCallback, sendNoteCallback, setSizeCallback, scaleFactor, dspPtr, bundlePath),
fUridMap(uridMap),
fUiResize(uiResz),
fUiTouch(uiTouch),
@@ -286,7 +286,7 @@ protected:
atomMidiEvent.data[2] = velocity;

// send to DSP side
fWriteFunction(fController, eventInPortIndex, sizeof(LV2_Atom_MidiEvent), fEventTransferURID, &atomMidiEvent);
fWriteFunction(fController, eventInPortIndex, lv2_atom_total_size(&atomMidiEvent.atom), fEventTransferURID, &atomMidiEvent);
}
#endif

@@ -434,22 +434,30 @@ static LV2UI_Handle lv2ui_instantiate(const LV2UI_Descriptor*, const char* uri,
}
#endif

float scaleFactor = 1.0f;
const intptr_t winId((intptr_t)parentId);

if (options != nullptr)
{
const LV2_URID uridAtomFloat(uridMap->map(uridMap->handle, LV2_ATOM__Float));
const LV2_URID uridSampleRate(uridMap->map(uridMap->handle, LV2_PARAMETERS__sampleRate));
const LV2_URID uridScaleFactor(uridMap->map(uridMap->handle, LV2_UI__scaleFactor));

for (int i=0; options[i].key != 0; ++i)
{
if (options[i].key == uridSampleRate)
/**/ if (options[i].key == uridSampleRate)
{
if (options[i].type == uridMap->map(uridMap->handle, LV2_ATOM__Float))
if (options[i].type == uridAtomFloat)
d_lastUiSampleRate = *(const float*)options[i].value;
else
d_stderr("Host provides UI sample-rate but has wrong value type");

break;
}
else if (options[i].key == uridScaleFactor)
{
if (options[i].type == uridAtomFloat)
scaleFactor = *(const float*)options[i].value;
else
d_stderr("Host provides UI scale factor but has wrong value type");
}
}
}
@@ -460,7 +468,7 @@ static LV2UI_Handle lv2ui_instantiate(const LV2UI_Descriptor*, const char* uri,
d_lastUiSampleRate = 44100.0;
}

return new UiLv2(bundlePath, winId, options, uridMap, uiResize, uiTouch, controller, writeFunction, widget, instance);
return new UiLv2(bundlePath, winId, options, uridMap, uiResize, uiTouch, controller, writeFunction, scaleFactor, widget, instance);
}

#define uiPtr ((UiLv2*)ui)


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

@@ -52,6 +52,7 @@
#define LV2_UI__portNotification LV2_UI_PREFIX "portNotification"
#define LV2_UI__portSubscribe LV2_UI_PREFIX "portSubscribe"
#define LV2_UI__resize LV2_UI_PREFIX "resize"
#define LV2_UI__scaleFactor LV2_UI_PREFIX "scaleFactor"
#define LV2_UI__showInterface LV2_UI_PREFIX "showInterface"
#define LV2_UI__touch LV2_UI_PREFIX "touch"
#define LV2_UI__ui LV2_UI_PREFIX "ui"


+ 2
- 1
dpf/dpf.doxygen View File

@@ -242,7 +242,8 @@ SEARCH_INCLUDES = YES
INCLUDE_PATH =
INCLUDE_FILE_PATTERNS =
PREDEFINED = DOXYGEN \
HAVE_DGL=1 \
HAVE_CAIRO=1 \
HAVE_OPENGL=1 \
DISTRHO_PLUGIN_NAME="Plugin Name" \
DISTRHO_PLUGIN_NUM_INPUTS=2 \
DISTRHO_PLUGIN_NUM_OUTPUTS=2 \


+ 1
- 1
dpf/utils/lv2-ttl-generator/GNUmakefile View File

@@ -2,7 +2,7 @@

all: build

ifeq ($(WIN32),true)
ifeq ($(WINDOWS),true)
build: ../lv2_ttl_generator.exe
else
build: ../lv2_ttl_generator


dpf/utils/png2c.py → dpf/utils/res2c.py View File

@@ -19,7 +19,7 @@ import os, sys

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

def png2c(namespace, filenames):
def res2c(namespace, filenames):

fdH = open("%s.hpp" % namespace, "w")
fdH.write("/* (Auto-generated binary data file). */\n")
@@ -42,12 +42,12 @@ def png2c(namespace, filenames):
shortFilename = filename.rsplit(os.sep, 1)[-1].split(".", 1)[0]
shortFilename = shortFilename.replace("-", "_")

pngData = open(filename, 'rb').read()
resData = open(filename, 'rb').read()

print("Generating data for \"%s\"" % (filename))

fdH.write(" extern const char* %sData;\n" % shortFilename)
fdH.write(" const unsigned int %sDataSize = %i;\n" % (shortFilename, len(pngData)))
fdH.write(" const unsigned int %sDataSize = %i;\n" % (shortFilename, len(resData)))

if tempIndex != len(filenames):
fdH.write("\n")
@@ -57,7 +57,7 @@ def png2c(namespace, filenames):
curColumn = 1
fdC.write(" ")

for data in pngData:
for data in resData:
if curColumn == 0:
fdC.write(" ")

@@ -90,24 +90,24 @@ def png2c(namespace, filenames):

if __name__ == '__main__':
if len(sys.argv) != 3:
print("Usage: %s <namespace> <artwork-folder>" % sys.argv[0])
print("Usage: %s <namespace> <resource-folder>" % sys.argv[0])
quit()

namespace = sys.argv[1].replace("-","_")
artFolder = sys.argv[2]
resFolder = sys.argv[2]

if not os.path.exists(artFolder):
print("Folder '%s' does not exist" % artFolder)
if not os.path.exists(resFolder):
print("Folder '%s' does not exist" % resFolder)
quit()

# find png files
pngFiles = []
# find resource files
resFiles = []

for root, dirs, files in os.walk(artFolder):
for name in [name for name in files if name.lower().endswith(".png")]:
pngFiles.append(os.path.join(root, name))
for root, dirs, files in os.walk(resFolder):
for name in files:
resFiles.append(os.path.join(root, name))

pngFiles.sort()
resFiles.sort()

# create code now
png2c(namespace, pngFiles)
res2c(namespace, resFiles)

+ 56
- 19
plugins/Kars/DistrhoPluginKars.cpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Kars Plugin, based on karplong by Chris Cannam.
* Copyright (C) 2015 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2015-2019 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
@@ -158,7 +158,8 @@ public:
midiEvents(m),
midiEventCount(0),
remainingFrames(f),
remainingMidiEventCount(mc) {}
remainingMidiEventCount(mc),
totalFramesUsed(0) {}
/**
Process a batch of events untill no more are available.
@@ -166,41 +167,76 @@ public:
*/
bool nextEvent()
{
if (remainingMidiEventCount == 0)
// nothing else to do
if (remainingFrames == 0)
return false;
// initial setup, need to find first MIDI event
if (totalFramesUsed == 0)
{
if (remainingFrames == 0)
return false;
// no MIDI events at all in this process cycle
if (remainingMidiEventCount == 0)
{
frames = remainingFrames;
remainingFrames = 0;
totalFramesUsed += frames;
return true;
}
// render audio until first midi event, if needed
if (const uint32_t firstEventFrame = midiEvents[0].frame)
{
frames = midiEvents[0].frame;
remainingFrames -= frames;
totalFramesUsed += frames;
return true;
}
}
else
{
for (uint32_t i=0; i<DISTRHO_PLUGIN_NUM_OUTPUTS; ++i)
outputs[i] += frames;
}
if (midiEventCount != 0)
midiEvents += midiEventCount;
// no more MIDI events available
if (remainingMidiEventCount == 0)
{
frames = remainingFrames;
midiEvents = nullptr;
midiEventCount = 0;
remainingFrames = 0;
totalFramesUsed += frames;
return true;
}
const uint32_t eventFrame = midiEvents[0].frame;
DISTRHO_SAFE_ASSERT_RETURN(eventFrame < remainingFrames, false);
// if there were midi events before, increment pointer
if (midiEventCount != 0)
midiEvents += midiEventCount;
midiEventCount = 1;
const uint32_t firstEventFrame = midiEvents[0].frame;
DISTRHO_SAFE_ASSERT_RETURN((firstEventFrame - frames) < remainingFrames, false);
for (uint32_t i=1; i<remainingMidiEventCount; ++i)
midiEventCount = 1;
while (midiEventCount < remainingMidiEventCount)
{
if (midiEvents[i].frame != eventFrame)
{
midiEventCount = i;
if (midiEvents[midiEventCount].frame == firstEventFrame)
++midiEventCount;
else
break;
}
}
frames = remainingFrames - eventFrame;
if (totalFramesUsed != 0)
{
// need to modify timestamp of midi events
MidiEvent* const rwEvents = const_cast<MidiEvent*>(midiEvents);
for (uint32_t i=0; i < midiEventCount; ++i)
rwEvents[i].frame -= totalFramesUsed;
}
frames = remainingFrames - firstEventFrame;
remainingFrames -= frames;
remainingMidiEventCount -= midiEventCount;
totalFramesUsed += frames;
return true;
}
@@ -208,6 +244,7 @@ private:
/** @internal */
uint32_t remainingFrames;
uint32_t remainingMidiEventCount;
uint32_t totalFramesUsed;
};
void DistrhoPluginKars::run(const float**, float** outputs, uint32_t frames, const MidiEvent* midiEvents, uint32_t midiEventCount)
@@ -254,9 +291,9 @@ void DistrhoPluginKars::run(const float**, float** outputs, uint32_t frames, con
if (fNotes[i].on != kNoteNull)
addSamples(out, i, amsh.frames);
}
}
fBlockStart += frames;
fBlockStart += amsh.frames;
}
}
void DistrhoPluginKars::addSamples(float* out, int voice, uint32_t frames)


+ 2
- 2
plugins/Kars/DistrhoPluginKars.hpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Kars Plugin, based on karplong by Chris Cannam.
* Copyright (C) 2015 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2015-2019 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
@@ -70,7 +70,7 @@ protected:
uint32_t getVersion() const noexcept override
{
return d_version(1, 0, 0);
return d_version(1, 1, 0);
}
int64_t getUniqueId() const noexcept override


+ 1
- 0
plugins/bitcrush/Makefile View File

@@ -24,6 +24,7 @@ include ../../dpf/Makefile.plugins.mk
# Extra flags

BUILD_CXX_FLAGS += -I../common -I../common/gen_dsp
BUILD_CXX_FLAGS += -Wno-unused-parameter

# --------------------------------------------------------------
# Enable all possible plugin types


+ 1
- 0
plugins/freeverb/Makefile View File

@@ -24,6 +24,7 @@ include ../../dpf/Makefile.plugins.mk
# Extra flags

BUILD_CXX_FLAGS += -I../common -I../common/gen_dsp
BUILD_CXX_FLAGS += -Wno-unused-parameter

# --------------------------------------------------------------
# Enable all possible plugin types


+ 1
- 0
plugins/gigaverb/Makefile View File

@@ -24,6 +24,7 @@ include ../../dpf/Makefile.plugins.mk
# Extra flags

BUILD_CXX_FLAGS += -I../common -I../common/gen_dsp
BUILD_CXX_FLAGS += -Wno-unused-parameter

# --------------------------------------------------------------
# Enable all possible plugin types


+ 1
- 1
plugins/glBars/DistrhoUIGLBars.cpp View File

@@ -3,7 +3,7 @@
* Copyright (C) 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson and 4Front Technologies
* Copyright (C) 2000 Christian Zander <phoenix@minion.de>
* Copyright (C) 2015 Nedko Arnaudov
* Copyright (C) 2016 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2016-2019 Filipe Coelho <falktx@falktx.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as


+ 1
- 2
plugins/glBars/DistrhoUIGLBars.hpp View File

@@ -3,7 +3,7 @@
* Copyright (C) 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson and 4Front Technologies
* Copyright (C) 2000 Christian Zander <phoenix@minion.de>
* Copyright (C) 2015 Nedko Arnaudov
* Copyright (C) 2016 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2016-2019 Filipe Coelho <falktx@falktx.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -45,7 +45,6 @@ protected:
// UI Callbacks

void uiIdle() override;
// void uiReshape(uint width, uint height) override;

// -------------------------------------------------------------------
// Widget Callbacks


+ 2
- 2
plugins/glBars/glBars.hpp View File

@@ -3,7 +3,7 @@
* Copyright (C) 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson and 4Front Technologies
* Copyright (C) 2000 Christian Zander <phoenix@minion.de>
* Copyright (C) 2015 Nedko Arnaudov
* Copyright (C) 2016 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2016-2019 Filipe Coelho <falktx@falktx.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -20,7 +20,7 @@
#ifndef GLBARS_STATE_HPP_INCLUDED
#define GLBARS_STATE_HPP_INCLUDED

#include "Base.hpp"
#include "OpenGL.hpp"

static inline
void draw_rectangle(GLfloat x1, GLfloat y1, GLfloat z1, GLfloat x2, GLfloat y2, GLfloat z2)


+ 1
- 0
plugins/pitchshift/Makefile View File

@@ -24,6 +24,7 @@ include ../../dpf/Makefile.plugins.mk
# Extra flags

BUILD_CXX_FLAGS += -I../common -I../common/gen_dsp
BUILD_CXX_FLAGS += -Wno-unused-parameter

# --------------------------------------------------------------
# Enable all possible plugin types


Loading…
Cancel
Save