@@ -20,7 +20,7 @@ HAVE_PROJM = $(shell pkg-config --exists libprojectM && echo true) | |||
# -------------------------------------------------------------- | |||
dgl: | |||
ifeq ($(HAVE_DGL),true) | |||
ifeq ($(HAVE_CAIRO_OR_OPENGL),true) | |||
$(MAKE) -C dpf/dgl | |||
endif | |||
@@ -50,7 +50,7 @@ plugins: dgl | |||
$(MAKE) all -C plugins/gigaverb | |||
$(MAKE) all -C plugins/pitchshift | |||
ifeq ($(HAVE_DGL),true) | |||
ifeq ($(HAVE_CAIRO_OR_OPENGL),true) | |||
# glBars (needs OpenGL) | |||
$(MAKE) all -C plugins/glBars | |||
@@ -58,7 +58,7 @@ ifeq ($(HAVE_PROJM),true) | |||
# ProM (needs OpenGL + ProjectM) | |||
$(MAKE) all -C plugins/ProM | |||
endif # HAVE_PROJM | |||
endif # HAVE_DGL | |||
endif # HAVE_CAIRO_OR_OPENGL | |||
ifneq ($(CROSS_COMPILING),true) | |||
gen: plugins dpf/utils/lv2_ttl_generator | |||
@@ -123,9 +123,9 @@ install: | |||
install -m 644 bin/*-dssi.* $(DESTDIR)$(PREFIX)/lib/dssi/ | |||
install -m 644 bin/*-vst.* $(DESTDIR)$(PREFIX)/lib/vst/ | |||
ifeq ($(HAVE_DGL),true) | |||
ifeq ($(HAVE_CAIRO_OR_OPENGL),true) | |||
cp -r bin/*-dssi $(DESTDIR)$(PREFIX)/lib/dssi/ | |||
endif # HAVE_DGL | |||
endif # HAVE_CAIRO_OR_OPENGL | |||
cp -r bin/*.lv2 $(DESTDIR)$(PREFIX)/lib/lv2/ | |||
ifeq ($(HAVE_JACK),true) | |||
@@ -142,12 +142,12 @@ ifeq ($(HAVE_JACK),true) | |||
install -m 755 bin/MaFreeverb $(DESTDIR)$(PREFIX)/bin/ | |||
install -m 755 bin/MaGigaverb $(DESTDIR)$(PREFIX)/bin/ | |||
install -m 755 bin/MaPitchshift $(DESTDIR)$(PREFIX)/bin/ | |||
ifeq ($(HAVE_DGL),true) | |||
ifeq ($(HAVE_CAIRO_OR_OPENGL),true) | |||
install -m 755 bin/glBars $(DESTDIR)$(PREFIX)/bin/ | |||
ifeq ($(HAVE_PROJM),true) | |||
install -m 755 bin/ProM $(DESTDIR)$(PREFIX)/bin/ | |||
endif # HAVE_PROJM | |||
endif # HAVE_DGL | |||
endif # HAVE_CAIRO_OR_OPENGL | |||
endif # HAVE_JACK | |||
# -------------------------------------------------------------- | |||
@@ -16,7 +16,7 @@ ifneq ($(HAIKU),true) | |||
ifneq ($(HURD),true) | |||
ifneq ($(LINUX),true) | |||
ifneq ($(MACOS),true) | |||
ifneq ($(WIN32),true) | |||
ifneq ($(WINDOWS),true) | |||
TARGET_MACHINE := $(shell $(CC) -dumpmachine) | |||
ifneq (,$(findstring bsd,$(TARGET_MACHINE))) | |||
@@ -35,7 +35,7 @@ ifneq (,$(findstring apple,$(TARGET_MACHINE))) | |||
MACOS=true | |||
endif | |||
ifneq (,$(findstring mingw,$(TARGET_MACHINE))) | |||
WIN32=true | |||
WINDOWS=true | |||
endif | |||
endif | |||
@@ -45,6 +45,16 @@ endif | |||
endif | |||
endif | |||
# --------------------------------------------------------------------------------------------------------------------- | |||
# Set PKG_CONFIG (can be overridden by environment variable) | |||
ifeq ($(WINDOWS),true) | |||
# Build statically on Windows by default | |||
PKG_CONFIG ?= pkg-config --static | |||
else | |||
PKG_CONFIG ?= pkg-config | |||
endif | |||
# --------------------------------------------------------------------------------------------------------------------- | |||
# Set LINUX_OR_MACOS | |||
@@ -57,14 +67,20 @@ LINUX_OR_MACOS=true | |||
endif | |||
# --------------------------------------------------------------------------------------------------------------------- | |||
# Set MACOS_OR_WIN32 | |||
# Set MACOS_OR_WINDOWS and HAIKU_OR_MACOS_OR_WINDOWS | |||
ifeq ($(HAIKU),true) | |||
HAIKU_OR_MACOS_OR_WINDOWS=true | |||
endif | |||
ifeq ($(MACOS),true) | |||
MACOS_OR_WIN32=true | |||
MACOS_OR_WINDOWS=true | |||
HAIKU_OR_MACOS_OR_WINDOWS=true | |||
endif | |||
ifeq ($(WIN32),true) | |||
MACOS_OR_WIN32=true | |||
ifeq ($(WINDOWS),true) | |||
MACOS_OR_WINDOWS=true | |||
HAIKU_OR_MACOS_OR_WINDOWS=true | |||
endif | |||
# --------------------------------------------------------------------------------------------------------------------- | |||
@@ -108,10 +124,12 @@ ifeq ($(NOOPT),true) | |||
BASE_OPTS = -O2 -ffast-math -fdata-sections -ffunction-sections | |||
endif | |||
ifeq ($(WIN32),true) | |||
ifeq ($(WINDOWS),true) | |||
# mingw has issues with this specific optimization | |||
# See https://github.com/falkTX/Carla/issues/696 | |||
BASE_OPTS += -fno-rerun-cse-after-loop | |||
# See https://github.com/falkTX/Carla/issues/855 | |||
BASE_OPTS += -mstackrealign | |||
ifeq ($(BUILDING_FOR_WINDOWS),true) | |||
BASE_FLAGS += -DBUILDING_CARLA_FOR_WINDOWS | |||
endif | |||
@@ -141,7 +159,7 @@ ifeq ($(MACOS_OLD),true) | |||
BUILD_CXX_FLAGS = $(BASE_FLAGS) $(CXXFLAGS) -DHAVE_CPP11_SUPPORT=0 | |||
endif | |||
ifeq ($(WIN32),true) | |||
ifeq ($(WINDOWS),true) | |||
# Always build statically on windows | |||
LINK_FLAGS += -static | |||
endif | |||
@@ -170,44 +188,81 @@ CXXFLAGS += -Weffc++ -Wnon-virtual-dtor -Woverloaded-virtual | |||
endif | |||
# --------------------------------------------------------------------------------------------------------------------- | |||
# Check for optional libs | |||
# Check for required libraries | |||
ifeq ($(MACOS_OR_WIN32),true) | |||
HAVE_DGL = true | |||
HAVE_CAIRO = $(shell $(PKG_CONFIG) --exists cairo && echo true) | |||
ifeq ($(HAIKU_OR_MACOS_OR_WINDOWS),true) | |||
HAVE_OPENGL = true | |||
else | |||
HAVE_DGL = $(shell pkg-config --exists gl x11 && echo true) | |||
HAVE_JACK = $(shell pkg-config --exists jack && echo true) | |||
HAVE_LIBLO = $(shell pkg-config --exists liblo && echo true) | |||
HAVE_OPENGL = $(shell $(PKG_CONFIG) --exists gl && echo true) | |||
HAVE_X11 = $(shell $(PKG_CONFIG) --exists x11 && echo true) | |||
endif | |||
ifneq ($(HAVE_DGL),true) | |||
$(error DGL missing 22) | |||
# --------------------------------------------------------------------------------------------------------------------- | |||
# Check for optional libraries | |||
HAVE_JACK = $(shell $(PKG_CONFIG) --exists jack && echo true) | |||
HAVE_LIBLO = $(shell $(PKG_CONFIG) --exists liblo && echo true) | |||
# --------------------------------------------------------------------------------------------------------------------- | |||
# Set Generic DGL stuff | |||
ifeq ($(MACOS),true) | |||
DGL_SYSTEM_LIBS += -framework Cocoa | |||
endif | |||
ifeq ($(WINDOWS),true) | |||
DGL_SYSTEM_LIBS += -lgdi32 | |||
endif | |||
ifneq ($(HAIKU_OR_MACOS_OR_WINDOWS),true) | |||
DGL_FLAGS += $(shell $(PKG_CONFIG) --cflags x11) | |||
DGL_SYSTEM_LIBS += $(shell $(PKG_CONFIG) --libs x11) | |||
endif | |||
# --------------------------------------------------------------------------------------------------------------------- | |||
# Set Cairo specific stuff | |||
ifeq ($(HAVE_CAIRO),true) | |||
DGL_FLAGS += -DHAVE_CAIRO | |||
CAIRO_FLAGS = $(shell $(PKG_CONFIG) --cflags cairo) | |||
CAIRO_LIBS = $(shell $(PKG_CONFIG) --libs cairo) | |||
HAVE_CAIRO_OR_OPENGL = true | |||
endif | |||
# --------------------------------------------------------------------------------------------------------------------- | |||
# Set libs stuff | |||
# Set OpenGL specific stuff | |||
ifeq ($(HAVE_OPENGL),true) | |||
ifeq ($(HAVE_DGL),true) | |||
DGL_FLAGS += -DHAVE_OPENGL | |||
ifeq ($(MACOS),true) | |||
DGL_LIBS = -framework OpenGL -framework Cocoa | |||
OPENGL_LIBS = -framework OpenGL | |||
endif | |||
ifeq ($(WIN32),true) | |||
DGL_LIBS = -lopengl32 -lgdi32 | |||
ifeq ($(WINDOWS),true) | |||
OPENGL_LIBS = -lopengl32 | |||
endif | |||
ifneq ($(MACOS_OR_WIN32),true) | |||
DGL_FLAGS = $(shell pkg-config --cflags gl x11) | |||
DGL_LIBS = $(shell pkg-config --libs gl x11) | |||
ifneq ($(MACOS_OR_WINDOWS),true) | |||
OPENGL_FLAGS = $(shell $(PKG_CONFIG) --cflags gl x11) | |||
OPENGL_LIBS = $(shell $(PKG_CONFIG) --libs gl x11) | |||
endif | |||
endif # HAVE_DGL | |||
HAVE_CAIRO_OR_OPENGL = true | |||
endif | |||
# --------------------------------------------------------------------------------------------------------------------- | |||
# Set app extension | |||
ifeq ($(WIN32),true) | |||
ifeq ($(WINDOWS),true) | |||
APP_EXT = .exe | |||
endif | |||
@@ -220,17 +275,17 @@ ifeq ($(MACOS),true) | |||
LIB_EXT = .dylib | |||
endif | |||
ifeq ($(WIN32),true) | |||
ifeq ($(WINDOWS),true) | |||
LIB_EXT = .dll | |||
endif | |||
# --------------------------------------------------------------------------------------------------------------------- | |||
# Set shared library CLI arg | |||
SHARED = -shared | |||
ifeq ($(MACOS),true) | |||
SHARED = -dynamiclib | |||
else | |||
SHARED = -shared | |||
endif | |||
# --------------------------------------------------------------------------------------------------------------------- |
@@ -15,10 +15,6 @@ endif | |||
include $(DPF_PATH)/Makefile.base.mk | |||
ifeq ($(FILES_UI),) | |||
HAVE_DGL = false | |||
endif | |||
# --------------------------------------------------------------------------------------------------------------------- | |||
# Basic setup | |||
@@ -28,8 +24,12 @@ BUILD_DIR = ../../build/$(NAME) | |||
BUILD_C_FLAGS += -I. | |||
BUILD_CXX_FLAGS += -I. -I$(DPF_PATH)/distrho -I$(DPF_PATH)/dgl | |||
ifeq ($(HAVE_DGL),true) | |||
BASE_FLAGS += -DHAVE_DGL | |||
ifeq ($(HAVE_CAIRO),true) | |||
DGL_FLAGS += -DHAVE_CAIRO | |||
endif | |||
ifeq ($(HAVE_OPENGL),true) | |||
DGL_FLAGS += -DHAVE_OPENGL | |||
endif | |||
ifeq ($(HAVE_JACK),true) | |||
@@ -59,7 +59,39 @@ lv2_ui = $(TARGET_DIR)/$(NAME).lv2/$(NAME)_ui$(LIB_EXT) | |||
vst = $(TARGET_DIR)/$(NAME)-vst$(LIB_EXT) | |||
# --------------------------------------------------------------------------------------------------------------------- | |||
# Handle plugins without UI | |||
# Handle UI stuff, disable UI support automatically | |||
ifeq ($(FILES_UI),) | |||
UI_TYPE = none | |||
endif | |||
ifeq ($(UI_TYPE),) | |||
UI_TYPE = opengl | |||
endif | |||
ifeq ($(UI_TYPE),cairo) | |||
ifeq ($(HAVE_CAIRO),true) | |||
DGL_FLAGS += $(CAIRO_FLAGS) -DDGL_CAIRO | |||
DGL_LIBS += $(CAIRO_LIBS) | |||
DGL_LIB = $(DPF_PATH)/build/libdgl-cairo.a | |||
HAVE_DGL = true | |||
else | |||
HAVE_DGL = false | |||
endif | |||
endif | |||
ifeq ($(UI_TYPE),opengl) | |||
ifeq ($(HAVE_OPENGL),true) | |||
DGL_FLAGS += $(OPENGL_FLAGS) -DDGL_OPENGL | |||
DGL_LIBS += $(OPENGL_LIBS) | |||
DGL_LIB = $(DPF_PATH)/build/libdgl-opengl.a | |||
HAVE_DGL = true | |||
else | |||
HAVE_DGL = false | |||
endif | |||
endif | |||
DGL_LIBS += $(DGL_SYSTEM_LIBS) | |||
ifneq ($(HAVE_DGL),true) | |||
dssi_ui = | |||
@@ -68,6 +100,9 @@ DGL_LIBS = | |||
OBJS_UI = | |||
endif | |||
# TODO split dsp and ui object build flags | |||
BASE_FLAGS += $(DGL_FLAGS) | |||
# --------------------------------------------------------------------------------------------------------------------- | |||
# all needs to be first | |||
@@ -81,6 +116,11 @@ $(BUILD_DIR)/%.c.o: %.c | |||
@echo "Compiling $<" | |||
@$(CC) $< $(BUILD_C_FLAGS) -c -o $@ | |||
$(BUILD_DIR)/%.cc.o: %.cc | |||
-@mkdir -p "$(shell dirname $(BUILD_DIR)/$<)" | |||
@echo "Compiling $<" | |||
@$(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@ | |||
$(BUILD_DIR)/%.cpp.o: %.cpp | |||
-@mkdir -p "$(shell dirname $(BUILD_DIR)/$<)" | |||
@echo "Compiling $<" | |||
@@ -105,12 +145,12 @@ $(BUILD_DIR)/DistrhoUIMain_%.cpp.o: $(DPF_PATH)/distrho/DistrhoUIMain.cpp | |||
$(BUILD_DIR)/DistrhoPluginMain_JACK.cpp.o: $(DPF_PATH)/distrho/DistrhoPluginMain.cpp | |||
-@mkdir -p $(BUILD_DIR) | |||
@echo "Compiling DistrhoPluginMain.cpp (JACK)" | |||
@$(CXX) $< $(BUILD_CXX_FLAGS) $(shell pkg-config --cflags jack) -DDISTRHO_PLUGIN_TARGET_JACK -c -o $@ | |||
@$(CXX) $< $(BUILD_CXX_FLAGS) $(shell $(PKG_CONFIG) --cflags jack) -DDISTRHO_PLUGIN_TARGET_JACK -c -o $@ | |||
$(BUILD_DIR)/DistrhoUIMain_DSSI.cpp.o: $(DPF_PATH)/distrho/DistrhoUIMain.cpp | |||
-@mkdir -p $(BUILD_DIR) | |||
@echo "Compiling DistrhoUIMain.cpp (DSSI)" | |||
@$(CXX) $< $(BUILD_CXX_FLAGS) $(shell pkg-config --cflags liblo) -DDISTRHO_PLUGIN_TARGET_DSSI -c -o $@ | |||
@$(CXX) $< $(BUILD_CXX_FLAGS) $(shell $(PKG_CONFIG) --cflags liblo) -DDISTRHO_PLUGIN_TARGET_DSSI -c -o $@ | |||
# --------------------------------------------------------------------------------------------------------------------- | |||
# JACK | |||
@@ -118,13 +158,13 @@ $(BUILD_DIR)/DistrhoUIMain_DSSI.cpp.o: $(DPF_PATH)/distrho/DistrhoUIMain.cpp | |||
jack: $(jack) | |||
ifeq ($(HAVE_DGL),true) | |||
$(jack): $(OBJS_DSP) $(OBJS_UI) $(BUILD_DIR)/DistrhoPluginMain_JACK.cpp.o $(BUILD_DIR)/DistrhoUIMain_JACK.cpp.o $(DPF_PATH)/build/libdgl.a | |||
$(jack): $(OBJS_DSP) $(OBJS_UI) $(BUILD_DIR)/DistrhoPluginMain_JACK.cpp.o $(BUILD_DIR)/DistrhoUIMain_JACK.cpp.o $(DGL_LIB) | |||
else | |||
$(jack): $(OBJS_DSP) $(BUILD_DIR)/DistrhoPluginMain_JACK.cpp.o | |||
endif | |||
-@mkdir -p $(shell dirname $@) | |||
@echo "Creating JACK standalone for $(NAME)" | |||
@$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(DGL_LIBS) $(shell pkg-config --libs jack) -o $@ | |||
@$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(DGL_LIBS) $(shell $(PKG_CONFIG) --libs jack) -o $@ | |||
# --------------------------------------------------------------------------------------------------------------------- | |||
# LADSPA | |||
@@ -148,10 +188,10 @@ $(dssi_dsp): $(OBJS_DSP) $(BUILD_DIR)/DistrhoPluginMain_DSSI.cpp.o | |||
@echo "Creating DSSI plugin library for $(NAME)" | |||
@$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(SHARED) -o $@ | |||
$(dssi_ui): $(OBJS_UI) $(BUILD_DIR)/DistrhoUIMain_DSSI.cpp.o $(DPF_PATH)/build/libdgl.a | |||
$(dssi_ui): $(OBJS_UI) $(BUILD_DIR)/DistrhoUIMain_DSSI.cpp.o $(DGL_LIB) | |||
-@mkdir -p $(shell dirname $@) | |||
@echo "Creating DSSI UI for $(NAME)" | |||
@$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(DGL_LIBS) $(shell pkg-config --libs liblo) -o $@ | |||
@$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(DGL_LIBS) $(shell $(PKG_CONFIG) --libs liblo) -o $@ | |||
# --------------------------------------------------------------------------------------------------------------------- | |||
# LV2 | |||
@@ -160,7 +200,7 @@ lv2: $(lv2) | |||
lv2_dsp: $(lv2_dsp) | |||
lv2_sep: $(lv2_dsp) $(lv2_ui) | |||
$(lv2): $(OBJS_DSP) $(OBJS_UI) $(BUILD_DIR)/DistrhoPluginMain_LV2.cpp.o $(BUILD_DIR)/DistrhoUIMain_LV2.cpp.o $(DPF_PATH)/build/libdgl.a | |||
$(lv2): $(OBJS_DSP) $(OBJS_UI) $(BUILD_DIR)/DistrhoPluginMain_LV2.cpp.o $(BUILD_DIR)/DistrhoUIMain_LV2.cpp.o $(DGL_LIB) | |||
-@mkdir -p $(shell dirname $@) | |||
@echo "Creating LV2 plugin for $(NAME)" | |||
@$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(DGL_LIBS) $(SHARED) -o $@ | |||
@@ -170,7 +210,7 @@ $(lv2_dsp): $(OBJS_DSP) $(BUILD_DIR)/DistrhoPluginMain_LV2.cpp.o | |||
@echo "Creating LV2 plugin library for $(NAME)" | |||
@$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(SHARED) -o $@ | |||
$(lv2_ui): $(OBJS_UI) $(BUILD_DIR)/DistrhoUIMain_LV2.cpp.o $(DPF_PATH)/build/libdgl.a | |||
$(lv2_ui): $(OBJS_UI) $(BUILD_DIR)/DistrhoUIMain_LV2.cpp.o $(DGL_LIB) | |||
-@mkdir -p $(shell dirname $@) | |||
@echo "Creating LV2 plugin UI for $(NAME)" | |||
@$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(DGL_LIBS) $(SHARED) -o $@ | |||
@@ -181,7 +221,7 @@ $(lv2_ui): $(OBJS_UI) $(BUILD_DIR)/DistrhoUIMain_LV2.cpp.o $(DPF_PATH)/build/lib | |||
vst: $(vst) | |||
ifeq ($(HAVE_DGL),true) | |||
$(vst): $(OBJS_DSP) $(OBJS_UI) $(BUILD_DIR)/DistrhoPluginMain_VST.cpp.o $(BUILD_DIR)/DistrhoUIMain_VST.cpp.o $(DPF_PATH)/build/libdgl.a | |||
$(vst): $(OBJS_DSP) $(OBJS_UI) $(BUILD_DIR)/DistrhoPluginMain_VST.cpp.o $(BUILD_DIR)/DistrhoUIMain_VST.cpp.o $(DGL_LIB) | |||
else | |||
$(vst): $(OBJS_DSP) $(BUILD_DIR)/DistrhoPluginMain_VST.cpp.o | |||
endif | |||
@@ -28,7 +28,7 @@ List of plugins made with DPF:<br/> | |||
- [Juice Plugins](https://github.com/DISTRHO/JuicePlugins) (work in progress) | |||
- [ZamAudio Suite](https://github.com/zamaudio/zam-plugins) | |||
- [DragonFly-Reverb](https://github.com/michaelwillis/dragonfly-reverb) | |||
- [Wolf-Shaper](https://github.com/pdesaulniers/wolf-shaper) | |||
- [Wolf-Shaper](https://github.com/pdesaulniers/wolf-shaper) and [Wolf-Spectrum](https://github.com/pdesaulniers/wolf-spectrum) | |||
- [YK Chorus](https://github.com/SpotlightKid/ykchorus) | |||
@@ -1,6 +1,6 @@ | |||
/* | |||
* DISTRHO Plugin Framework (DPF) | |||
* Copyright (C) 2012-2016 Filipe Coelho <falktx@falktx.com> | |||
* Copyright (C) 2012-2019 Filipe Coelho <falktx@falktx.com> | |||
* | |||
* Permission to use, copy, modify, and/or distribute this software for any purpose with | |||
* or without fee is hereby granted, provided that the above copyright notice and this | |||
@@ -31,89 +31,6 @@ | |||
#define END_NAMESPACE_DGL } | |||
#define USE_NAMESPACE_DGL using namespace DGL_NAMESPACE; | |||
#ifdef DISTRHO_OS_WINDOWS | |||
// ----------------------------------------------------------------------- | |||
// Fix OpenGL includes for Windows, based on glfw code | |||
#ifndef APIENTRY | |||
# define APIENTRY __stdcall | |||
#endif // APIENTRY | |||
/* We need WINGDIAPI defined */ | |||
#ifndef WINGDIAPI | |||
# if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__POCC__) | |||
# define WINGDIAPI __declspec(dllimport) | |||
# elif defined(__LCC__) | |||
# define WINGDIAPI __stdcall | |||
# else | |||
# define WINGDIAPI extern | |||
# endif | |||
# define DGL_WINGDIAPI_DEFINED | |||
#endif // WINGDIAPI | |||
/* Some <GL/glu.h> files also need CALLBACK defined */ | |||
#ifndef CALLBACK | |||
# if defined(_MSC_VER) | |||
# if (defined(_M_MRX000) || defined(_M_IX86) || defined(_M_ALPHA) || defined(_M_PPC)) && !defined(MIDL_PASS) | |||
# define CALLBACK __stdcall | |||
# else | |||
# define CALLBACK | |||
# endif | |||
# else | |||
# define CALLBACK __stdcall | |||
# endif | |||
# define DGL_CALLBACK_DEFINED | |||
#endif // CALLBACK | |||
/* Most GL/glu.h variants on Windows need wchar_t */ | |||
#include <cstddef> | |||
#endif // DISTRHO_OS_WINDOWS | |||
// ----------------------------------------------------------------------- | |||
// OpenGL includes | |||
#ifdef DISTRHO_OS_MAC | |||
# include <OpenGL/gl.h> | |||
#else | |||
# ifndef DISTRHO_OS_WINDOWS | |||
# define GL_GLEXT_PROTOTYPES | |||
# endif | |||
# include <GL/gl.h> | |||
# include <GL/glext.h> | |||
#endif | |||
// ----------------------------------------------------------------------- | |||
// Missing OpenGL defines | |||
#if defined(GL_BGR_EXT) && ! defined(GL_BGR) | |||
# define GL_BGR GL_BGR_EXT | |||
#endif | |||
#if defined(GL_BGRA_EXT) && ! defined(GL_BGRA) | |||
# define GL_BGRA GL_BGRA_EXT | |||
#endif | |||
#ifndef GL_CLAMP_TO_BORDER | |||
# define GL_CLAMP_TO_BORDER 0x812D | |||
#endif | |||
#ifdef DISTRHO_OS_WINDOWS | |||
// ----------------------------------------------------------------------- | |||
// Fix OpenGL includes for Windows, based on glfw code | |||
#ifdef DGL_WINGDIAPI_DEFINED | |||
# undef WINGDIAPI | |||
# undef DGL_WINGDIAPI_DEFINED | |||
#endif | |||
#ifdef DGL_CALLBACK_DEFINED | |||
# undef CALLBACK | |||
# undef DGL_CALLBACK_DEFINED | |||
#endif | |||
#endif // DISTRHO_OS_WINDOWS | |||
START_NAMESPACE_DGL | |||
// ----------------------------------------------------------------------- | |||
@@ -172,6 +89,11 @@ enum Key { | |||
// ----------------------------------------------------------------------- | |||
// Base DGL classes | |||
/** | |||
Graphics context, definition depends on build type. | |||
*/ | |||
struct GraphicsContext; | |||
/** | |||
Idle callback. | |||
*/ | |||
@@ -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) | |||
* Copyright (C) 2012-2016 Filipe Coelho <falktx@falktx.com> | |||
* Copyright (C) 2012-2019 Filipe Coelho <falktx@falktx.com> | |||
* | |||
* Permission to use, copy, modify, and/or distribute this software for any purpose with | |||
* or without fee is hereby granted, provided that the above copyright notice and this | |||
@@ -482,6 +482,7 @@ private: | |||
// cached values | |||
float fTheta, fCos, fSin; | |||
/** @internal */ | |||
void _draw(const bool outline); | |||
}; | |||
@@ -516,16 +517,6 @@ public: | |||
*/ | |||
Triangle(const Triangle<T>& tri) noexcept; | |||
/** | |||
Draw this triangle using the current OpenGL state. | |||
*/ | |||
void draw(); | |||
/** | |||
Draw lines (outline of this triangle) using the current OpenGL state. | |||
*/ | |||
void drawOutline(); | |||
/** | |||
Return true if triangle is null (all its points are equal). | |||
An null triangle is also invalid. | |||
@@ -549,6 +540,16 @@ public: | |||
*/ | |||
bool isInvalid() const noexcept; | |||
/** | |||
Draw this triangle using the current OpenGL state. | |||
*/ | |||
void draw(); | |||
/** | |||
Draw lines (outline of this triangle) using the current OpenGL state. | |||
*/ | |||
void drawOutline(); | |||
Triangle<T>& operator=(const Triangle<T>& tri) noexcept; | |||
bool operator==(const Triangle<T>& tri) const noexcept; | |||
bool operator!=(const Triangle<T>& tri) const noexcept; | |||
@@ -556,6 +557,7 @@ public: | |||
private: | |||
Point<T> fPos1, fPos2, fPos3; | |||
/** @internal */ | |||
void _draw(const bool outline); | |||
}; | |||
@@ -740,6 +742,7 @@ private: | |||
Point<T> fPos; | |||
Size<T> fSize; | |||
/** @internal */ | |||
void _draw(const bool outline); | |||
}; | |||
@@ -1,6 +1,6 @@ | |||
/* | |||
* DISTRHO Plugin Framework (DPF) | |||
* Copyright (C) 2012-2016 Filipe Coelho <falktx@falktx.com> | |||
* Copyright (C) 2012-2019 Filipe Coelho <falktx@falktx.com> | |||
* | |||
* Permission to use, copy, modify, and/or distribute this software for any purpose with | |||
* or without fee is hereby granted, provided that the above copyright notice and this | |||
@@ -17,14 +17,15 @@ | |||
#ifndef DGL_IMAGE_HPP_INCLUDED | |||
#define DGL_IMAGE_HPP_INCLUDED | |||
#include "Geometry.hpp" | |||
#include "ImageBase.hpp" | |||
#include "OpenGL.hpp" | |||
START_NAMESPACE_DGL | |||
// ----------------------------------------------------------------------- | |||
/** | |||
Base DGL Image class. | |||
OpenGL Image class. | |||
This is an Image class that handles raw image data in pixels. | |||
You can init the image data on the contructor or later on by calling loadFromMemory(). | |||
@@ -35,7 +36,7 @@ START_NAMESPACE_DGL | |||
Images are drawn on screen via 2D textures. | |||
*/ | |||
class Image | |||
class Image : public ImageBase | |||
{ | |||
public: | |||
/** | |||
@@ -47,13 +48,20 @@ public: | |||
Constructor using raw image data. | |||
@note @a rawData must remain valid for the lifetime of this Image. | |||
*/ | |||
Image(const char* const rawData, const uint width, const uint height, const GLenum format = GL_BGRA, const GLenum type = GL_UNSIGNED_BYTE); | |||
Image(const char* const rawData, | |||
const uint width, | |||
const uint height, | |||
const GLenum format = GL_BGRA, | |||
const GLenum type = GL_UNSIGNED_BYTE); | |||
/** | |||
Constructor using raw image data. | |||
@note @a rawData must remain valid for the lifetime of this Image. | |||
*/ | |||
Image(const char* const rawData, const Size<uint>& size, const GLenum format = GL_BGRA, const GLenum type = GL_UNSIGNED_BYTE); | |||
Image(const char* const rawData, | |||
const Size<uint>& size, | |||
const GLenum format = GL_BGRA, | |||
const GLenum type = GL_UNSIGNED_BYTE); | |||
/** | |||
Constructor using another image data. | |||
@@ -63,44 +71,26 @@ public: | |||
/** | |||
Destructor. | |||
*/ | |||
~Image(); | |||
~Image() override; | |||
/** | |||
Load image data from memory. | |||
@note @a rawData must remain valid for the lifetime of this Image. | |||
*/ | |||
void loadFromMemory(const char* const rawData, const uint width, const uint height, const GLenum format = GL_BGRA, const GLenum type = GL_UNSIGNED_BYTE) noexcept; | |||
void loadFromMemory(const char* const rawData, | |||
const uint width, | |||
const uint height, | |||
const GLenum format = GL_BGRA, | |||
const GLenum type = GL_UNSIGNED_BYTE) noexcept; | |||
/** | |||
Load image data from memory. | |||
@note @a rawData must remain valid for the lifetime of this Image. | |||
*/ | |||
void loadFromMemory(const char* const rawData, const Size<uint>& size, const GLenum format = GL_BGRA, const GLenum type = GL_UNSIGNED_BYTE) noexcept; | |||
/** | |||
Check if this image is valid. | |||
*/ | |||
bool isValid() const noexcept; | |||
/** | |||
Get width. | |||
*/ | |||
uint getWidth() const noexcept; | |||
/** | |||
Get height. | |||
*/ | |||
uint getHeight() const noexcept; | |||
/** | |||
Get size. | |||
*/ | |||
const Size<uint>& getSize() const noexcept; | |||
/** | |||
Get the raw image data. | |||
*/ | |||
const char* getRawData() const noexcept; | |||
void loadFromMemory(const char* const rawData, | |||
const Size<uint>& size, | |||
const GLenum format = GL_BGRA, | |||
const GLenum type = GL_UNSIGNED_BYTE) noexcept; | |||
/** | |||
Get the image format. | |||
@@ -113,27 +103,15 @@ public: | |||
GLenum getType() const noexcept; | |||
/** | |||
Draw this image at (0, 0) point. | |||
*/ | |||
void draw(); | |||
/** | |||
Draw this image at (x, y) point. | |||
TODO document this. | |||
*/ | |||
void drawAt(const int x, const int y); | |||
/** | |||
Draw this image at position @a pos. | |||
*/ | |||
void drawAt(const Point<int>& pos); | |||
Image& operator=(const Image& image) noexcept; | |||
bool operator==(const Image& image) const noexcept; | |||
bool operator!=(const Image& image) const noexcept; | |||
protected: | |||
/** @internal */ | |||
void _drawAt(const Point<int>& pos) override; | |||
private: | |||
const char* fRawData; | |||
Size<uint> fSize; | |||
GLenum fFormat; | |||
GLenum fType; | |||
GLuint fTextureId; | |||
@@ -144,4 +122,4 @@ private: | |||
END_NAMESPACE_DGL | |||
#endif // DGL_IMAGE_HPP_INCLUDED | |||
#endif |
@@ -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_CXX_FLAGS += $(DGL_FLAGS) -I. -Isrc | |||
BUILD_CXX_FLAGS += $(DGL_FLAGS) -I. -Isrc -DDONT_SET_USING_DGL_NAMESPACE -Wno-unused-parameter | |||
LINK_FLAGS += $(DGL_LIBS) | |||
# ifneq ($(MACOS_OLD),true) | |||
@@ -19,36 +19,78 @@ LINK_FLAGS += $(DGL_LIBS) | |||
# --------------------------------------------------------------------------------------------------------------------- | |||
OBJS = \ | |||
OBJS_common = \ | |||
../build/dgl/Application.cpp.o \ | |||
../build/dgl/Color.cpp.o \ | |||
../build/dgl/Geometry.cpp.o \ | |||
../build/dgl/Image.cpp.o \ | |||
../build/dgl/ImageWidgets.cpp.o \ | |||
../build/dgl/NanoVG.cpp.o \ | |||
../build/dgl/ImageBase.cpp.o \ | |||
../build/dgl/Resources.cpp.o \ | |||
../build/dgl/Widget.cpp.o | |||
# TODO: ImageWidgets.cpp | |||
# --------------------------------------------------------------------------------------------------------------------- | |||
OBJS_cairo = $(OBJS_common) \ | |||
../build/dgl/Cairo.cpp.cairo.o \ | |||
../build/dgl/WidgetPrivateData.cpp.cairo.o | |||
ifeq ($(MACOS),true) | |||
OBJS_cairo += ../build/dgl/Window.mm.cairo.o | |||
else | |||
OBJS_cairo += ../build/dgl/Window.cpp.cairo.o | |||
endif | |||
# --------------------------------------------------------------------------------------------------------------------- | |||
OBJS_opengl = $(OBJS_common) \ | |||
../build/dgl/OpenGL.cpp.opengl.o \ | |||
../build/dgl/Image.cpp.opengl.o \ | |||
../build/dgl/ImageWidgets.cpp.opengl.o \ | |||
../build/dgl/NanoVG.cpp.opengl.o \ | |||
../build/dgl/WidgetPrivateData.cpp.opengl.o | |||
ifeq ($(MACOS),true) | |||
OBJS += ../build/dgl/Window.mm.o | |||
OBJS_opengl += ../build/dgl/Window.mm.opengl.o | |||
else | |||
OBJS += ../build/dgl/Window.cpp.o | |||
OBJS_opengl += ../build/dgl/Window.cpp.opengl.o | |||
endif | |||
TARGET = ../build/libdgl.a | |||
# --------------------------------------------------------------------------------------------------------------------- | |||
ifeq ($(HAVE_CAIRO),true) | |||
TARGETS += ../build/libdgl-cairo.a | |||
endif | |||
ifeq ($(HAVE_OPENGL),true) | |||
TARGETS += ../build/libdgl-opengl.a | |||
# Compat name, to be removed soon | |||
TARGETS += ../build/libdgl.a | |||
endif | |||
# --------------------------------------------------------------------------------------------------------------------- | |||
all: $(TARGET) | |||
all: $(TARGETS) | |||
# --------------------------------------------------------------------------------------------------------------------- | |||
../build/libdgl.a: $(OBJS) | |||
../build/libdgl-cairo.a: $(OBJS_cairo) | |||
-@mkdir -p ../build | |||
@echo "Creating libdgl-cairo.a" | |||
@rm -f $@ | |||
@$(AR) crs $@ $^ | |||
../build/libdgl-opengl.a: $(OBJS_opengl) | |||
-@mkdir -p ../build | |||
@echo "Creating libdgl.a" | |||
@echo "Creating libdgl-opengl.a" | |||
@rm -f $@ | |||
@$(AR) crs $@ $^ | |||
# Compat name, to be removed soon | |||
../build/libdgl.a: ../build/libdgl-opengl.a | |||
@echo "Symlinking libdgl.a" | |||
@ln -sf $< $@ | |||
# --------------------------------------------------------------------------------------------------------------------- | |||
../build/dgl/%.c.o: src/%.c | |||
@@ -61,26 +103,52 @@ all: $(TARGET) | |||
@echo "Compiling $<" | |||
@$(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@ | |||
../build/dgl/Window.cpp.o: src/Window.cpp src/sofd/* src/pugl/* | |||
# --------------------------------------------------------------------------------------------------------------------- | |||
../build/dgl/%.cpp.cairo.o: src/%.cpp | |||
-@mkdir -p ../build/dgl | |||
@echo "Compiling $<" | |||
@$(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@ | |||
@echo "Compiling $< (Cairo variant)" | |||
@$(CXX) $< $(BUILD_CXX_FLAGS) -DDGL_CAIRO -c -o $@ | |||
../build/dgl/Window.mm.o: src/Window.cpp src/sofd/* src/pugl/* | |||
../build/dgl/Window.cpp.cairo.o: src/Window.cpp src/sofd/* src/pugl/* | |||
-@mkdir -p ../build/dgl | |||
@echo "Compiling $<" | |||
@$(CXX) $< $(BUILD_CXX_FLAGS) -ObjC++ -c -o $@ | |||
@echo "Compiling $< (Cairo variant)" | |||
@$(CXX) $< $(BUILD_CXX_FLAGS) -DDGL_CAIRO -c -o $@ | |||
../build/dgl/Window.mm.cairo.o: src/Window.cpp src/sofd/* src/pugl/* | |||
-@mkdir -p ../build/dgl | |||
@echo "Compiling $< (Cairo variant)" | |||
@$(CXX) $< $(BUILD_CXX_FLAGS) -DDGL_CAIRO -ObjC++ -c -o $@ | |||
# --------------------------------------------------------------------------------------------------------------------- | |||
../build/dgl/%.cpp.opengl.o: src/%.cpp | |||
-@mkdir -p ../build/dgl | |||
@echo "Compiling $< (OpenGL variant)" | |||
@$(CXX) $< $(BUILD_CXX_FLAGS) -DDGL_OPENGL -c -o $@ | |||
../build/dgl/Window.cpp.opengl.o: src/Window.cpp src/sofd/* src/pugl/* | |||
-@mkdir -p ../build/dgl | |||
@echo "Compiling $< (OpenGL variant)" | |||
@$(CXX) $< $(BUILD_CXX_FLAGS) -DDGL_OPENGL -c -o $@ | |||
../build/dgl/Window.mm.opengl.o: src/Window.cpp src/sofd/* src/pugl/* | |||
-@mkdir -p ../build/dgl | |||
@echo "Compiling $< (OpenGL variant)" | |||
@$(CXX) $< $(BUILD_CXX_FLAGS) -DDGL_OPENGL -ObjC++ -c -o $@ | |||
# --------------------------------------------------------------------------------------------------------------------- | |||
clean: | |||
rm -rf ../build/dgl ../build/libdgl.* | |||
rm -rf ../build/dgl ../build/libdgl*.* | |||
debug: | |||
$(MAKE) DEBUG=true | |||
# --------------------------------------------------------------------------------------------------------------------- | |||
-include $(OBJS:%.o=%.d) | |||
-include $(OBJS_common:%.o=%.d) | |||
-include $(OBJS_cairo:%.o=%.d) | |||
-include $(OBJS_opengl:%.o=%.d) | |||
# --------------------------------------------------------------------------------------------------------------------- |
@@ -1,6 +1,6 @@ | |||
/* | |||
* DISTRHO Plugin Framework (DPF) | |||
* Copyright (C) 2012-2016 Filipe Coelho <falktx@falktx.com> | |||
* Copyright (C) 2012-2019 Filipe Coelho <falktx@falktx.com> | |||
* | |||
* Permission to use, copy, modify, and/or distribute this software for any purpose with | |||
* or without fee is hereby granted, provided that the above copyright notice and this | |||
@@ -18,6 +18,7 @@ | |||
#define DGL_NANO_WIDGET_HPP_INCLUDED | |||
#include "Color.hpp" | |||
#include "OpenGL.hpp" | |||
#include "Widget.hpp" | |||
#ifndef DGL_NO_SHARED_RESOURCES | |||
@@ -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) | |||
* Copyright (C) 2012-2016 Filipe Coelho <falktx@falktx.com> | |||
* Copyright (C) 2012-2019 Filipe Coelho <falktx@falktx.com> | |||
* | |||
* Permission to use, copy, modify, and/or distribute this software for any purpose with | |||
* or without fee is hereby granted, provided that the above copyright notice and this | |||
@@ -77,7 +77,7 @@ public: | |||
explicit Window(Application& app); | |||
explicit Window(Application& app, Window& parent); | |||
explicit Window(Application& app, intptr_t parentId, bool resizable); | |||
explicit Window(Application& app, intptr_t parentId, double scaling, bool resizable); | |||
virtual ~Window(); | |||
void show(); | |||
@@ -113,7 +113,6 @@ public: | |||
void setTransientWinId(uintptr_t winId); | |||
double getScaling() const noexcept; | |||
void setScaling(double scaling) noexcept; | |||
bool getIgnoringKeyRepeat() const noexcept; | |||
void setIgnoringKeyRepeat(bool ignore) noexcept; | |||
@@ -121,6 +120,8 @@ public: | |||
Application& getApp() const noexcept; | |||
intptr_t getWindowId() const noexcept; | |||
const GraphicsContext& getGraphicsContext() const noexcept; | |||
void addIdleCallback(IdleCallback* const callback); | |||
void removeIdleCallback(IdleCallback* const callback); | |||
@@ -134,6 +135,9 @@ protected: | |||
virtual void fileBrowserSelected(const char* filename); | |||
#endif | |||
// internal | |||
void _setAutoScaling(double scaling) noexcept; | |||
private: | |||
struct PrivateData; | |||
PrivateData* const pData; | |||
@@ -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" | |||
#ifndef HAVE_DCAIRO | |||
#include "nanovg/nanovg.h" | |||
#endif | |||
START_NAMESPACE_DGL | |||
// ----------------------------------------------------------------------- | |||
static float computeHue(float h, float m1, float m2) | |||
{ | |||
if (h < 0) h += 1; | |||
if (h > 1) h -= 1; | |||
if (h < 1.0f/6.0f) | |||
return m1 + (m2 - m1) * h * 6.0f; | |||
if (h < 3.0f/6.0f) | |||
return m2; | |||
if (h < 4.0f/6.0f) | |||
return m1 + (m2 - m1) * (2.0f/3.0f - h) * 6.0f; | |||
return m1; | |||
} | |||
static void fixRange(float& value) | |||
{ | |||
/**/ if (value < 0.0f) | |||
@@ -105,7 +120,20 @@ Color::Color(const Color& color1, const Color& color2, float u) noexcept | |||
Color Color::fromHSL(float hue, float saturation, float lightness, float alpha) | |||
{ | |||
return nvgHSLA(hue, saturation, lightness, static_cast<uchar>(getFixedRange(alpha)*255.0f)); | |||
float m1, m2; | |||
Color col; | |||
hue = fmodf(hue, 1.0f); | |||
if (hue < 0.0f) hue += 1.0f; | |||
fixRange(saturation); | |||
fixRange(lightness); | |||
m2 = lightness <= 0.5f ? (lightness * (1 + saturation)) : (lightness + saturation - lightness * saturation); | |||
m1 = 2 * lightness - m2; | |||
col.red = computeHue(hue + 1.0f/3.0f, m1, m2); | |||
col.green = computeHue(hue, m1, m2); | |||
col.blue = computeHue(hue - 1.0f/3.0f, m1, m2); | |||
col.alpha = alpha; | |||
col.fixBounds(); | |||
return col; | |||
} | |||
Color Color::fromHTML(const char* rgb, float alpha) | |||
@@ -224,22 +252,4 @@ void Color::fixBounds() noexcept | |||
// ----------------------------------------------------------------------- | |||
Color::Color(const NVGcolor& c) noexcept | |||
: red(c.r), green(c.g), blue(c.b), alpha(c.a) | |||
{ | |||
fixBounds(); | |||
} | |||
Color::operator NVGcolor() const noexcept | |||
{ | |||
NVGcolor nc; | |||
nc.r = red; | |||
nc.g = green; | |||
nc.b = blue; | |||
nc.a = alpha; | |||
return nc; | |||
} | |||
// ----------------------------------------------------------------------- | |||
END_NAMESPACE_DGL |
@@ -1,6 +1,6 @@ | |||
/* | |||
* DISTRHO Plugin Framework (DPF) | |||
* Copyright (C) 2012-2016 Filipe Coelho <falktx@falktx.com> | |||
* Copyright (C) 2012-2019 Filipe Coelho <falktx@falktx.com> | |||
* | |||
* Permission to use, copy, modify, and/or distribute this software for any purpose with | |||
* or without fee is hereby granted, provided that the above copyright notice and this | |||
@@ -441,21 +441,6 @@ void Line<T>::moveBy(const Point<T>& pos) noexcept | |||
fPosEnd.moveBy(pos); | |||
} | |||
template<typename T> | |||
void Line<T>::draw() | |||
{ | |||
DISTRHO_SAFE_ASSERT_RETURN(fPosStart != fPosEnd,); | |||
glBegin(GL_LINES); | |||
{ | |||
glVertex2d(fPosStart.fX, fPosStart.fY); | |||
glVertex2d(fPosEnd.fX, fPosEnd.fY); | |||
} | |||
glEnd(); | |||
} | |||
template<typename T> | |||
bool Line<T>::isNull() const noexcept | |||
{ | |||
@@ -650,27 +635,6 @@ bool Circle<T>::operator!=(const Circle<T>& cir) const noexcept | |||
return (fPos != cir.fPos || d_isNotEqual(fSize, cir.fSize) || fNumSegments != cir.fNumSegments); | |||
} | |||
template<typename T> | |||
void Circle<T>::_draw(const bool outline) | |||
{ | |||
DISTRHO_SAFE_ASSERT_RETURN(fNumSegments >= 3 && fSize > 0.0f,); | |||
double t, x = fSize, y = 0.0; | |||
glBegin(outline ? GL_LINE_LOOP : GL_POLYGON); | |||
for (uint i=0; i<fNumSegments; ++i) | |||
{ | |||
glVertex2d(x + fPos.fX, y + fPos.fY); | |||
t = x; | |||
x = fCos * x - fSin * y; | |||
y = fSin * t + fCos * y; | |||
} | |||
glEnd(); | |||
} | |||
// ----------------------------------------------------------------------- | |||
// Triangle | |||
@@ -698,18 +662,6 @@ Triangle<T>::Triangle(const Triangle<T>& tri) noexcept | |||
fPos2(tri.fPos2), | |||
fPos3(tri.fPos3) {} | |||
template<typename T> | |||
void Triangle<T>::draw() | |||
{ | |||
_draw(false); | |||
} | |||
template<typename T> | |||
void Triangle<T>::drawOutline() | |||
{ | |||
_draw(true); | |||
} | |||
template<typename T> | |||
bool Triangle<T>::isNull() const noexcept | |||
{ | |||
@@ -734,6 +686,18 @@ bool Triangle<T>::isInvalid() const noexcept | |||
return fPos1 == fPos2 || fPos1 == fPos3; | |||
} | |||
template<typename T> | |||
void Triangle<T>::draw() | |||
{ | |||
_draw(false); | |||
} | |||
template<typename T> | |||
void Triangle<T>::drawOutline() | |||
{ | |||
_draw(true); | |||
} | |||
template<typename T> | |||
Triangle<T>& Triangle<T>::operator=(const Triangle<T>& tri) noexcept | |||
{ | |||
@@ -755,22 +719,6 @@ bool Triangle<T>::operator!=(const Triangle<T>& tri) const noexcept | |||
return (fPos1 != tri.fPos1 || fPos2 != tri.fPos2 || fPos3 != tri.fPos3); | |||
} | |||
template<typename T> | |||
void Triangle<T>::_draw(const bool outline) | |||
{ | |||
DISTRHO_SAFE_ASSERT_RETURN(fPos1 != fPos2 && fPos1 != fPos3,); | |||
glBegin(outline ? GL_LINE_LOOP : GL_TRIANGLES); | |||
{ | |||
glVertex2d(fPos1.fX, fPos1.fY); | |||
glVertex2d(fPos2.fX, fPos2.fY); | |||
glVertex2d(fPos3.fX, fPos3.fY); | |||
} | |||
glEnd(); | |||
} | |||
// ----------------------------------------------------------------------- | |||
// Rectangle | |||
@@ -998,30 +946,6 @@ bool Rectangle<T>::operator!=(const Rectangle<T>& rect) const noexcept | |||
return (fPos != rect.fPos || fSize != rect.fSize); | |||
} | |||
template<typename T> | |||
void Rectangle<T>::_draw(const bool outline) | |||
{ | |||
DISTRHO_SAFE_ASSERT_RETURN(fSize.isValid(),); | |||
glBegin(outline ? GL_LINE_LOOP : GL_QUADS); | |||
{ | |||
glTexCoord2f(0.0f, 0.0f); | |||
glVertex2d(fPos.fX, fPos.fY); | |||
glTexCoord2f(1.0f, 0.0f); | |||
glVertex2d(fPos.fX+fSize.fWidth, fPos.fY); | |||
glTexCoord2f(1.0f, 1.0f); | |||
glVertex2d(fPos.fX+fSize.fWidth, fPos.fY+fSize.fHeight); | |||
glTexCoord2f(0.0f, 1.0f); | |||
glVertex2d(fPos.fX, fPos.fY+fSize.fHeight); | |||
} | |||
glEnd(); | |||
} | |||
// ----------------------------------------------------------------------- | |||
// Possible template data types | |||
@@ -1,6 +1,6 @@ | |||
/* | |||
* DISTRHO Plugin Framework (DPF) | |||
* Copyright (C) 2012-2016 Filipe Coelho <falktx@falktx.com> | |||
* Copyright (C) 2012-2019 Filipe Coelho <falktx@falktx.com> | |||
* | |||
* Permission to use, copy, modify, and/or distribute this software for any purpose with | |||
* or without fee is hereby granted, provided that the above copyright notice and this | |||
@@ -21,8 +21,7 @@ START_NAMESPACE_DGL | |||
// ----------------------------------------------------------------------- | |||
Image::Image() | |||
: fRawData(nullptr), | |||
fSize(0, 0), | |||
: ImageBase(), | |||
fFormat(0), | |||
fType(0), | |||
fTextureId(0), | |||
@@ -31,20 +30,18 @@ Image::Image() | |||
glGenTextures(1, &fTextureId); | |||
} | |||
Image::Image(const char* const rawData, const uint width, const uint height, const GLenum format, const GLenum type) | |||
: fRawData(rawData), | |||
fSize(width, height), | |||
fFormat(format), | |||
fType(type), | |||
Image::Image(const Image& image) | |||
: ImageBase(image), | |||
fFormat(image.fFormat), | |||
fType(image.fType), | |||
fTextureId(0), | |||
fIsReady(false) | |||
{ | |||
glGenTextures(1, &fTextureId); | |||
} | |||
Image::Image(const char* const rawData, const Size<uint>& size, const GLenum format, const GLenum type) | |||
: fRawData(rawData), | |||
fSize(size), | |||
Image::Image(const char* const rawData, const uint width, const uint height, const GLenum format, const GLenum type) | |||
: ImageBase(rawData, width, height), | |||
fFormat(format), | |||
fType(type), | |||
fTextureId(0), | |||
@@ -53,11 +50,10 @@ Image::Image(const char* const rawData, const Size<uint>& size, const GLenum for | |||
glGenTextures(1, &fTextureId); | |||
} | |||
Image::Image(const Image& image) | |||
: fRawData(image.fRawData), | |||
fSize(image.fSize), | |||
fFormat(image.fFormat), | |||
fType(image.fType), | |||
Image::Image(const char* const rawData, const Size<uint>& size, const GLenum format, const GLenum type) | |||
: ImageBase(rawData, size), | |||
fFormat(format), | |||
fType(type), | |||
fTextureId(0), | |||
fIsReady(false) | |||
{ | |||
@@ -75,12 +71,19 @@ Image::~Image() | |||
} | |||
} | |||
void Image::loadFromMemory(const char* const rawData, const uint width, const uint height, const GLenum format, const GLenum type) noexcept | |||
void Image::loadFromMemory(const char* const rawData, | |||
const uint width, | |||
const uint height, | |||
const GLenum format, | |||
const GLenum type) noexcept | |||
{ | |||
loadFromMemory(rawData, Size<uint>(width, height), format, type); | |||
} | |||
void Image::loadFromMemory(const char* const rawData, const Size<uint>& size, const GLenum format, const GLenum type) noexcept | |||
void Image::loadFromMemory(const char* const rawData, | |||
const Size<uint>& size, | |||
const GLenum format, | |||
const GLenum type) noexcept | |||
{ | |||
fRawData = rawData; | |||
fSize = size; | |||
@@ -89,31 +92,6 @@ void Image::loadFromMemory(const char* const rawData, const Size<uint>& size, co | |||
fIsReady = false; | |||
} | |||
bool Image::isValid() const noexcept | |||
{ | |||
return (fRawData != nullptr && fSize.getWidth() > 0 && fSize.getHeight() > 0); | |||
} | |||
uint Image::getWidth() const noexcept | |||
{ | |||
return fSize.getWidth(); | |||
} | |||
uint Image::getHeight() const noexcept | |||
{ | |||
return fSize.getHeight(); | |||
} | |||
const Size<uint>& Image::getSize() const noexcept | |||
{ | |||
return fSize; | |||
} | |||
const char* Image::getRawData() const noexcept | |||
{ | |||
return fRawData; | |||
} | |||
GLenum Image::getFormat() const noexcept | |||
{ | |||
return fFormat; | |||
@@ -124,17 +102,17 @@ GLenum Image::getType() const noexcept | |||
return fType; | |||
} | |||
void Image::draw() | |||
{ | |||
drawAt(0, 0); | |||
} | |||
void Image::drawAt(const int x, const int y) | |||
Image& Image::operator=(const Image& image) noexcept | |||
{ | |||
drawAt(Point<int>(x, y)); | |||
fRawData = image.fRawData; | |||
fSize = image.fSize; | |||
fFormat = image.fFormat; | |||
fType = image.fType; | |||
fIsReady = false; | |||
return *this; | |||
} | |||
void Image::drawAt(const Point<int>& pos) | |||
void Image::_drawAt(const Point<int>& pos) | |||
{ | |||
if (fTextureId == 0 || ! isValid()) | |||
return; | |||
@@ -169,26 +147,4 @@ void Image::drawAt(const Point<int>& pos) | |||
// ----------------------------------------------------------------------- | |||
Image& Image::operator=(const Image& image) noexcept | |||
{ | |||
fRawData = image.fRawData; | |||
fSize = image.fSize; | |||
fFormat = image.fFormat; | |||
fType = image.fType; | |||
fIsReady = false; | |||
return *this; | |||
} | |||
bool Image::operator==(const Image& image) const noexcept | |||
{ | |||
return (fRawData == image.fRawData && fSize == image.fSize); | |||
} | |||
bool Image::operator!=(const Image& image) const noexcept | |||
{ | |||
return !operator==(image); | |||
} | |||
// ----------------------------------------------------------------------- | |||
END_NAMESPACE_DGL |
@@ -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) | |||
* Copyright (C) 2012-2016 Filipe Coelho <falktx@falktx.com> | |||
* Copyright (C) 2012-2019 Filipe Coelho <falktx@falktx.com> | |||
* | |||
* Permission to use, copy, modify, and/or distribute this software for any purpose with | |||
* or without fee is hereby granted, provided that the above copyright notice and this | |||
@@ -14,9 +14,13 @@ | |||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |||
*/ | |||
#include "../Image.hpp" | |||
#include "Common.hpp" | |||
#include "WidgetPrivateData.hpp" | |||
// FIXME make this code more generic and move GL specific bits to OpenGL.cpp | |||
#include "../OpenGL.hpp" | |||
START_NAMESPACE_DGL | |||
// ----------------------------------------------------------------------- | |||
@@ -1,6 +1,6 @@ | |||
/* | |||
* DISTRHO Plugin Framework (DPF) | |||
* Copyright (C) 2012-2018 Filipe Coelho <falktx@falktx.com> | |||
* Copyright (C) 2012-2019 Filipe Coelho <falktx@falktx.com> | |||
* | |||
* Permission to use, copy, modify, and/or distribute this software for any purpose with | |||
* or without fee is hereby granted, provided that the above copyright notice and this | |||
@@ -124,6 +124,25 @@ DGL_EXT(PFNGLVERTEXATTRIBPOINTERPROC, glVertexAttribPointer) | |||
START_NAMESPACE_DGL | |||
// ----------------------------------------------------------------------- | |||
// DGL Color class conversion | |||
Color::Color(const NVGcolor& c) noexcept | |||
: red(c.r), green(c.g), blue(c.b), alpha(c.a) | |||
{ | |||
fixBounds(); | |||
} | |||
Color::operator NVGcolor() const noexcept | |||
{ | |||
NVGcolor nc; | |||
nc.r = red; | |||
nc.g = green; | |||
nc.b = blue; | |||
nc.a = alpha; | |||
return nc; | |||
} | |||
// ----------------------------------------------------------------------- | |||
// NanoImage | |||
@@ -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) | |||
* Copyright (C) 2012-2016 Filipe Coelho <falktx@falktx.com> | |||
* Copyright (C) 2012-2019 Filipe Coelho <falktx@falktx.com> | |||
* | |||
* Permission to use, copy, modify, and/or distribute this software for any purpose with | |||
* or without fee is hereby granted, provided that the above copyright notice and this | |||
@@ -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) | |||
* Copyright (C) 2012-2018 Filipe Coelho <falktx@falktx.com> | |||
* Copyright (C) 2012-2019 Filipe Coelho <falktx@falktx.com> | |||
* | |||
* Permission to use, copy, modify, and/or distribute this software for any purpose with | |||
* or without fee is hereby granted, provided that the above copyright notice and this | |||
@@ -63,61 +63,8 @@ struct Widget::PrivateData { | |||
subWidgets.clear(); | |||
} | |||
void display(const uint width, const uint height, const double scaling, const bool renderingSubWidget) | |||
{ | |||
if ((skipDisplay && ! renderingSubWidget) || size.isInvalid() || ! visible) | |||
return; | |||
bool needsDisableScissor = false; | |||
// reset color | |||
glColor4f(1.0f, 1.0f, 1.0f, 1.0f); | |||
if (needsFullViewport || (absolutePos.isZero() && size == Size<uint>(width, height))) | |||
{ | |||
// full viewport size | |||
glViewport(0, | |||
-(height * scaling - height), | |||
width * scaling, | |||
height * scaling); | |||
} | |||
else if (needsScaling) | |||
{ | |||
// limit viewport to widget bounds | |||
glViewport(absolutePos.getX(), | |||
height - self->getHeight() - absolutePos.getY(), | |||
self->getWidth(), | |||
self->getHeight()); | |||
} | |||
else | |||
{ | |||
// only set viewport pos | |||
glViewport(absolutePos.getX() * scaling, | |||
-std::round((height * scaling - height) + (absolutePos.getY() * scaling)), | |||
std::round(width * scaling), | |||
std::round(height * scaling)); | |||
// then cut the outer bounds | |||
glScissor(absolutePos.getX() * scaling, | |||
height - std::round((self->getHeight() + absolutePos.getY()) * scaling), | |||
std::round(self->getWidth() * scaling), | |||
std::round(self->getHeight() * scaling)); | |||
glEnable(GL_SCISSOR_TEST); | |||
needsDisableScissor = true; | |||
} | |||
// display widget | |||
self->onDisplay(); | |||
if (needsDisableScissor) | |||
{ | |||
glDisable(GL_SCISSOR_TEST); | |||
needsDisableScissor = false; | |||
} | |||
displaySubWidgets(width, height, scaling); | |||
} | |||
// display function is different depending on build type | |||
void display(const uint width, const uint height, const double scaling, const bool renderingSubWidget); | |||
void displaySubWidgets(const uint width, const uint height, const double scaling) | |||
{ | |||
@@ -19,6 +19,15 @@ | |||
#include "../Base.hpp" | |||
#ifdef DGL_CAIRO | |||
# define PUGL_CAIRO | |||
# include "../Cairo.hpp" | |||
#endif | |||
#ifdef DGL_OPENGL | |||
# define PUGL_OPENGL | |||
# include "../OpenGL.hpp" | |||
#endif | |||
#include "pugl/pugl.h" | |||
#if defined(__GNUC__) && (__GNUC__ >= 7) | |||
@@ -84,6 +93,7 @@ struct Window::PrivateData { | |||
fWidth(1), | |||
fHeight(1), | |||
fScaling(1.0), | |||
fAutoScaling(1.0), | |||
fTitle(nullptr), | |||
fWidgets(), | |||
fModal(), | |||
@@ -115,6 +125,7 @@ struct Window::PrivateData { | |||
fWidth(1), | |||
fHeight(1), | |||
fScaling(1.0), | |||
fAutoScaling(1.0), | |||
fTitle(nullptr), | |||
fWidgets(), | |||
fModal(parent.pData), | |||
@@ -147,7 +158,7 @@ struct Window::PrivateData { | |||
#endif | |||
} | |||
PrivateData(Application& app, Window* const self, const intptr_t parentId, const bool resizable) | |||
PrivateData(Application& app, Window* const self, const intptr_t parentId, const double scaling, const bool resizable) | |||
: fApp(app), | |||
fSelf(self), | |||
fView(puglInit()), | |||
@@ -157,7 +168,8 @@ struct Window::PrivateData { | |||
fUsingEmbed(parentId != 0), | |||
fWidth(1), | |||
fHeight(1), | |||
fScaling(1.0), | |||
fScaling(scaling), | |||
fAutoScaling(1.0), | |||
fTitle(nullptr), | |||
fWidgets(), | |||
fModal(), | |||
@@ -222,11 +234,12 @@ struct Window::PrivateData { | |||
puglCreateWindow(fView, nullptr); | |||
PuglInternals* impl = fView->impl; | |||
#if defined(DISTRHO_OS_WINDOWS) | |||
hwnd = impl->hwnd; | |||
DISTRHO_SAFE_ASSERT(hwnd != 0); | |||
#elif defined(DISTRHO_OS_MAC) | |||
mView = impl->glview; | |||
mView = impl->view; | |||
mWindow = impl->window; | |||
DISTRHO_SAFE_ASSERT(mView != nullptr); | |||
if (fUsingEmbed) { | |||
@@ -555,6 +568,7 @@ struct Window::PrivateData { | |||
void setGeometryConstraints(uint width, uint height, bool aspect) | |||
{ | |||
// Did you forget to set DISTRHO_UI_USER_RESIZABLE ? | |||
DISTRHO_SAFE_ASSERT_RETURN(fResizable,); | |||
fView->min_width = width; | |||
@@ -701,11 +715,11 @@ struct Window::PrivateData { | |||
return fScaling; | |||
} | |||
void setScaling(double scaling) noexcept | |||
void setAutoScaling(const double scaling) noexcept | |||
{ | |||
DISTRHO_SAFE_ASSERT_RETURN(scaling > 0.0,); | |||
fScaling = scaling; | |||
fAutoScaling = scaling; | |||
} | |||
// ------------------------------------------------------------------- | |||
@@ -773,7 +787,7 @@ struct Window::PrivateData { | |||
FOR_EACH_WIDGET(it) | |||
{ | |||
Widget* const widget(*it); | |||
widget->pData->display(fWidth, fHeight, fScaling, false); | |||
widget->pData->display(fWidth, fHeight, fAutoScaling, false); | |||
} | |||
fSelf->onDisplayAfter(); | |||
@@ -843,8 +857,8 @@ struct Window::PrivateData { | |||
if (fModal.childFocus != nullptr) | |||
return fModal.childFocus->focus(); | |||
x /= fScaling; | |||
y /= fScaling; | |||
x /= fAutoScaling; | |||
y /= fAutoScaling; | |||
Widget::MouseEvent ev; | |||
ev.button = button; | |||
@@ -870,8 +884,8 @@ struct Window::PrivateData { | |||
if (fModal.childFocus != nullptr) | |||
return; | |||
x /= fScaling; | |||
y /= fScaling; | |||
x /= fAutoScaling; | |||
y /= fAutoScaling; | |||
Widget::MotionEvent ev; | |||
ev.mod = static_cast<Modifier>(puglGetModifiers(fView)); | |||
@@ -895,10 +909,10 @@ struct Window::PrivateData { | |||
if (fModal.childFocus != nullptr) | |||
return; | |||
x /= fScaling; | |||
y /= fScaling; | |||
dx /= fScaling; | |||
dy /= fScaling; | |||
x /= fAutoScaling; | |||
y /= fAutoScaling; | |||
dx /= fAutoScaling; | |||
dy /= fAutoScaling; | |||
Widget::ScrollEvent ev; | |||
ev.delta = Point<float>(dx, dy); | |||
@@ -1038,9 +1052,10 @@ struct Window::PrivateData { | |||
// ------------------------------------------------------------------- | |||
Application& fApp; | |||
Window* fSelf; | |||
PuglView* fView; | |||
Application& fApp; | |||
Window* fSelf; | |||
GraphicsContext fContext; | |||
PuglView* fView; | |||
bool fFirstInit; | |||
bool fVisible; | |||
@@ -1049,6 +1064,7 @@ struct Window::PrivateData { | |||
uint fWidth; | |||
uint fHeight; | |||
double fScaling; | |||
double fAutoScaling; | |||
char* fTitle; | |||
std::list<Widget*> fWidgets; | |||
@@ -1081,7 +1097,7 @@ struct Window::PrivateData { | |||
HWND hwndParent; | |||
#elif defined(DISTRHO_OS_MAC) | |||
bool fNeedsIdle; | |||
PuglOpenGLView* mView; | |||
NSView<PuglGenericView>* mView; | |||
id mWindow; | |||
id mParentWindow; | |||
#else | |||
@@ -1155,8 +1171,8 @@ Window::Window(Application& app) | |||
Window::Window(Application& app, Window& parent) | |||
: pData(new PrivateData(app, this, parent)) {} | |||
Window::Window(Application& app, intptr_t parentId, bool resizable) | |||
: pData(new PrivateData(app, this, parentId, resizable)) {} | |||
Window::Window(Application& app, intptr_t parentId, double scaling, bool resizable) | |||
: pData(new PrivateData(app, this, parentId, scaling, resizable)) {} | |||
Window::~Window() | |||
{ | |||
@@ -1347,11 +1363,6 @@ double Window::getScaling() const noexcept | |||
return pData->getScaling(); | |||
} | |||
void Window::setScaling(double scaling) noexcept | |||
{ | |||
pData->setScaling(scaling); | |||
} | |||
bool Window::getIgnoringKeyRepeat() const noexcept | |||
{ | |||
return pData->getIgnoringKeyRepeat(); | |||
@@ -1372,6 +1383,20 @@ intptr_t Window::getWindowId() const noexcept | |||
return puglGetNativeWindow(pData->fView); | |||
} | |||
const GraphicsContext& Window::getGraphicsContext() const noexcept | |||
{ | |||
GraphicsContext& context = pData->fContext; | |||
#ifdef DGL_CAIRO | |||
context.cairo = (cairo_t*)puglGetContext(pData->fView); | |||
#endif | |||
return context; | |||
} | |||
void Window::_setAutoScaling(double scaling) noexcept | |||
{ | |||
pData->setAutoScaling(scaling); | |||
} | |||
void Window::_addWidget(Widget* const widget) | |||
{ | |||
pData->addWidget(widget); | |||
@@ -1407,8 +1432,10 @@ void Window::removeIdleCallback(IdleCallback* const callback) | |||
void Window::onDisplayBefore() | |||
{ | |||
#ifdef DGL_OPENGL | |||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | |||
glLoadIdentity(); | |||
#endif | |||
} | |||
void Window::onDisplayAfter() | |||
@@ -1417,6 +1444,7 @@ void Window::onDisplayAfter() | |||
void Window::onReshape(uint width, uint height) | |||
{ | |||
#ifdef DGL_OPENGL | |||
glEnable(GL_BLEND); | |||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | |||
glMatrixMode(GL_PROJECTION); | |||
@@ -1425,6 +1453,7 @@ void Window::onReshape(uint width, uint height) | |||
glViewport(0, 0, static_cast<GLsizei>(width), static_cast<GLsizei>(height)); | |||
glMatrixMode(GL_MODELVIEW); | |||
glLoadIdentity(); | |||
#endif | |||
} | |||
void Window::onClose() | |||
@@ -1,5 +1,6 @@ | |||
/* | |||
Copyright 2012-2014 David Robillard <http://drobilla.net> | |||
Copyright 2012-2019 Filipe Coelho <falktx@falktx.com> | |||
Permission to use, copy, modify, and/or distribute this software for any | |||
purpose with or without fee is hereby granted, provided that the above | |||
@@ -29,19 +30,13 @@ | |||
platforms so they are included here to allow for pure portable programs. | |||
*/ | |||
#ifdef __APPLE__ | |||
# include "OpenGL/gl.h" | |||
# include <OpenGL/gl.h> | |||
#else | |||
# ifdef _WIN32 | |||
# include <winsock2.h> | |||
# include <windows.h> /* Broken Windows GL headers require this */ | |||
# endif | |||
# include "GL/gl.h" | |||
#endif | |||
#ifdef _WIN32 | |||
# define PUGL_API | |||
#else | |||
# define PUGL_API __attribute__((visibility("hidden"))) | |||
# include <GL/gl.h> | |||
#endif | |||
#ifdef __cplusplus | |||
@@ -237,31 +232,31 @@ typedef void (*PuglFileSelectedFunc)(PuglView* view, const char* filename); | |||
To create a window, call the various puglInit* functions as necessary, then | |||
call puglCreateWindow(). | |||
*/ | |||
PUGL_API PuglView* | |||
PuglView* | |||
puglInit(void); | |||
/** | |||
Set the parent window before creating a window (for embedding). | |||
*/ | |||
PUGL_API void | |||
void | |||
puglInitWindowParent(PuglView* view, PuglNativeWindow parent); | |||
/** | |||
Set the window size before creating a window. | |||
*/ | |||
PUGL_API void | |||
void | |||
puglInitWindowSize(PuglView* view, int width, int height); | |||
/** | |||
Set the minimum window size before creating a window. | |||
*/ | |||
PUGL_API void | |||
void | |||
puglInitWindowMinSize(PuglView* view, int width, int height); | |||
/** | |||
Enable or disable resizing before creating a window. | |||
*/ | |||
PUGL_API void | |||
void | |||
puglInitUserResizable(PuglView* view, bool resizable); | |||
/** | |||
@@ -270,7 +265,7 @@ puglInitUserResizable(PuglView* view, bool resizable); | |||
On X11, parent_id must be a Window. | |||
On OSX, parent_id must be an NSView*. | |||
*/ | |||
PUGL_API void | |||
void | |||
puglInitTransientFor(PuglView* view, uintptr_t parent); | |||
/** | |||
@@ -288,7 +283,7 @@ puglInitTransientFor(PuglView* view, uintptr_t parent); | |||
@return 1 (pugl does not currently support multiple windows). | |||
*/ | |||
PUGL_API int | |||
int | |||
puglCreateWindow(PuglView* view, const char* title); | |||
/** | |||
@@ -299,7 +294,7 @@ puglCreateWindow(PuglView* view, const char* title); | |||
@param height Window height in pixels. | |||
@param resizable Whether window should be user resizable. | |||
*/ | |||
PUGL_API PuglView* | |||
PuglView* | |||
puglCreate(PuglNativeWindow parent, | |||
const char* title, | |||
int min_width, | |||
@@ -312,19 +307,19 @@ puglCreate(PuglNativeWindow parent, | |||
/** | |||
Show Window (external ui) | |||
*/ | |||
PUGL_API void | |||
void | |||
puglShowWindow(PuglView* view); | |||
/** | |||
Hide Window (external ui) | |||
*/ | |||
PUGL_API void | |||
void | |||
puglHideWindow(PuglView* view); | |||
/** | |||
Return the native window handle. | |||
*/ | |||
PUGL_API PuglNativeWindow | |||
PuglNativeWindow | |||
puglGetNativeWindow(PuglView* view); | |||
/** | |||
@@ -340,19 +335,27 @@ puglGetNativeWindow(PuglView* view); | |||
Note the lack of this facility makes GLUT unsuitable for plugins or | |||
non-trivial programs; this mistake is largely why Pugl exists. | |||
*/ | |||
PUGL_API void | |||
void | |||
puglSetHandle(PuglView* view, PuglHandle handle); | |||
/** | |||
Get the handle to be passed to all callbacks. | |||
*/ | |||
PUGL_API PuglHandle | |||
PuglHandle | |||
puglGetHandle(PuglView* view); | |||
/** | |||
Get the drawing context. | |||
For Cairo contexts, this returns a pointer to a cairo_t. | |||
For everything else, this is unused and returns NULL. | |||
*/ | |||
void* | |||
puglGetContext(PuglView* view); | |||
/** | |||
Return the timestamp (if any) of the currently-processing event. | |||
*/ | |||
PUGL_API uint32_t | |||
uint32_t | |||
puglGetEventTimestamp(PuglView* view); | |||
/** | |||
@@ -360,13 +363,13 @@ puglGetEventTimestamp(PuglView* view); | |||
This should only be called from an event handler. | |||
*/ | |||
PUGL_API int | |||
int | |||
puglGetModifiers(PuglView* view); | |||
/** | |||
Ignore synthetic repeated key events. | |||
*/ | |||
PUGL_API void | |||
void | |||
puglIgnoreKeyRepeat(PuglView* view, bool ignore); | |||
/** | |||
@@ -378,61 +381,61 @@ puglIgnoreKeyRepeat(PuglView* view, bool ignore); | |||
/** | |||
Set the function to call when the window is closed. | |||
*/ | |||
PUGL_API void | |||
void | |||
puglSetCloseFunc(PuglView* view, PuglCloseFunc closeFunc); | |||
/** | |||
Set the display function which should draw the UI using GL. | |||
*/ | |||
PUGL_API void | |||
void | |||
puglSetDisplayFunc(PuglView* view, PuglDisplayFunc displayFunc); | |||
/** | |||
Set the function to call on keyboard events. | |||
*/ | |||
PUGL_API void | |||
void | |||
puglSetKeyboardFunc(PuglView* view, PuglKeyboardFunc keyboardFunc); | |||
/** | |||
Set the function to call on mouse motion. | |||
*/ | |||
PUGL_API void | |||
void | |||
puglSetMotionFunc(PuglView* view, PuglMotionFunc motionFunc); | |||
/** | |||
Set the function to call on mouse button events. | |||
*/ | |||
PUGL_API void | |||
void | |||
puglSetMouseFunc(PuglView* view, PuglMouseFunc mouseFunc); | |||
/** | |||
Set the function to call on scroll events. | |||
*/ | |||
PUGL_API void | |||
void | |||
puglSetScrollFunc(PuglView* view, PuglScrollFunc scrollFunc); | |||
/** | |||
Set the function to call on special events. | |||
*/ | |||
PUGL_API void | |||
void | |||
puglSetSpecialFunc(PuglView* view, PuglSpecialFunc specialFunc); | |||
/** | |||
Set the function to call when the window size changes. | |||
*/ | |||
PUGL_API void | |||
void | |||
puglSetReshapeFunc(PuglView* view, PuglReshapeFunc reshapeFunc); | |||
/** | |||
Set callback function to change window size. | |||
*/ | |||
PUGL_API void | |||
void | |||
puglSetResizeFunc(PuglView* view, PuglResizeFunc resizeFunc); | |||
/** | |||
Set the function to call on file-browser selections. | |||
*/ | |||
PUGL_API void | |||
void | |||
puglSetFileSelectedFunc(PuglView* view, PuglFileSelectedFunc fileSelectedFunc); | |||
/** | |||
@@ -442,13 +445,13 @@ puglSetFileSelectedFunc(PuglView* view, PuglFileSelectedFunc fileSelectedFunc); | |||
/** | |||
TODO document this. | |||
*/ | |||
PUGL_API int | |||
int | |||
puglUpdateGeometryConstraints(PuglView* view, int min_width, int min_height, bool aspect); | |||
/** | |||
Grab the input focus. | |||
*/ | |||
PUGL_API void | |||
void | |||
puglGrabFocus(PuglView* view); | |||
/** | |||
@@ -457,25 +460,25 @@ puglGrabFocus(PuglView* view); | |||
This handles input events as well as rendering, so it should be called | |||
regularly and rapidly enough to keep the UI responsive. | |||
*/ | |||
PUGL_API PuglStatus | |||
PuglStatus | |||
puglProcessEvents(PuglView* view); | |||
/** | |||
Request a redisplay on the next call to puglProcessEvents(). | |||
*/ | |||
PUGL_API void | |||
void | |||
puglPostRedisplay(PuglView* view); | |||
/** | |||
Request a resize on the next call to puglProcessEvents(). | |||
*/ | |||
PUGL_API void | |||
void | |||
puglPostResize(PuglView* view); | |||
/** | |||
Destroy a GL window. | |||
*/ | |||
PUGL_API void | |||
void | |||
puglDestroy(PuglView* view); | |||
/** | |||
@@ -1,5 +1,6 @@ | |||
/* | |||
Copyright 2012-2014 David Robillard <http://drobilla.net> | |||
Copyright 2012-2019 Filipe Coelho <falktx@falktx.com> | |||
Permission to use, copy, modify, and/or distribute this software for any | |||
purpose with or without fee is hereby granted, provided that the above | |||
@@ -239,6 +240,7 @@ puglLeaveContext(PuglView* view, bool flush); | |||
static void | |||
puglDefaultReshape(int width, int height) | |||
{ | |||
#ifdef PUGL_OPENGL | |||
#ifdef ROBTK_HERE | |||
glViewport(0, 0, width, height); | |||
glMatrixMode(GL_PROJECTION); | |||
@@ -257,4 +259,5 @@ puglDefaultReshape(int width, int height) | |||
glMatrixMode(GL_MODELVIEW); | |||
glLoadIdentity(); | |||
#endif | |||
#endif // PUGL_OPENGL | |||
} |
@@ -1,5 +1,6 @@ | |||
/* | |||
Copyright 2012 David Robillard <http://drobilla.net> | |||
Copyright 2012-2019 Filipe Coelho <falktx@falktx.com> | |||
Permission to use, copy, modify, and/or distribute this software for any | |||
purpose with or without fee is hereby granted, provided that the above | |||
@@ -20,6 +21,10 @@ | |||
#include <stdlib.h> | |||
#ifdef PUGL_CAIRO | |||
#import <cairo.h> | |||
#import <cairo-quartz.h> | |||
#endif | |||
#import <Cocoa/Cocoa.h> | |||
#include "pugl_internal.h" | |||
@@ -93,7 +98,200 @@ puglDisplay(PuglView* view) | |||
} | |||
} | |||
@interface PuglOpenGLView : NSOpenGLView | |||
@protocol PuglGenericView | |||
@required | |||
- (PuglView *) puglview; | |||
- (void) setPuglview:(PuglView *)pv; | |||
- (NSTrackingArea *) puglTrackingArea; | |||
- (void) setPuglTrackingArea:(NSTrackingArea *)area; | |||
@end | |||
static unsigned | |||
getModifiers(PuglView* view, NSEvent* ev) | |||
{ | |||
const unsigned modifierFlags = [ev modifierFlags]; | |||
view->event_timestamp_ms = fmod([ev timestamp] * 1000.0, UINT32_MAX); | |||
unsigned mods = 0; | |||
mods |= (modifierFlags & NSShiftKeyMask) ? PUGL_MOD_SHIFT : 0; | |||
mods |= (modifierFlags & NSControlKeyMask) ? PUGL_MOD_CTRL : 0; | |||
mods |= (modifierFlags & NSAlternateKeyMask) ? PUGL_MOD_ALT : 0; | |||
mods |= (modifierFlags & NSCommandKeyMask) ? PUGL_MOD_SUPER : 0; | |||
return mods; | |||
} | |||
static int | |||
getFixedAppKitButton(NSInteger button) | |||
{ | |||
switch (button) { | |||
case 0: return 1; | |||
case 1: return 3; | |||
case 2: return 2; | |||
default: return button; | |||
} | |||
} | |||
static void | |||
cursorUpdate(NSView<PuglGenericView> *self, NSEvent* event) | |||
{ | |||
[[NSCursor arrowCursor] set]; | |||
(void)self; | |||
(void)event; | |||
} | |||
static void | |||
updateTrackingAreas(NSView<PuglGenericView> *self) | |||
{ | |||
static const int opts = NSTrackingMouseEnteredAndExited | |||
| NSTrackingMouseMoved | |||
| NSTrackingEnabledDuringMouseDrag | |||
| NSTrackingInVisibleRect | |||
| NSTrackingActiveAlways | |||
| NSTrackingCursorUpdate; | |||
NSTrackingArea *trackingArea = [self puglTrackingArea]; | |||
if (trackingArea != nil) { | |||
[self removeTrackingArea:trackingArea]; | |||
[trackingArea release]; | |||
} | |||
trackingArea = [[NSTrackingArea alloc] initWithRect:[self bounds] | |||
options:opts | |||
owner:self | |||
userInfo:nil]; | |||
[self setPuglTrackingArea:trackingArea]; | |||
[self addTrackingArea:trackingArea]; | |||
} | |||
static void | |||
viewWillMoveToWindow(NSView<PuglGenericView> *self, NSWindow* newWindow) | |||
{ | |||
if (newWindow != nil) { | |||
[newWindow setAcceptsMouseMovedEvents:YES]; | |||
[newWindow makeFirstResponder:self]; | |||
} | |||
} | |||
static void | |||
reshape(NSView<PuglGenericView> *self) | |||
{ | |||
PuglView* puglview = [self puglview]; | |||
NSRect bounds = [self bounds]; | |||
int width = bounds.size.width; | |||
int height = bounds.size.height; | |||
puglEnterContext(puglview); | |||
if (puglview->reshapeFunc) { | |||
puglview->reshapeFunc(puglview, width, height); | |||
} else { | |||
puglDefaultReshape(width, height); | |||
} | |||
puglLeaveContext(puglview, false); | |||
puglview->width = width; | |||
puglview->height = height; | |||
} | |||
static void | |||
mouseMoved(NSView<PuglGenericView> *self, NSEvent *event) | |||
{ | |||
PuglView* puglview = [self puglview]; | |||
if (puglview->motionFunc) { | |||
NSPoint loc = [self convertPoint:[event locationInWindow] fromView:nil]; | |||
puglview->mods = getModifiers(puglview, event); | |||
puglview->motionFunc(puglview, loc.x, loc.y); | |||
} | |||
} | |||
static void | |||
mouseDown(NSView<PuglGenericView> *self, NSEvent *event) | |||
{ | |||
PuglView* puglview = [self puglview]; | |||
if (puglview->mouseFunc) { | |||
NSPoint loc = [self convertPoint:[event locationInWindow] fromView:nil]; | |||
puglview->mods = getModifiers(puglview, event); | |||
puglview->mouseFunc(puglview, getFixedAppKitButton([event buttonNumber]), true, loc.x, loc.y); | |||
} | |||
} | |||
static void | |||
mouseUp(NSView<PuglGenericView> *self, NSEvent *event) | |||
{ | |||
PuglView* puglview = [self puglview]; | |||
if (puglview->mouseFunc) { | |||
NSPoint loc = [self convertPoint:[event locationInWindow] fromView:nil]; | |||
puglview->mods = getModifiers(puglview, event); | |||
puglview->mouseFunc(puglview, getFixedAppKitButton([event buttonNumber]), false, loc.x, loc.y); | |||
} | |||
} | |||
static void | |||
scrollWheel(NSView<PuglGenericView> *self, NSEvent *event) | |||
{ | |||
PuglView* puglview = [self puglview]; | |||
if (puglview->scrollFunc) { | |||
NSPoint loc = [self convertPoint:[event locationInWindow] fromView:nil]; | |||
puglview->mods = getModifiers(puglview, event); | |||
puglview->scrollFunc(puglview, | |||
loc.x, loc.y, | |||
[event deltaX], [event deltaY]); | |||
} | |||
} | |||
static void | |||
keyDown(NSView<PuglGenericView> *self, NSEvent *event) | |||
{ | |||
PuglView* puglview = [self puglview]; | |||
if (puglview->keyboardFunc && !(puglview->ignoreKeyRepeat && [event isARepeat])) { | |||
NSString* chars = [event characters]; | |||
puglview->mods = getModifiers(puglview, event); | |||
puglview->keyboardFunc(puglview, true, [chars characterAtIndex:0]); | |||
} | |||
} | |||
static void | |||
keyUp(NSView<PuglGenericView> *self, NSEvent *event) | |||
{ | |||
PuglView* puglview = [self puglview]; | |||
if (puglview->keyboardFunc) { | |||
NSString* chars = [event characters]; | |||
puglview->mods = getModifiers(puglview, event); | |||
puglview->keyboardFunc(puglview, false, [chars characterAtIndex:0]); | |||
} | |||
} | |||
static void | |||
flagsChanged(NSView<PuglGenericView> *self, NSEvent *event) | |||
{ | |||
PuglView* puglview = [self puglview]; | |||
if (puglview->specialFunc) { | |||
const unsigned mods = getModifiers(puglview, event); | |||
if ((mods & PUGL_MOD_SHIFT) != (puglview->mods & PUGL_MOD_SHIFT)) { | |||
puglview->specialFunc(puglview, mods & PUGL_MOD_SHIFT, PUGL_KEY_SHIFT); | |||
} else if ((mods & PUGL_MOD_CTRL) != (puglview->mods & PUGL_MOD_CTRL)) { | |||
puglview->specialFunc(puglview, mods & PUGL_MOD_CTRL, PUGL_KEY_CTRL); | |||
} else if ((mods & PUGL_MOD_ALT) != (puglview->mods & PUGL_MOD_ALT)) { | |||
puglview->specialFunc(puglview, mods & PUGL_MOD_ALT, PUGL_KEY_ALT); | |||
} else if ((mods & PUGL_MOD_SUPER) != (puglview->mods & PUGL_MOD_SUPER)) { | |||
puglview->specialFunc(puglview, mods & PUGL_MOD_SUPER, PUGL_KEY_SUPER); | |||
} | |||
puglview->mods = mods; | |||
} | |||
} | |||
#ifdef PUGL_OPENGL | |||
@interface PuglOpenGLView : NSOpenGLView<PuglGenericView> | |||
{ | |||
@public | |||
PuglView* puglview; | |||
@@ -101,6 +299,11 @@ puglDisplay(PuglView* view) | |||
bool doubleBuffered; | |||
} | |||
- (PuglView *) puglview; | |||
- (void) setPuglview:(PuglView *)pv; | |||
- (NSTrackingArea *) puglTrackingArea; | |||
- (void) setPuglTrackingArea:(NSTrackingArea *)area; | |||
- (BOOL) acceptsFirstMouse:(NSEvent*)e; | |||
- (BOOL) acceptsFirstResponder; | |||
- (BOOL) isFlipped; | |||
@@ -130,6 +333,21 @@ puglDisplay(PuglView* view) | |||
@end | |||
@implementation PuglOpenGLView | |||
- (PuglView *) puglview { | |||
return self->puglview; | |||
} | |||
- (void) setPuglview:(PuglView *)pv { | |||
self->puglview = pv; | |||
} | |||
- (NSTrackingArea *) puglTrackingArea { | |||
return self->trackingArea; | |||
} | |||
- (void) setPuglTrackingArea:(NSTrackingArea *)area { | |||
self->trackingArea = area; | |||
} | |||
- (BOOL) acceptsFirstMouse:(NSEvent*)e | |||
{ | |||
@@ -209,22 +427,7 @@ puglDisplay(PuglView* view) | |||
[[self openGLContext] update]; | |||
NSRect bounds = [self bounds]; | |||
int width = bounds.size.width; | |||
int height = bounds.size.height; | |||
puglEnterContext(puglview); | |||
if (puglview->reshapeFunc) { | |||
puglview->reshapeFunc(puglview, width, height); | |||
} else { | |||
puglDefaultReshape(width, height); | |||
} | |||
puglLeaveContext(puglview, false); | |||
puglview->width = width; | |||
puglview->height = height; | |||
reshape(self); | |||
} | |||
- (void) drawRect:(NSRect)r | |||
@@ -239,182 +442,326 @@ puglDisplay(PuglView* view) | |||
- (void) cursorUpdate:(NSEvent*)e | |||
{ | |||
[[NSCursor arrowCursor] set]; | |||
// unused | |||
return; (void)e; | |||
cursorUpdate(self, e); | |||
} | |||
- (void) updateTrackingAreas | |||
{ | |||
static const int opts = NSTrackingMouseEnteredAndExited | |||
| NSTrackingMouseMoved | |||
| NSTrackingEnabledDuringMouseDrag | |||
| NSTrackingInVisibleRect | |||
| NSTrackingActiveAlways | |||
| NSTrackingCursorUpdate; | |||
if (trackingArea != nil) { | |||
[self removeTrackingArea:trackingArea]; | |||
[trackingArea release]; | |||
} | |||
trackingArea = [[NSTrackingArea alloc] initWithRect:[self bounds] | |||
options:opts | |||
owner:self | |||
userInfo:nil]; | |||
[self addTrackingArea:trackingArea]; | |||
updateTrackingAreas(self); | |||
[super updateTrackingAreas]; | |||
} | |||
- (void) viewWillMoveToWindow:(NSWindow*)newWindow | |||
{ | |||
if (newWindow != nil) { | |||
[newWindow setAcceptsMouseMovedEvents:YES]; | |||
[newWindow makeFirstResponder:self]; | |||
} | |||
viewWillMoveToWindow(self, newWindow); | |||
[super viewWillMoveToWindow:newWindow]; | |||
} | |||
static unsigned | |||
getModifiers(PuglView* view, NSEvent* ev) | |||
- (void) mouseMoved:(NSEvent*)event | |||
{ | |||
const unsigned modifierFlags = [ev modifierFlags]; | |||
mouseMoved(self, event); | |||
} | |||
view->event_timestamp_ms = fmod([ev timestamp] * 1000.0, UINT32_MAX); | |||
- (void) mouseDragged:(NSEvent*)event | |||
{ | |||
mouseMoved(self, event); | |||
} | |||
unsigned mods = 0; | |||
mods |= (modifierFlags & NSShiftKeyMask) ? PUGL_MOD_SHIFT : 0; | |||
mods |= (modifierFlags & NSControlKeyMask) ? PUGL_MOD_CTRL : 0; | |||
mods |= (modifierFlags & NSAlternateKeyMask) ? PUGL_MOD_ALT : 0; | |||
mods |= (modifierFlags & NSCommandKeyMask) ? PUGL_MOD_SUPER : 0; | |||
return mods; | |||
- (void) rightMouseDragged:(NSEvent*)event | |||
{ | |||
mouseMoved(self, event); | |||
} | |||
static int | |||
getFixedAppKitButton(NSInteger button) | |||
- (void) otherMouseDragged:(NSEvent*)event | |||
{ | |||
switch (button) { | |||
case 0: return 1; | |||
case 1: return 3; | |||
case 2: return 2; | |||
default: return button; | |||
mouseMoved(self, event); | |||
} | |||
- (void) mouseDown:(NSEvent*)event | |||
{ | |||
mouseDown(self, event); | |||
} | |||
- (void) rightMouseDown:(NSEvent*)event | |||
{ | |||
mouseDown(self, event); | |||
} | |||
- (void) otherMouseDown:(NSEvent*)event | |||
{ | |||
mouseDown(self, event); | |||
} | |||
- (void) mouseUp:(NSEvent*)event | |||
{ | |||
mouseUp(self, event); | |||
} | |||
- (void) rightMouseUp:(NSEvent*)event | |||
{ | |||
mouseUp(self, event); | |||
} | |||
- (void) otherMouseUp:(NSEvent*)event | |||
{ | |||
mouseUp(self, event); | |||
} | |||
- (void) scrollWheel:(NSEvent*)event | |||
{ | |||
scrollWheel(self, event); | |||
} | |||
- (void) keyDown:(NSEvent*)event | |||
{ | |||
keyDown(self, event); | |||
} | |||
- (void) keyUp:(NSEvent*)event | |||
{ | |||
keyUp(self, event); | |||
} | |||
- (void) flagsChanged:(NSEvent*)event | |||
{ | |||
flagsChanged(self, event); | |||
} | |||
@end | |||
#endif | |||
#ifdef PUGL_CAIRO | |||
@interface PuglCairoView : NSView<PuglGenericView> | |||
{ | |||
PuglView* puglview; | |||
cairo_t* cr; | |||
NSTrackingArea* trackingArea; | |||
} | |||
- (PuglView *) puglview; | |||
- (void) setPuglview:(PuglView *)pv; | |||
- (NSTrackingArea *) puglTrackingArea; | |||
- (void) setPuglTrackingArea:(NSTrackingArea *)area; | |||
- (cairo_t *) cairoContext; | |||
- (BOOL) acceptsFirstMouse:(NSEvent*)e; | |||
- (BOOL) acceptsFirstResponder; | |||
- (BOOL) isFlipped; | |||
- (BOOL) isOpaque; | |||
- (BOOL) preservesContentInLiveResize; | |||
- (id) initWithFrame:(NSRect)frame; | |||
- (void) reshape; | |||
- (void) drawRect:(NSRect)r; | |||
- (void) cursorUpdate:(NSEvent*)e; | |||
- (void) updateTrackingAreas; | |||
- (void) viewWillMoveToWindow:(NSWindow*)newWindow; | |||
- (void) mouseMoved:(NSEvent*)event; | |||
- (void) mouseDragged:(NSEvent*)event; | |||
- (void) rightMouseDragged:(NSEvent*)event; | |||
- (void) otherMouseDragged:(NSEvent*)event; | |||
- (void) mouseDown:(NSEvent*)event; | |||
- (void) rightMouseDown:(NSEvent*)event; | |||
- (void) otherMouseDown:(NSEvent*)event; | |||
- (void) mouseUp:(NSEvent*)event; | |||
- (void) rightMouseUp:(NSEvent*)event; | |||
- (void) otherMouseUp:(NSEvent*)event; | |||
- (void) scrollWheel:(NSEvent*)event; | |||
- (void) keyDown:(NSEvent*)event; | |||
- (void) keyUp:(NSEvent*)event; | |||
- (void) flagsChanged:(NSEvent*)event; | |||
@end | |||
@implementation PuglCairoView | |||
- (PuglView *) puglview { | |||
return self->puglview; | |||
} | |||
- (void) setPuglview:(PuglView *)pv { | |||
self->puglview = pv; | |||
} | |||
- (NSTrackingArea *) puglTrackingArea { | |||
return self->trackingArea; | |||
} | |||
- (void) setPuglTrackingArea:(NSTrackingArea *)area { | |||
self->trackingArea = area; | |||
} | |||
- (cairo_t *) cairoContext { | |||
return cr; | |||
} | |||
- (BOOL) acceptsFirstMouse:(NSEvent*)e | |||
{ | |||
return YES; | |||
// unused | |||
(void)e; | |||
} | |||
- (BOOL) acceptsFirstResponder | |||
{ | |||
return YES; | |||
} | |||
- (BOOL) isFlipped | |||
{ | |||
return YES; | |||
} | |||
- (BOOL) isOpaque | |||
{ | |||
return YES; | |||
} | |||
- (BOOL) preservesContentInLiveResize | |||
{ | |||
return NO; | |||
} | |||
- (id) initWithFrame:(NSRect)frame { | |||
puglview = nil; | |||
cr = NULL; | |||
trackingArea = nil; | |||
[super initWithFrame:frame]; | |||
return self; | |||
} | |||
- (void) reshape | |||
{ | |||
if (!puglview) { | |||
/* NOTE: Apparently reshape gets called when the GC gets around to | |||
deleting the view (?), so we must have reset puglview to NULL when | |||
this comes around. | |||
*/ | |||
return; | |||
} | |||
reshape(self); | |||
} | |||
- (void) drawRect:(NSRect)r { | |||
CGContextRef ctx = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; | |||
NSRect bounds = [self bounds]; | |||
cairo_surface_t* surface; | |||
cairo_t* cairo; | |||
surface = cairo_quartz_surface_create_for_cg_context(ctx, bounds.size.width, bounds.size.height); | |||
if (surface) { | |||
cairo = cairo_create(surface); | |||
if (cairo) { | |||
self->cr = cairo; | |||
puglEnterContext(puglview); | |||
puglDisplay(puglview); | |||
puglLeaveContext(puglview, true); | |||
self->cr = NULL; | |||
cairo_destroy(cairo); | |||
} | |||
cairo_surface_destroy(surface); | |||
} | |||
} | |||
- (void) cursorUpdate:(NSEvent*)e | |||
{ | |||
cursorUpdate(self, e); | |||
} | |||
- (void) updateTrackingAreas | |||
{ | |||
updateTrackingAreas(self); | |||
[super updateTrackingAreas]; | |||
} | |||
- (void) viewWillMoveToWindow:(NSWindow*)newWindow | |||
{ | |||
viewWillMoveToWindow(self, newWindow); | |||
[super viewWillMoveToWindow:newWindow]; | |||
} | |||
- (void) mouseMoved:(NSEvent*)event | |||
{ | |||
if (puglview->motionFunc) { | |||
NSPoint loc = [self convertPoint:[event locationInWindow] fromView:nil]; | |||
puglview->mods = getModifiers(puglview, event); | |||
puglview->motionFunc(puglview, loc.x, loc.y); | |||
} | |||
mouseMoved(self, event); | |||
} | |||
- (void) mouseDragged:(NSEvent*)event | |||
{ | |||
[self mouseMoved:event]; | |||
mouseMoved(self, event); | |||
} | |||
- (void) rightMouseDragged:(NSEvent*)event | |||
{ | |||
[self mouseDragged:event]; | |||
mouseMoved(self, event); | |||
} | |||
- (void) otherMouseDragged:(NSEvent*)event | |||
{ | |||
[self mouseDragged:event]; | |||
mouseMoved(self, event); | |||
} | |||
- (void) mouseDown:(NSEvent*)event | |||
{ | |||
if (puglview->mouseFunc) { | |||
NSPoint loc = [self convertPoint:[event locationInWindow] fromView:nil]; | |||
puglview->mods = getModifiers(puglview, event); | |||
puglview->mouseFunc(puglview, getFixedAppKitButton([event buttonNumber]), true, loc.x, loc.y); | |||
} | |||
mouseDown(self, event); | |||
} | |||
- (void) rightMouseDown:(NSEvent*)event | |||
{ | |||
[self mouseDown:event]; | |||
mouseDown(self, event); | |||
} | |||
- (void) otherMouseDown:(NSEvent*)event | |||
{ | |||
[self mouseDown:event]; | |||
mouseDown(self, event); | |||
} | |||
- (void) mouseUp:(NSEvent*)event | |||
{ | |||
if (puglview->mouseFunc) { | |||
NSPoint loc = [self convertPoint:[event locationInWindow] fromView:nil]; | |||
puglview->mods = getModifiers(puglview, event); | |||
puglview->mouseFunc(puglview, getFixedAppKitButton([event buttonNumber]), false, loc.x, loc.y); | |||
} | |||
mouseUp(self, event); | |||
} | |||
- (void) rightMouseUp:(NSEvent*)event | |||
{ | |||
[self mouseUp:event]; | |||
mouseUp(self, event); | |||
} | |||
- (void) otherMouseUp:(NSEvent*)event | |||
{ | |||
[self mouseUp:event]; | |||
mouseUp(self, event); | |||
} | |||
- (void) scrollWheel:(NSEvent*)event | |||
{ | |||
if (puglview->scrollFunc) { | |||
NSPoint loc = [self convertPoint:[event locationInWindow] fromView:nil]; | |||
puglview->mods = getModifiers(puglview, event); | |||
puglview->scrollFunc(puglview, | |||
loc.x, loc.y, | |||
[event deltaX], [event deltaY]); | |||
} | |||
scrollWheel(self, event); | |||
} | |||
- (void) keyDown:(NSEvent*)event | |||
{ | |||
if (puglview->keyboardFunc && !(puglview->ignoreKeyRepeat && [event isARepeat])) { | |||
NSString* chars = [event characters]; | |||
puglview->mods = getModifiers(puglview, event); | |||
puglview->keyboardFunc(puglview, true, [chars characterAtIndex:0]); | |||
} | |||
keyDown(self, event); | |||
} | |||
- (void) keyUp:(NSEvent*)event | |||
{ | |||
if (puglview->keyboardFunc) { | |||
NSString* chars = [event characters]; | |||
puglview->mods = getModifiers(puglview, event); | |||
puglview->keyboardFunc(puglview, false, [chars characterAtIndex:0]); | |||
} | |||
keyUp(self, event); | |||
} | |||
- (void) flagsChanged:(NSEvent*)event | |||
{ | |||
if (puglview->specialFunc) { | |||
const unsigned mods = getModifiers(puglview, event); | |||
if ((mods & PUGL_MOD_SHIFT) != (puglview->mods & PUGL_MOD_SHIFT)) { | |||
puglview->specialFunc(puglview, mods & PUGL_MOD_SHIFT, PUGL_KEY_SHIFT); | |||
} else if ((mods & PUGL_MOD_CTRL) != (puglview->mods & PUGL_MOD_CTRL)) { | |||
puglview->specialFunc(puglview, mods & PUGL_MOD_CTRL, PUGL_KEY_CTRL); | |||
} else if ((mods & PUGL_MOD_ALT) != (puglview->mods & PUGL_MOD_ALT)) { | |||
puglview->specialFunc(puglview, mods & PUGL_MOD_ALT, PUGL_KEY_ALT); | |||
} else if ((mods & PUGL_MOD_SUPER) != (puglview->mods & PUGL_MOD_SUPER)) { | |||
puglview->specialFunc(puglview, mods & PUGL_MOD_SUPER, PUGL_KEY_SUPER); | |||
} | |||
puglview->mods = mods; | |||
} | |||
flagsChanged(self, event); | |||
} | |||
@end | |||
#endif | |||
struct PuglInternalsImpl { | |||
PuglOpenGLView* glview; | |||
union { | |||
NSView<PuglGenericView>* view; | |||
#ifdef PUGL_OPENGL | |||
PuglOpenGLView* glview; | |||
#endif | |||
#ifdef PUGL_CAIRO | |||
PuglCairoView* cairoview; | |||
#endif | |||
}; | |||
id window; | |||
}; | |||
@@ -427,19 +774,23 @@ puglInitInternals() | |||
void | |||
puglEnterContext(PuglView* view) | |||
{ | |||
#ifdef PUGL_OPENGL | |||
[[view->impl->glview openGLContext] makeCurrentContext]; | |||
#endif | |||
} | |||
void | |||
puglLeaveContext(PuglView* view, bool flush) | |||
{ | |||
if (flush) { | |||
#ifdef PUGL_OPENGL | |||
if (view->impl->glview->doubleBuffered) { | |||
[[view->impl->glview openGLContext] flushBuffer]; | |||
} else { | |||
glFlush(); | |||
} | |||
//[NSOpenGLContext clearCurrentContext]; | |||
#endif | |||
} | |||
} | |||
@@ -451,22 +802,27 @@ puglCreateWindow(PuglView* view, const char* title) | |||
[NSAutoreleasePool new]; | |||
[NSApplication sharedApplication]; | |||
#ifdef PUGL_OPENGL | |||
impl->glview = [PuglOpenGLView new]; | |||
#endif | |||
#ifdef PUGL_CAIRO | |||
impl->cairoview = [PuglCairoView new]; | |||
#endif | |||
if (!impl->glview) { | |||
if (!impl->view) { | |||
return 1; | |||
} | |||
impl->glview->puglview = view; | |||
[impl->view setPuglview:view]; | |||
if (view->user_resizable) { | |||
[impl->glview setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable]; | |||
[impl->view setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable]; | |||
} | |||
if (view->parent) { | |||
[impl->glview retain]; | |||
[impl->view retain]; | |||
NSView* pview = (NSView*)view->parent; | |||
[pview addSubview:impl->glview]; | |||
[pview addSubview:impl->view]; | |||
return 0; | |||
} | |||
@@ -482,8 +838,8 @@ puglCreateWindow(PuglView* view, const char* title) | |||
} | |||
[window setPuglview:view]; | |||
[window setContentView:impl->glview]; | |||
[window makeFirstResponder:impl->glview]; | |||
[window setContentView:impl->view]; | |||
[window makeFirstResponder:impl->view]; | |||
[window makeKeyAndOrderFront:window]; | |||
// wait for first puglShowWindow | |||
@@ -505,7 +861,7 @@ puglShowWindow(PuglView* view) | |||
if (impl->window) { | |||
[impl->window setIsVisible:YES]; | |||
} else { | |||
[view->impl->glview setHidden:NO]; | |||
[view->impl->view setHidden:NO]; | |||
} | |||
} | |||
@@ -517,21 +873,21 @@ puglHideWindow(PuglView* view) | |||
if (impl->window) { | |||
[impl->window setIsVisible:NO]; | |||
} else { | |||
[impl->glview setHidden:YES]; | |||
[impl->view setHidden:YES]; | |||
} | |||
} | |||
void | |||
puglDestroy(PuglView* view) | |||
{ | |||
view->impl->glview->puglview = NULL; | |||
[view->impl->view setPuglview:NULL]; | |||
if (view->impl->window) { | |||
[view->impl->window close]; | |||
[view->impl->glview release]; | |||
[view->impl->view release]; | |||
[view->impl->window release]; | |||
} else { | |||
[view->impl->glview release]; | |||
[view->impl->view release]; | |||
} | |||
free(view->impl); | |||
@@ -551,13 +907,25 @@ void | |||
puglPostRedisplay(PuglView* view) | |||
{ | |||
view->redisplay = true; | |||
[view->impl->glview setNeedsDisplay:YES]; | |||
[view->impl->view setNeedsDisplay:YES]; | |||
} | |||
PuglNativeWindow | |||
puglGetNativeWindow(PuglView* view) | |||
{ | |||
return (PuglNativeWindow)view->impl->glview; | |||
return (PuglNativeWindow)view->impl->view; | |||
} | |||
void* | |||
puglGetContext(PuglView* view) | |||
{ | |||
#ifdef PUGL_CAIRO | |||
return [view->impl->cairoview cairoContext]; | |||
#endif | |||
return NULL; | |||
// may be unused | |||
(void)view; | |||
} | |||
int | |||
@@ -1,5 +1,6 @@ | |||
/* | |||
Copyright 2012-2014 David Robillard <http://drobilla.net> | |||
Copyright 2012-2019 Filipe Coelho <falktx@falktx.com> | |||
Permission to use, copy, modify, and/or distribute this software for any | |||
purpose with or without fee is hereby granted, provided that the above | |||
@@ -18,16 +19,22 @@ | |||
@file pugl_win.cpp Windows/WGL Pugl Implementation. | |||
*/ | |||
#include <ctime> | |||
#include <cstdio> | |||
#include <cstdlib> | |||
#include <winsock2.h> | |||
#include <windows.h> | |||
#include <windowsx.h> | |||
#ifdef PUGL_CAIRO | |||
#include <cairo/cairo.h> | |||
#include <cairo/cairo-win32.h> | |||
#endif | |||
#ifdef PUGL_OPENGL | |||
#include <GL/gl.h> | |||
#endif | |||
#include <ctime> | |||
#include <cstdio> | |||
#include <cstdlib> | |||
#include "pugl/pugl_internal.h" | |||
#include "pugl_internal.h" | |||
#ifndef WM_MOUSEWHEEL | |||
# define WM_MOUSEWHEEL 0x020A | |||
@@ -48,8 +55,15 @@ HINSTANCE hInstance = NULL; | |||
struct PuglInternalsImpl { | |||
HWND hwnd; | |||
#ifdef PUGL_OPENGL | |||
HDC hdc; | |||
HGLRC hglrc; | |||
#endif | |||
#ifdef PUGL_CAIRO | |||
cairo_t* buffer_cr; | |||
cairo_surface_t* buffer_surface; | |||
#endif | |||
HDC paintHdc; | |||
WNDCLASS wc; | |||
}; | |||
@@ -76,17 +90,21 @@ puglInitInternals() | |||
void | |||
puglEnterContext(PuglView* view) | |||
{ | |||
#ifdef PUGL_OPENGL | |||
wglMakeCurrent(view->impl->hdc, view->impl->hglrc); | |||
#endif | |||
} | |||
void | |||
puglLeaveContext(PuglView* view, bool flush) | |||
{ | |||
#ifdef PUGL_OPENGL | |||
if (flush) { | |||
glFlush(); | |||
SwapBuffers(view->impl->hdc); | |||
} | |||
wglMakeCurrent(NULL, NULL); | |||
#endif | |||
} | |||
int | |||
@@ -124,7 +142,6 @@ puglCreateWindow(PuglView* view, const char* title) | |||
if (!RegisterClass(&impl->wc)) { | |||
free((void*)impl->wc.lpszClassName); | |||
free(impl); | |||
free(view); | |||
return 1; | |||
} | |||
@@ -155,12 +172,12 @@ puglCreateWindow(PuglView* view, const char* title) | |||
UnregisterClass(impl->wc.lpszClassName, NULL); | |||
free((void*)impl->wc.lpszClassName); | |||
free(impl); | |||
free(view); | |||
return 1; | |||
} | |||
SetWindowLongPtr(impl->hwnd, GWLP_USERDATA, (LONG_PTR)view); | |||
#ifdef PUGL_OPENGL | |||
impl->hdc = GetDC(impl->hwnd); | |||
PIXELFORMATDESCRIPTOR pfd; | |||
@@ -183,9 +200,9 @@ puglCreateWindow(PuglView* view, const char* title) | |||
UnregisterClass (impl->wc.lpszClassName, NULL); | |||
free((void*)impl->wc.lpszClassName); | |||
free(impl); | |||
free(view); | |||
return 1; | |||
} | |||
#endif | |||
return PUGL_SUCCESS; | |||
} | |||
@@ -205,13 +222,25 @@ puglHideWindow(PuglView* view) | |||
void | |||
puglDestroy(PuglView* view) | |||
{ | |||
if (!view) { | |||
return; | |||
} | |||
PuglInternals* const impl = view->impl; | |||
#ifdef PUGL_OPENGL | |||
wglMakeCurrent(NULL, NULL); | |||
wglDeleteContext(view->impl->hglrc); | |||
ReleaseDC(view->impl->hwnd, view->impl->hdc); | |||
DestroyWindow(view->impl->hwnd); | |||
UnregisterClass(view->impl->wc.lpszClassName, NULL); | |||
free((void*)view->impl->wc.lpszClassName); | |||
free(view->impl); | |||
wglDeleteContext(impl->hglrc); | |||
ReleaseDC(impl->hwnd, impl->hdc); | |||
#endif | |||
#ifdef PUGL_CAIRO | |||
cairo_destroy(impl->buffer_cr); | |||
cairo_surface_destroy(impl->buffer_surface); | |||
#endif | |||
DestroyWindow(impl->hwnd); | |||
UnregisterClass(impl->wc.lpszClassName, NULL); | |||
free((void*)impl->wc.lpszClassName); | |||
free(impl); | |||
free(view); | |||
} | |||
@@ -233,14 +262,57 @@ puglReshape(PuglView* view, int width, int height) | |||
static void | |||
puglDisplay(PuglView* view) | |||
{ | |||
PuglInternals* impl = view->impl; | |||
bool success = true; | |||
puglEnterContext(view); | |||
view->redisplay = false; | |||
if (view->displayFunc) { | |||
view->displayFunc(view); | |||
#ifdef PUGL_CAIRO | |||
cairo_t *wc = NULL; | |||
cairo_t *bc = NULL; | |||
cairo_surface_t *ws = NULL; | |||
cairo_surface_t *bs = NULL; | |||
HDC hdc = impl->paintHdc; | |||
bc = impl->buffer_cr; | |||
bs = impl->buffer_surface; | |||
int w = view->width; | |||
int h = view->height; | |||
int bw = bs ? cairo_image_surface_get_width(bs) : -1; | |||
int bh = bs ? cairo_image_surface_get_height(bs) : -1; | |||
ws = hdc ? cairo_win32_surface_create(hdc) : NULL; | |||
wc = ws ? cairo_create(ws) : NULL; | |||
if (wc && (!bc || bw != w || bh != h)) { | |||
cairo_destroy(bc); | |||
cairo_surface_destroy(bs); | |||
bs = cairo_surface_create_similar_image(ws, CAIRO_FORMAT_ARGB32, w, h); | |||
bc = bs ? cairo_create(bs) : NULL; | |||
impl->buffer_cr = bc; | |||
impl->buffer_surface = bs; | |||
} | |||
success = wc != NULL && bc != NULL; | |||
#endif | |||
if (success) { | |||
view->redisplay = false; | |||
if (view->displayFunc) { | |||
view->displayFunc(view); | |||
} | |||
#ifdef PUGL_CAIRO | |||
cairo_set_source_surface(wc, bs, 0, 0); | |||
cairo_paint(wc); | |||
#endif | |||
} | |||
puglLeaveContext(view, true); | |||
puglLeaveContext(view, success); | |||
#ifdef PUGL_CAIRO | |||
cairo_destroy(wc); | |||
cairo_surface_destroy(ws); | |||
#endif | |||
return; | |||
(void)impl; | |||
} | |||
static PuglKey | |||
@@ -329,8 +401,9 @@ handleMessage(PuglView* view, UINT message, WPARAM wParam, LPARAM lParam) | |||
mmi->ptMinTrackSize.y = view->min_height; | |||
break; | |||
case WM_PAINT: | |||
BeginPaint(view->impl->hwnd, &ps); | |||
view->impl->paintHdc = BeginPaint(view->impl->hwnd, &ps); | |||
puglDisplay(view); | |||
view->impl->paintHdc = NULL; | |||
EndPaint(view->impl->hwnd, &ps); | |||
break; | |||
case WM_MOUSEMOVE: | |||
@@ -469,6 +542,18 @@ puglGetNativeWindow(PuglView* view) | |||
return (PuglNativeWindow)view->impl->hwnd; | |||
} | |||
void* | |||
puglGetContext(PuglView* view) | |||
{ | |||
#ifdef PUGL_CAIRO | |||
return view->impl->buffer_cr; | |||
#endif | |||
return NULL; | |||
// may be unused | |||
(void)view; | |||
} | |||
int | |||
puglUpdateGeometryConstraints(PuglView* view, int min_width, int min_height, bool aspect) | |||
{ | |||
@@ -2,6 +2,7 @@ | |||
Copyright 2012-2014 David Robillard <http://drobilla.net> | |||
Copyright 2011-2012 Ben Loftis, Harrison Consoles | |||
Copyright 2013,2015 Robin Gareus <robin@gareus.org> | |||
Copyright 2012-2019 Filipe Coelho <falktx@falktx.com> | |||
Permission to use, copy, modify, and/or distribute this software for any | |||
purpose with or without fee is hereby granted, provided that the above | |||
@@ -24,8 +25,14 @@ | |||
#include <stdlib.h> | |||
#include <string.h> | |||
#ifdef PUGL_CAIRO | |||
#include <cairo/cairo.h> | |||
#include <cairo/cairo-xlib.h> | |||
#endif | |||
#ifdef PUGL_OPENGL | |||
#include <GL/gl.h> | |||
#include <GL/glx.h> | |||
#endif | |||
#include <X11/Xatom.h> | |||
#include <X11/Xlib.h> | |||
#include <X11/Xutil.h> | |||
@@ -53,10 +60,19 @@ struct PuglInternalsImpl { | |||
Display* display; | |||
int screen; | |||
Window win; | |||
#ifdef PUGL_CAIRO | |||
cairo_t* xlib_cr; | |||
cairo_t* buffer_cr; | |||
cairo_surface_t* xlib_surface; | |||
cairo_surface_t* buffer_surface; | |||
#endif | |||
#ifdef PUGL_OPENGL | |||
GLXContext ctx; | |||
Bool doubleBuffered; | |||
#endif | |||
}; | |||
#ifdef PUGL_OPENGL | |||
/** | |||
Attributes for single-buffered RGBA with at least | |||
4 bits per color and a 16 bit depth buffer. | |||
@@ -102,6 +118,7 @@ static int attrListDblMS[] = { | |||
GLX_SAMPLES, 4, | |||
None | |||
}; | |||
#endif | |||
PuglInternals* | |||
puglInitInternals(void) | |||
@@ -112,12 +129,15 @@ puglInitInternals(void) | |||
void | |||
puglEnterContext(PuglView* view) | |||
{ | |||
#ifdef PUGL_OPENGL | |||
glXMakeCurrent(view->impl->display, view->impl->win, view->impl->ctx); | |||
#endif | |||
} | |||
void | |||
puglLeaveContext(PuglView* view, bool flush) | |||
{ | |||
#ifdef PUGL_OPENGL | |||
if (flush) { | |||
glFlush(); | |||
if (view->impl->doubleBuffered) { | |||
@@ -125,12 +145,13 @@ puglLeaveContext(PuglView* view, bool flush) | |||
} | |||
} | |||
glXMakeCurrent(view->impl->display, None, NULL); | |||
#endif | |||
} | |||
int | |||
puglCreateWindow(PuglView* view, const char* title) | |||
{ | |||
PuglInternals* impl = (PuglInternals*)calloc(1, sizeof(PuglInternals)); | |||
PuglInternals* impl = view->impl; | |||
if (!impl) { | |||
return 1; | |||
} | |||
@@ -142,9 +163,12 @@ puglCreateWindow(PuglView* view, const char* title) | |||
return 1; | |||
} | |||
impl->screen = DefaultScreen(impl->display); | |||
impl->doubleBuffered = True; | |||
XVisualInfo* vi = glXChooseVisual(impl->display, impl->screen, attrListDblMS); | |||
XVisualInfo* vi = NULL; | |||
#ifdef PUGL_OPENGL | |||
impl->doubleBuffered = True; | |||
vi = glXChooseVisual(impl->display, impl->screen, attrListDblMS); | |||
if (!vi) { | |||
vi = glXChooseVisual(impl->display, impl->screen, attrListDbl); | |||
@@ -157,6 +181,13 @@ puglCreateWindow(PuglView* view, const char* title) | |||
vi = glXChooseVisual(impl->display, impl->screen, attrListSgl); | |||
impl->doubleBuffered = False; | |||
} | |||
#endif | |||
#ifdef PUGL_CAIRO | |||
XVisualInfo pat; | |||
int n; | |||
pat.screen = impl->screen; | |||
vi = XGetVisualInfo(impl->display, VisualScreenMask, &pat, &n); | |||
#endif | |||
if (!vi) { | |||
XCloseDisplay(impl->display); | |||
@@ -165,18 +196,23 @@ puglCreateWindow(PuglView* view, const char* title) | |||
} | |||
#ifdef PUGL_VERBOSE | |||
#ifdef PUGL_OPENGL | |||
int glxMajor, glxMinor; | |||
glXQueryVersion(impl->display, &glxMajor, &glxMinor); | |||
printf("puGL: GLX-Version : %d.%d\n", glxMajor, glxMinor); | |||
#endif | |||
#endif | |||
#ifdef PUGL_OPENGL | |||
impl->ctx = glXCreateContext(impl->display, vi, 0, GL_TRUE); | |||
if (!impl->ctx) { | |||
XFree(vi); | |||
XCloseDisplay(impl->display); | |||
free(impl); | |||
return 1; | |||
} | |||
#endif | |||
Window xParent = view->parent | |||
? (Window)view->parent | |||
@@ -201,11 +237,36 @@ puglCreateWindow(PuglView* view, const char* title) | |||
CWBorderPixel | CWColormap | CWEventMask, &attr); | |||
if (!impl->win) { | |||
#ifdef PUGL_OPENGL | |||
glXDestroyContext(impl->display, impl->ctx); | |||
#endif | |||
XFree(vi); | |||
XCloseDisplay(impl->display); | |||
free(impl); | |||
return 1; | |||
} | |||
#ifdef PUGL_CAIRO | |||
impl->xlib_surface = cairo_xlib_surface_create( | |||
impl->display, impl->win, vi->visual, view->width, view->height); | |||
if (impl->xlib_surface == NULL || cairo_surface_status(impl->xlib_surface) != CAIRO_STATUS_SUCCESS) { | |||
printf("puGL: failed to create cairo surface\n"); | |||
} | |||
else { | |||
impl->xlib_cr = cairo_create(impl->xlib_surface); | |||
} | |||
if (impl->xlib_cr == NULL || cairo_status(impl->xlib_cr) != CAIRO_STATUS_SUCCESS) { | |||
cairo_destroy(impl->xlib_cr); | |||
cairo_surface_destroy(impl->xlib_surface); | |||
XDestroyWindow(impl->display, impl->win); | |||
XFree(vi); | |||
XCloseDisplay(impl->display); | |||
free(impl); | |||
printf("puGL: failed to create cairo context\n"); | |||
return 1; | |||
} | |||
#endif | |||
if (view->width > 1 || view->height > 1) { | |||
puglUpdateGeometryConstraints(view, view->min_width, view->min_height, view->min_width != view->width); | |||
XResizeWindow(view->impl->display, view->impl->win, view->width, view->height); | |||
@@ -227,11 +288,13 @@ puglCreateWindow(PuglView* view, const char* title) | |||
} | |||
#ifdef PUGL_VERBOSE | |||
#ifdef PUGL_OPENGL | |||
if (glXIsDirect(impl->display, impl->ctx)) { | |||
printf("puGL: DRI enabled (to disable, set LIBGL_ALWAYS_INDIRECT=1\n"); | |||
} else { | |||
printf("puGL: No DRI available\n"); | |||
} | |||
#endif | |||
#endif | |||
XFree(vi); | |||
@@ -244,14 +307,25 @@ puglDestroy(PuglView* view) | |||
if (!view) { | |||
return; | |||
} | |||
PuglInternals* const impl = view->impl; | |||
#ifndef DGL_FILE_BROWSER_DISABLED | |||
x_fib_close(view->impl->display); | |||
x_fib_close(impl->display); | |||
#endif | |||
glXDestroyContext(view->impl->display, view->impl->ctx); | |||
XDestroyWindow(view->impl->display, view->impl->win); | |||
XCloseDisplay(view->impl->display); | |||
free(view->impl); | |||
#ifdef PUGL_OPENGL | |||
glXDestroyContext(impl->display, impl->ctx); | |||
#endif | |||
#ifdef PUGL_CAIRO | |||
cairo_destroy(impl->xlib_cr); | |||
cairo_destroy(impl->buffer_cr); | |||
cairo_surface_destroy(impl->xlib_surface); | |||
cairo_surface_destroy(impl->buffer_surface); | |||
#endif | |||
XDestroyWindow(impl->display, impl->win); | |||
XCloseDisplay(impl->display); | |||
free(impl); | |||
free(view); | |||
} | |||
@@ -287,14 +361,47 @@ puglReshape(PuglView* view, int width, int height) | |||
static void | |||
puglDisplay(PuglView* view) | |||
{ | |||
PuglInternals* impl = view->impl; | |||
puglEnterContext(view); | |||
#ifdef PUGL_CAIRO | |||
cairo_t* bc = impl->buffer_cr; | |||
cairo_surface_t* xs = impl->xlib_surface; | |||
cairo_surface_t* bs = impl->buffer_surface; | |||
int w = cairo_xlib_surface_get_width(xs); | |||
int h = cairo_xlib_surface_get_height(xs); | |||
int bw = bs ? cairo_image_surface_get_width(bs) : -1; | |||
int bh = bs ? cairo_image_surface_get_height(bs) : -1; | |||
if (!bc || bw != w || bh != h) { | |||
cairo_destroy(bc); | |||
cairo_surface_destroy(bs); | |||
bs = cairo_surface_create_similar_image(xs, CAIRO_FORMAT_ARGB32, w, h); | |||
bc = bs ? cairo_create(bs) : NULL; | |||
impl->buffer_cr = bc; | |||
impl->buffer_surface = bs; | |||
} | |||
if (!bc) { | |||
puglLeaveContext(view, false); | |||
return; | |||
} | |||
#endif | |||
view->redisplay = false; | |||
if (view->displayFunc) { | |||
view->displayFunc(view); | |||
} | |||
#ifdef PUGL_CAIRO | |||
cairo_t* xc = impl->xlib_cr; | |||
cairo_set_source_surface(xc, impl->buffer_surface, 0, 0); | |||
cairo_paint(xc); | |||
#endif | |||
puglLeaveContext(view, true); | |||
(void)impl; | |||
} | |||
static void | |||
@@ -554,6 +661,12 @@ puglProcessEvents(PuglView* view) | |||
} | |||
if (conf_width != -1) { | |||
#ifdef PUGL_CAIRO | |||
// Resize surfaces/contexts before dispatching | |||
view->redisplay = true; | |||
cairo_xlib_surface_set_size(view->impl->xlib_surface, | |||
conf_width, conf_height); | |||
#endif | |||
puglReshape(view, conf_width, conf_height); | |||
} | |||
@@ -586,6 +699,18 @@ puglGetNativeWindow(PuglView* view) | |||
return view->impl->win; | |||
} | |||
void* | |||
puglGetContext(PuglView* view) | |||
{ | |||
#ifdef PUGL_CAIRO | |||
return view->impl->buffer_cr; | |||
#endif | |||
return NULL; | |||
// may be unused | |||
(void)view; | |||
} | |||
int | |||
puglUpdateGeometryConstraints(PuglView* view, int min_width, int min_height, bool aspect) | |||
{ | |||
@@ -417,6 +417,10 @@ START_NAMESPACE_DISTRHO | |||
}; | |||
@endcode | |||
This is a work-in-progress documentation page. States, MIDI, Latency, Time-Position and UI are still TODO. | |||
*/ | |||
#if 0 | |||
@section States | |||
describe them | |||
@@ -431,7 +435,7 @@ START_NAMESPACE_DISTRHO | |||
@section UI | |||
describe them | |||
*/ | |||
#endif | |||
/* ------------------------------------------------------------------------------------------------------------ | |||
* Plugin Macros */ | |||
@@ -543,6 +547,16 @@ START_NAMESPACE_DISTRHO | |||
*/ | |||
#define DISTRHO_PLUGIN_WANT_STATE 1 | |||
/** | |||
Wherever the plugin implements the full state API. | |||
When this macro is enabled, the plugin must implement a new getState(const char* key) function, which the host calls when saving its session/project. | |||
This is useful for plugins that have custom internal values not exposed to the host as key-value state pairs or parameters. | |||
Most simple effects and synths will not need this. | |||
@note this macro is automatically enabled if a plugin has programs and state, as the key-value state pairs need to be updated when the current program changes. | |||
@see Plugin::getState(const char*) | |||
*/ | |||
#define DISTRHO_PLUGIN_WANT_FULL_STATE 1 | |||
/** | |||
Wherever the plugin wants time position information from the host. | |||
@see Plugin::getTimePosition() | |||
@@ -226,7 +226,7 @@ struct ParameterRanges { | |||
/** | |||
Get a fixed value within range. | |||
*/ | |||
const float& getFixedValue(const float& value) const noexcept | |||
float getFixedValue(const float& value) const noexcept | |||
{ | |||
if (value <= min) | |||
return min; | |||
@@ -32,6 +32,13 @@ typedef DGL_NAMESPACE::NanoWidget UIWidget; | |||
typedef DGL_NAMESPACE::Widget UIWidget; | |||
#endif | |||
#ifdef DGL_CAIRO | |||
# include "Cairo.hpp" | |||
#endif | |||
#ifdef DGL_OPENGL | |||
# include "OpenGL.hpp" | |||
#endif | |||
START_NAMESPACE_DISTRHO | |||
/* ------------------------------------------------------------------------------------------------------------ | |||
@@ -62,7 +69,7 @@ public: | |||
*/ | |||
virtual ~UI(); | |||
#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI | |||
#if DISTRHO_UI_USER_RESIZABLE && !DISTRHO_PLUGIN_HAS_EXTERNAL_UI | |||
/** | |||
Set geometry constraints for the UI when resized by the user, and optionally scale UI automatically. | |||
@see Window::setGeometryConstraints(uint,uint,bool) | |||
@@ -82,13 +89,17 @@ public: | |||
/** | |||
editParameter. | |||
@TODO Document this. | |||
Touch/pressed-down event. | |||
Lets the host know the user is tweaking a parameter. | |||
Required in some hosts to record automation. | |||
*/ | |||
void editParameter(uint32_t index, bool started); | |||
/** | |||
setParameterValue. | |||
@TODO Document this. | |||
Change a parameter value in the Plugin. | |||
*/ | |||
void setParameterValue(uint32_t index, float value); | |||
@@ -131,6 +142,13 @@ public: | |||
*/ | |||
static const char* getNextBundlePath() noexcept; | |||
/** | |||
Get the scale factor that will be used for the next UI. | |||
@note: This function is only valid during createUI(), | |||
it will return 1.0 when called from anywhere else. | |||
*/ | |||
static double getNextScaleFactor() noexcept; | |||
# if DISTRHO_PLUGIN_HAS_EMBED_UI | |||
/** | |||
Get the Window Id that will be used for the next created window. | |||
@@ -97,7 +97,7 @@ | |||
// Define DISTRHO_PLUGIN_HAS_EMBED_UI if needed | |||
#ifndef DISTRHO_PLUGIN_HAS_EMBED_UI | |||
# ifdef HAVE_DGL | |||
# if defined(HAVE_CAIRO) || defined(HAVE_OPENGL) | |||
# define DISTRHO_PLUGIN_HAS_EMBED_UI 1 | |||
# else | |||
# define DISTRHO_PLUGIN_HAS_EMBED_UI 0 | |||
@@ -139,7 +139,7 @@ | |||
// ----------------------------------------------------------------------- | |||
// Disable UI if DGL or External UI is not available | |||
#if DISTRHO_PLUGIN_HAS_UI && ! DISTRHO_PLUGIN_HAS_EXTERNAL_UI && ! defined(HAVE_DGL) | |||
#if DISTRHO_PLUGIN_HAS_UI && ! DISTRHO_PLUGIN_HAS_EXTERNAL_UI && ! defined(HAVE_CAIRO) && ! defined(HAVE_OPENGL) | |||
# undef DISTRHO_PLUGIN_HAS_UI | |||
# define DISTRHO_PLUGIN_HAS_UI 0 | |||
#endif | |||
@@ -81,6 +81,16 @@ static void initSignalHandler() | |||
// ----------------------------------------------------------------------- | |||
#if DISTRHO_PLUGIN_HAS_UI | |||
// TODO | |||
static double getDesktopScaleFactor() noexcept | |||
{ | |||
return 1.0; | |||
} | |||
#endif | |||
// ----------------------------------------------------------------------- | |||
#if DISTRHO_PLUGIN_HAS_UI | |||
class PluginJack : public IdleCallback | |||
#else | |||
@@ -91,7 +101,7 @@ public: | |||
PluginJack(jack_client_t* const client) | |||
: fPlugin(this, writeMidiCallback), | |||
#if DISTRHO_PLUGIN_HAS_UI | |||
fUI(this, 0, nullptr, setParameterValueCallback, setStateCallback, nullptr, setSizeCallback, fPlugin.getInstancePointer()), | |||
fUI(this, 0, nullptr, setParameterValueCallback, setStateCallback, nullptr, setSizeCallback, getDesktopScaleFactor(), fPlugin.getInstancePointer()), | |||
#endif | |||
fClient(client) | |||
{ | |||
@@ -545,7 +545,7 @@ public: | |||
#ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD | |||
for (uint32_t i=0; i<DISTRHO_PLUGIN_NUM_OUTPUTS; ++i) | |||
mod_license_run_noise(fRunCount, fPortAudioOuts[i], sampleCount, i); | |||
mod_license_run_silence(fRunCount, fPortAudioOuts[i], sampleCount, i); | |||
#endif | |||
#if DISTRHO_PLUGIN_WANT_TIMEPOS | |||
@@ -719,7 +719,7 @@ void lv2_generate_ttl(const char* const basename) | |||
if (value.length() < 10) | |||
presetString += " \"" + value + "\" ;\n"; | |||
else | |||
presetString += "\n\"\"\"\n" + value + "\n\"\"\" ;\n"; | |||
presetString += "\n\"\"\"" + value + "\"\"\" ;\n"; | |||
} | |||
if (numParameters > 0) | |||
@@ -161,12 +161,12 @@ public: | |||
class UIVst | |||
{ | |||
public: | |||
UIVst(const audioMasterCallback audioMaster, AEffect* const effect, ParameterCheckHelper* const uiHelper, PluginExporter* const plugin, const intptr_t winId) | |||
UIVst(const audioMasterCallback audioMaster, AEffect* const effect, ParameterCheckHelper* const uiHelper, PluginExporter* const plugin, const intptr_t winId, const float scaleFactor) | |||
: fAudioMaster(audioMaster), | |||
fEffect(effect), | |||
fUiHelper(uiHelper), | |||
fPlugin(plugin), | |||
fUI(this, winId, editParameterCallback, setParameterCallback, setStateCallback, sendNoteCallback, setSizeCallback, plugin->getInstancePointer()), | |||
fUI(this, winId, editParameterCallback, setParameterCallback, setStateCallback, sendNoteCallback, setSizeCallback, scaleFactor, plugin->getInstancePointer()), | |||
fShouldCaptureVstKeys(false) | |||
{ | |||
// FIXME only needed for windows? | |||
@@ -575,8 +575,11 @@ public: | |||
else | |||
{ | |||
d_lastUiSampleRate = fPlugin.getSampleRate(); | |||
// TODO | |||
const float scaleFactor = 1.0f; | |||
UIExporter tmpUI(nullptr, 0, nullptr, nullptr, nullptr, nullptr, nullptr, fPlugin.getInstancePointer()); | |||
UIExporter tmpUI(nullptr, 0, nullptr, nullptr, nullptr, nullptr, nullptr, scaleFactor, fPlugin.getInstancePointer()); | |||
fVstRect.right = tmpUI.getWidth(); | |||
fVstRect.bottom = tmpUI.getHeight(); | |||
tmpUI.quit(); | |||
@@ -595,8 +598,11 @@ public: | |||
} | |||
# endif | |||
d_lastUiSampleRate = fPlugin.getSampleRate(); | |||
// TODO | |||
const float scaleFactor = 1.0f; | |||
fVstUI = new UIVst(fAudioMaster, fEffect, this, &fPlugin, (intptr_t)ptr); | |||
fVstUI = new UIVst(fAudioMaster, fEffect, this, &fPlugin, (intptr_t)ptr, scaleFactor); | |||
# if DISTRHO_PLUGIN_WANT_FULL_STATE | |||
// Update current state from plugin side | |||
@@ -27,8 +27,9 @@ START_NAMESPACE_DISTRHO | |||
double d_lastUiSampleRate = 0.0; | |||
void* d_lastUiDspPtr = nullptr; | |||
#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI | |||
uintptr_t g_nextWindowId = 0; | |||
const char* g_nextBundlePath = nullptr; | |||
double g_nextScaleFactor = 1.0; | |||
uintptr_t g_nextWindowId = 0; | |||
#else | |||
Window* d_lastUiWindow = nullptr; | |||
#endif | |||
@@ -57,7 +58,7 @@ UI::~UI() | |||
delete pData; | |||
} | |||
#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI | |||
#if DISTRHO_UI_USER_RESIZABLE && !DISTRHO_PLUGIN_HAS_EXTERNAL_UI | |||
void UI::setGeometryConstraints(uint minWidth, uint minHeight, bool keepAspectRatio, bool automaticallyScale) | |||
{ | |||
DISTRHO_SAFE_ASSERT_RETURN(minWidth > 0,); | |||
@@ -67,7 +68,13 @@ void UI::setGeometryConstraints(uint minWidth, uint minHeight, bool keepAspectRa | |||
pData->minWidth = minWidth; | |||
pData->minHeight = minHeight; | |||
getParentWindow().setGeometryConstraints(minWidth, minHeight, keepAspectRatio); | |||
Window& window(getParentWindow()); | |||
const double uiScaleFactor = window.getScaling(); | |||
window.setGeometryConstraints(minWidth * uiScaleFactor, minHeight * uiScaleFactor, keepAspectRatio); | |||
if (d_isNotZero(uiScaleFactor - 1.0)) | |||
setSize(getWidth() * uiScaleFactor, getHeight() * uiScaleFactor); | |||
} | |||
#endif | |||
@@ -122,6 +129,11 @@ const char* UI::getNextBundlePath() noexcept | |||
return g_nextBundlePath; | |||
} | |||
double UI::getNextScaleFactor() noexcept | |||
{ | |||
return g_nextScaleFactor; | |||
} | |||
# if DISTRHO_PLUGIN_HAS_EMBED_UI | |||
uintptr_t UI::getNextWindowId() noexcept | |||
{ | |||
@@ -147,6 +159,7 @@ void UI::uiFileBrowserSelected(const char*) | |||
void UI::uiReshape(uint width, uint height) | |||
{ | |||
#ifdef DGL_OPENGL | |||
glEnable(GL_BLEND); | |||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | |||
glMatrixMode(GL_PROJECTION); | |||
@@ -155,6 +168,11 @@ void UI::uiReshape(uint width, uint height) | |||
glViewport(0, 0, static_cast<GLsizei>(width), static_cast<GLsizei>(height)); | |||
glMatrixMode(GL_MODELVIEW); | |||
glLoadIdentity(); | |||
#else | |||
// unused | |||
(void)width; | |||
(void)height; | |||
#endif | |||
} | |||
/* ------------------------------------------------------------------------------------------------------------ | |||
@@ -37,11 +37,13 @@ START_NAMESPACE_DISTRHO | |||
extern double d_lastUiSampleRate; | |||
extern void* d_lastUiDspPtr; | |||
#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI | |||
#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI | |||
extern const char* g_nextBundlePath; | |||
extern double g_nextScaleFactor; | |||
extern uintptr_t g_nextWindowId; | |||
#else | |||
extern Window* d_lastUiWindow; | |||
#endif | |||
extern uintptr_t g_nextWindowId; | |||
extern const char* g_nextBundlePath; | |||
// ----------------------------------------------------------------------- | |||
// UI callbacks | |||
@@ -149,15 +151,17 @@ struct UI::PrivateData { | |||
#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI | |||
static inline | |||
UI* createUiWrapper(void* const dspPtr, const uintptr_t winId, const char* const bundlePath) | |||
UI* createUiWrapper(void* const dspPtr, const uintptr_t winId, const double scaleFactor, const char* const bundlePath) | |||
{ | |||
d_lastUiDspPtr = dspPtr; | |||
g_nextWindowId = winId; | |||
g_nextBundlePath = bundlePath; | |||
UI* const ret = createUI(); | |||
d_lastUiDspPtr = nullptr; | |||
g_nextWindowId = 0; | |||
g_nextBundlePath = nullptr; | |||
d_lastUiDspPtr = dspPtr; | |||
g_nextWindowId = winId; | |||
g_nextScaleFactor = scaleFactor; | |||
g_nextBundlePath = bundlePath; | |||
UI* const ret = createUI(); | |||
d_lastUiDspPtr = nullptr; | |||
g_nextWindowId = 0; | |||
g_nextScaleFactor = 1.0; | |||
g_nextBundlePath = nullptr; | |||
return ret; | |||
} | |||
#else // DISTRHO_PLUGIN_HAS_EXTERNAL_UI | |||
@@ -175,8 +179,8 @@ UI* createUiWrapper(void* const dspPtr, Window* const window) | |||
class UIExporterWindow : public Window | |||
{ | |||
public: | |||
UIExporterWindow(Application& app, const intptr_t winId, void* const dspPtr) | |||
: Window(app, winId, DISTRHO_UI_USER_RESIZABLE), | |||
UIExporterWindow(Application& app, const intptr_t winId, const double scaleFactor, void* const dspPtr) | |||
: Window(app, winId, scaleFactor, DISTRHO_UI_USER_RESIZABLE), | |||
fUI(createUiWrapper(dspPtr, this)), | |||
fIsReady(false) | |||
{ | |||
@@ -214,7 +218,7 @@ protected: | |||
{ | |||
const double scaleHorizontal = static_cast<double>(width) / static_cast<double>(pData->minWidth); | |||
const double scaleVertical = static_cast<double>(height) / static_cast<double>(pData->minHeight); | |||
setScaling(scaleHorizontal < scaleVertical ? scaleHorizontal : scaleVertical); | |||
_setAutoScaling(scaleHorizontal < scaleVertical ? scaleHorizontal : scaleVertical); | |||
} | |||
pData->resizeInProgress = true; | |||
@@ -254,13 +258,14 @@ public: | |||
const setStateFunc setStateCall, | |||
const sendNoteFunc sendNoteCall, | |||
const setSizeFunc setSizeCall, | |||
const float scaleFactor = 1.0f, | |||
void* const dspPtr = nullptr, | |||
const char* const bundlePath = nullptr) | |||
#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI | |||
: fUI(createUiWrapper(dspPtr, winId, bundlePath)), | |||
: fUI(createUiWrapper(dspPtr, winId, scaleFactor, bundlePath)), | |||
#else | |||
: glApp(), | |||
glWindow(glApp, winId, dspPtr), | |||
glWindow(glApp, winId, scaleFactor, dspPtr), | |||
fChangingSize(false), | |||
fUI(glWindow.getUI()), | |||
#endif | |||
@@ -53,8 +53,8 @@ public: | |||
UiLv2(const char* const bundlePath, const intptr_t winId, | |||
const LV2_Options_Option* options, const LV2_URID_Map* const uridMap, const LV2UI_Resize* const uiResz, const LV2UI_Touch* uiTouch, | |||
const LV2UI_Controller controller, const LV2UI_Write_Function writeFunc, | |||
LV2UI_Widget* const widget, void* const dspPtr) | |||
: fUI(this, winId, editParameterCallback, setParameterCallback, setStateCallback, sendNoteCallback, setSizeCallback, dspPtr, bundlePath), | |||
const float scaleFactor, LV2UI_Widget* const widget, void* const dspPtr) | |||
: fUI(this, winId, editParameterCallback, setParameterCallback, setStateCallback, sendNoteCallback, setSizeCallback, scaleFactor, dspPtr, bundlePath), | |||
fUridMap(uridMap), | |||
fUiResize(uiResz), | |||
fUiTouch(uiTouch), | |||
@@ -286,7 +286,7 @@ protected: | |||
atomMidiEvent.data[2] = velocity; | |||
// send to DSP side | |||
fWriteFunction(fController, eventInPortIndex, sizeof(LV2_Atom_MidiEvent), fEventTransferURID, &atomMidiEvent); | |||
fWriteFunction(fController, eventInPortIndex, lv2_atom_total_size(&atomMidiEvent.atom), fEventTransferURID, &atomMidiEvent); | |||
} | |||
#endif | |||
@@ -434,22 +434,30 @@ static LV2UI_Handle lv2ui_instantiate(const LV2UI_Descriptor*, const char* uri, | |||
} | |||
#endif | |||
float scaleFactor = 1.0f; | |||
const intptr_t winId((intptr_t)parentId); | |||
if (options != nullptr) | |||
{ | |||
const LV2_URID uridAtomFloat(uridMap->map(uridMap->handle, LV2_ATOM__Float)); | |||
const LV2_URID uridSampleRate(uridMap->map(uridMap->handle, LV2_PARAMETERS__sampleRate)); | |||
const LV2_URID uridScaleFactor(uridMap->map(uridMap->handle, LV2_UI__scaleFactor)); | |||
for (int i=0; options[i].key != 0; ++i) | |||
{ | |||
if (options[i].key == uridSampleRate) | |||
/**/ if (options[i].key == uridSampleRate) | |||
{ | |||
if (options[i].type == uridMap->map(uridMap->handle, LV2_ATOM__Float)) | |||
if (options[i].type == uridAtomFloat) | |||
d_lastUiSampleRate = *(const float*)options[i].value; | |||
else | |||
d_stderr("Host provides UI sample-rate but has wrong value type"); | |||
break; | |||
} | |||
else if (options[i].key == uridScaleFactor) | |||
{ | |||
if (options[i].type == uridAtomFloat) | |||
scaleFactor = *(const float*)options[i].value; | |||
else | |||
d_stderr("Host provides UI scale factor but has wrong value type"); | |||
} | |||
} | |||
} | |||
@@ -460,7 +468,7 @@ static LV2UI_Handle lv2ui_instantiate(const LV2UI_Descriptor*, const char* uri, | |||
d_lastUiSampleRate = 44100.0; | |||
} | |||
return new UiLv2(bundlePath, winId, options, uridMap, uiResize, uiTouch, controller, writeFunction, widget, instance); | |||
return new UiLv2(bundlePath, winId, options, uridMap, uiResize, uiTouch, controller, writeFunction, scaleFactor, widget, instance); | |||
} | |||
#define uiPtr ((UiLv2*)ui) | |||
@@ -52,6 +52,7 @@ | |||
#define LV2_UI__portNotification LV2_UI_PREFIX "portNotification" | |||
#define LV2_UI__portSubscribe LV2_UI_PREFIX "portSubscribe" | |||
#define LV2_UI__resize LV2_UI_PREFIX "resize" | |||
#define LV2_UI__scaleFactor LV2_UI_PREFIX "scaleFactor" | |||
#define LV2_UI__showInterface LV2_UI_PREFIX "showInterface" | |||
#define LV2_UI__touch LV2_UI_PREFIX "touch" | |||
#define LV2_UI__ui LV2_UI_PREFIX "ui" | |||
@@ -242,7 +242,8 @@ SEARCH_INCLUDES = YES | |||
INCLUDE_PATH = | |||
INCLUDE_FILE_PATTERNS = | |||
PREDEFINED = DOXYGEN \ | |||
HAVE_DGL=1 \ | |||
HAVE_CAIRO=1 \ | |||
HAVE_OPENGL=1 \ | |||
DISTRHO_PLUGIN_NAME="Plugin Name" \ | |||
DISTRHO_PLUGIN_NUM_INPUTS=2 \ | |||
DISTRHO_PLUGIN_NUM_OUTPUTS=2 \ | |||
@@ -2,7 +2,7 @@ | |||
all: build | |||
ifeq ($(WIN32),true) | |||
ifeq ($(WINDOWS),true) | |||
build: ../lv2_ttl_generator.exe | |||
else | |||
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.write("/* (Auto-generated binary data file). */\n") | |||
@@ -42,12 +42,12 @@ def png2c(namespace, filenames): | |||
shortFilename = filename.rsplit(os.sep, 1)[-1].split(".", 1)[0] | |||
shortFilename = shortFilename.replace("-", "_") | |||
pngData = open(filename, 'rb').read() | |||
resData = open(filename, 'rb').read() | |||
print("Generating data for \"%s\"" % (filename)) | |||
fdH.write(" extern const char* %sData;\n" % shortFilename) | |||
fdH.write(" const unsigned int %sDataSize = %i;\n" % (shortFilename, len(pngData))) | |||
fdH.write(" const unsigned int %sDataSize = %i;\n" % (shortFilename, len(resData))) | |||
if tempIndex != len(filenames): | |||
fdH.write("\n") | |||
@@ -57,7 +57,7 @@ def png2c(namespace, filenames): | |||
curColumn = 1 | |||
fdC.write(" ") | |||
for data in pngData: | |||
for data in resData: | |||
if curColumn == 0: | |||
fdC.write(" ") | |||
@@ -90,24 +90,24 @@ def png2c(namespace, filenames): | |||
if __name__ == '__main__': | |||
if len(sys.argv) != 3: | |||
print("Usage: %s <namespace> <artwork-folder>" % sys.argv[0]) | |||
print("Usage: %s <namespace> <resource-folder>" % sys.argv[0]) | |||
quit() | |||
namespace = sys.argv[1].replace("-","_") | |||
artFolder = sys.argv[2] | |||
resFolder = sys.argv[2] | |||
if not os.path.exists(artFolder): | |||
print("Folder '%s' does not exist" % artFolder) | |||
if not os.path.exists(resFolder): | |||
print("Folder '%s' does not exist" % resFolder) | |||
quit() | |||
# find png files | |||
pngFiles = [] | |||
# find resource files | |||
resFiles = [] | |||
for root, dirs, files in os.walk(artFolder): | |||
for name in [name for name in files if name.lower().endswith(".png")]: | |||
pngFiles.append(os.path.join(root, name)) | |||
for root, dirs, files in os.walk(resFolder): | |||
for name in files: | |||
resFiles.append(os.path.join(root, name)) | |||
pngFiles.sort() | |||
resFiles.sort() | |||
# create code now | |||
png2c(namespace, pngFiles) | |||
res2c(namespace, resFiles) |
@@ -1,6 +1,6 @@ | |||
/* | |||
* DISTRHO Kars Plugin, based on karplong by Chris Cannam. | |||
* Copyright (C) 2015 Filipe Coelho <falktx@falktx.com> | |||
* Copyright (C) 2015-2019 Filipe Coelho <falktx@falktx.com> | |||
* | |||
* Permission to use, copy, modify, and/or distribute this software for any purpose with | |||
* or without fee is hereby granted, provided that the above copyright notice and this | |||
@@ -158,7 +158,8 @@ public: | |||
midiEvents(m), | |||
midiEventCount(0), | |||
remainingFrames(f), | |||
remainingMidiEventCount(mc) {} | |||
remainingMidiEventCount(mc), | |||
totalFramesUsed(0) {} | |||
/** | |||
Process a batch of events untill no more are available. | |||
@@ -166,41 +167,76 @@ public: | |||
*/ | |||
bool nextEvent() | |||
{ | |||
if (remainingMidiEventCount == 0) | |||
// nothing else to do | |||
if (remainingFrames == 0) | |||
return false; | |||
// initial setup, need to find first MIDI event | |||
if (totalFramesUsed == 0) | |||
{ | |||
if (remainingFrames == 0) | |||
return false; | |||
// no MIDI events at all in this process cycle | |||
if (remainingMidiEventCount == 0) | |||
{ | |||
frames = remainingFrames; | |||
remainingFrames = 0; | |||
totalFramesUsed += frames; | |||
return true; | |||
} | |||
// render audio until first midi event, if needed | |||
if (const uint32_t firstEventFrame = midiEvents[0].frame) | |||
{ | |||
frames = midiEvents[0].frame; | |||
remainingFrames -= frames; | |||
totalFramesUsed += frames; | |||
return true; | |||
} | |||
} | |||
else | |||
{ | |||
for (uint32_t i=0; i<DISTRHO_PLUGIN_NUM_OUTPUTS; ++i) | |||
outputs[i] += frames; | |||
} | |||
if (midiEventCount != 0) | |||
midiEvents += midiEventCount; | |||
// no more MIDI events available | |||
if (remainingMidiEventCount == 0) | |||
{ | |||
frames = remainingFrames; | |||
midiEvents = nullptr; | |||
midiEventCount = 0; | |||
remainingFrames = 0; | |||
totalFramesUsed += frames; | |||
return true; | |||
} | |||
const uint32_t eventFrame = midiEvents[0].frame; | |||
DISTRHO_SAFE_ASSERT_RETURN(eventFrame < remainingFrames, false); | |||
// if there were midi events before, increment pointer | |||
if (midiEventCount != 0) | |||
midiEvents += midiEventCount; | |||
midiEventCount = 1; | |||
const uint32_t firstEventFrame = midiEvents[0].frame; | |||
DISTRHO_SAFE_ASSERT_RETURN((firstEventFrame - frames) < remainingFrames, false); | |||
for (uint32_t i=1; i<remainingMidiEventCount; ++i) | |||
midiEventCount = 1; | |||
while (midiEventCount < remainingMidiEventCount) | |||
{ | |||
if (midiEvents[i].frame != eventFrame) | |||
{ | |||
midiEventCount = i; | |||
if (midiEvents[midiEventCount].frame == firstEventFrame) | |||
++midiEventCount; | |||
else | |||
break; | |||
} | |||
} | |||
frames = remainingFrames - eventFrame; | |||
if (totalFramesUsed != 0) | |||
{ | |||
// need to modify timestamp of midi events | |||
MidiEvent* const rwEvents = const_cast<MidiEvent*>(midiEvents); | |||
for (uint32_t i=0; i < midiEventCount; ++i) | |||
rwEvents[i].frame -= totalFramesUsed; | |||
} | |||
frames = remainingFrames - firstEventFrame; | |||
remainingFrames -= frames; | |||
remainingMidiEventCount -= midiEventCount; | |||
totalFramesUsed += frames; | |||
return true; | |||
} | |||
@@ -208,6 +244,7 @@ private: | |||
/** @internal */ | |||
uint32_t remainingFrames; | |||
uint32_t remainingMidiEventCount; | |||
uint32_t totalFramesUsed; | |||
}; | |||
void DistrhoPluginKars::run(const float**, float** outputs, uint32_t frames, const MidiEvent* midiEvents, uint32_t midiEventCount) | |||
@@ -254,9 +291,9 @@ void DistrhoPluginKars::run(const float**, float** outputs, uint32_t frames, con | |||
if (fNotes[i].on != kNoteNull) | |||
addSamples(out, i, amsh.frames); | |||
} | |||
} | |||
fBlockStart += frames; | |||
fBlockStart += amsh.frames; | |||
} | |||
} | |||
void DistrhoPluginKars::addSamples(float* out, int voice, uint32_t frames) | |||
@@ -1,6 +1,6 @@ | |||
/* | |||
* DISTRHO Kars Plugin, based on karplong by Chris Cannam. | |||
* Copyright (C) 2015 Filipe Coelho <falktx@falktx.com> | |||
* Copyright (C) 2015-2019 Filipe Coelho <falktx@falktx.com> | |||
* | |||
* Permission to use, copy, modify, and/or distribute this software for any purpose with | |||
* or without fee is hereby granted, provided that the above copyright notice and this | |||
@@ -70,7 +70,7 @@ protected: | |||
uint32_t getVersion() const noexcept override | |||
{ | |||
return d_version(1, 0, 0); | |||
return d_version(1, 1, 0); | |||
} | |||
int64_t getUniqueId() const noexcept override | |||
@@ -24,6 +24,7 @@ include ../../dpf/Makefile.plugins.mk | |||
# Extra flags | |||
BUILD_CXX_FLAGS += -I../common -I../common/gen_dsp | |||
BUILD_CXX_FLAGS += -Wno-unused-parameter | |||
# -------------------------------------------------------------- | |||
# Enable all possible plugin types | |||
@@ -24,6 +24,7 @@ include ../../dpf/Makefile.plugins.mk | |||
# Extra flags | |||
BUILD_CXX_FLAGS += -I../common -I../common/gen_dsp | |||
BUILD_CXX_FLAGS += -Wno-unused-parameter | |||
# -------------------------------------------------------------- | |||
# Enable all possible plugin types | |||
@@ -24,6 +24,7 @@ include ../../dpf/Makefile.plugins.mk | |||
# Extra flags | |||
BUILD_CXX_FLAGS += -I../common -I../common/gen_dsp | |||
BUILD_CXX_FLAGS += -Wno-unused-parameter | |||
# -------------------------------------------------------------- | |||
# Enable all possible plugin types | |||
@@ -3,7 +3,7 @@ | |||
* Copyright (C) 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson and 4Front Technologies | |||
* Copyright (C) 2000 Christian Zander <phoenix@minion.de> | |||
* Copyright (C) 2015 Nedko Arnaudov | |||
* Copyright (C) 2016 Filipe Coelho <falktx@falktx.com> | |||
* Copyright (C) 2016-2019 Filipe Coelho <falktx@falktx.com> | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU General Public License as | |||
@@ -3,7 +3,7 @@ | |||
* Copyright (C) 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson and 4Front Technologies | |||
* Copyright (C) 2000 Christian Zander <phoenix@minion.de> | |||
* Copyright (C) 2015 Nedko Arnaudov | |||
* Copyright (C) 2016 Filipe Coelho <falktx@falktx.com> | |||
* Copyright (C) 2016-2019 Filipe Coelho <falktx@falktx.com> | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU General Public License as | |||
@@ -45,7 +45,6 @@ protected: | |||
// UI Callbacks | |||
void uiIdle() override; | |||
// void uiReshape(uint width, uint height) override; | |||
// ------------------------------------------------------------------- | |||
// Widget Callbacks | |||
@@ -3,7 +3,7 @@ | |||
* Copyright (C) 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson and 4Front Technologies | |||
* Copyright (C) 2000 Christian Zander <phoenix@minion.de> | |||
* Copyright (C) 2015 Nedko Arnaudov | |||
* Copyright (C) 2016 Filipe Coelho <falktx@falktx.com> | |||
* Copyright (C) 2016-2019 Filipe Coelho <falktx@falktx.com> | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
@@ -20,7 +20,7 @@ | |||
#ifndef GLBARS_STATE_HPP_INCLUDED | |||
#define GLBARS_STATE_HPP_INCLUDED | |||
#include "Base.hpp" | |||
#include "OpenGL.hpp" | |||
static inline | |||
void draw_rectangle(GLfloat x1, GLfloat y1, GLfloat z1, GLfloat x2, GLfloat y2, GLfloat z2) | |||
@@ -24,6 +24,7 @@ include ../../dpf/Makefile.plugins.mk | |||
# Extra flags | |||
BUILD_CXX_FLAGS += -I../common -I../common/gen_dsp | |||
BUILD_CXX_FLAGS += -Wno-unused-parameter | |||
# -------------------------------------------------------------- | |||
# Enable all possible plugin types | |||