@@ -20,7 +20,7 @@ HAVE_PROJM = $(shell pkg-config --exists libprojectM && echo true) | |||||
# -------------------------------------------------------------- | # -------------------------------------------------------------- | ||||
dgl: | dgl: | ||||
ifeq ($(HAVE_DGL),true) | |||||
ifeq ($(HAVE_CAIRO_OR_OPENGL),true) | |||||
$(MAKE) -C dpf/dgl | $(MAKE) -C dpf/dgl | ||||
endif | endif | ||||
@@ -50,7 +50,7 @@ plugins: dgl | |||||
$(MAKE) all -C plugins/gigaverb | $(MAKE) all -C plugins/gigaverb | ||||
$(MAKE) all -C plugins/pitchshift | $(MAKE) all -C plugins/pitchshift | ||||
ifeq ($(HAVE_DGL),true) | |||||
ifeq ($(HAVE_CAIRO_OR_OPENGL),true) | |||||
# glBars (needs OpenGL) | # glBars (needs OpenGL) | ||||
$(MAKE) all -C plugins/glBars | $(MAKE) all -C plugins/glBars | ||||
@@ -58,7 +58,7 @@ ifeq ($(HAVE_PROJM),true) | |||||
# ProM (needs OpenGL + ProjectM) | # ProM (needs OpenGL + ProjectM) | ||||
$(MAKE) all -C plugins/ProM | $(MAKE) all -C plugins/ProM | ||||
endif # HAVE_PROJM | endif # HAVE_PROJM | ||||
endif # HAVE_DGL | |||||
endif # HAVE_CAIRO_OR_OPENGL | |||||
ifneq ($(CROSS_COMPILING),true) | ifneq ($(CROSS_COMPILING),true) | ||||
gen: plugins dpf/utils/lv2_ttl_generator | 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/*-dssi.* $(DESTDIR)$(PREFIX)/lib/dssi/ | ||||
install -m 644 bin/*-vst.* $(DESTDIR)$(PREFIX)/lib/vst/ | 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/ | cp -r bin/*-dssi $(DESTDIR)$(PREFIX)/lib/dssi/ | ||||
endif # HAVE_DGL | |||||
endif # HAVE_CAIRO_OR_OPENGL | |||||
cp -r bin/*.lv2 $(DESTDIR)$(PREFIX)/lib/lv2/ | cp -r bin/*.lv2 $(DESTDIR)$(PREFIX)/lib/lv2/ | ||||
ifeq ($(HAVE_JACK),true) | ifeq ($(HAVE_JACK),true) | ||||
@@ -142,12 +142,12 @@ ifeq ($(HAVE_JACK),true) | |||||
install -m 755 bin/MaFreeverb $(DESTDIR)$(PREFIX)/bin/ | install -m 755 bin/MaFreeverb $(DESTDIR)$(PREFIX)/bin/ | ||||
install -m 755 bin/MaGigaverb $(DESTDIR)$(PREFIX)/bin/ | install -m 755 bin/MaGigaverb $(DESTDIR)$(PREFIX)/bin/ | ||||
install -m 755 bin/MaPitchshift $(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/ | install -m 755 bin/glBars $(DESTDIR)$(PREFIX)/bin/ | ||||
ifeq ($(HAVE_PROJM),true) | ifeq ($(HAVE_PROJM),true) | ||||
install -m 755 bin/ProM $(DESTDIR)$(PREFIX)/bin/ | install -m 755 bin/ProM $(DESTDIR)$(PREFIX)/bin/ | ||||
endif # HAVE_PROJM | endif # HAVE_PROJM | ||||
endif # HAVE_DGL | |||||
endif # HAVE_CAIRO_OR_OPENGL | |||||
endif # HAVE_JACK | endif # HAVE_JACK | ||||
# -------------------------------------------------------------- | # -------------------------------------------------------------- | ||||
@@ -16,7 +16,7 @@ ifneq ($(HAIKU),true) | |||||
ifneq ($(HURD),true) | ifneq ($(HURD),true) | ||||
ifneq ($(LINUX),true) | ifneq ($(LINUX),true) | ||||
ifneq ($(MACOS),true) | ifneq ($(MACOS),true) | ||||
ifneq ($(WIN32),true) | |||||
ifneq ($(WINDOWS),true) | |||||
TARGET_MACHINE := $(shell $(CC) -dumpmachine) | TARGET_MACHINE := $(shell $(CC) -dumpmachine) | ||||
ifneq (,$(findstring bsd,$(TARGET_MACHINE))) | ifneq (,$(findstring bsd,$(TARGET_MACHINE))) | ||||
@@ -35,7 +35,7 @@ ifneq (,$(findstring apple,$(TARGET_MACHINE))) | |||||
MACOS=true | MACOS=true | ||||
endif | endif | ||||
ifneq (,$(findstring mingw,$(TARGET_MACHINE))) | ifneq (,$(findstring mingw,$(TARGET_MACHINE))) | ||||
WIN32=true | |||||
WINDOWS=true | |||||
endif | endif | ||||
endif | endif | ||||
@@ -45,6 +45,16 @@ endif | |||||
endif | 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 | # Set LINUX_OR_MACOS | ||||
@@ -57,14 +67,20 @@ LINUX_OR_MACOS=true | |||||
endif | 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) | ifeq ($(MACOS),true) | ||||
MACOS_OR_WIN32=true | |||||
MACOS_OR_WINDOWS=true | |||||
HAIKU_OR_MACOS_OR_WINDOWS=true | |||||
endif | endif | ||||
ifeq ($(WIN32),true) | |||||
MACOS_OR_WIN32=true | |||||
ifeq ($(WINDOWS),true) | |||||
MACOS_OR_WINDOWS=true | |||||
HAIKU_OR_MACOS_OR_WINDOWS=true | |||||
endif | endif | ||||
# --------------------------------------------------------------------------------------------------------------------- | # --------------------------------------------------------------------------------------------------------------------- | ||||
@@ -108,10 +124,12 @@ ifeq ($(NOOPT),true) | |||||
BASE_OPTS = -O2 -ffast-math -fdata-sections -ffunction-sections | BASE_OPTS = -O2 -ffast-math -fdata-sections -ffunction-sections | ||||
endif | endif | ||||
ifeq ($(WIN32),true) | |||||
ifeq ($(WINDOWS),true) | |||||
# mingw has issues with this specific optimization | # mingw has issues with this specific optimization | ||||
# See https://github.com/falkTX/Carla/issues/696 | # See https://github.com/falkTX/Carla/issues/696 | ||||
BASE_OPTS += -fno-rerun-cse-after-loop | BASE_OPTS += -fno-rerun-cse-after-loop | ||||
# See https://github.com/falkTX/Carla/issues/855 | |||||
BASE_OPTS += -mstackrealign | |||||
ifeq ($(BUILDING_FOR_WINDOWS),true) | ifeq ($(BUILDING_FOR_WINDOWS),true) | ||||
BASE_FLAGS += -DBUILDING_CARLA_FOR_WINDOWS | BASE_FLAGS += -DBUILDING_CARLA_FOR_WINDOWS | ||||
endif | endif | ||||
@@ -141,7 +159,7 @@ ifeq ($(MACOS_OLD),true) | |||||
BUILD_CXX_FLAGS = $(BASE_FLAGS) $(CXXFLAGS) -DHAVE_CPP11_SUPPORT=0 | BUILD_CXX_FLAGS = $(BASE_FLAGS) $(CXXFLAGS) -DHAVE_CPP11_SUPPORT=0 | ||||
endif | endif | ||||
ifeq ($(WIN32),true) | |||||
ifeq ($(WINDOWS),true) | |||||
# Always build statically on windows | # Always build statically on windows | ||||
LINK_FLAGS += -static | LINK_FLAGS += -static | ||||
endif | endif | ||||
@@ -170,44 +188,81 @@ CXXFLAGS += -Weffc++ -Wnon-virtual-dtor -Woverloaded-virtual | |||||
endif | 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 | 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 | 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 | endif | ||||
# --------------------------------------------------------------------------------------------------------------------- | # --------------------------------------------------------------------------------------------------------------------- | ||||
# Set libs stuff | |||||
# Set OpenGL specific stuff | |||||
ifeq ($(HAVE_OPENGL),true) | |||||
ifeq ($(HAVE_DGL),true) | |||||
DGL_FLAGS += -DHAVE_OPENGL | |||||
ifeq ($(MACOS),true) | ifeq ($(MACOS),true) | ||||
DGL_LIBS = -framework OpenGL -framework Cocoa | |||||
OPENGL_LIBS = -framework OpenGL | |||||
endif | endif | ||||
ifeq ($(WIN32),true) | |||||
DGL_LIBS = -lopengl32 -lgdi32 | |||||
ifeq ($(WINDOWS),true) | |||||
OPENGL_LIBS = -lopengl32 | |||||
endif | 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 | ||||
endif # HAVE_DGL | |||||
HAVE_CAIRO_OR_OPENGL = true | |||||
endif | |||||
# --------------------------------------------------------------------------------------------------------------------- | # --------------------------------------------------------------------------------------------------------------------- | ||||
# Set app extension | # Set app extension | ||||
ifeq ($(WIN32),true) | |||||
ifeq ($(WINDOWS),true) | |||||
APP_EXT = .exe | APP_EXT = .exe | ||||
endif | endif | ||||
@@ -220,17 +275,17 @@ ifeq ($(MACOS),true) | |||||
LIB_EXT = .dylib | LIB_EXT = .dylib | ||||
endif | endif | ||||
ifeq ($(WIN32),true) | |||||
ifeq ($(WINDOWS),true) | |||||
LIB_EXT = .dll | LIB_EXT = .dll | ||||
endif | endif | ||||
# --------------------------------------------------------------------------------------------------------------------- | # --------------------------------------------------------------------------------------------------------------------- | ||||
# Set shared library CLI arg | # Set shared library CLI arg | ||||
SHARED = -shared | |||||
ifeq ($(MACOS),true) | ifeq ($(MACOS),true) | ||||
SHARED = -dynamiclib | SHARED = -dynamiclib | ||||
else | |||||
SHARED = -shared | |||||
endif | endif | ||||
# --------------------------------------------------------------------------------------------------------------------- | # --------------------------------------------------------------------------------------------------------------------- |
@@ -15,10 +15,6 @@ endif | |||||
include $(DPF_PATH)/Makefile.base.mk | include $(DPF_PATH)/Makefile.base.mk | ||||
ifeq ($(FILES_UI),) | |||||
HAVE_DGL = false | |||||
endif | |||||
# --------------------------------------------------------------------------------------------------------------------- | # --------------------------------------------------------------------------------------------------------------------- | ||||
# Basic setup | # Basic setup | ||||
@@ -28,8 +24,12 @@ BUILD_DIR = ../../build/$(NAME) | |||||
BUILD_C_FLAGS += -I. | BUILD_C_FLAGS += -I. | ||||
BUILD_CXX_FLAGS += -I. -I$(DPF_PATH)/distrho -I$(DPF_PATH)/dgl | 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 | endif | ||||
ifeq ($(HAVE_JACK),true) | 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) | 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) | ifneq ($(HAVE_DGL),true) | ||||
dssi_ui = | dssi_ui = | ||||
@@ -68,6 +100,9 @@ DGL_LIBS = | |||||
OBJS_UI = | OBJS_UI = | ||||
endif | endif | ||||
# TODO split dsp and ui object build flags | |||||
BASE_FLAGS += $(DGL_FLAGS) | |||||
# --------------------------------------------------------------------------------------------------------------------- | # --------------------------------------------------------------------------------------------------------------------- | ||||
# all needs to be first | # all needs to be first | ||||
@@ -81,6 +116,11 @@ $(BUILD_DIR)/%.c.o: %.c | |||||
@echo "Compiling $<" | @echo "Compiling $<" | ||||
@$(CC) $< $(BUILD_C_FLAGS) -c -o $@ | @$(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 | $(BUILD_DIR)/%.cpp.o: %.cpp | ||||
-@mkdir -p "$(shell dirname $(BUILD_DIR)/$<)" | -@mkdir -p "$(shell dirname $(BUILD_DIR)/$<)" | ||||
@echo "Compiling $<" | @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 | $(BUILD_DIR)/DistrhoPluginMain_JACK.cpp.o: $(DPF_PATH)/distrho/DistrhoPluginMain.cpp | ||||
-@mkdir -p $(BUILD_DIR) | -@mkdir -p $(BUILD_DIR) | ||||
@echo "Compiling DistrhoPluginMain.cpp (JACK)" | @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 | $(BUILD_DIR)/DistrhoUIMain_DSSI.cpp.o: $(DPF_PATH)/distrho/DistrhoUIMain.cpp | ||||
-@mkdir -p $(BUILD_DIR) | -@mkdir -p $(BUILD_DIR) | ||||
@echo "Compiling DistrhoUIMain.cpp (DSSI)" | @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 | # JACK | ||||
@@ -118,13 +158,13 @@ $(BUILD_DIR)/DistrhoUIMain_DSSI.cpp.o: $(DPF_PATH)/distrho/DistrhoUIMain.cpp | |||||
jack: $(jack) | jack: $(jack) | ||||
ifeq ($(HAVE_DGL),true) | 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 | else | ||||
$(jack): $(OBJS_DSP) $(BUILD_DIR)/DistrhoPluginMain_JACK.cpp.o | $(jack): $(OBJS_DSP) $(BUILD_DIR)/DistrhoPluginMain_JACK.cpp.o | ||||
endif | endif | ||||
-@mkdir -p $(shell dirname $@) | -@mkdir -p $(shell dirname $@) | ||||
@echo "Creating JACK standalone for $(NAME)" | @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 | # LADSPA | ||||
@@ -148,10 +188,10 @@ $(dssi_dsp): $(OBJS_DSP) $(BUILD_DIR)/DistrhoPluginMain_DSSI.cpp.o | |||||
@echo "Creating DSSI plugin library for $(NAME)" | @echo "Creating DSSI plugin library for $(NAME)" | ||||
@$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(SHARED) -o $@ | @$(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 $@) | -@mkdir -p $(shell dirname $@) | ||||
@echo "Creating DSSI UI for $(NAME)" | @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 | # LV2 | ||||
@@ -160,7 +200,7 @@ lv2: $(lv2) | |||||
lv2_dsp: $(lv2_dsp) | lv2_dsp: $(lv2_dsp) | ||||
lv2_sep: $(lv2_dsp) $(lv2_ui) | 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 $@) | -@mkdir -p $(shell dirname $@) | ||||
@echo "Creating LV2 plugin for $(NAME)" | @echo "Creating LV2 plugin for $(NAME)" | ||||
@$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(DGL_LIBS) $(SHARED) -o $@ | @$(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)" | @echo "Creating LV2 plugin library for $(NAME)" | ||||
@$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(SHARED) -o $@ | @$(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 $@) | -@mkdir -p $(shell dirname $@) | ||||
@echo "Creating LV2 plugin UI for $(NAME)" | @echo "Creating LV2 plugin UI for $(NAME)" | ||||
@$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(DGL_LIBS) $(SHARED) -o $@ | @$(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) | vst: $(vst) | ||||
ifeq ($(HAVE_DGL),true) | 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 | else | ||||
$(vst): $(OBJS_DSP) $(BUILD_DIR)/DistrhoPluginMain_VST.cpp.o | $(vst): $(OBJS_DSP) $(BUILD_DIR)/DistrhoPluginMain_VST.cpp.o | ||||
endif | endif | ||||
@@ -28,7 +28,7 @@ List of plugins made with DPF:<br/> | |||||
- [Juice Plugins](https://github.com/DISTRHO/JuicePlugins) (work in progress) | - [Juice Plugins](https://github.com/DISTRHO/JuicePlugins) (work in progress) | ||||
- [ZamAudio Suite](https://github.com/zamaudio/zam-plugins) | - [ZamAudio Suite](https://github.com/zamaudio/zam-plugins) | ||||
- [DragonFly-Reverb](https://github.com/michaelwillis/dragonfly-reverb) | - [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) | - [YK Chorus](https://github.com/SpotlightKid/ykchorus) | ||||
@@ -1,6 +1,6 @@ | |||||
/* | /* | ||||
* DISTRHO Plugin Framework (DPF) | * 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 | * 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 | * or without fee is hereby granted, provided that the above copyright notice and this | ||||
@@ -31,89 +31,6 @@ | |||||
#define END_NAMESPACE_DGL } | #define END_NAMESPACE_DGL } | ||||
#define USE_NAMESPACE_DGL using namespace DGL_NAMESPACE; | #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 | START_NAMESPACE_DGL | ||||
// ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
@@ -172,6 +89,11 @@ enum Key { | |||||
// ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
// Base DGL classes | // Base DGL classes | ||||
/** | |||||
Graphics context, definition depends on build type. | |||||
*/ | |||||
struct GraphicsContext; | |||||
/** | /** | ||||
Idle callback. | Idle callback. | ||||
*/ | */ | ||||
@@ -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,6 +1,6 @@ | |||||
/* | /* | ||||
* DISTRHO Plugin Framework (DPF) | * 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 | * 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 | * or without fee is hereby granted, provided that the above copyright notice and this | ||||
@@ -482,6 +482,7 @@ private: | |||||
// cached values | // cached values | ||||
float fTheta, fCos, fSin; | float fTheta, fCos, fSin; | ||||
/** @internal */ | |||||
void _draw(const bool outline); | void _draw(const bool outline); | ||||
}; | }; | ||||
@@ -516,16 +517,6 @@ public: | |||||
*/ | */ | ||||
Triangle(const Triangle<T>& tri) noexcept; | 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). | Return true if triangle is null (all its points are equal). | ||||
An null triangle is also invalid. | An null triangle is also invalid. | ||||
@@ -549,6 +540,16 @@ public: | |||||
*/ | */ | ||||
bool isInvalid() const noexcept; | 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; | Triangle<T>& operator=(const Triangle<T>& tri) noexcept; | ||||
bool operator==(const Triangle<T>& tri) const noexcept; | bool operator==(const Triangle<T>& tri) const noexcept; | ||||
bool operator!=(const Triangle<T>& tri) const noexcept; | bool operator!=(const Triangle<T>& tri) const noexcept; | ||||
@@ -556,6 +557,7 @@ public: | |||||
private: | private: | ||||
Point<T> fPos1, fPos2, fPos3; | Point<T> fPos1, fPos2, fPos3; | ||||
/** @internal */ | |||||
void _draw(const bool outline); | void _draw(const bool outline); | ||||
}; | }; | ||||
@@ -740,6 +742,7 @@ private: | |||||
Point<T> fPos; | Point<T> fPos; | ||||
Size<T> fSize; | Size<T> fSize; | ||||
/** @internal */ | |||||
void _draw(const bool outline); | void _draw(const bool outline); | ||||
}; | }; | ||||
@@ -1,6 +1,6 @@ | |||||
/* | /* | ||||
* DISTRHO Plugin Framework (DPF) | * 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 | * 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 | * or without fee is hereby granted, provided that the above copyright notice and this | ||||
@@ -17,14 +17,15 @@ | |||||
#ifndef DGL_IMAGE_HPP_INCLUDED | #ifndef DGL_IMAGE_HPP_INCLUDED | ||||
#define DGL_IMAGE_HPP_INCLUDED | #define DGL_IMAGE_HPP_INCLUDED | ||||
#include "Geometry.hpp" | |||||
#include "ImageBase.hpp" | |||||
#include "OpenGL.hpp" | |||||
START_NAMESPACE_DGL | START_NAMESPACE_DGL | ||||
// ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
/** | /** | ||||
Base DGL Image class. | |||||
OpenGL Image class. | |||||
This is an Image class that handles raw image data in pixels. | 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(). | 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. | Images are drawn on screen via 2D textures. | ||||
*/ | */ | ||||
class Image | |||||
class Image : public ImageBase | |||||
{ | { | ||||
public: | public: | ||||
/** | /** | ||||
@@ -47,13 +48,20 @@ public: | |||||
Constructor using raw image data. | Constructor using raw image data. | ||||
@note @a rawData must remain valid for the lifetime of this Image. | @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. | Constructor using raw image data. | ||||
@note @a rawData must remain valid for the lifetime of this Image. | @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. | Constructor using another image data. | ||||
@@ -63,44 +71,26 @@ public: | |||||
/** | /** | ||||
Destructor. | Destructor. | ||||
*/ | */ | ||||
~Image(); | |||||
~Image() override; | |||||
/** | /** | ||||
Load image data from memory. | Load image data from memory. | ||||
@note @a rawData must remain valid for the lifetime of this Image. | @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. | Load image data from memory. | ||||
@note @a rawData must remain valid for the lifetime of this Image. | @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. | Get the image format. | ||||
@@ -113,27 +103,15 @@ public: | |||||
GLenum getType() const noexcept; | 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; | 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: | private: | ||||
const char* fRawData; | |||||
Size<uint> fSize; | |||||
GLenum fFormat; | GLenum fFormat; | ||||
GLenum fType; | GLenum fType; | ||||
GLuint fTextureId; | GLuint fTextureId; | ||||
@@ -144,4 +122,4 @@ private: | |||||
END_NAMESPACE_DGL | END_NAMESPACE_DGL | ||||
#endif // DGL_IMAGE_HPP_INCLUDED | |||||
#endif |
@@ -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 |
@@ -9,7 +9,7 @@ include ../Makefile.base.mk | |||||
# --------------------------------------------------------------------------------------------------------------------- | # --------------------------------------------------------------------------------------------------------------------- | ||||
BUILD_C_FLAGS += $(DGL_FLAGS) -I. -Isrc | 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) | LINK_FLAGS += $(DGL_LIBS) | ||||
# ifneq ($(MACOS_OLD),true) | # ifneq ($(MACOS_OLD),true) | ||||
@@ -19,36 +19,78 @@ LINK_FLAGS += $(DGL_LIBS) | |||||
# --------------------------------------------------------------------------------------------------------------------- | # --------------------------------------------------------------------------------------------------------------------- | ||||
OBJS = \ | |||||
OBJS_common = \ | |||||
../build/dgl/Application.cpp.o \ | ../build/dgl/Application.cpp.o \ | ||||
../build/dgl/Color.cpp.o \ | ../build/dgl/Color.cpp.o \ | ||||
../build/dgl/Geometry.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/Resources.cpp.o \ | ||||
../build/dgl/Widget.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) | ifeq ($(MACOS),true) | ||||
OBJS += ../build/dgl/Window.mm.o | |||||
OBJS_opengl += ../build/dgl/Window.mm.opengl.o | |||||
else | else | ||||
OBJS += ../build/dgl/Window.cpp.o | |||||
OBJS_opengl += ../build/dgl/Window.cpp.opengl.o | |||||
endif | 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 | -@mkdir -p ../build | ||||
@echo "Creating libdgl.a" | |||||
@echo "Creating libdgl-opengl.a" | |||||
@rm -f $@ | @rm -f $@ | ||||
@$(AR) crs $@ $^ | @$(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 | ../build/dgl/%.c.o: src/%.c | ||||
@@ -61,26 +103,52 @@ all: $(TARGET) | |||||
@echo "Compiling $<" | @echo "Compiling $<" | ||||
@$(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@ | @$(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 | -@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 | -@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: | clean: | ||||
rm -rf ../build/dgl ../build/libdgl.* | |||||
rm -rf ../build/dgl ../build/libdgl*.* | |||||
debug: | debug: | ||||
$(MAKE) DEBUG=true | $(MAKE) DEBUG=true | ||||
# --------------------------------------------------------------------------------------------------------------------- | # --------------------------------------------------------------------------------------------------------------------- | ||||
-include $(OBJS:%.o=%.d) | |||||
-include $(OBJS_common:%.o=%.d) | |||||
-include $(OBJS_cairo:%.o=%.d) | |||||
-include $(OBJS_opengl:%.o=%.d) | |||||
# --------------------------------------------------------------------------------------------------------------------- | # --------------------------------------------------------------------------------------------------------------------- |
@@ -1,6 +1,6 @@ | |||||
/* | /* | ||||
* DISTRHO Plugin Framework (DPF) | * 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 | * 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 | * or without fee is hereby granted, provided that the above copyright notice and this | ||||
@@ -18,6 +18,7 @@ | |||||
#define DGL_NANO_WIDGET_HPP_INCLUDED | #define DGL_NANO_WIDGET_HPP_INCLUDED | ||||
#include "Color.hpp" | #include "Color.hpp" | ||||
#include "OpenGL.hpp" | |||||
#include "Widget.hpp" | #include "Widget.hpp" | ||||
#ifndef DGL_NO_SHARED_RESOURCES | #ifndef DGL_NO_SHARED_RESOURCES | ||||
@@ -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,6 +1,6 @@ | |||||
/* | /* | ||||
* DISTRHO Plugin Framework (DPF) | * 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 | * 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 | * or without fee is hereby granted, provided that the above copyright notice and this | ||||
@@ -77,7 +77,7 @@ public: | |||||
explicit Window(Application& app); | explicit Window(Application& app); | ||||
explicit Window(Application& app, Window& parent); | 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(); | virtual ~Window(); | ||||
void show(); | void show(); | ||||
@@ -113,7 +113,6 @@ public: | |||||
void setTransientWinId(uintptr_t winId); | void setTransientWinId(uintptr_t winId); | ||||
double getScaling() const noexcept; | double getScaling() const noexcept; | ||||
void setScaling(double scaling) noexcept; | |||||
bool getIgnoringKeyRepeat() const noexcept; | bool getIgnoringKeyRepeat() const noexcept; | ||||
void setIgnoringKeyRepeat(bool ignore) noexcept; | void setIgnoringKeyRepeat(bool ignore) noexcept; | ||||
@@ -121,6 +120,8 @@ public: | |||||
Application& getApp() const noexcept; | Application& getApp() const noexcept; | ||||
intptr_t getWindowId() const noexcept; | intptr_t getWindowId() const noexcept; | ||||
const GraphicsContext& getGraphicsContext() const noexcept; | |||||
void addIdleCallback(IdleCallback* const callback); | void addIdleCallback(IdleCallback* const callback); | ||||
void removeIdleCallback(IdleCallback* const callback); | void removeIdleCallback(IdleCallback* const callback); | ||||
@@ -134,6 +135,9 @@ protected: | |||||
virtual void fileBrowserSelected(const char* filename); | virtual void fileBrowserSelected(const char* filename); | ||||
#endif | #endif | ||||
// internal | |||||
void _setAutoScaling(double scaling) noexcept; | |||||
private: | private: | ||||
struct PrivateData; | struct PrivateData; | ||||
PrivateData* const pData; | PrivateData* const pData; | ||||
@@ -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 |
@@ -16,12 +16,27 @@ | |||||
#include "../Color.hpp" | #include "../Color.hpp" | ||||
#ifndef HAVE_DCAIRO | |||||
#include "nanovg/nanovg.h" | #include "nanovg/nanovg.h" | ||||
#endif | |||||
START_NAMESPACE_DGL | 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) | static void fixRange(float& value) | ||||
{ | { | ||||
/**/ if (value < 0.0f) | /**/ 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) | 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) | 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 | END_NAMESPACE_DGL |
@@ -1,6 +1,6 @@ | |||||
/* | /* | ||||
* DISTRHO Plugin Framework (DPF) | * 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 | * 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 | * 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); | 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> | template<typename T> | ||||
bool Line<T>::isNull() const noexcept | 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); | 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 | // Triangle | ||||
@@ -698,18 +662,6 @@ Triangle<T>::Triangle(const Triangle<T>& tri) noexcept | |||||
fPos2(tri.fPos2), | fPos2(tri.fPos2), | ||||
fPos3(tri.fPos3) {} | fPos3(tri.fPos3) {} | ||||
template<typename T> | |||||
void Triangle<T>::draw() | |||||
{ | |||||
_draw(false); | |||||
} | |||||
template<typename T> | |||||
void Triangle<T>::drawOutline() | |||||
{ | |||||
_draw(true); | |||||
} | |||||
template<typename T> | template<typename T> | ||||
bool Triangle<T>::isNull() const noexcept | bool Triangle<T>::isNull() const noexcept | ||||
{ | { | ||||
@@ -734,6 +686,18 @@ bool Triangle<T>::isInvalid() const noexcept | |||||
return fPos1 == fPos2 || fPos1 == fPos3; | 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> | template<typename T> | ||||
Triangle<T>& Triangle<T>::operator=(const Triangle<T>& tri) noexcept | 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); | 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 | // Rectangle | ||||
@@ -998,30 +946,6 @@ bool Rectangle<T>::operator!=(const Rectangle<T>& rect) const noexcept | |||||
return (fPos != rect.fPos || fSize != rect.fSize); | 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 | // Possible template data types | ||||
@@ -1,6 +1,6 @@ | |||||
/* | /* | ||||
* DISTRHO Plugin Framework (DPF) | * 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 | * 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 | * or without fee is hereby granted, provided that the above copyright notice and this | ||||
@@ -21,8 +21,7 @@ START_NAMESPACE_DGL | |||||
// ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
Image::Image() | Image::Image() | ||||
: fRawData(nullptr), | |||||
fSize(0, 0), | |||||
: ImageBase(), | |||||
fFormat(0), | fFormat(0), | ||||
fType(0), | fType(0), | ||||
fTextureId(0), | fTextureId(0), | ||||
@@ -31,20 +30,18 @@ Image::Image() | |||||
glGenTextures(1, &fTextureId); | 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), | fTextureId(0), | ||||
fIsReady(false) | fIsReady(false) | ||||
{ | { | ||||
glGenTextures(1, &fTextureId); | 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), | fFormat(format), | ||||
fType(type), | fType(type), | ||||
fTextureId(0), | fTextureId(0), | ||||
@@ -53,11 +50,10 @@ Image::Image(const char* const rawData, const Size<uint>& size, const GLenum for | |||||
glGenTextures(1, &fTextureId); | 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), | fTextureId(0), | ||||
fIsReady(false) | 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); | 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; | fRawData = rawData; | ||||
fSize = size; | fSize = size; | ||||
@@ -89,31 +92,6 @@ void Image::loadFromMemory(const char* const rawData, const Size<uint>& size, co | |||||
fIsReady = false; | 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 | GLenum Image::getFormat() const noexcept | ||||
{ | { | ||||
return fFormat; | return fFormat; | ||||
@@ -124,17 +102,17 @@ GLenum Image::getType() const noexcept | |||||
return fType; | 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()) | if (fTextureId == 0 || ! isValid()) | ||||
return; | 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 | END_NAMESPACE_DGL |
@@ -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 |
@@ -1,6 +1,6 @@ | |||||
/* | /* | ||||
* DISTRHO Plugin Framework (DPF) | * 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 | * 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 | * 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. | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||||
*/ | */ | ||||
#include "../Image.hpp" | |||||
#include "Common.hpp" | #include "Common.hpp" | ||||
#include "WidgetPrivateData.hpp" | #include "WidgetPrivateData.hpp" | ||||
// FIXME make this code more generic and move GL specific bits to OpenGL.cpp | |||||
#include "../OpenGL.hpp" | |||||
START_NAMESPACE_DGL | START_NAMESPACE_DGL | ||||
// ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
@@ -1,6 +1,6 @@ | |||||
/* | /* | ||||
* DISTRHO Plugin Framework (DPF) | * 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 | * 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 | * 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 | 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 | // NanoImage | ||||
@@ -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,6 +1,6 @@ | |||||
/* | /* | ||||
* DISTRHO Plugin Framework (DPF) | * 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 | * 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 | * or without fee is hereby granted, provided that the above copyright notice and this | ||||
@@ -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 |
@@ -1,6 +1,6 @@ | |||||
/* | /* | ||||
* DISTRHO Plugin Framework (DPF) | * 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 | * 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 | * or without fee is hereby granted, provided that the above copyright notice and this | ||||
@@ -63,61 +63,8 @@ struct Widget::PrivateData { | |||||
subWidgets.clear(); | 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) | void displaySubWidgets(const uint width, const uint height, const double scaling) | ||||
{ | { | ||||
@@ -19,6 +19,15 @@ | |||||
#include "../Base.hpp" | #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" | #include "pugl/pugl.h" | ||||
#if defined(__GNUC__) && (__GNUC__ >= 7) | #if defined(__GNUC__) && (__GNUC__ >= 7) | ||||
@@ -84,6 +93,7 @@ struct Window::PrivateData { | |||||
fWidth(1), | fWidth(1), | ||||
fHeight(1), | fHeight(1), | ||||
fScaling(1.0), | fScaling(1.0), | ||||
fAutoScaling(1.0), | |||||
fTitle(nullptr), | fTitle(nullptr), | ||||
fWidgets(), | fWidgets(), | ||||
fModal(), | fModal(), | ||||
@@ -115,6 +125,7 @@ struct Window::PrivateData { | |||||
fWidth(1), | fWidth(1), | ||||
fHeight(1), | fHeight(1), | ||||
fScaling(1.0), | fScaling(1.0), | ||||
fAutoScaling(1.0), | |||||
fTitle(nullptr), | fTitle(nullptr), | ||||
fWidgets(), | fWidgets(), | ||||
fModal(parent.pData), | fModal(parent.pData), | ||||
@@ -147,7 +158,7 @@ struct Window::PrivateData { | |||||
#endif | #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), | : fApp(app), | ||||
fSelf(self), | fSelf(self), | ||||
fView(puglInit()), | fView(puglInit()), | ||||
@@ -157,7 +168,8 @@ struct Window::PrivateData { | |||||
fUsingEmbed(parentId != 0), | fUsingEmbed(parentId != 0), | ||||
fWidth(1), | fWidth(1), | ||||
fHeight(1), | fHeight(1), | ||||
fScaling(1.0), | |||||
fScaling(scaling), | |||||
fAutoScaling(1.0), | |||||
fTitle(nullptr), | fTitle(nullptr), | ||||
fWidgets(), | fWidgets(), | ||||
fModal(), | fModal(), | ||||
@@ -222,11 +234,12 @@ struct Window::PrivateData { | |||||
puglCreateWindow(fView, nullptr); | puglCreateWindow(fView, nullptr); | ||||
PuglInternals* impl = fView->impl; | PuglInternals* impl = fView->impl; | ||||
#if defined(DISTRHO_OS_WINDOWS) | #if defined(DISTRHO_OS_WINDOWS) | ||||
hwnd = impl->hwnd; | hwnd = impl->hwnd; | ||||
DISTRHO_SAFE_ASSERT(hwnd != 0); | DISTRHO_SAFE_ASSERT(hwnd != 0); | ||||
#elif defined(DISTRHO_OS_MAC) | #elif defined(DISTRHO_OS_MAC) | ||||
mView = impl->glview; | |||||
mView = impl->view; | |||||
mWindow = impl->window; | mWindow = impl->window; | ||||
DISTRHO_SAFE_ASSERT(mView != nullptr); | DISTRHO_SAFE_ASSERT(mView != nullptr); | ||||
if (fUsingEmbed) { | if (fUsingEmbed) { | ||||
@@ -555,6 +568,7 @@ struct Window::PrivateData { | |||||
void setGeometryConstraints(uint width, uint height, bool aspect) | void setGeometryConstraints(uint width, uint height, bool aspect) | ||||
{ | { | ||||
// Did you forget to set DISTRHO_UI_USER_RESIZABLE ? | |||||
DISTRHO_SAFE_ASSERT_RETURN(fResizable,); | DISTRHO_SAFE_ASSERT_RETURN(fResizable,); | ||||
fView->min_width = width; | fView->min_width = width; | ||||
@@ -701,11 +715,11 @@ struct Window::PrivateData { | |||||
return fScaling; | return fScaling; | ||||
} | } | ||||
void setScaling(double scaling) noexcept | |||||
void setAutoScaling(const double scaling) noexcept | |||||
{ | { | ||||
DISTRHO_SAFE_ASSERT_RETURN(scaling > 0.0,); | DISTRHO_SAFE_ASSERT_RETURN(scaling > 0.0,); | ||||
fScaling = scaling; | |||||
fAutoScaling = scaling; | |||||
} | } | ||||
// ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
@@ -773,7 +787,7 @@ struct Window::PrivateData { | |||||
FOR_EACH_WIDGET(it) | FOR_EACH_WIDGET(it) | ||||
{ | { | ||||
Widget* const widget(*it); | Widget* const widget(*it); | ||||
widget->pData->display(fWidth, fHeight, fScaling, false); | |||||
widget->pData->display(fWidth, fHeight, fAutoScaling, false); | |||||
} | } | ||||
fSelf->onDisplayAfter(); | fSelf->onDisplayAfter(); | ||||
@@ -843,8 +857,8 @@ struct Window::PrivateData { | |||||
if (fModal.childFocus != nullptr) | if (fModal.childFocus != nullptr) | ||||
return fModal.childFocus->focus(); | return fModal.childFocus->focus(); | ||||
x /= fScaling; | |||||
y /= fScaling; | |||||
x /= fAutoScaling; | |||||
y /= fAutoScaling; | |||||
Widget::MouseEvent ev; | Widget::MouseEvent ev; | ||||
ev.button = button; | ev.button = button; | ||||
@@ -870,8 +884,8 @@ struct Window::PrivateData { | |||||
if (fModal.childFocus != nullptr) | if (fModal.childFocus != nullptr) | ||||
return; | return; | ||||
x /= fScaling; | |||||
y /= fScaling; | |||||
x /= fAutoScaling; | |||||
y /= fAutoScaling; | |||||
Widget::MotionEvent ev; | Widget::MotionEvent ev; | ||||
ev.mod = static_cast<Modifier>(puglGetModifiers(fView)); | ev.mod = static_cast<Modifier>(puglGetModifiers(fView)); | ||||
@@ -895,10 +909,10 @@ struct Window::PrivateData { | |||||
if (fModal.childFocus != nullptr) | if (fModal.childFocus != nullptr) | ||||
return; | return; | ||||
x /= fScaling; | |||||
y /= fScaling; | |||||
dx /= fScaling; | |||||
dy /= fScaling; | |||||
x /= fAutoScaling; | |||||
y /= fAutoScaling; | |||||
dx /= fAutoScaling; | |||||
dy /= fAutoScaling; | |||||
Widget::ScrollEvent ev; | Widget::ScrollEvent ev; | ||||
ev.delta = Point<float>(dx, dy); | 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 fFirstInit; | ||||
bool fVisible; | bool fVisible; | ||||
@@ -1049,6 +1064,7 @@ struct Window::PrivateData { | |||||
uint fWidth; | uint fWidth; | ||||
uint fHeight; | uint fHeight; | ||||
double fScaling; | double fScaling; | ||||
double fAutoScaling; | |||||
char* fTitle; | char* fTitle; | ||||
std::list<Widget*> fWidgets; | std::list<Widget*> fWidgets; | ||||
@@ -1081,7 +1097,7 @@ struct Window::PrivateData { | |||||
HWND hwndParent; | HWND hwndParent; | ||||
#elif defined(DISTRHO_OS_MAC) | #elif defined(DISTRHO_OS_MAC) | ||||
bool fNeedsIdle; | bool fNeedsIdle; | ||||
PuglOpenGLView* mView; | |||||
NSView<PuglGenericView>* mView; | |||||
id mWindow; | id mWindow; | ||||
id mParentWindow; | id mParentWindow; | ||||
#else | #else | ||||
@@ -1155,8 +1171,8 @@ Window::Window(Application& app) | |||||
Window::Window(Application& app, Window& parent) | Window::Window(Application& app, Window& parent) | ||||
: pData(new PrivateData(app, this, 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() | Window::~Window() | ||||
{ | { | ||||
@@ -1347,11 +1363,6 @@ double Window::getScaling() const noexcept | |||||
return pData->getScaling(); | return pData->getScaling(); | ||||
} | } | ||||
void Window::setScaling(double scaling) noexcept | |||||
{ | |||||
pData->setScaling(scaling); | |||||
} | |||||
bool Window::getIgnoringKeyRepeat() const noexcept | bool Window::getIgnoringKeyRepeat() const noexcept | ||||
{ | { | ||||
return pData->getIgnoringKeyRepeat(); | return pData->getIgnoringKeyRepeat(); | ||||
@@ -1372,6 +1383,20 @@ intptr_t Window::getWindowId() const noexcept | |||||
return puglGetNativeWindow(pData->fView); | 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) | void Window::_addWidget(Widget* const widget) | ||||
{ | { | ||||
pData->addWidget(widget); | pData->addWidget(widget); | ||||
@@ -1407,8 +1432,10 @@ void Window::removeIdleCallback(IdleCallback* const callback) | |||||
void Window::onDisplayBefore() | void Window::onDisplayBefore() | ||||
{ | { | ||||
#ifdef DGL_OPENGL | |||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | ||||
glLoadIdentity(); | glLoadIdentity(); | ||||
#endif | |||||
} | } | ||||
void Window::onDisplayAfter() | void Window::onDisplayAfter() | ||||
@@ -1417,6 +1444,7 @@ void Window::onDisplayAfter() | |||||
void Window::onReshape(uint width, uint height) | void Window::onReshape(uint width, uint height) | ||||
{ | { | ||||
#ifdef DGL_OPENGL | |||||
glEnable(GL_BLEND); | glEnable(GL_BLEND); | ||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | ||||
glMatrixMode(GL_PROJECTION); | 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)); | glViewport(0, 0, static_cast<GLsizei>(width), static_cast<GLsizei>(height)); | ||||
glMatrixMode(GL_MODELVIEW); | glMatrixMode(GL_MODELVIEW); | ||||
glLoadIdentity(); | glLoadIdentity(); | ||||
#endif | |||||
} | } | ||||
void Window::onClose() | void Window::onClose() | ||||
@@ -1,5 +1,6 @@ | |||||
/* | /* | ||||
Copyright 2012-2014 David Robillard <http://drobilla.net> | 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 | Permission to use, copy, modify, and/or distribute this software for any | ||||
purpose with or without fee is hereby granted, provided that the above | 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. | platforms so they are included here to allow for pure portable programs. | ||||
*/ | */ | ||||
#ifdef __APPLE__ | #ifdef __APPLE__ | ||||
# include "OpenGL/gl.h" | |||||
# include <OpenGL/gl.h> | |||||
#else | #else | ||||
# ifdef _WIN32 | # ifdef _WIN32 | ||||
# include <winsock2.h> | # include <winsock2.h> | ||||
# include <windows.h> /* Broken Windows GL headers require this */ | # include <windows.h> /* Broken Windows GL headers require this */ | ||||
# endif | # endif | ||||
# include "GL/gl.h" | |||||
#endif | |||||
#ifdef _WIN32 | |||||
# define PUGL_API | |||||
#else | |||||
# define PUGL_API __attribute__((visibility("hidden"))) | |||||
# include <GL/gl.h> | |||||
#endif | #endif | ||||
#ifdef __cplusplus | #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 | To create a window, call the various puglInit* functions as necessary, then | ||||
call puglCreateWindow(). | call puglCreateWindow(). | ||||
*/ | */ | ||||
PUGL_API PuglView* | |||||
PuglView* | |||||
puglInit(void); | puglInit(void); | ||||
/** | /** | ||||
Set the parent window before creating a window (for embedding). | Set the parent window before creating a window (for embedding). | ||||
*/ | */ | ||||
PUGL_API void | |||||
void | |||||
puglInitWindowParent(PuglView* view, PuglNativeWindow parent); | puglInitWindowParent(PuglView* view, PuglNativeWindow parent); | ||||
/** | /** | ||||
Set the window size before creating a window. | Set the window size before creating a window. | ||||
*/ | */ | ||||
PUGL_API void | |||||
void | |||||
puglInitWindowSize(PuglView* view, int width, int height); | puglInitWindowSize(PuglView* view, int width, int height); | ||||
/** | /** | ||||
Set the minimum window size before creating a window. | Set the minimum window size before creating a window. | ||||
*/ | */ | ||||
PUGL_API void | |||||
void | |||||
puglInitWindowMinSize(PuglView* view, int width, int height); | puglInitWindowMinSize(PuglView* view, int width, int height); | ||||
/** | /** | ||||
Enable or disable resizing before creating a window. | Enable or disable resizing before creating a window. | ||||
*/ | */ | ||||
PUGL_API void | |||||
void | |||||
puglInitUserResizable(PuglView* view, bool resizable); | puglInitUserResizable(PuglView* view, bool resizable); | ||||
/** | /** | ||||
@@ -270,7 +265,7 @@ puglInitUserResizable(PuglView* view, bool resizable); | |||||
On X11, parent_id must be a Window. | On X11, parent_id must be a Window. | ||||
On OSX, parent_id must be an NSView*. | On OSX, parent_id must be an NSView*. | ||||
*/ | */ | ||||
PUGL_API void | |||||
void | |||||
puglInitTransientFor(PuglView* view, uintptr_t parent); | 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). | @return 1 (pugl does not currently support multiple windows). | ||||
*/ | */ | ||||
PUGL_API int | |||||
int | |||||
puglCreateWindow(PuglView* view, const char* title); | puglCreateWindow(PuglView* view, const char* title); | ||||
/** | /** | ||||
@@ -299,7 +294,7 @@ puglCreateWindow(PuglView* view, const char* title); | |||||
@param height Window height in pixels. | @param height Window height in pixels. | ||||
@param resizable Whether window should be user resizable. | @param resizable Whether window should be user resizable. | ||||
*/ | */ | ||||
PUGL_API PuglView* | |||||
PuglView* | |||||
puglCreate(PuglNativeWindow parent, | puglCreate(PuglNativeWindow parent, | ||||
const char* title, | const char* title, | ||||
int min_width, | int min_width, | ||||
@@ -312,19 +307,19 @@ puglCreate(PuglNativeWindow parent, | |||||
/** | /** | ||||
Show Window (external ui) | Show Window (external ui) | ||||
*/ | */ | ||||
PUGL_API void | |||||
void | |||||
puglShowWindow(PuglView* view); | puglShowWindow(PuglView* view); | ||||
/** | /** | ||||
Hide Window (external ui) | Hide Window (external ui) | ||||
*/ | */ | ||||
PUGL_API void | |||||
void | |||||
puglHideWindow(PuglView* view); | puglHideWindow(PuglView* view); | ||||
/** | /** | ||||
Return the native window handle. | Return the native window handle. | ||||
*/ | */ | ||||
PUGL_API PuglNativeWindow | |||||
PuglNativeWindow | |||||
puglGetNativeWindow(PuglView* view); | puglGetNativeWindow(PuglView* view); | ||||
/** | /** | ||||
@@ -340,19 +335,27 @@ puglGetNativeWindow(PuglView* view); | |||||
Note the lack of this facility makes GLUT unsuitable for plugins or | Note the lack of this facility makes GLUT unsuitable for plugins or | ||||
non-trivial programs; this mistake is largely why Pugl exists. | non-trivial programs; this mistake is largely why Pugl exists. | ||||
*/ | */ | ||||
PUGL_API void | |||||
void | |||||
puglSetHandle(PuglView* view, PuglHandle handle); | puglSetHandle(PuglView* view, PuglHandle handle); | ||||
/** | /** | ||||
Get the handle to be passed to all callbacks. | Get the handle to be passed to all callbacks. | ||||
*/ | */ | ||||
PUGL_API PuglHandle | |||||
PuglHandle | |||||
puglGetHandle(PuglView* view); | 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. | Return the timestamp (if any) of the currently-processing event. | ||||
*/ | */ | ||||
PUGL_API uint32_t | |||||
uint32_t | |||||
puglGetEventTimestamp(PuglView* view); | puglGetEventTimestamp(PuglView* view); | ||||
/** | /** | ||||
@@ -360,13 +363,13 @@ puglGetEventTimestamp(PuglView* view); | |||||
This should only be called from an event handler. | This should only be called from an event handler. | ||||
*/ | */ | ||||
PUGL_API int | |||||
int | |||||
puglGetModifiers(PuglView* view); | puglGetModifiers(PuglView* view); | ||||
/** | /** | ||||
Ignore synthetic repeated key events. | Ignore synthetic repeated key events. | ||||
*/ | */ | ||||
PUGL_API void | |||||
void | |||||
puglIgnoreKeyRepeat(PuglView* view, bool ignore); | puglIgnoreKeyRepeat(PuglView* view, bool ignore); | ||||
/** | /** | ||||
@@ -378,61 +381,61 @@ puglIgnoreKeyRepeat(PuglView* view, bool ignore); | |||||
/** | /** | ||||
Set the function to call when the window is closed. | Set the function to call when the window is closed. | ||||
*/ | */ | ||||
PUGL_API void | |||||
void | |||||
puglSetCloseFunc(PuglView* view, PuglCloseFunc closeFunc); | puglSetCloseFunc(PuglView* view, PuglCloseFunc closeFunc); | ||||
/** | /** | ||||
Set the display function which should draw the UI using GL. | Set the display function which should draw the UI using GL. | ||||
*/ | */ | ||||
PUGL_API void | |||||
void | |||||
puglSetDisplayFunc(PuglView* view, PuglDisplayFunc displayFunc); | puglSetDisplayFunc(PuglView* view, PuglDisplayFunc displayFunc); | ||||
/** | /** | ||||
Set the function to call on keyboard events. | Set the function to call on keyboard events. | ||||
*/ | */ | ||||
PUGL_API void | |||||
void | |||||
puglSetKeyboardFunc(PuglView* view, PuglKeyboardFunc keyboardFunc); | puglSetKeyboardFunc(PuglView* view, PuglKeyboardFunc keyboardFunc); | ||||
/** | /** | ||||
Set the function to call on mouse motion. | Set the function to call on mouse motion. | ||||
*/ | */ | ||||
PUGL_API void | |||||
void | |||||
puglSetMotionFunc(PuglView* view, PuglMotionFunc motionFunc); | puglSetMotionFunc(PuglView* view, PuglMotionFunc motionFunc); | ||||
/** | /** | ||||
Set the function to call on mouse button events. | Set the function to call on mouse button events. | ||||
*/ | */ | ||||
PUGL_API void | |||||
void | |||||
puglSetMouseFunc(PuglView* view, PuglMouseFunc mouseFunc); | puglSetMouseFunc(PuglView* view, PuglMouseFunc mouseFunc); | ||||
/** | /** | ||||
Set the function to call on scroll events. | Set the function to call on scroll events. | ||||
*/ | */ | ||||
PUGL_API void | |||||
void | |||||
puglSetScrollFunc(PuglView* view, PuglScrollFunc scrollFunc); | puglSetScrollFunc(PuglView* view, PuglScrollFunc scrollFunc); | ||||
/** | /** | ||||
Set the function to call on special events. | Set the function to call on special events. | ||||
*/ | */ | ||||
PUGL_API void | |||||
void | |||||
puglSetSpecialFunc(PuglView* view, PuglSpecialFunc specialFunc); | puglSetSpecialFunc(PuglView* view, PuglSpecialFunc specialFunc); | ||||
/** | /** | ||||
Set the function to call when the window size changes. | Set the function to call when the window size changes. | ||||
*/ | */ | ||||
PUGL_API void | |||||
void | |||||
puglSetReshapeFunc(PuglView* view, PuglReshapeFunc reshapeFunc); | puglSetReshapeFunc(PuglView* view, PuglReshapeFunc reshapeFunc); | ||||
/** | /** | ||||
Set callback function to change window size. | Set callback function to change window size. | ||||
*/ | */ | ||||
PUGL_API void | |||||
void | |||||
puglSetResizeFunc(PuglView* view, PuglResizeFunc resizeFunc); | puglSetResizeFunc(PuglView* view, PuglResizeFunc resizeFunc); | ||||
/** | /** | ||||
Set the function to call on file-browser selections. | Set the function to call on file-browser selections. | ||||
*/ | */ | ||||
PUGL_API void | |||||
void | |||||
puglSetFileSelectedFunc(PuglView* view, PuglFileSelectedFunc fileSelectedFunc); | puglSetFileSelectedFunc(PuglView* view, PuglFileSelectedFunc fileSelectedFunc); | ||||
/** | /** | ||||
@@ -442,13 +445,13 @@ puglSetFileSelectedFunc(PuglView* view, PuglFileSelectedFunc fileSelectedFunc); | |||||
/** | /** | ||||
TODO document this. | TODO document this. | ||||
*/ | */ | ||||
PUGL_API int | |||||
int | |||||
puglUpdateGeometryConstraints(PuglView* view, int min_width, int min_height, bool aspect); | puglUpdateGeometryConstraints(PuglView* view, int min_width, int min_height, bool aspect); | ||||
/** | /** | ||||
Grab the input focus. | Grab the input focus. | ||||
*/ | */ | ||||
PUGL_API void | |||||
void | |||||
puglGrabFocus(PuglView* view); | puglGrabFocus(PuglView* view); | ||||
/** | /** | ||||
@@ -457,25 +460,25 @@ puglGrabFocus(PuglView* view); | |||||
This handles input events as well as rendering, so it should be called | This handles input events as well as rendering, so it should be called | ||||
regularly and rapidly enough to keep the UI responsive. | regularly and rapidly enough to keep the UI responsive. | ||||
*/ | */ | ||||
PUGL_API PuglStatus | |||||
PuglStatus | |||||
puglProcessEvents(PuglView* view); | puglProcessEvents(PuglView* view); | ||||
/** | /** | ||||
Request a redisplay on the next call to puglProcessEvents(). | Request a redisplay on the next call to puglProcessEvents(). | ||||
*/ | */ | ||||
PUGL_API void | |||||
void | |||||
puglPostRedisplay(PuglView* view); | puglPostRedisplay(PuglView* view); | ||||
/** | /** | ||||
Request a resize on the next call to puglProcessEvents(). | Request a resize on the next call to puglProcessEvents(). | ||||
*/ | */ | ||||
PUGL_API void | |||||
void | |||||
puglPostResize(PuglView* view); | puglPostResize(PuglView* view); | ||||
/** | /** | ||||
Destroy a GL window. | Destroy a GL window. | ||||
*/ | */ | ||||
PUGL_API void | |||||
void | |||||
puglDestroy(PuglView* view); | puglDestroy(PuglView* view); | ||||
/** | /** | ||||
@@ -1,5 +1,6 @@ | |||||
/* | /* | ||||
Copyright 2012-2014 David Robillard <http://drobilla.net> | 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 | Permission to use, copy, modify, and/or distribute this software for any | ||||
purpose with or without fee is hereby granted, provided that the above | purpose with or without fee is hereby granted, provided that the above | ||||
@@ -239,6 +240,7 @@ puglLeaveContext(PuglView* view, bool flush); | |||||
static void | static void | ||||
puglDefaultReshape(int width, int height) | puglDefaultReshape(int width, int height) | ||||
{ | { | ||||
#ifdef PUGL_OPENGL | |||||
#ifdef ROBTK_HERE | #ifdef ROBTK_HERE | ||||
glViewport(0, 0, width, height); | glViewport(0, 0, width, height); | ||||
glMatrixMode(GL_PROJECTION); | glMatrixMode(GL_PROJECTION); | ||||
@@ -257,4 +259,5 @@ puglDefaultReshape(int width, int height) | |||||
glMatrixMode(GL_MODELVIEW); | glMatrixMode(GL_MODELVIEW); | ||||
glLoadIdentity(); | glLoadIdentity(); | ||||
#endif | #endif | ||||
#endif // PUGL_OPENGL | |||||
} | } |
@@ -1,5 +1,6 @@ | |||||
/* | /* | ||||
Copyright 2012 David Robillard <http://drobilla.net> | 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 | Permission to use, copy, modify, and/or distribute this software for any | ||||
purpose with or without fee is hereby granted, provided that the above | purpose with or without fee is hereby granted, provided that the above | ||||
@@ -20,6 +21,10 @@ | |||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#ifdef PUGL_CAIRO | |||||
#import <cairo.h> | |||||
#import <cairo-quartz.h> | |||||
#endif | |||||
#import <Cocoa/Cocoa.h> | #import <Cocoa/Cocoa.h> | ||||
#include "pugl_internal.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 | @public | ||||
PuglView* puglview; | PuglView* puglview; | ||||
@@ -101,6 +299,11 @@ puglDisplay(PuglView* view) | |||||
bool doubleBuffered; | bool doubleBuffered; | ||||
} | } | ||||
- (PuglView *) puglview; | |||||
- (void) setPuglview:(PuglView *)pv; | |||||
- (NSTrackingArea *) puglTrackingArea; | |||||
- (void) setPuglTrackingArea:(NSTrackingArea *)area; | |||||
- (BOOL) acceptsFirstMouse:(NSEvent*)e; | - (BOOL) acceptsFirstMouse:(NSEvent*)e; | ||||
- (BOOL) acceptsFirstResponder; | - (BOOL) acceptsFirstResponder; | ||||
- (BOOL) isFlipped; | - (BOOL) isFlipped; | ||||
@@ -130,6 +333,21 @@ puglDisplay(PuglView* view) | |||||
@end | @end | ||||
@implementation PuglOpenGLView | @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 | - (BOOL) acceptsFirstMouse:(NSEvent*)e | ||||
{ | { | ||||
@@ -209,22 +427,7 @@ puglDisplay(PuglView* view) | |||||
[[self openGLContext] update]; | [[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 | - (void) drawRect:(NSRect)r | ||||
@@ -239,182 +442,326 @@ puglDisplay(PuglView* view) | |||||
- (void) cursorUpdate:(NSEvent*)e | - (void) cursorUpdate:(NSEvent*)e | ||||
{ | { | ||||
[[NSCursor arrowCursor] set]; | |||||
// unused | |||||
return; (void)e; | |||||
cursorUpdate(self, e); | |||||
} | } | ||||
- (void) updateTrackingAreas | - (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]; | [super updateTrackingAreas]; | ||||
} | } | ||||
- (void) viewWillMoveToWindow:(NSWindow*)newWindow | - (void) viewWillMoveToWindow:(NSWindow*)newWindow | ||||
{ | { | ||||
if (newWindow != nil) { | |||||
[newWindow setAcceptsMouseMovedEvents:YES]; | |||||
[newWindow makeFirstResponder:self]; | |||||
} | |||||
viewWillMoveToWindow(self, newWindow); | |||||
[super viewWillMoveToWindow: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 | - (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 | - (void) mouseDragged:(NSEvent*)event | ||||
{ | { | ||||
[self mouseMoved:event]; | |||||
mouseMoved(self, event); | |||||
} | } | ||||
- (void) rightMouseDragged:(NSEvent*)event | - (void) rightMouseDragged:(NSEvent*)event | ||||
{ | { | ||||
[self mouseDragged:event]; | |||||
mouseMoved(self, event); | |||||
} | } | ||||
- (void) otherMouseDragged:(NSEvent*)event | - (void) otherMouseDragged:(NSEvent*)event | ||||
{ | { | ||||
[self mouseDragged:event]; | |||||
mouseMoved(self, event); | |||||
} | } | ||||
- (void) mouseDown:(NSEvent*)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 | - (void) rightMouseDown:(NSEvent*)event | ||||
{ | { | ||||
[self mouseDown:event]; | |||||
mouseDown(self, event); | |||||
} | } | ||||
- (void) otherMouseDown:(NSEvent*)event | - (void) otherMouseDown:(NSEvent*)event | ||||
{ | { | ||||
[self mouseDown:event]; | |||||
mouseDown(self, event); | |||||
} | } | ||||
- (void) mouseUp:(NSEvent*)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 | - (void) rightMouseUp:(NSEvent*)event | ||||
{ | { | ||||
[self mouseUp:event]; | |||||
mouseUp(self, event); | |||||
} | } | ||||
- (void) otherMouseUp:(NSEvent*)event | - (void) otherMouseUp:(NSEvent*)event | ||||
{ | { | ||||
[self mouseUp:event]; | |||||
mouseUp(self, event); | |||||
} | } | ||||
- (void) scrollWheel:(NSEvent*)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 | - (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 | - (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 | - (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 | @end | ||||
#endif | |||||
struct PuglInternalsImpl { | struct PuglInternalsImpl { | ||||
PuglOpenGLView* glview; | |||||
union { | |||||
NSView<PuglGenericView>* view; | |||||
#ifdef PUGL_OPENGL | |||||
PuglOpenGLView* glview; | |||||
#endif | |||||
#ifdef PUGL_CAIRO | |||||
PuglCairoView* cairoview; | |||||
#endif | |||||
}; | |||||
id window; | id window; | ||||
}; | }; | ||||
@@ -427,19 +774,23 @@ puglInitInternals() | |||||
void | void | ||||
puglEnterContext(PuglView* view) | puglEnterContext(PuglView* view) | ||||
{ | { | ||||
#ifdef PUGL_OPENGL | |||||
[[view->impl->glview openGLContext] makeCurrentContext]; | [[view->impl->glview openGLContext] makeCurrentContext]; | ||||
#endif | |||||
} | } | ||||
void | void | ||||
puglLeaveContext(PuglView* view, bool flush) | puglLeaveContext(PuglView* view, bool flush) | ||||
{ | { | ||||
if (flush) { | if (flush) { | ||||
#ifdef PUGL_OPENGL | |||||
if (view->impl->glview->doubleBuffered) { | if (view->impl->glview->doubleBuffered) { | ||||
[[view->impl->glview openGLContext] flushBuffer]; | [[view->impl->glview openGLContext] flushBuffer]; | ||||
} else { | } else { | ||||
glFlush(); | glFlush(); | ||||
} | } | ||||
//[NSOpenGLContext clearCurrentContext]; | //[NSOpenGLContext clearCurrentContext]; | ||||
#endif | |||||
} | } | ||||
} | } | ||||
@@ -451,22 +802,27 @@ puglCreateWindow(PuglView* view, const char* title) | |||||
[NSAutoreleasePool new]; | [NSAutoreleasePool new]; | ||||
[NSApplication sharedApplication]; | [NSApplication sharedApplication]; | ||||
#ifdef PUGL_OPENGL | |||||
impl->glview = [PuglOpenGLView new]; | impl->glview = [PuglOpenGLView new]; | ||||
#endif | |||||
#ifdef PUGL_CAIRO | |||||
impl->cairoview = [PuglCairoView new]; | |||||
#endif | |||||
if (!impl->glview) { | |||||
if (!impl->view) { | |||||
return 1; | return 1; | ||||
} | } | ||||
impl->glview->puglview = view; | |||||
[impl->view setPuglview:view]; | |||||
if (view->user_resizable) { | if (view->user_resizable) { | ||||
[impl->glview setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable]; | |||||
[impl->view setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable]; | |||||
} | } | ||||
if (view->parent) { | if (view->parent) { | ||||
[impl->glview retain]; | |||||
[impl->view retain]; | |||||
NSView* pview = (NSView*)view->parent; | NSView* pview = (NSView*)view->parent; | ||||
[pview addSubview:impl->glview]; | |||||
[pview addSubview:impl->view]; | |||||
return 0; | return 0; | ||||
} | } | ||||
@@ -482,8 +838,8 @@ puglCreateWindow(PuglView* view, const char* title) | |||||
} | } | ||||
[window setPuglview:view]; | [window setPuglview:view]; | ||||
[window setContentView:impl->glview]; | |||||
[window makeFirstResponder:impl->glview]; | |||||
[window setContentView:impl->view]; | |||||
[window makeFirstResponder:impl->view]; | |||||
[window makeKeyAndOrderFront:window]; | [window makeKeyAndOrderFront:window]; | ||||
// wait for first puglShowWindow | // wait for first puglShowWindow | ||||
@@ -505,7 +861,7 @@ puglShowWindow(PuglView* view) | |||||
if (impl->window) { | if (impl->window) { | ||||
[impl->window setIsVisible:YES]; | [impl->window setIsVisible:YES]; | ||||
} else { | } else { | ||||
[view->impl->glview setHidden:NO]; | |||||
[view->impl->view setHidden:NO]; | |||||
} | } | ||||
} | } | ||||
@@ -517,21 +873,21 @@ puglHideWindow(PuglView* view) | |||||
if (impl->window) { | if (impl->window) { | ||||
[impl->window setIsVisible:NO]; | [impl->window setIsVisible:NO]; | ||||
} else { | } else { | ||||
[impl->glview setHidden:YES]; | |||||
[impl->view setHidden:YES]; | |||||
} | } | ||||
} | } | ||||
void | void | ||||
puglDestroy(PuglView* view) | puglDestroy(PuglView* view) | ||||
{ | { | ||||
view->impl->glview->puglview = NULL; | |||||
[view->impl->view setPuglview:NULL]; | |||||
if (view->impl->window) { | if (view->impl->window) { | ||||
[view->impl->window close]; | [view->impl->window close]; | ||||
[view->impl->glview release]; | |||||
[view->impl->view release]; | |||||
[view->impl->window release]; | [view->impl->window release]; | ||||
} else { | } else { | ||||
[view->impl->glview release]; | |||||
[view->impl->view release]; | |||||
} | } | ||||
free(view->impl); | free(view->impl); | ||||
@@ -551,13 +907,25 @@ void | |||||
puglPostRedisplay(PuglView* view) | puglPostRedisplay(PuglView* view) | ||||
{ | { | ||||
view->redisplay = true; | view->redisplay = true; | ||||
[view->impl->glview setNeedsDisplay:YES]; | |||||
[view->impl->view setNeedsDisplay:YES]; | |||||
} | } | ||||
PuglNativeWindow | PuglNativeWindow | ||||
puglGetNativeWindow(PuglView* view) | 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 | int | ||||
@@ -1,5 +1,6 @@ | |||||
/* | /* | ||||
Copyright 2012-2014 David Robillard <http://drobilla.net> | 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 | Permission to use, copy, modify, and/or distribute this software for any | ||||
purpose with or without fee is hereby granted, provided that the above | purpose with or without fee is hereby granted, provided that the above | ||||
@@ -18,16 +19,22 @@ | |||||
@file pugl_win.cpp Windows/WGL Pugl Implementation. | @file pugl_win.cpp Windows/WGL Pugl Implementation. | ||||
*/ | */ | ||||
#include <ctime> | |||||
#include <cstdio> | |||||
#include <cstdlib> | |||||
#include <winsock2.h> | #include <winsock2.h> | ||||
#include <windows.h> | #include <windows.h> | ||||
#include <windowsx.h> | #include <windowsx.h> | ||||
#ifdef PUGL_CAIRO | |||||
#include <cairo/cairo.h> | |||||
#include <cairo/cairo-win32.h> | |||||
#endif | |||||
#ifdef PUGL_OPENGL | |||||
#include <GL/gl.h> | #include <GL/gl.h> | ||||
#endif | |||||
#include <ctime> | |||||
#include <cstdio> | |||||
#include <cstdlib> | |||||
#include "pugl/pugl_internal.h" | |||||
#include "pugl_internal.h" | |||||
#ifndef WM_MOUSEWHEEL | #ifndef WM_MOUSEWHEEL | ||||
# define WM_MOUSEWHEEL 0x020A | # define WM_MOUSEWHEEL 0x020A | ||||
@@ -48,8 +55,15 @@ HINSTANCE hInstance = NULL; | |||||
struct PuglInternalsImpl { | struct PuglInternalsImpl { | ||||
HWND hwnd; | HWND hwnd; | ||||
#ifdef PUGL_OPENGL | |||||
HDC hdc; | HDC hdc; | ||||
HGLRC hglrc; | HGLRC hglrc; | ||||
#endif | |||||
#ifdef PUGL_CAIRO | |||||
cairo_t* buffer_cr; | |||||
cairo_surface_t* buffer_surface; | |||||
#endif | |||||
HDC paintHdc; | |||||
WNDCLASS wc; | WNDCLASS wc; | ||||
}; | }; | ||||
@@ -76,17 +90,21 @@ puglInitInternals() | |||||
void | void | ||||
puglEnterContext(PuglView* view) | puglEnterContext(PuglView* view) | ||||
{ | { | ||||
#ifdef PUGL_OPENGL | |||||
wglMakeCurrent(view->impl->hdc, view->impl->hglrc); | wglMakeCurrent(view->impl->hdc, view->impl->hglrc); | ||||
#endif | |||||
} | } | ||||
void | void | ||||
puglLeaveContext(PuglView* view, bool flush) | puglLeaveContext(PuglView* view, bool flush) | ||||
{ | { | ||||
#ifdef PUGL_OPENGL | |||||
if (flush) { | if (flush) { | ||||
glFlush(); | glFlush(); | ||||
SwapBuffers(view->impl->hdc); | SwapBuffers(view->impl->hdc); | ||||
} | } | ||||
wglMakeCurrent(NULL, NULL); | wglMakeCurrent(NULL, NULL); | ||||
#endif | |||||
} | } | ||||
int | int | ||||
@@ -124,7 +142,6 @@ puglCreateWindow(PuglView* view, const char* title) | |||||
if (!RegisterClass(&impl->wc)) { | if (!RegisterClass(&impl->wc)) { | ||||
free((void*)impl->wc.lpszClassName); | free((void*)impl->wc.lpszClassName); | ||||
free(impl); | free(impl); | ||||
free(view); | |||||
return 1; | return 1; | ||||
} | } | ||||
@@ -155,12 +172,12 @@ puglCreateWindow(PuglView* view, const char* title) | |||||
UnregisterClass(impl->wc.lpszClassName, NULL); | UnregisterClass(impl->wc.lpszClassName, NULL); | ||||
free((void*)impl->wc.lpszClassName); | free((void*)impl->wc.lpszClassName); | ||||
free(impl); | free(impl); | ||||
free(view); | |||||
return 1; | return 1; | ||||
} | } | ||||
SetWindowLongPtr(impl->hwnd, GWLP_USERDATA, (LONG_PTR)view); | SetWindowLongPtr(impl->hwnd, GWLP_USERDATA, (LONG_PTR)view); | ||||
#ifdef PUGL_OPENGL | |||||
impl->hdc = GetDC(impl->hwnd); | impl->hdc = GetDC(impl->hwnd); | ||||
PIXELFORMATDESCRIPTOR pfd; | PIXELFORMATDESCRIPTOR pfd; | ||||
@@ -183,9 +200,9 @@ puglCreateWindow(PuglView* view, const char* title) | |||||
UnregisterClass (impl->wc.lpszClassName, NULL); | UnregisterClass (impl->wc.lpszClassName, NULL); | ||||
free((void*)impl->wc.lpszClassName); | free((void*)impl->wc.lpszClassName); | ||||
free(impl); | free(impl); | ||||
free(view); | |||||
return 1; | return 1; | ||||
} | } | ||||
#endif | |||||
return PUGL_SUCCESS; | return PUGL_SUCCESS; | ||||
} | } | ||||
@@ -205,13 +222,25 @@ puglHideWindow(PuglView* view) | |||||
void | void | ||||
puglDestroy(PuglView* view) | puglDestroy(PuglView* view) | ||||
{ | { | ||||
if (!view) { | |||||
return; | |||||
} | |||||
PuglInternals* const impl = view->impl; | |||||
#ifdef PUGL_OPENGL | |||||
wglMakeCurrent(NULL, NULL); | 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); | free(view); | ||||
} | } | ||||
@@ -233,14 +262,57 @@ puglReshape(PuglView* view, int width, int height) | |||||
static void | static void | ||||
puglDisplay(PuglView* view) | puglDisplay(PuglView* view) | ||||
{ | { | ||||
PuglInternals* impl = view->impl; | |||||
bool success = true; | |||||
puglEnterContext(view); | 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 | static PuglKey | ||||
@@ -329,8 +401,9 @@ handleMessage(PuglView* view, UINT message, WPARAM wParam, LPARAM lParam) | |||||
mmi->ptMinTrackSize.y = view->min_height; | mmi->ptMinTrackSize.y = view->min_height; | ||||
break; | break; | ||||
case WM_PAINT: | case WM_PAINT: | ||||
BeginPaint(view->impl->hwnd, &ps); | |||||
view->impl->paintHdc = BeginPaint(view->impl->hwnd, &ps); | |||||
puglDisplay(view); | puglDisplay(view); | ||||
view->impl->paintHdc = NULL; | |||||
EndPaint(view->impl->hwnd, &ps); | EndPaint(view->impl->hwnd, &ps); | ||||
break; | break; | ||||
case WM_MOUSEMOVE: | case WM_MOUSEMOVE: | ||||
@@ -469,6 +542,18 @@ puglGetNativeWindow(PuglView* view) | |||||
return (PuglNativeWindow)view->impl->hwnd; | 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 | int | ||||
puglUpdateGeometryConstraints(PuglView* view, int min_width, int min_height, bool aspect) | puglUpdateGeometryConstraints(PuglView* view, int min_width, int min_height, bool aspect) | ||||
{ | { | ||||
@@ -2,6 +2,7 @@ | |||||
Copyright 2012-2014 David Robillard <http://drobilla.net> | Copyright 2012-2014 David Robillard <http://drobilla.net> | ||||
Copyright 2011-2012 Ben Loftis, Harrison Consoles | Copyright 2011-2012 Ben Loftis, Harrison Consoles | ||||
Copyright 2013,2015 Robin Gareus <robin@gareus.org> | 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 | Permission to use, copy, modify, and/or distribute this software for any | ||||
purpose with or without fee is hereby granted, provided that the above | purpose with or without fee is hereby granted, provided that the above | ||||
@@ -24,8 +25,14 @@ | |||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <string.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/gl.h> | ||||
#include <GL/glx.h> | #include <GL/glx.h> | ||||
#endif | |||||
#include <X11/Xatom.h> | #include <X11/Xatom.h> | ||||
#include <X11/Xlib.h> | #include <X11/Xlib.h> | ||||
#include <X11/Xutil.h> | #include <X11/Xutil.h> | ||||
@@ -53,10 +60,19 @@ struct PuglInternalsImpl { | |||||
Display* display; | Display* display; | ||||
int screen; | int screen; | ||||
Window win; | 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; | GLXContext ctx; | ||||
Bool doubleBuffered; | Bool doubleBuffered; | ||||
#endif | |||||
}; | }; | ||||
#ifdef PUGL_OPENGL | |||||
/** | /** | ||||
Attributes for single-buffered RGBA with at least | Attributes for single-buffered RGBA with at least | ||||
4 bits per color and a 16 bit depth buffer. | 4 bits per color and a 16 bit depth buffer. | ||||
@@ -102,6 +118,7 @@ static int attrListDblMS[] = { | |||||
GLX_SAMPLES, 4, | GLX_SAMPLES, 4, | ||||
None | None | ||||
}; | }; | ||||
#endif | |||||
PuglInternals* | PuglInternals* | ||||
puglInitInternals(void) | puglInitInternals(void) | ||||
@@ -112,12 +129,15 @@ puglInitInternals(void) | |||||
void | void | ||||
puglEnterContext(PuglView* view) | puglEnterContext(PuglView* view) | ||||
{ | { | ||||
#ifdef PUGL_OPENGL | |||||
glXMakeCurrent(view->impl->display, view->impl->win, view->impl->ctx); | glXMakeCurrent(view->impl->display, view->impl->win, view->impl->ctx); | ||||
#endif | |||||
} | } | ||||
void | void | ||||
puglLeaveContext(PuglView* view, bool flush) | puglLeaveContext(PuglView* view, bool flush) | ||||
{ | { | ||||
#ifdef PUGL_OPENGL | |||||
if (flush) { | if (flush) { | ||||
glFlush(); | glFlush(); | ||||
if (view->impl->doubleBuffered) { | if (view->impl->doubleBuffered) { | ||||
@@ -125,12 +145,13 @@ puglLeaveContext(PuglView* view, bool flush) | |||||
} | } | ||||
} | } | ||||
glXMakeCurrent(view->impl->display, None, NULL); | glXMakeCurrent(view->impl->display, None, NULL); | ||||
#endif | |||||
} | } | ||||
int | int | ||||
puglCreateWindow(PuglView* view, const char* title) | puglCreateWindow(PuglView* view, const char* title) | ||||
{ | { | ||||
PuglInternals* impl = (PuglInternals*)calloc(1, sizeof(PuglInternals)); | |||||
PuglInternals* impl = view->impl; | |||||
if (!impl) { | if (!impl) { | ||||
return 1; | return 1; | ||||
} | } | ||||
@@ -142,9 +163,12 @@ puglCreateWindow(PuglView* view, const char* title) | |||||
return 1; | return 1; | ||||
} | } | ||||
impl->screen = DefaultScreen(impl->display); | 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) { | if (!vi) { | ||||
vi = glXChooseVisual(impl->display, impl->screen, attrListDbl); | vi = glXChooseVisual(impl->display, impl->screen, attrListDbl); | ||||
@@ -157,6 +181,13 @@ puglCreateWindow(PuglView* view, const char* title) | |||||
vi = glXChooseVisual(impl->display, impl->screen, attrListSgl); | vi = glXChooseVisual(impl->display, impl->screen, attrListSgl); | ||||
impl->doubleBuffered = False; | 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) { | if (!vi) { | ||||
XCloseDisplay(impl->display); | XCloseDisplay(impl->display); | ||||
@@ -165,18 +196,23 @@ puglCreateWindow(PuglView* view, const char* title) | |||||
} | } | ||||
#ifdef PUGL_VERBOSE | #ifdef PUGL_VERBOSE | ||||
#ifdef PUGL_OPENGL | |||||
int glxMajor, glxMinor; | int glxMajor, glxMinor; | ||||
glXQueryVersion(impl->display, &glxMajor, &glxMinor); | glXQueryVersion(impl->display, &glxMajor, &glxMinor); | ||||
printf("puGL: GLX-Version : %d.%d\n", glxMajor, glxMinor); | printf("puGL: GLX-Version : %d.%d\n", glxMajor, glxMinor); | ||||
#endif | #endif | ||||
#endif | |||||
#ifdef PUGL_OPENGL | |||||
impl->ctx = glXCreateContext(impl->display, vi, 0, GL_TRUE); | impl->ctx = glXCreateContext(impl->display, vi, 0, GL_TRUE); | ||||
if (!impl->ctx) { | if (!impl->ctx) { | ||||
XFree(vi); | |||||
XCloseDisplay(impl->display); | XCloseDisplay(impl->display); | ||||
free(impl); | free(impl); | ||||
return 1; | return 1; | ||||
} | } | ||||
#endif | |||||
Window xParent = view->parent | Window xParent = view->parent | ||||
? (Window)view->parent | ? (Window)view->parent | ||||
@@ -201,11 +237,36 @@ puglCreateWindow(PuglView* view, const char* title) | |||||
CWBorderPixel | CWColormap | CWEventMask, &attr); | CWBorderPixel | CWColormap | CWEventMask, &attr); | ||||
if (!impl->win) { | if (!impl->win) { | ||||
#ifdef PUGL_OPENGL | |||||
glXDestroyContext(impl->display, impl->ctx); | |||||
#endif | |||||
XFree(vi); | |||||
XCloseDisplay(impl->display); | XCloseDisplay(impl->display); | ||||
free(impl); | free(impl); | ||||
return 1; | 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) { | if (view->width > 1 || view->height > 1) { | ||||
puglUpdateGeometryConstraints(view, view->min_width, view->min_height, view->min_width != view->width); | puglUpdateGeometryConstraints(view, view->min_width, view->min_height, view->min_width != view->width); | ||||
XResizeWindow(view->impl->display, view->impl->win, view->width, view->height); | 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_VERBOSE | ||||
#ifdef PUGL_OPENGL | |||||
if (glXIsDirect(impl->display, impl->ctx)) { | if (glXIsDirect(impl->display, impl->ctx)) { | ||||
printf("puGL: DRI enabled (to disable, set LIBGL_ALWAYS_INDIRECT=1\n"); | printf("puGL: DRI enabled (to disable, set LIBGL_ALWAYS_INDIRECT=1\n"); | ||||
} else { | } else { | ||||
printf("puGL: No DRI available\n"); | printf("puGL: No DRI available\n"); | ||||
} | } | ||||
#endif | |||||
#endif | #endif | ||||
XFree(vi); | XFree(vi); | ||||
@@ -244,14 +307,25 @@ puglDestroy(PuglView* view) | |||||
if (!view) { | if (!view) { | ||||
return; | return; | ||||
} | } | ||||
PuglInternals* const impl = view->impl; | |||||
#ifndef DGL_FILE_BROWSER_DISABLED | #ifndef DGL_FILE_BROWSER_DISABLED | ||||
x_fib_close(view->impl->display); | |||||
x_fib_close(impl->display); | |||||
#endif | #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); | free(view); | ||||
} | } | ||||
@@ -287,14 +361,47 @@ puglReshape(PuglView* view, int width, int height) | |||||
static void | static void | ||||
puglDisplay(PuglView* view) | puglDisplay(PuglView* view) | ||||
{ | { | ||||
PuglInternals* impl = view->impl; | |||||
puglEnterContext(view); | 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; | view->redisplay = false; | ||||
if (view->displayFunc) { | if (view->displayFunc) { | ||||
view->displayFunc(view); | 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); | puglLeaveContext(view, true); | ||||
(void)impl; | |||||
} | } | ||||
static void | static void | ||||
@@ -554,6 +661,12 @@ puglProcessEvents(PuglView* view) | |||||
} | } | ||||
if (conf_width != -1) { | 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); | puglReshape(view, conf_width, conf_height); | ||||
} | } | ||||
@@ -586,6 +699,18 @@ puglGetNativeWindow(PuglView* view) | |||||
return view->impl->win; | 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 | int | ||||
puglUpdateGeometryConstraints(PuglView* view, int min_width, int min_height, bool aspect) | puglUpdateGeometryConstraints(PuglView* view, int min_width, int min_height, bool aspect) | ||||
{ | { | ||||
@@ -417,6 +417,10 @@ START_NAMESPACE_DISTRHO | |||||
}; | }; | ||||
@endcode | @endcode | ||||
This is a work-in-progress documentation page. States, MIDI, Latency, Time-Position and UI are still TODO. | |||||
*/ | |||||
#if 0 | |||||
@section States | @section States | ||||
describe them | describe them | ||||
@@ -431,7 +435,7 @@ START_NAMESPACE_DISTRHO | |||||
@section UI | @section UI | ||||
describe them | describe them | ||||
*/ | |||||
#endif | |||||
/* ------------------------------------------------------------------------------------------------------------ | /* ------------------------------------------------------------------------------------------------------------ | ||||
* Plugin Macros */ | * Plugin Macros */ | ||||
@@ -543,6 +547,16 @@ START_NAMESPACE_DISTRHO | |||||
*/ | */ | ||||
#define DISTRHO_PLUGIN_WANT_STATE 1 | #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. | Wherever the plugin wants time position information from the host. | ||||
@see Plugin::getTimePosition() | @see Plugin::getTimePosition() | ||||
@@ -226,7 +226,7 @@ struct ParameterRanges { | |||||
/** | /** | ||||
Get a fixed value within range. | Get a fixed value within range. | ||||
*/ | */ | ||||
const float& getFixedValue(const float& value) const noexcept | |||||
float getFixedValue(const float& value) const noexcept | |||||
{ | { | ||||
if (value <= min) | if (value <= min) | ||||
return min; | return min; | ||||
@@ -32,6 +32,13 @@ typedef DGL_NAMESPACE::NanoWidget UIWidget; | |||||
typedef DGL_NAMESPACE::Widget UIWidget; | typedef DGL_NAMESPACE::Widget UIWidget; | ||||
#endif | #endif | ||||
#ifdef DGL_CAIRO | |||||
# include "Cairo.hpp" | |||||
#endif | |||||
#ifdef DGL_OPENGL | |||||
# include "OpenGL.hpp" | |||||
#endif | |||||
START_NAMESPACE_DISTRHO | START_NAMESPACE_DISTRHO | ||||
/* ------------------------------------------------------------------------------------------------------------ | /* ------------------------------------------------------------------------------------------------------------ | ||||
@@ -62,7 +69,7 @@ public: | |||||
*/ | */ | ||||
virtual ~UI(); | 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. | Set geometry constraints for the UI when resized by the user, and optionally scale UI automatically. | ||||
@see Window::setGeometryConstraints(uint,uint,bool) | @see Window::setGeometryConstraints(uint,uint,bool) | ||||
@@ -82,13 +89,17 @@ public: | |||||
/** | /** | ||||
editParameter. | 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); | void editParameter(uint32_t index, bool started); | ||||
/** | /** | ||||
setParameterValue. | setParameterValue. | ||||
@TODO Document this. | |||||
Change a parameter value in the Plugin. | |||||
*/ | */ | ||||
void setParameterValue(uint32_t index, float value); | void setParameterValue(uint32_t index, float value); | ||||
@@ -131,6 +142,13 @@ public: | |||||
*/ | */ | ||||
static const char* getNextBundlePath() noexcept; | 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 | # if DISTRHO_PLUGIN_HAS_EMBED_UI | ||||
/** | /** | ||||
Get the Window Id that will be used for the next created window. | Get the Window Id that will be used for the next created window. | ||||
@@ -97,7 +97,7 @@ | |||||
// Define DISTRHO_PLUGIN_HAS_EMBED_UI if needed | // Define DISTRHO_PLUGIN_HAS_EMBED_UI if needed | ||||
#ifndef DISTRHO_PLUGIN_HAS_EMBED_UI | #ifndef DISTRHO_PLUGIN_HAS_EMBED_UI | ||||
# ifdef HAVE_DGL | |||||
# if defined(HAVE_CAIRO) || defined(HAVE_OPENGL) | |||||
# define DISTRHO_PLUGIN_HAS_EMBED_UI 1 | # define DISTRHO_PLUGIN_HAS_EMBED_UI 1 | ||||
# else | # else | ||||
# define DISTRHO_PLUGIN_HAS_EMBED_UI 0 | # define DISTRHO_PLUGIN_HAS_EMBED_UI 0 | ||||
@@ -139,7 +139,7 @@ | |||||
// ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
// Disable UI if DGL or External UI is not available | // 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 | # undef DISTRHO_PLUGIN_HAS_UI | ||||
# define DISTRHO_PLUGIN_HAS_UI 0 | # define DISTRHO_PLUGIN_HAS_UI 0 | ||||
#endif | #endif | ||||
@@ -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 | #if DISTRHO_PLUGIN_HAS_UI | ||||
class PluginJack : public IdleCallback | class PluginJack : public IdleCallback | ||||
#else | #else | ||||
@@ -91,7 +101,7 @@ public: | |||||
PluginJack(jack_client_t* const client) | PluginJack(jack_client_t* const client) | ||||
: fPlugin(this, writeMidiCallback), | : fPlugin(this, writeMidiCallback), | ||||
#if DISTRHO_PLUGIN_HAS_UI | #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 | #endif | ||||
fClient(client) | fClient(client) | ||||
{ | { | ||||
@@ -545,7 +545,7 @@ public: | |||||
#ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD | #ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD | ||||
for (uint32_t i=0; i<DISTRHO_PLUGIN_NUM_OUTPUTS; ++i) | 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 | #endif | ||||
#if DISTRHO_PLUGIN_WANT_TIMEPOS | #if DISTRHO_PLUGIN_WANT_TIMEPOS | ||||
@@ -719,7 +719,7 @@ void lv2_generate_ttl(const char* const basename) | |||||
if (value.length() < 10) | if (value.length() < 10) | ||||
presetString += " \"" + value + "\" ;\n"; | presetString += " \"" + value + "\" ;\n"; | ||||
else | else | ||||
presetString += "\n\"\"\"\n" + value + "\n\"\"\" ;\n"; | |||||
presetString += "\n\"\"\"" + value + "\"\"\" ;\n"; | |||||
} | } | ||||
if (numParameters > 0) | if (numParameters > 0) | ||||
@@ -161,12 +161,12 @@ public: | |||||
class UIVst | class UIVst | ||||
{ | { | ||||
public: | 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), | : fAudioMaster(audioMaster), | ||||
fEffect(effect), | fEffect(effect), | ||||
fUiHelper(uiHelper), | fUiHelper(uiHelper), | ||||
fPlugin(plugin), | 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) | fShouldCaptureVstKeys(false) | ||||
{ | { | ||||
// FIXME only needed for windows? | // FIXME only needed for windows? | ||||
@@ -575,8 +575,11 @@ public: | |||||
else | else | ||||
{ | { | ||||
d_lastUiSampleRate = fPlugin.getSampleRate(); | 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.right = tmpUI.getWidth(); | ||||
fVstRect.bottom = tmpUI.getHeight(); | fVstRect.bottom = tmpUI.getHeight(); | ||||
tmpUI.quit(); | tmpUI.quit(); | ||||
@@ -595,8 +598,11 @@ public: | |||||
} | } | ||||
# endif | # endif | ||||
d_lastUiSampleRate = fPlugin.getSampleRate(); | 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 | # if DISTRHO_PLUGIN_WANT_FULL_STATE | ||||
// Update current state from plugin side | // Update current state from plugin side | ||||
@@ -27,8 +27,9 @@ START_NAMESPACE_DISTRHO | |||||
double d_lastUiSampleRate = 0.0; | double d_lastUiSampleRate = 0.0; | ||||
void* d_lastUiDspPtr = nullptr; | void* d_lastUiDspPtr = nullptr; | ||||
#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI | #if DISTRHO_PLUGIN_HAS_EXTERNAL_UI | ||||
uintptr_t g_nextWindowId = 0; | |||||
const char* g_nextBundlePath = nullptr; | const char* g_nextBundlePath = nullptr; | ||||
double g_nextScaleFactor = 1.0; | |||||
uintptr_t g_nextWindowId = 0; | |||||
#else | #else | ||||
Window* d_lastUiWindow = nullptr; | Window* d_lastUiWindow = nullptr; | ||||
#endif | #endif | ||||
@@ -57,7 +58,7 @@ UI::~UI() | |||||
delete pData; | 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) | void UI::setGeometryConstraints(uint minWidth, uint minHeight, bool keepAspectRatio, bool automaticallyScale) | ||||
{ | { | ||||
DISTRHO_SAFE_ASSERT_RETURN(minWidth > 0,); | DISTRHO_SAFE_ASSERT_RETURN(minWidth > 0,); | ||||
@@ -67,7 +68,13 @@ void UI::setGeometryConstraints(uint minWidth, uint minHeight, bool keepAspectRa | |||||
pData->minWidth = minWidth; | pData->minWidth = minWidth; | ||||
pData->minHeight = minHeight; | 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 | #endif | ||||
@@ -122,6 +129,11 @@ const char* UI::getNextBundlePath() noexcept | |||||
return g_nextBundlePath; | return g_nextBundlePath; | ||||
} | } | ||||
double UI::getNextScaleFactor() noexcept | |||||
{ | |||||
return g_nextScaleFactor; | |||||
} | |||||
# if DISTRHO_PLUGIN_HAS_EMBED_UI | # if DISTRHO_PLUGIN_HAS_EMBED_UI | ||||
uintptr_t UI::getNextWindowId() noexcept | uintptr_t UI::getNextWindowId() noexcept | ||||
{ | { | ||||
@@ -147,6 +159,7 @@ void UI::uiFileBrowserSelected(const char*) | |||||
void UI::uiReshape(uint width, uint height) | void UI::uiReshape(uint width, uint height) | ||||
{ | { | ||||
#ifdef DGL_OPENGL | |||||
glEnable(GL_BLEND); | glEnable(GL_BLEND); | ||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | ||||
glMatrixMode(GL_PROJECTION); | 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)); | glViewport(0, 0, static_cast<GLsizei>(width), static_cast<GLsizei>(height)); | ||||
glMatrixMode(GL_MODELVIEW); | glMatrixMode(GL_MODELVIEW); | ||||
glLoadIdentity(); | glLoadIdentity(); | ||||
#else | |||||
// unused | |||||
(void)width; | |||||
(void)height; | |||||
#endif | |||||
} | } | ||||
/* ------------------------------------------------------------------------------------------------------------ | /* ------------------------------------------------------------------------------------------------------------ | ||||
@@ -37,11 +37,13 @@ START_NAMESPACE_DISTRHO | |||||
extern double d_lastUiSampleRate; | extern double d_lastUiSampleRate; | ||||
extern void* d_lastUiDspPtr; | 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; | extern Window* d_lastUiWindow; | ||||
#endif | #endif | ||||
extern uintptr_t g_nextWindowId; | |||||
extern const char* g_nextBundlePath; | |||||
// ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
// UI callbacks | // UI callbacks | ||||
@@ -149,15 +151,17 @@ struct UI::PrivateData { | |||||
#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI | #if DISTRHO_PLUGIN_HAS_EXTERNAL_UI | ||||
static inline | 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; | return ret; | ||||
} | } | ||||
#else // DISTRHO_PLUGIN_HAS_EXTERNAL_UI | #else // DISTRHO_PLUGIN_HAS_EXTERNAL_UI | ||||
@@ -175,8 +179,8 @@ UI* createUiWrapper(void* const dspPtr, Window* const window) | |||||
class UIExporterWindow : public Window | class UIExporterWindow : public Window | ||||
{ | { | ||||
public: | 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)), | fUI(createUiWrapper(dspPtr, this)), | ||||
fIsReady(false) | fIsReady(false) | ||||
{ | { | ||||
@@ -214,7 +218,7 @@ protected: | |||||
{ | { | ||||
const double scaleHorizontal = static_cast<double>(width) / static_cast<double>(pData->minWidth); | const double scaleHorizontal = static_cast<double>(width) / static_cast<double>(pData->minWidth); | ||||
const double scaleVertical = static_cast<double>(height) / static_cast<double>(pData->minHeight); | 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; | pData->resizeInProgress = true; | ||||
@@ -254,13 +258,14 @@ public: | |||||
const setStateFunc setStateCall, | const setStateFunc setStateCall, | ||||
const sendNoteFunc sendNoteCall, | const sendNoteFunc sendNoteCall, | ||||
const setSizeFunc setSizeCall, | const setSizeFunc setSizeCall, | ||||
const float scaleFactor = 1.0f, | |||||
void* const dspPtr = nullptr, | void* const dspPtr = nullptr, | ||||
const char* const bundlePath = nullptr) | const char* const bundlePath = nullptr) | ||||
#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI | #if DISTRHO_PLUGIN_HAS_EXTERNAL_UI | ||||
: fUI(createUiWrapper(dspPtr, winId, bundlePath)), | |||||
: fUI(createUiWrapper(dspPtr, winId, scaleFactor, bundlePath)), | |||||
#else | #else | ||||
: glApp(), | : glApp(), | ||||
glWindow(glApp, winId, dspPtr), | |||||
glWindow(glApp, winId, scaleFactor, dspPtr), | |||||
fChangingSize(false), | fChangingSize(false), | ||||
fUI(glWindow.getUI()), | fUI(glWindow.getUI()), | ||||
#endif | #endif | ||||
@@ -53,8 +53,8 @@ public: | |||||
UiLv2(const char* const bundlePath, const intptr_t winId, | 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 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, | 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), | fUridMap(uridMap), | ||||
fUiResize(uiResz), | fUiResize(uiResz), | ||||
fUiTouch(uiTouch), | fUiTouch(uiTouch), | ||||
@@ -286,7 +286,7 @@ protected: | |||||
atomMidiEvent.data[2] = velocity; | atomMidiEvent.data[2] = velocity; | ||||
// send to DSP side | // 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 | #endif | ||||
@@ -434,22 +434,30 @@ static LV2UI_Handle lv2ui_instantiate(const LV2UI_Descriptor*, const char* uri, | |||||
} | } | ||||
#endif | #endif | ||||
float scaleFactor = 1.0f; | |||||
const intptr_t winId((intptr_t)parentId); | const intptr_t winId((intptr_t)parentId); | ||||
if (options != nullptr) | 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 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) | 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; | d_lastUiSampleRate = *(const float*)options[i].value; | ||||
else | else | ||||
d_stderr("Host provides UI sample-rate but has wrong value type"); | 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; | 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) | #define uiPtr ((UiLv2*)ui) | ||||
@@ -52,6 +52,7 @@ | |||||
#define LV2_UI__portNotification LV2_UI_PREFIX "portNotification" | #define LV2_UI__portNotification LV2_UI_PREFIX "portNotification" | ||||
#define LV2_UI__portSubscribe LV2_UI_PREFIX "portSubscribe" | #define LV2_UI__portSubscribe LV2_UI_PREFIX "portSubscribe" | ||||
#define LV2_UI__resize LV2_UI_PREFIX "resize" | #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__showInterface LV2_UI_PREFIX "showInterface" | ||||
#define LV2_UI__touch LV2_UI_PREFIX "touch" | #define LV2_UI__touch LV2_UI_PREFIX "touch" | ||||
#define LV2_UI__ui LV2_UI_PREFIX "ui" | #define LV2_UI__ui LV2_UI_PREFIX "ui" | ||||
@@ -242,7 +242,8 @@ SEARCH_INCLUDES = YES | |||||
INCLUDE_PATH = | INCLUDE_PATH = | ||||
INCLUDE_FILE_PATTERNS = | INCLUDE_FILE_PATTERNS = | ||||
PREDEFINED = DOXYGEN \ | PREDEFINED = DOXYGEN \ | ||||
HAVE_DGL=1 \ | |||||
HAVE_CAIRO=1 \ | |||||
HAVE_OPENGL=1 \ | |||||
DISTRHO_PLUGIN_NAME="Plugin Name" \ | DISTRHO_PLUGIN_NAME="Plugin Name" \ | ||||
DISTRHO_PLUGIN_NUM_INPUTS=2 \ | DISTRHO_PLUGIN_NUM_INPUTS=2 \ | ||||
DISTRHO_PLUGIN_NUM_OUTPUTS=2 \ | DISTRHO_PLUGIN_NUM_OUTPUTS=2 \ | ||||
@@ -2,7 +2,7 @@ | |||||
all: build | all: build | ||||
ifeq ($(WIN32),true) | |||||
ifeq ($(WINDOWS),true) | |||||
build: ../lv2_ttl_generator.exe | build: ../lv2_ttl_generator.exe | ||||
else | else | ||||
build: ../lv2_ttl_generator | build: ../lv2_ttl_generator | ||||
@@ -19,7 +19,7 @@ import os, sys | |||||
# ----------------------------------------------------- | # ----------------------------------------------------- | ||||
def png2c(namespace, filenames): | |||||
def res2c(namespace, filenames): | |||||
fdH = open("%s.hpp" % namespace, "w") | fdH = open("%s.hpp" % namespace, "w") | ||||
fdH.write("/* (Auto-generated binary data file). */\n") | 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 = filename.rsplit(os.sep, 1)[-1].split(".", 1)[0] | ||||
shortFilename = shortFilename.replace("-", "_") | shortFilename = shortFilename.replace("-", "_") | ||||
pngData = open(filename, 'rb').read() | |||||
resData = open(filename, 'rb').read() | |||||
print("Generating data for \"%s\"" % (filename)) | print("Generating data for \"%s\"" % (filename)) | ||||
fdH.write(" extern const char* %sData;\n" % shortFilename) | 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): | if tempIndex != len(filenames): | ||||
fdH.write("\n") | fdH.write("\n") | ||||
@@ -57,7 +57,7 @@ def png2c(namespace, filenames): | |||||
curColumn = 1 | curColumn = 1 | ||||
fdC.write(" ") | fdC.write(" ") | ||||
for data in pngData: | |||||
for data in resData: | |||||
if curColumn == 0: | if curColumn == 0: | ||||
fdC.write(" ") | fdC.write(" ") | ||||
@@ -90,24 +90,24 @@ def png2c(namespace, filenames): | |||||
if __name__ == '__main__': | if __name__ == '__main__': | ||||
if len(sys.argv) != 3: | if len(sys.argv) != 3: | ||||
print("Usage: %s <namespace> <artwork-folder>" % sys.argv[0]) | |||||
print("Usage: %s <namespace> <resource-folder>" % sys.argv[0]) | |||||
quit() | quit() | ||||
namespace = sys.argv[1].replace("-","_") | 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() | 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 | # create code now | ||||
png2c(namespace, pngFiles) | |||||
res2c(namespace, resFiles) |
@@ -1,6 +1,6 @@ | |||||
/* | /* | ||||
* DISTRHO Kars Plugin, based on karplong by Chris Cannam. | * 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 | * 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 | * or without fee is hereby granted, provided that the above copyright notice and this | ||||
@@ -158,7 +158,8 @@ public: | |||||
midiEvents(m), | midiEvents(m), | ||||
midiEventCount(0), | midiEventCount(0), | ||||
remainingFrames(f), | remainingFrames(f), | ||||
remainingMidiEventCount(mc) {} | |||||
remainingMidiEventCount(mc), | |||||
totalFramesUsed(0) {} | |||||
/** | /** | ||||
Process a batch of events untill no more are available. | Process a batch of events untill no more are available. | ||||
@@ -166,41 +167,76 @@ public: | |||||
*/ | */ | ||||
bool nextEvent() | 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) | for (uint32_t i=0; i<DISTRHO_PLUGIN_NUM_OUTPUTS; ++i) | ||||
outputs[i] += frames; | outputs[i] += frames; | ||||
} | |||||
if (midiEventCount != 0) | |||||
midiEvents += midiEventCount; | |||||
// no more MIDI events available | |||||
if (remainingMidiEventCount == 0) | |||||
{ | |||||
frames = remainingFrames; | frames = remainingFrames; | ||||
midiEvents = nullptr; | midiEvents = nullptr; | ||||
midiEventCount = 0; | midiEventCount = 0; | ||||
remainingFrames = 0; | remainingFrames = 0; | ||||
totalFramesUsed += frames; | |||||
return true; | 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; | 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; | remainingFrames -= frames; | ||||
remainingMidiEventCount -= midiEventCount; | remainingMidiEventCount -= midiEventCount; | ||||
totalFramesUsed += frames; | |||||
return true; | return true; | ||||
} | } | ||||
@@ -208,6 +244,7 @@ private: | |||||
/** @internal */ | /** @internal */ | ||||
uint32_t remainingFrames; | uint32_t remainingFrames; | ||||
uint32_t remainingMidiEventCount; | uint32_t remainingMidiEventCount; | ||||
uint32_t totalFramesUsed; | |||||
}; | }; | ||||
void DistrhoPluginKars::run(const float**, float** outputs, uint32_t frames, const MidiEvent* midiEvents, uint32_t midiEventCount) | 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) | if (fNotes[i].on != kNoteNull) | ||||
addSamples(out, i, amsh.frames); | addSamples(out, i, amsh.frames); | ||||
} | } | ||||
} | |||||
fBlockStart += frames; | |||||
fBlockStart += amsh.frames; | |||||
} | |||||
} | } | ||||
void DistrhoPluginKars::addSamples(float* out, int voice, uint32_t frames) | void DistrhoPluginKars::addSamples(float* out, int voice, uint32_t frames) | ||||
@@ -1,6 +1,6 @@ | |||||
/* | /* | ||||
* DISTRHO Kars Plugin, based on karplong by Chris Cannam. | * 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 | * 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 | * 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 | uint32_t getVersion() const noexcept override | ||||
{ | { | ||||
return d_version(1, 0, 0); | |||||
return d_version(1, 1, 0); | |||||
} | } | ||||
int64_t getUniqueId() const noexcept override | int64_t getUniqueId() const noexcept override | ||||
@@ -24,6 +24,7 @@ include ../../dpf/Makefile.plugins.mk | |||||
# Extra flags | # Extra flags | ||||
BUILD_CXX_FLAGS += -I../common -I../common/gen_dsp | BUILD_CXX_FLAGS += -I../common -I../common/gen_dsp | ||||
BUILD_CXX_FLAGS += -Wno-unused-parameter | |||||
# -------------------------------------------------------------- | # -------------------------------------------------------------- | ||||
# Enable all possible plugin types | # Enable all possible plugin types | ||||
@@ -24,6 +24,7 @@ include ../../dpf/Makefile.plugins.mk | |||||
# Extra flags | # Extra flags | ||||
BUILD_CXX_FLAGS += -I../common -I../common/gen_dsp | BUILD_CXX_FLAGS += -I../common -I../common/gen_dsp | ||||
BUILD_CXX_FLAGS += -Wno-unused-parameter | |||||
# -------------------------------------------------------------- | # -------------------------------------------------------------- | ||||
# Enable all possible plugin types | # Enable all possible plugin types | ||||
@@ -24,6 +24,7 @@ include ../../dpf/Makefile.plugins.mk | |||||
# Extra flags | # Extra flags | ||||
BUILD_CXX_FLAGS += -I../common -I../common/gen_dsp | BUILD_CXX_FLAGS += -I../common -I../common/gen_dsp | ||||
BUILD_CXX_FLAGS += -Wno-unused-parameter | |||||
# -------------------------------------------------------------- | # -------------------------------------------------------------- | ||||
# Enable all possible plugin types | # Enable all possible plugin types | ||||
@@ -3,7 +3,7 @@ | |||||
* Copyright (C) 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson and 4Front Technologies | * 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) 2000 Christian Zander <phoenix@minion.de> | ||||
* Copyright (C) 2015 Nedko Arnaudov | * 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 | * This program is free software; you can redistribute it and/or | ||||
* modify it under the terms of the GNU General Public License as | * modify it under the terms of the GNU General Public License as | ||||
@@ -3,7 +3,7 @@ | |||||
* Copyright (C) 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson and 4Front Technologies | * 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) 2000 Christian Zander <phoenix@minion.de> | ||||
* Copyright (C) 2015 Nedko Arnaudov | * 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 | * This program is free software; you can redistribute it and/or | ||||
* modify it under the terms of the GNU General Public License as | * modify it under the terms of the GNU General Public License as | ||||
@@ -45,7 +45,6 @@ protected: | |||||
// UI Callbacks | // UI Callbacks | ||||
void uiIdle() override; | void uiIdle() override; | ||||
// void uiReshape(uint width, uint height) override; | |||||
// ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
// Widget Callbacks | // Widget Callbacks | ||||
@@ -3,7 +3,7 @@ | |||||
* Copyright (C) 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson and 4Front Technologies | * 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) 2000 Christian Zander <phoenix@minion.de> | ||||
* Copyright (C) 2015 Nedko Arnaudov | * 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 | * This program is free software; you can redistribute it and/or | ||||
* modify it under the terms of the GNU Lesser General Public | * modify it under the terms of the GNU Lesser General Public | ||||
@@ -20,7 +20,7 @@ | |||||
#ifndef GLBARS_STATE_HPP_INCLUDED | #ifndef GLBARS_STATE_HPP_INCLUDED | ||||
#define GLBARS_STATE_HPP_INCLUDED | #define GLBARS_STATE_HPP_INCLUDED | ||||
#include "Base.hpp" | |||||
#include "OpenGL.hpp" | |||||
static inline | static inline | ||||
void draw_rectangle(GLfloat x1, GLfloat y1, GLfloat z1, GLfloat x2, GLfloat y2, GLfloat z2) | void draw_rectangle(GLfloat x1, GLfloat y1, GLfloat z1, GLfloat x2, GLfloat y2, GLfloat z2) | ||||
@@ -24,6 +24,7 @@ include ../../dpf/Makefile.plugins.mk | |||||
# Extra flags | # Extra flags | ||||
BUILD_CXX_FLAGS += -I../common -I../common/gen_dsp | BUILD_CXX_FLAGS += -I../common -I../common/gen_dsp | ||||
BUILD_CXX_FLAGS += -Wno-unused-parameter | |||||
# -------------------------------------------------------------- | # -------------------------------------------------------------- | ||||
# Enable all possible plugin types | # Enable all possible plugin types | ||||