Signed-off-by: falkTX <falktx@falktx.com>tags/v1.5
| @@ -138,7 +138,6 @@ endif # HAVE_CAIRO_OR_OPENGL | |||
| endif # MACOS | |||
| cp -r bin/*.lv2 $(DESTDIR)$(PREFIX)/lib/lv2/ | |||
| ifeq ($(HAVE_JACK),true) | |||
| install -m 755 bin/Kars$(APP_EXT) $(DESTDIR)$(PREFIX)/bin/ | |||
| install -m 755 bin/3BandEQ$(APP_EXT) $(DESTDIR)$(PREFIX)/bin/ | |||
| install -m 755 bin/3BandSplitter$(APP_EXT) $(DESTDIR)$(PREFIX)/bin/ | |||
| @@ -158,7 +157,6 @@ ifeq ($(HAVE_PROJM),true) | |||
| install -m 755 bin/ProM$(APP_EXT) $(DESTDIR)$(PREFIX)/bin/ | |||
| endif # HAVE_PROJM | |||
| endif # HAVE_OPENGL | |||
| endif # HAVE_JACK | |||
| # -------------------------------------------------------------- | |||
| @@ -26,11 +26,10 @@ endif | |||
| ifneq (,$(findstring haiku,$(TARGET_MACHINE))) | |||
| HAIKU=true | |||
| endif | |||
| ifneq (,$(findstring gnu,$(TARGET_MACHINE))) | |||
| HURD=true | |||
| endif | |||
| ifneq (,$(findstring linux,$(TARGET_MACHINE))) | |||
| LINUX=true | |||
| else ifneq (,$(findstring gnu,$(TARGET_MACHINE))) | |||
| HURD=true | |||
| endif | |||
| ifneq (,$(findstring apple,$(TARGET_MACHINE))) | |||
| MACOS=true | |||
| @@ -184,7 +183,7 @@ CXXFLAGS += -fvisibility-inlines-hidden | |||
| endif | |||
| BUILD_C_FLAGS = $(BASE_FLAGS) -std=gnu99 $(CFLAGS) | |||
| BUILD_CXX_FLAGS = $(BASE_FLAGS) -std=gnu++0x $(CXXFLAGS) | |||
| BUILD_CXX_FLAGS = $(BASE_FLAGS) -std=gnu++11 $(CXXFLAGS) | |||
| LINK_FLAGS = $(LINK_OPTS) $(LDFLAGS) | |||
| ifneq ($(MACOS),true) | |||
| @@ -438,3 +437,47 @@ SILENT = @ | |||
| endif | |||
| # --------------------------------------------------------------------------------------------------------------------- | |||
| # all needs to be first | |||
| all: | |||
| # --------------------------------------------------------------------------------------------------------------------- | |||
| # helper to print what is available/possible to build | |||
| print_available = @echo $(1): $(shell echo $($(1)) | grep -q true && echo Yes || echo No) | |||
| features: | |||
| @echo === Detected CPU | |||
| $(call print_available,CPU_AARCH64) | |||
| $(call print_available,CPU_ARM) | |||
| $(call print_available,CPU_ARM64) | |||
| $(call print_available,CPU_ARM_OR_AARCH64) | |||
| $(call print_available,CPU_I386) | |||
| $(call print_available,CPU_I386_OR_X86_64) | |||
| @echo === Detected OS | |||
| $(call print_available,BSD) | |||
| $(call print_available,HAIKU) | |||
| $(call print_available,HURD) | |||
| $(call print_available,LINUX) | |||
| $(call print_available,MACOS) | |||
| $(call print_available,WINDOWS) | |||
| $(call print_available,HAIKU_OR_MACOS_OR_WINDOWS) | |||
| $(call print_available,LINUX_OR_MACOS) | |||
| $(call print_available,MACOS_OR_WINDOWS) | |||
| $(call print_available,UNIX) | |||
| @echo === Detected features | |||
| $(call print_available,HAVE_ALSA) | |||
| $(call print_available,HAVE_CAIRO) | |||
| $(call print_available,HAVE_DGL) | |||
| $(call print_available,HAVE_LIBLO) | |||
| $(call print_available,HAVE_OPENGL) | |||
| $(call print_available,HAVE_PULSEAUDIO) | |||
| $(call print_available,HAVE_RTAUDIO) | |||
| $(call print_available,HAVE_STUB) | |||
| $(call print_available,HAVE_VULKAN) | |||
| $(call print_available,HAVE_X11) | |||
| $(call print_available,HAVE_XCURSOR) | |||
| $(call print_available,HAVE_XEXT) | |||
| $(call print_available,HAVE_XRANDR) | |||
| # --------------------------------------------------------------------------------------------------------------------- | |||
| @@ -75,8 +75,10 @@ ifeq ($(LINUX),true) | |||
| VST3_FILENAME = $(TARGET_PROCESSOR)-linux/$(NAME).so | |||
| endif | |||
| ifeq ($(MACOS),true) | |||
| ifneq ($(MACOS_OLD),true) | |||
| VST3_FILENAME = MacOS/$(NAME) | |||
| endif | |||
| endif | |||
| ifeq ($(WINDOWS),true) | |||
| VST3_FILENAME = $(TARGET_PROCESSOR)-win/$(NAME).vst3 | |||
| endif | |||
| @@ -140,7 +142,7 @@ endif | |||
| ifeq ($(UI_TYPE),cairo) | |||
| ifeq ($(HAVE_CAIRO),true) | |||
| DGL_FLAGS += -DDGL_CAIRO | |||
| DGL_FLAGS += -DDGL_CAIRO -DHAVE_DGL | |||
| DGL_FLAGS += $(CAIRO_FLAGS) | |||
| DGL_LIBS += $(CAIRO_LIBS) | |||
| DGL_LIB = $(DPF_PATH)/build/libdgl-cairo.a | |||
| @@ -152,7 +154,7 @@ endif | |||
| ifeq ($(UI_TYPE),opengl) | |||
| ifeq ($(HAVE_OPENGL),true) | |||
| DGL_FLAGS += -DDGL_OPENGL | |||
| DGL_FLAGS += -DDGL_OPENGL -DHAVE_DGL | |||
| DGL_FLAGS += $(OPENGL_FLAGS) | |||
| DGL_LIBS += $(OPENGL_LIBS) | |||
| DGL_LIB = $(DPF_PATH)/build/libdgl-opengl.a | |||
| @@ -164,7 +166,7 @@ endif | |||
| ifeq ($(UI_TYPE),vulkan) | |||
| ifeq ($(HAVE_VULKAN),true) | |||
| DGL_FLAGS += -DDGL_VULKAN | |||
| DGL_FLAGS += -DDGL_VULKAN -DHAVE_DGL | |||
| DGL_FLAGS += $(VULKAN_FLAGS) | |||
| DGL_LIBS += $(VULKAN_LIBS) | |||
| DGL_LIB = $(DPF_PATH)/build/libdgl-vulkan.a | |||
| @@ -328,7 +330,11 @@ lv2: $(lv2) | |||
| lv2_dsp: $(lv2_dsp) | |||
| lv2_sep: $(lv2_dsp) $(lv2_ui) | |||
| ifeq ($(HAVE_DGL),true) | |||
| $(lv2): $(OBJS_DSP) $(OBJS_UI) $(BUILD_DIR)/DistrhoPluginMain_LV2.cpp.o $(BUILD_DIR)/DistrhoUIMain_LV2.cpp.o $(DGL_LIB) | |||
| else | |||
| $(lv2): $(OBJS_DSP) $(OBJS_UI) $(BUILD_DIR)/DistrhoPluginMain_LV2.cpp.o | |||
| endif | |||
| -@mkdir -p $(shell dirname $@) | |||
| @echo "Creating LV2 plugin for $(NAME)" | |||
| $(SILENT)$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(DGL_LIBS) $(SHARED) $(SYMBOLS_LV2) $(SYMBOLS_LV2UI) -o $@ | |||
| @@ -209,6 +209,7 @@ function(dpf__build_ladspa NAME) | |||
| target_link_libraries("${NAME}-ladspa" PRIVATE "${NAME}-dsp") | |||
| set_target_properties("${NAME}-ladspa" PROPERTIES | |||
| LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin/$<0:>" | |||
| ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/obj/ladspa/$<0:>" | |||
| OUTPUT_NAME "${NAME}-ladspa" | |||
| PREFIX "") | |||
| endfunction() | |||
| @@ -236,6 +237,7 @@ function(dpf__build_dssi NAME DGL_LIBRARY) | |||
| target_link_libraries("${NAME}-dssi" PRIVATE "${NAME}-dsp") | |||
| set_target_properties("${NAME}-dssi" PROPERTIES | |||
| LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin/$<0:>" | |||
| ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/obj/dssi/$<0:>" | |||
| OUTPUT_NAME "${NAME}-dssi" | |||
| PREFIX "") | |||
| @@ -265,6 +267,7 @@ function(dpf__build_lv2 NAME DGL_LIBRARY MONOLITHIC) | |||
| target_link_libraries("${NAME}-lv2" PRIVATE "${NAME}-dsp") | |||
| set_target_properties("${NAME}-lv2" PROPERTIES | |||
| LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin/${NAME}.lv2/$<0:>" | |||
| ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/obj/lv2/$<0:>" | |||
| OUTPUT_NAME "${NAME}_dsp" | |||
| PREFIX "") | |||
| @@ -280,6 +283,7 @@ function(dpf__build_lv2 NAME DGL_LIBRARY MONOLITHIC) | |||
| target_link_libraries("${NAME}-lv2-ui" PRIVATE "${NAME}-ui") | |||
| set_target_properties("${NAME}-lv2-ui" PROPERTIES | |||
| LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin/${NAME}.lv2/$<0:>" | |||
| ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/obj/lv2/$<0:>" | |||
| OUTPUT_NAME "${NAME}_ui" | |||
| PREFIX "") | |||
| endif() | |||
| @@ -310,6 +314,7 @@ function(dpf__build_vst2 NAME DGL_LIBRARY) | |||
| target_link_libraries("${NAME}-vst2" PRIVATE "${NAME}-dsp" "${NAME}-ui") | |||
| set_target_properties("${NAME}-vst2" PROPERTIES | |||
| LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin/$<0:>" | |||
| ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/obj/vst2/$<0:>" | |||
| OUTPUT_NAME "${NAME}-vst2" | |||
| PREFIX "") | |||
| endfunction() | |||
| @@ -363,7 +368,7 @@ function(dpf__add_dgl_cairo) | |||
| target_link_libraries(dgl-cairo PRIVATE dgl-system-libs) | |||
| add_library(dgl-cairo-definitions INTERFACE) | |||
| target_compile_definitions(dgl-cairo-definitions INTERFACE "DGL_CAIRO" "HAVE_CAIRO") | |||
| target_compile_definitions(dgl-cairo-definitions INTERFACE "DGL_CAIRO" "HAVE_CAIRO" "HAVE_DGL") | |||
| target_include_directories(dgl-cairo PUBLIC ${CAIRO_INCLUDE_DIRS}) | |||
| if(MINGW) | |||
| @@ -429,7 +434,7 @@ function(dpf__add_dgl_opengl) | |||
| target_link_libraries(dgl-opengl PRIVATE dgl-system-libs) | |||
| add_library(dgl-opengl-definitions INTERFACE) | |||
| target_compile_definitions(dgl-opengl-definitions INTERFACE "DGL_OPENGL" "HAVE_OPENGL") | |||
| target_compile_definitions(dgl-opengl-definitions INTERFACE "DGL_OPENGL" "HAVE_OPENGL" "HAVE_DGL") | |||
| target_include_directories(dgl-opengl PUBLIC "${OPENGL_INCLUDE_DIR}") | |||
| target_link_libraries(dgl-opengl PRIVATE dgl-opengl-definitions "${OPENGL_gl_LIBRARY}") | |||
| @@ -753,6 +753,11 @@ public: | |||
| */ | |||
| bool contains(const Point<T>& pos) const noexcept; | |||
| /** | |||
| Check if this rectangle contains the point @a pos affected by a custom scale. | |||
| */ | |||
| bool containsAfterScaling(const Point<T>& pos, double scaling) const noexcept; | |||
| /** | |||
| Check if this rectangle contains the point @a pos of another type. | |||
| */ | |||
| @@ -14,7 +14,10 @@ BUILD_CXX_FLAGS += -Isrc/pugl-upstream/include | |||
| LINK_FLAGS += $(DGL_LIBS) | |||
| # TODO fix these after pugl-upstream is done | |||
| BUILD_CXX_FLAGS += -Wno-attributes -Wno-extra -Wno-missing-field-initializers -Wno-narrowing | |||
| BUILD_CXX_FLAGS += -Wno-attributes -Wno-extra -Wno-missing-field-initializers | |||
| ifneq ($(MACOS),true) | |||
| BUILD_CXX_FLAGS += -Wno-narrowing | |||
| endif | |||
| # ifneq ($(MACOS_OLD),true) | |||
| # needed by sofd right now, fix later | |||
| @@ -107,6 +107,14 @@ public: | |||
| DISTRHO_DEPRECATED_BY("getWindow()") | |||
| Window& getParentWindow() const noexcept { return getWindow(); } | |||
| protected: | |||
| bool onKeyboard(const KeyboardEvent&) override; | |||
| bool onSpecial(const SpecialEvent&) override; | |||
| bool onCharacterInput(const CharacterInputEvent&) override; | |||
| bool onMouse(const MouseEvent&) override; | |||
| bool onMotion(const MotionEvent&) override; | |||
| bool onScroll(const ScrollEvent&) override; | |||
| private: | |||
| struct PrivateData; | |||
| PrivateData* const pData; | |||
| @@ -150,7 +150,11 @@ public: | |||
| : BaseEvent(), | |||
| keycode(0), | |||
| character(0), | |||
| #ifdef DISTRHO_PROPER_CPP11_SUPPORT | |||
| string{'\0','\0','\0','\0','\0','\0','\0','\0'} {} | |||
| #else | |||
| string() { std::memset(string, 0, sizeof(string)); } | |||
| #endif | |||
| }; | |||
| /** | |||
| @@ -64,6 +64,11 @@ Application::PrivateData::PrivateData(const bool standalone) | |||
| #ifdef HAVE_X11 | |||
| sofdFileDialogSetup(world); | |||
| #endif | |||
| #ifdef DISTRHO_OS_MAC | |||
| if (standalone) | |||
| puglMacOSActivateApp(); | |||
| #endif | |||
| } | |||
| Application::PrivateData::~PrivateData() | |||
| @@ -726,21 +726,21 @@ void SubWidget::PrivateData::display(const uint width, const uint height, const | |||
| cairo_matrix_t matrix; | |||
| cairo_get_matrix(handle, &matrix); | |||
| if (needsFullViewportForDrawing || (absolutePos.isZero() && self->getSize() == Size<uint>(width, height))) | |||
| { | |||
| // full viewport size | |||
| cairo_translate(handle, 0, 0); | |||
| } | |||
| else if (needsViewportScaling) | |||
| if (needsViewportScaling) | |||
| { | |||
| // limit viewport to widget bounds | |||
| // NOTE only used for nanovg for now, which is not relevant here | |||
| } | |||
| else if (needsFullViewportForDrawing || (absolutePos.isZero() && self->getSize() == Size<uint>(width, height))) | |||
| { | |||
| // full viewport size | |||
| cairo_translate(handle, 0, 0); | |||
| cairo_scale(handle, autoScaleFactor, autoScaleFactor); | |||
| } | |||
| else | |||
| { | |||
| // set viewport pos | |||
| cairo_translate(handle, absolutePos.getX(), absolutePos.getY()); | |||
| cairo_translate(handle, absolutePos.getX() * autoScaleFactor, absolutePos.getY() * autoScaleFactor); | |||
| // then cut the outer bounds | |||
| cairo_rectangle(handle, | |||
| @@ -751,6 +751,9 @@ void SubWidget::PrivateData::display(const uint width, const uint height, const | |||
| cairo_clip(handle); | |||
| needsResetClip = true; | |||
| // set viewport scaling | |||
| cairo_scale(handle, autoScaleFactor, autoScaleFactor); | |||
| } | |||
| // display widget | |||
| @@ -771,24 +774,34 @@ void TopLevelWidget::PrivateData::display() | |||
| if (! selfw->pData->visible) | |||
| return; | |||
| cairo_t* const handle = static_cast<const CairoGraphicsContext&>(self->getGraphicsContext()).handle; | |||
| const Size<uint> size(window.getSize()); | |||
| const uint width = size.getWidth(); | |||
| const uint height = size.getHeight(); | |||
| const double autoScaleFactor = window.pData->autoScaleFactor; | |||
| // FIXME anything needed here? | |||
| #if 0 | |||
| cairo_matrix_t matrix; | |||
| cairo_get_matrix(handle, &matrix); | |||
| // full viewport size | |||
| if (window.pData->autoScaling) | |||
| glViewport(0, -(height * autoScaleFactor - height), width * autoScaleFactor, height * autoScaleFactor); | |||
| { | |||
| cairo_translate(handle, 0, 0); | |||
| cairo_scale(handle, autoScaleFactor, autoScaleFactor); | |||
| } | |||
| else | |||
| glViewport(0, 0, width, height); | |||
| #endif | |||
| { | |||
| cairo_translate(handle, 0, 0); | |||
| cairo_scale(handle, 1.0, 1.0); | |||
| } | |||
| // main widget drawing | |||
| self->onDisplay(); | |||
| cairo_set_matrix(handle, &matrix); | |||
| // now draw subwidgets if there are any | |||
| selfw->pData->displaySubWidgets(width, height, autoScaleFactor); | |||
| } | |||
| @@ -925,6 +925,12 @@ bool Rectangle<uint>::contains(const Point<double>& p) const noexcept | |||
| return (p.x >= pos.x && p.y >= pos.y && p.x <= pos.x+size.fWidth && p.y <= pos.y+size.fHeight); | |||
| } | |||
| template<typename T> | |||
| bool Rectangle<T>::containsAfterScaling(const Point<T>& p, const double scaling) const noexcept | |||
| { | |||
| return (p.x >= pos.x && p.y >= pos.y && p.x/scaling <= pos.x+size.fWidth && p.y/scaling <= pos.y+size.fHeight); | |||
| } | |||
| template<typename T> | |||
| bool Rectangle<T>::containsX(const T& x) const noexcept | |||
| { | |||
| @@ -29,8 +29,11 @@ ImageBaseAboutWindow<ImageType>::ImageBaseAboutWindow(Window& parentWindow, cons | |||
| setResizable(false); | |||
| setTitle("About"); | |||
| if (image.isValid()) | |||
| setSize(image.getSize()); | |||
| if (image.isInvalid()) | |||
| return; | |||
| setSize(image.getSize()); | |||
| setGeometryConstraints(image.getWidth(), image.getHeight(), true, true); | |||
| } | |||
| template <class ImageType> | |||
| @@ -41,8 +44,11 @@ ImageBaseAboutWindow<ImageType>::ImageBaseAboutWindow(TopLevelWidget* const pare | |||
| setResizable(false); | |||
| setTitle("About"); | |||
| if (image.isValid()) | |||
| setSize(image.getSize()); | |||
| if (image.isInvalid()) | |||
| return; | |||
| setSize(image.getSize()); | |||
| setGeometryConstraints(image.getWidth(), image.getHeight(), true, true); | |||
| } | |||
| template <class ImageType> | |||
| @@ -52,7 +58,12 @@ void ImageBaseAboutWindow<ImageType>::setImage(const ImageType& image) | |||
| return; | |||
| img = image; | |||
| if (image.isInvalid()) | |||
| return; | |||
| setSize(image.getSize()); | |||
| setGeometryConstraints(image.getWidth(), image.getHeight(), true, true); | |||
| } | |||
| template <class ImageType> | |||
| @@ -598,7 +598,10 @@ void SubWidget::PrivateData::display(const uint width, const uint height, const | |||
| else if (needsFullViewportForDrawing || (absolutePos.isZero() && self->getSize() == Size<uint>(width, height))) | |||
| { | |||
| // full viewport size | |||
| glViewport(0, 0, static_cast<int>(width), static_cast<int>(height)); | |||
| glViewport(0, | |||
| -static_cast<int>(height * autoScaleFactor - height + 0.5), | |||
| static_cast<int>(width * autoScaleFactor + 0.5), | |||
| static_cast<int>(height * autoScaleFactor + 0.5)); | |||
| } | |||
| else | |||
| { | |||
| @@ -646,9 +649,9 @@ void TopLevelWidget::PrivateData::display() | |||
| if (window.pData->autoScaling) | |||
| { | |||
| glViewport(0, | |||
| -static_cast<int>(height * autoScaleFactor - height), | |||
| static_cast<int>(width * autoScaleFactor), | |||
| static_cast<int>(height * autoScaleFactor)); | |||
| -static_cast<int>(height * autoScaleFactor - height + 0.5), | |||
| static_cast<int>(width * autoScaleFactor + 0.5), | |||
| static_cast<int>(height * autoScaleFactor + 0.5)); | |||
| } | |||
| else | |||
| { | |||
| @@ -19,7 +19,7 @@ | |||
| START_NAMESPACE_DGL | |||
| // ----------------------------------------------------------------------- | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| TopLevelWidget::TopLevelWidget(Window& windowToMapTo) | |||
| : Widget(this), | |||
| @@ -93,6 +93,38 @@ void TopLevelWidget::setGeometryConstraints(const uint minimumWidth, | |||
| pData->window.setGeometryConstraints(minimumWidth, minimumHeight, keepAspectRatio, automaticallyScale); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| bool TopLevelWidget::onKeyboard(const KeyboardEvent&) | |||
| { | |||
| return false; | |||
| } | |||
| bool TopLevelWidget::onSpecial(const SpecialEvent&) | |||
| { | |||
| return false; | |||
| } | |||
| bool TopLevelWidget::onCharacterInput(const CharacterInputEvent&) | |||
| { | |||
| return false; | |||
| } | |||
| bool TopLevelWidget::onMouse(const MouseEvent&) | |||
| { | |||
| return false; | |||
| } | |||
| bool TopLevelWidget::onMotion(const MotionEvent&) | |||
| { | |||
| return false; | |||
| } | |||
| bool TopLevelWidget::onScroll(const ScrollEvent&) | |||
| { | |||
| return false; | |||
| } | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| END_NAMESPACE_DGL | |||
| @@ -156,12 +156,16 @@ void Window::setSize(uint width, uint height) | |||
| if (pData->isEmbed) | |||
| { | |||
| const double scaleFactor = pData->scaleFactor; | |||
| const uint minWidth = static_cast<uint>(pData->minWidth * scaleFactor + 0.5); | |||
| const uint minHeight = static_cast<uint>(pData->minHeight * scaleFactor + 0.5); | |||
| // handle geometry constraints here | |||
| if (width < pData->minWidth) | |||
| width = pData->minWidth; | |||
| if (width < minWidth) | |||
| width = minWidth; | |||
| if (height < pData->minHeight) | |||
| height = pData->minHeight; | |||
| if (height < minHeight) | |||
| height = minHeight; | |||
| if (pData->keepAspectRatio) | |||
| { | |||
| @@ -265,12 +269,21 @@ void Window::repaint() noexcept | |||
| void Window::repaint(const Rectangle<uint>& rect) noexcept | |||
| { | |||
| const PuglRect prect = { | |||
| PuglRect prect = { | |||
| static_cast<double>(rect.getX()), | |||
| static_cast<double>(rect.getY()), | |||
| static_cast<double>(rect.getWidth()), | |||
| static_cast<double>(rect.getHeight()), | |||
| }; | |||
| if (pData->autoScaling) | |||
| { | |||
| const double autoScaleFactor = pData->autoScaleFactor; | |||
| prect.x *= autoScaleFactor; | |||
| prect.y *= autoScaleFactor; | |||
| prect.width *= autoScaleFactor; | |||
| prect.height *= autoScaleFactor; | |||
| } | |||
| puglPostRedisplayRect(pData->view, prect); | |||
| } | |||
| @@ -287,12 +300,6 @@ void Window::setGeometryConstraints(const uint minimumWidth, | |||
| DISTRHO_SAFE_ASSERT_RETURN(minimumWidth > 0,); | |||
| DISTRHO_SAFE_ASSERT_RETURN(minimumHeight > 0,); | |||
| if (pData->isEmbed) { | |||
| // nothing to do here | |||
| } else if (! isResizable()) { | |||
| setResizable(true); | |||
| } | |||
| pData->minWidth = minimumWidth; | |||
| pData->minHeight = minimumHeight; | |||
| pData->autoScaling = automaticallyScale; | |||
| @@ -64,12 +64,13 @@ START_NAMESPACE_DGL | |||
| static const char* const kWin32SelectedFileCancelled = "__dpf_cancelled__"; | |||
| #endif | |||
| static double getDesktopScaleFactor() | |||
| static double getDesktopScaleFactor(const PuglView* const view) | |||
| { | |||
| // allow custom scale for testing | |||
| if (const char* const scale = getenv("DPF_SCALE_FACTOR")) | |||
| return std::max(1.0, std::atof(scale)); | |||
| return 1.0; | |||
| return puglGetDesktopScaleFactor(view); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| @@ -84,7 +85,7 @@ Window::PrivateData::PrivateData(Application& a, Window* const s) | |||
| isClosed(true), | |||
| isVisible(false), | |||
| isEmbed(false), | |||
| scaleFactor(getDesktopScaleFactor()), | |||
| scaleFactor(getDesktopScaleFactor(view)), | |||
| autoScaling(false), | |||
| autoScaleFactor(1.0), | |||
| minWidth(0), | |||
| @@ -137,7 +138,7 @@ Window::PrivateData::PrivateData(Application& a, Window* const s, | |||
| isClosed(parentWindowHandle == 0), | |||
| isVisible(parentWindowHandle != 0), | |||
| isEmbed(parentWindowHandle != 0), | |||
| scaleFactor(scale != 0.0 ? scale : getDesktopScaleFactor()), | |||
| scaleFactor(scale != 0.0 ? scale : getDesktopScaleFactor(view)), | |||
| autoScaling(false), | |||
| autoScaleFactor(1.0), | |||
| minWidth(0), | |||
| @@ -167,7 +168,7 @@ Window::PrivateData::PrivateData(Application& a, Window* const s, | |||
| isClosed(parentWindowHandle == 0), | |||
| isVisible(parentWindowHandle != 0), | |||
| isEmbed(parentWindowHandle != 0), | |||
| scaleFactor(scale != 0.0 ? scale : getDesktopScaleFactor()), | |||
| scaleFactor(scale != 0.0 ? scale : getDesktopScaleFactor(view)), | |||
| autoScaling(false), | |||
| autoScaleFactor(1.0), | |||
| minWidth(0), | |||
| @@ -362,7 +363,11 @@ void Window::PrivateData::focus() | |||
| if (! isEmbed) | |||
| puglRaiseWindow(view); | |||
| #ifdef HAVE_X11 | |||
| puglX11GrabFocus(view); | |||
| #else | |||
| puglGrabFocus(view); | |||
| #endif | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| @@ -110,6 +110,10 @@ START_NAMESPACE_DGL | |||
| # define PuglWrapperView DISTRHO_MACOS_NAMESPACE_MACRO(DGL_NAMESPACE, PuglWrapperView) | |||
| # define PuglWindow DISTRHO_MACOS_NAMESPACE_MACRO(DGL_NAMESPACE, PuglWindow) | |||
| # endif | |||
| # ifndef __MAC_10_9 | |||
| # define NSModalResponseOK NSOKButton | |||
| typedef NSUInteger NSEventSubtype; | |||
| # endif | |||
| # pragma clang diagnostic push | |||
| # pragma clang diagnostic ignored "-Wdeprecated-declarations" | |||
| # import "pugl-upstream/src/mac.m" | |||
| @@ -193,13 +197,35 @@ const char* puglGetWindowTitle(const PuglView* const view) | |||
| return view->title; | |||
| } | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| // get global scale factor | |||
| double puglGetDesktopScaleFactor(const PuglView* const view) | |||
| { | |||
| #if defined(DISTRHO_OS_MAC) | |||
| if (NSWindow* const window = view->impl->window ? view->impl->window | |||
| : [view->impl->wrapperView window]) | |||
| return [window screen].backingScaleFactor; | |||
| return [NSScreen mainScreen].backingScaleFactor; | |||
| #else | |||
| return 1.0; | |||
| // unused | |||
| (void)view; | |||
| #endif | |||
| } | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| // bring view window into the foreground, aka "raise" window | |||
| void puglRaiseWindow(PuglView* view) | |||
| void puglRaiseWindow(PuglView* const view) | |||
| { | |||
| #if defined(DISTRHO_OS_HAIKU) || defined(DISTRHO_OS_MAC) | |||
| #if defined(DISTRHO_OS_HAIKU) | |||
| // nothing here yet | |||
| #elif defined(DISTRHO_OS_MAC) | |||
| if (NSWindow* const window = view->impl->window ? view->impl->window | |||
| : [view->impl->wrapperView window]) | |||
| [window orderFrontRegardless]; | |||
| #elif defined(DISTRHO_OS_WINDOWS) | |||
| SetForegroundWindow(view->impl->hwnd); | |||
| SetActiveWindow(view->impl->hwnd); | |||
| @@ -276,9 +302,30 @@ PuglStatus puglSetWindowSize(PuglView* const view, const uint width, const uint | |||
| view->defaultHeight = height; | |||
| #if defined(DISTRHO_OS_HAIKU) || defined(DISTRHO_OS_MAC) | |||
| // keep upstream behaviour | |||
| // replace the 2 views setFrame with setFrameSize | |||
| const PuglRect frame = { view->frame.x, view->frame.y, (double)width, (double)height }; | |||
| return puglSetFrame(view, frame); | |||
| PuglInternals* const impl = view->impl; | |||
| // Update view frame to exactly the requested frame in Pugl coordinates | |||
| view->frame = frame; | |||
| const NSRect framePx = rectToNsRect(frame); | |||
| const NSRect framePt = nsRectToPoints(view, framePx); | |||
| if (impl->window) | |||
| { | |||
| // Resize window to fit new content rect | |||
| const NSRect screenPt = rectToScreen(viewScreen(view), framePt); | |||
| const NSRect winFrame = [impl->window frameRectForContentRect:screenPt]; | |||
| [impl->window setFrame:winFrame display:NO]; | |||
| } | |||
| // Resize views | |||
| const NSSize sizePx = NSMakeSize(frame.width, frame.height); | |||
| const NSSize sizePt = [impl->drawView convertSizeFromBacking:sizePx]; | |||
| [impl->wrapperView setFrameSize:(impl->window ? sizePt : framePt.size)]; | |||
| [impl->drawView setFrameSize:sizePt]; | |||
| #elif defined(DISTRHO_OS_WINDOWS) | |||
| // matches upstream pugl, except we add SWP_NOMOVE flag | |||
| if (view->impl->hwnd) | |||
| @@ -391,6 +438,15 @@ bool puglMacOSFilePanelOpen(PuglView* const view, | |||
| return true; | |||
| } | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| // macOS specific, allow standalone window to gain focus | |||
| void puglMacOSActivateApp() | |||
| { | |||
| [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; | |||
| [NSApp activateIgnoringOtherApps:YES]; | |||
| } | |||
| #endif | |||
| #ifdef DISTRHO_OS_WINDOWS | |||
| @@ -450,6 +506,28 @@ void puglWin32SetWindowResizable(PuglView* const view, const bool resizable) | |||
| #endif | |||
| #ifdef HAVE_X11 | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| // X11 specific, safer way to grab focus | |||
| PuglStatus puglX11GrabFocus(PuglView* const view) | |||
| { | |||
| PuglInternals* const impl = view->impl; | |||
| XWindowAttributes wa; | |||
| std::memset(&wa, 0, sizeof(wa)); | |||
| DISTRHO_SAFE_ASSERT_RETURN(XGetWindowAttributes(impl->display, impl->win, &wa), PUGL_UNKNOWN_ERROR); | |||
| if (wa.map_state == IsViewable) | |||
| { | |||
| XRaiseWindow(impl->display, impl->win); | |||
| XSetInputFocus(impl->display, impl->win, RevertToPointerRoot, CurrentTime); | |||
| XSync(impl->display, False); | |||
| } | |||
| return PUGL_SUCCESS; | |||
| } | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| // X11 specific, setup event loop filter for sofd file dialog | |||
| @@ -20,9 +20,14 @@ | |||
| #include "../Base.hpp" | |||
| /* we will include all header files used in pugl in their C++ friendly form, then pugl stuff in custom namespace */ | |||
| #include <cstdbool> | |||
| #include <cstddef> | |||
| #include <cstdint> | |||
| #ifdef DISTRHO_PROPER_CPP11_SUPPORT | |||
| # include <cstdbool> | |||
| # include <cstdint> | |||
| #else | |||
| # include <stdbool.h> | |||
| # include <stdint.h> | |||
| #endif | |||
| #define PUGL_API | |||
| #define PUGL_DISABLE_DEPRECATED | |||
| @@ -62,6 +67,10 @@ puglGetTransientParent(const PuglView* view); | |||
| PUGL_API const char* | |||
| puglGetWindowTitle(const PuglView* view); | |||
| // get global scale factor | |||
| PUGL_API double | |||
| puglGetDesktopScaleFactor(const PuglView* view); | |||
| // bring view window into the foreground, aka "raise" window | |||
| PUGL_API void | |||
| puglRaiseWindow(PuglView* view); | |||
| @@ -90,6 +99,10 @@ puglFallbackOnResize(PuglView* view); | |||
| // macOS specific, setup file browser dialog | |||
| typedef void (*openPanelCallback)(PuglView* view, const char* path); | |||
| bool puglMacOSFilePanelOpen(PuglView* view, const char* startDir, const char* title, uint flags, openPanelCallback callback); | |||
| // macOS specific, allow standalone window to gain focus | |||
| PUGL_API void | |||
| puglMacOSActivateApp(); | |||
| #endif | |||
| #ifdef DISTRHO_OS_WINDOWS | |||
| @@ -107,6 +120,10 @@ puglWin32SetWindowResizable(PuglView* view, bool resizable); | |||
| #endif | |||
| #ifdef HAVE_X11 | |||
| // X11 specific, safer way to grab focus | |||
| PUGL_API PuglStatus | |||
| puglX11GrabFocus(PuglView* view); | |||
| // X11 specific, setup event loop filter for sofd file dialog | |||
| PUGL_API void | |||
| sofdFileDialogSetup(PuglWorld* world); | |||
| @@ -74,8 +74,13 @@ public: | |||
| /** | |||
| UI class constructor. | |||
| The UI should be initialized to a default state that matches the plugin side. | |||
| When @a automaticallyScale is set to true, DPF will automatically scale up the UI | |||
| to fit the host/desktop scale factor.@n | |||
| It assumes aspect ratio is meant to be kept. | |||
| Manually call setGeometryConstraints instead if keeping UI aspect ratio is not required. | |||
| */ | |||
| UI(uint width = 0, uint height = 0); | |||
| UI(uint width = 0, uint height = 0, bool automaticallyScale = false); | |||
| /** | |||
| Destructor. | |||
| @@ -38,7 +38,7 @@ | |||
| typedef SSIZE_T ssize_t; | |||
| #endif | |||
| #if defined(DISTRHO_OS_MAC) && ! defined(CARLA_OS_MAC) && ! defined(DISTRHO_PROPER_CPP11_SUPPORT) | |||
| #if ! defined(CARLA_MATH_UTILS_HPP_INCLUDED) && ! defined(DISTRHO_PROPER_CPP11_SUPPORT) | |||
| namespace std { | |||
| inline float fmin(float __x, float __y) | |||
| { return __builtin_fminf(__x, __y); } | |||
| @@ -31,6 +31,8 @@ typedef HMODULE lib_t; | |||
| typedef void* lib_t; | |||
| #endif | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| // library related calls | |||
| @@ -129,4 +131,6 @@ const char* lib_error(const char* const filename) noexcept | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| #endif // DISTRHO_LIBRARY_UTILS_HPP_INCLUDED | |||
| @@ -59,12 +59,12 @@ public: | |||
| /* | |||
| * Simple char string. | |||
| */ | |||
| explicit String(char* const strBuf, const bool copyData = true) noexcept | |||
| explicit String(char* const strBuf, const bool reallocData = true) noexcept | |||
| : fBuffer(_null()), | |||
| fBufferLen(0), | |||
| fBufferAlloc(false) | |||
| { | |||
| if (copyData || strBuf == nullptr) | |||
| if (reallocData || strBuf == nullptr) | |||
| { | |||
| _dup(strBuf); | |||
| } | |||
| @@ -930,7 +930,7 @@ String operator+(const String& strBefore, const char* const strBufAfter) noexcep | |||
| std::memcpy(newBuf, strBefore.buffer(), strBeforeLen); | |||
| std::memcpy(newBuf + strBeforeLen, strBufAfter, strBufAfterLen + 1); | |||
| return String(newBuf); | |||
| return String(newBuf, false); | |||
| } | |||
| static inline | |||
| @@ -950,7 +950,7 @@ String operator+(const char* const strBufBefore, const String& strAfter) noexcep | |||
| std::memcpy(newBuf, strBufBefore, strBufBeforeLen); | |||
| std::memcpy(newBuf + strBufBeforeLen, strAfter.buffer(), strAfterLen + 1); | |||
| return String(newBuf); | |||
| return String(newBuf, false); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| @@ -58,12 +58,13 @@ | |||
| #elif __cplusplus >= 201103L || (defined(__GNUC__) && defined(__GXX_EXPERIMENTAL_CXX0X__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 405) || __has_extension(cxx_noexcept) || (defined(_MSC_VER) && _MSVC_LANG >= 201103L) | |||
| # define DISTRHO_PROPER_CPP11_SUPPORT | |||
| # if (defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) < 407 && ! defined(__clang__)) || (defined(__clang__) && ! __has_extension(cxx_override_control)) | |||
| # define override // gcc4.7+ only | |||
| # define final // gcc4.7+ only | |||
| # define override /* gcc4.7+ only */ | |||
| # define final /* gcc4.7+ only */ | |||
| # endif | |||
| #endif | |||
| #ifndef DISTRHO_PROPER_CPP11_SUPPORT | |||
| # define constexpr | |||
| # define noexcept throw() | |||
| # define override | |||
| # define final | |||
| @@ -71,7 +72,7 @@ | |||
| #endif | |||
| /* Define DISTRHO_DEPRECATED */ | |||
| #if defined(__GNUC__) | |||
| #if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 480 | |||
| # define DISTRHO_DEPRECATED __attribute__((deprecated)) | |||
| #elif defined(_MSC_VER) | |||
| # define DISTRHO_DEPRECATED [[deprecated]] /* Note: __declspec(deprecated) it not applicable to enum members */ | |||
| @@ -80,9 +81,9 @@ | |||
| #endif | |||
| /* Define DISTRHO_DEPRECATED_BY */ | |||
| #if defined(__clang__) | |||
| #if defined(__clang__) && defined(DISTRHO_PROPER_CPP11_SUPPORT) | |||
| # define DISTRHO_DEPRECATED_BY(other) __attribute__((deprecated("", other))) | |||
| #elif defined(__GNUC__) | |||
| #elif defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 480 | |||
| # define DISTRHO_DEPRECATED_BY(other) __attribute__((deprecated("Use " other))) | |||
| #else | |||
| # define DISTRHO_DEPRECATED_BY(other) DISTRHO_DEPRECATED | |||
| @@ -51,7 +51,7 @@ | |||
| # define DISTRHO_PLUGIN_LV2_STATE_PREFIX "urn:distrho:" | |||
| #endif | |||
| #define DISTRHO_LV2_USE_EVENTS_IN (DISTRHO_PLUGIN_WANT_MIDI_INPUT || DISTRHO_PLUGIN_WANT_TIMEPOS || (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI)) | |||
| #define DISTRHO_LV2_USE_EVENTS_IN (DISTRHO_PLUGIN_WANT_MIDI_INPUT || DISTRHO_PLUGIN_WANT_TIMEPOS || (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI) || DISTRHO_PLUGIN_WANT_STATEFILES) | |||
| #define DISTRHO_LV2_USE_EVENTS_OUT (DISTRHO_PLUGIN_WANT_MIDI_OUTPUT || (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI)) | |||
| START_NAMESPACE_DISTRHO | |||
| @@ -74,7 +74,7 @@ | |||
| # define DISTRHO_LV2_UI_TYPE "UI" | |||
| #endif | |||
| #define DISTRHO_LV2_USE_EVENTS_IN (DISTRHO_PLUGIN_WANT_MIDI_INPUT || DISTRHO_PLUGIN_WANT_TIMEPOS || (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI)) | |||
| #define DISTRHO_LV2_USE_EVENTS_IN (DISTRHO_PLUGIN_WANT_MIDI_INPUT || DISTRHO_PLUGIN_WANT_TIMEPOS || (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI) || DISTRHO_PLUGIN_WANT_STATEFILES) | |||
| #define DISTRHO_LV2_USE_EVENTS_OUT (DISTRHO_PLUGIN_WANT_MIDI_OUTPUT || (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI)) | |||
| #define DISTRHO_BYPASS_PARAMETER_NAME "lv2_enabled" | |||
| @@ -22,6 +22,11 @@ | |||
| # define DISTRHO_PLUGIN_HAS_UI 0 | |||
| #endif | |||
| #if DISTRHO_PLUGIN_HAS_UI && ! defined(HAVE_DGL) | |||
| # undef DISTRHO_PLUGIN_HAS_UI | |||
| # define DISTRHO_PLUGIN_HAS_UI 0 | |||
| #endif | |||
| #if DISTRHO_PLUGIN_HAS_UI | |||
| # include "DistrhoUIInternal.hpp" | |||
| # include "../extra/RingBuffer.hpp" | |||
| @@ -127,7 +132,7 @@ struct ParameterAndNotesHelper | |||
| # endif | |||
| #endif | |||
| { | |||
| #ifndef DISTRHO_PROPER_CPP11_SUPPORT | |||
| #if DISTRHO_PLUGIN_HAS_UI && DISTRHO_PLUGIN_WANT_MIDI_INPUT && ! defined(DISTRHO_PROPER_CPP11_SUPPORT) | |||
| std::memset(¬esRingBuffer, 0, sizeof(notesRingBuffer)); | |||
| #endif | |||
| } | |||
| @@ -184,7 +189,8 @@ public: | |||
| nullptr, // TODO file request | |||
| nullptr, | |||
| plugin->getInstancePointer(), | |||
| scaleFactor) | |||
| scaleFactor), | |||
| fHasScaleFactor(d_isNotZero(scaleFactor)) | |||
| # if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI | |||
| , fKeyboardModifiers(0) | |||
| # endif | |||
| @@ -223,11 +229,21 @@ public: | |||
| return fUI.getHeight(); | |||
| } | |||
| double getScaleFactor() const | |||
| { | |||
| return fUI.getScaleFactor(); | |||
| } | |||
| void setSampleRate(const double newSampleRate) | |||
| { | |||
| fUI.setSampleRate(newSampleRate, true); | |||
| } | |||
| void notifyScaleFactorChanged(const double scaleFactor) | |||
| { | |||
| fUI.notifyScaleFactorChanged(scaleFactor); | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| // functions called from the plugin side, may block | |||
| @@ -382,9 +398,15 @@ protected: | |||
| hostCallback(audioMasterAutomate, index, 0, nullptr, perValue); | |||
| } | |||
| void setSize(const uint width, const uint height) | |||
| void setSize(uint width, uint height) | |||
| { | |||
| // fUI.setWindowSize(width, height); | |||
| // figure out scale factor ourselves if the host doesn't support it | |||
| if (! fHasScaleFactor) | |||
| { | |||
| const double scaleFactor = fUI.getScaleFactor(); | |||
| width /= scaleFactor; | |||
| height /= scaleFactor; | |||
| } | |||
| hostCallback(audioMasterSizeWindow, width, height); | |||
| } | |||
| @@ -416,6 +438,7 @@ private: | |||
| // Plugin UI | |||
| UIExporter fUI; | |||
| const bool fHasScaleFactor; | |||
| # if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI | |||
| uint16_t fKeyboardModifiers; | |||
| # endif | |||
| @@ -494,7 +517,7 @@ public: | |||
| fVstRect.left = 0; | |||
| fVstRect.bottom = 0; | |||
| fVstRect.right = 0; | |||
| fLastScaleFactor = 1.0f; | |||
| fLastScaleFactor = 0.0f; | |||
| if (parameterCount != 0) | |||
| { | |||
| @@ -665,6 +688,13 @@ public: | |||
| { | |||
| fVstRect.right = fVstUI->getWidth(); | |||
| fVstRect.bottom = fVstUI->getHeight(); | |||
| // figure out scale factor ourselves if the host doesn't support it | |||
| if (fLastScaleFactor == 0.0f) | |||
| { | |||
| const double scaleFactor = fVstUI->getScaleFactor(); | |||
| fVstRect.right /= scaleFactor; | |||
| fVstRect.bottom /= scaleFactor; | |||
| } | |||
| } | |||
| else | |||
| { | |||
| @@ -673,6 +703,13 @@ public: | |||
| fPlugin.getInstancePointer(), fLastScaleFactor); | |||
| fVstRect.right = tmpUI.getWidth(); | |||
| fVstRect.bottom = tmpUI.getHeight(); | |||
| // figure out scale factor ourselves if the host doesn't support it | |||
| if (fLastScaleFactor == 0.0f) | |||
| { | |||
| const double scaleFactor = tmpUI.getScaleFactor(); | |||
| fVstRect.right /= scaleFactor; | |||
| fVstRect.bottom /= scaleFactor; | |||
| } | |||
| tmpUI.quit(); | |||
| } | |||
| *(ERect**)ptr = &fVstRect; | |||
| @@ -993,7 +1030,15 @@ public: | |||
| case effVendorSpecific: | |||
| #if DISTRHO_PLUGIN_HAS_UI | |||
| if (index == CCONST('P', 'r', 'e', 'S') && value == CCONST('A', 'e', 'C', 's')) | |||
| { | |||
| if (d_isEqual(fLastScaleFactor, opt)) | |||
| break; | |||
| fLastScaleFactor = opt; | |||
| if (fVstUI != nullptr) | |||
| fVstUI->notifyScaleFactorChanged(opt); | |||
| } | |||
| #endif | |||
| break; | |||
| @@ -46,13 +46,18 @@ PluginWindow& UI::PrivateData::createNextWindow(UI* const ui, const uint width, | |||
| /* ------------------------------------------------------------------------------------------------------------ | |||
| * UI */ | |||
| UI::UI(const uint width, const uint height) | |||
| UI::UI(const uint width, const uint height, const bool automaticallyScale) | |||
| : UIWidget(UI::PrivateData::createNextWindow(this, width, height)), | |||
| uiData(UI::PrivateData::s_nextPrivateData) | |||
| { | |||
| #if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI | |||
| if (width > 0 && height > 0) | |||
| { | |||
| Widget::setSize(width, height); | |||
| if (automaticallyScale) | |||
| setGeometryConstraints(width, height, true, true); | |||
| } | |||
| #endif | |||
| } | |||
| @@ -59,7 +59,7 @@ public: | |||
| const fileRequestFunc fileRequestCall, | |||
| const char* const bundlePath = nullptr, | |||
| void* const dspPtr = nullptr, | |||
| const double scaleFactor = 1.0, | |||
| const double scaleFactor = 0.0, | |||
| const uint32_t bgColor = 0, | |||
| const uint32_t fgColor = 0xffffffff) | |||
| : ui(nullptr), | |||
| @@ -128,6 +128,11 @@ public: | |||
| return uiData->window->getHeight(); | |||
| } | |||
| double getScaleFactor() const noexcept | |||
| { | |||
| return uiData->window->getScaleFactor(); | |||
| } | |||
| bool isVisible() const noexcept | |||
| { | |||
| return uiData->window->isVisible(); | |||
| @@ -321,7 +326,7 @@ public: | |||
| bool handlePluginKeyboard(const bool press, const uint key, const uint16_t mods) | |||
| { | |||
| // TODO also trigger Character input event | |||
| Widget::KeyboardEvent ev; | |||
| DGL_NAMESPACE::Widget::KeyboardEvent ev; | |||
| ev.press = press; | |||
| ev.key = key; | |||
| ev.mod = mods; | |||
| @@ -330,7 +335,7 @@ public: | |||
| bool handlePluginSpecial(const bool press, const DGL_NAMESPACE::Key key, const uint16_t mods) | |||
| { | |||
| Widget::SpecialEvent ev; | |||
| DGL_NAMESPACE::Widget::SpecialEvent ev; | |||
| ev.press = press; | |||
| ev.key = key; | |||
| ev.mod = mods; | |||
| @@ -340,6 +345,13 @@ public: | |||
| // ------------------------------------------------------------------- | |||
| void notifyScaleFactorChanged(const double scaleFactor) | |||
| { | |||
| DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr,); | |||
| ui->uiScaleFactorChanged(scaleFactor); | |||
| } | |||
| void setSampleRate(const double sampleRate, const bool doCallback = false) | |||
| { | |||
| DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr,); | |||
| @@ -70,10 +70,10 @@ public: | |||
| // TODO external ui stuff | |||
| class PluginWindow | |||
| { | |||
| UI* const ui; | |||
| DISTRHO_NAMESPACE::UI* const ui; | |||
| public: | |||
| explicit PluginWindow(UI* const uiPtr, | |||
| explicit PluginWindow(DISTRHO_NAMESPACE::UI* const uiPtr, | |||
| PluginApplication& app, | |||
| const uintptr_t parentWindowHandle, | |||
| const uint width, | |||
| @@ -107,10 +107,10 @@ public: | |||
| #else | |||
| class PluginWindow : public Window | |||
| { | |||
| UI* const ui; | |||
| DISTRHO_NAMESPACE::UI* const ui; | |||
| public: | |||
| explicit PluginWindow(UI* const uiPtr, | |||
| explicit PluginWindow(DISTRHO_NAMESPACE::UI* const uiPtr, | |||
| PluginApplication& app, | |||
| const uintptr_t parentWindowHandle, | |||
| const uint width, | |||
| @@ -312,7 +312,7 @@ inline bool UI::PrivateData::fileRequestCallback(const char* const key) | |||
| snprintf(title, sizeof(title)-1u, DISTRHO_PLUGIN_NAME ": %s", key); | |||
| title[sizeof(title)-1u] = '\0'; | |||
| Window::FileBrowserOptions opts; | |||
| DGL_NAMESPACE::Window::FileBrowserOptions opts; | |||
| opts.title = title; | |||
| return window->openFileBrowser(opts); | |||
| #endif | |||
| @@ -36,9 +36,11 @@ | |||
| #include "../../extra/LibraryUtils.hpp" | |||
| // in case JACK fails, we fallback to RtAudio's native API | |||
| #include "RtAudioBridge.hpp" | |||
| #ifdef RTAUDIO_API_TYPE | |||
| # include "rtaudio/RtAudio.cpp" | |||
| #ifdef DISTRHO_PROPER_CPP11_SUPPORT | |||
| # include "RtAudioBridge.hpp" | |||
| # ifdef RTAUDIO_API_TYPE | |||
| # include "rtaudio/RtAudio.cpp" | |||
| # endif | |||
| #endif | |||
| // ----------------------------------------------------------------------------- | |||
| @@ -422,6 +424,7 @@ struct JackBridge { | |||
| # else | |||
| const char* const filename("libjack.so.0"); | |||
| # endif | |||
| USE_NAMESPACE_DISTRHO | |||
| lib = lib_open(filename); | |||
| @@ -561,6 +564,8 @@ struct JackBridge { | |||
| ~JackBridge() noexcept | |||
| { | |||
| USE_NAMESPACE_DISTRHO | |||
| if (lib != nullptr) | |||
| { | |||
| lib_close(lib); | |||
| @@ -37,8 +37,12 @@ | |||
| # define Point CorePoint /* fix conflict between DGL and macOS Point name */ | |||
| # include "rtaudio/RtAudio.h" | |||
| # undef Point | |||
| # include "../../extra/RingBuffer.hpp" | |||
| # include "../../extra/ScopedPointer.hpp" | |||
| using DISTRHO_NAMESPACE::HeapRingBuffer; | |||
| using DISTRHO_NAMESPACE::ScopedPointer; | |||
| struct RtAudioBridge { | |||
| // pointer to RtAudio instance | |||
| ScopedPointer<RtAudio> handle; | |||
| @@ -58,9 +62,23 @@ struct RtAudioBridge { | |||
| void* jackProcessArg = nullptr; | |||
| // Runtime buffers | |||
| enum PortMask { | |||
| kPortMaskAudio = 0x1000, | |||
| kPortMaskMIDI = 0x2000, | |||
| kPortMaskInput = 0x4000, | |||
| kPortMaskOutput = 0x8000, | |||
| kPortMaskInputMIDI = kPortMaskInput|kPortMaskMIDI, | |||
| kPortMaskOutputMIDI = kPortMaskOutput|kPortMaskMIDI, | |||
| }; | |||
| #if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0 | |||
| float* audioBuffers[DISTRHO_PLUGIN_NUM_INPUTS + DISTRHO_PLUGIN_NUM_OUTPUTS]; | |||
| // TODO midi buffer, likely using ringbuffer class | |||
| #endif | |||
| #if DISTRHO_PLUGIN_WANT_MIDI_INPUT | |||
| HeapRingBuffer midiInBuffer; | |||
| #endif | |||
| #if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT | |||
| HeapRingBuffer midiOutBuffer; | |||
| #endif | |||
| bool open() | |||
| { | |||
| @@ -90,6 +108,13 @@ struct RtAudioBridge { | |||
| handle = rtAudio; | |||
| bufferSize = rtAudioBufferFrames; | |||
| sampleRate = handle->getStreamSampleRate(); | |||
| #if DISTRHO_PLUGIN_WANT_MIDI_INPUT | |||
| midiInBuffer.createBuffer(128); | |||
| #endif | |||
| #if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT | |||
| midiOutBuffer.createBuffer(128); | |||
| #endif | |||
| return true; | |||
| } | |||
| @@ -148,7 +173,8 @@ struct RtAudioBridge { | |||
| else | |||
| return nullptr; | |||
| const uintptr_t ret = (isAudio ? 0x1000 : 0x2000) | (isInput ? 0x4000 : 0x8000); | |||
| const uintptr_t ret = (isAudio ? kPortMaskAudio : kPortMaskMIDI) | |||
| | (isInput ? kPortMaskInput : kPortMaskOutput); | |||
| return (jack_port_t*)(ret + (isAudio ? (isInput ? numAudioIns++ : numAudioOuts++) | |||
| : (isInput ? numMidiIns++ : numMidiOuts++))); | |||
| @@ -157,10 +183,19 @@ struct RtAudioBridge { | |||
| void* getPortBuffer(jack_port_t* const port) | |||
| { | |||
| const uintptr_t portMask = (uintptr_t)port; | |||
| DISTRHO_SAFE_ASSERT_RETURN(portMask != 0x0, nullptr); | |||
| #if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0 | |||
| if (portMask & 0x1000) | |||
| return audioBuffers[(portMask & 0x4000 ? 0 : DISTRHO_PLUGIN_NUM_INPUTS) + (portMask & 0x0fff)]; | |||
| if (portMask & kPortMaskAudio) | |||
| return audioBuffers[(portMask & kPortMaskInput ? 0 : DISTRHO_PLUGIN_NUM_INPUTS) + (portMask & 0x0fff)]; | |||
| #endif | |||
| #if DISTRHO_PLUGIN_WANT_MIDI_INPUT | |||
| if ((portMask & kPortMaskInputMIDI) == kPortMaskInputMIDI) | |||
| return &midiInBuffer; | |||
| #endif | |||
| #if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT | |||
| if ((portMask & kPortMaskOutputMIDI) == kPortMaskOutputMIDI) | |||
| return &midiOutBuffer; | |||
| #endif | |||
| return nullptr; | |||
| @@ -24,7 +24,7 @@ namespace Art = DistrhoArtwork3BandEQ; | |||
| // ----------------------------------------------------------------------- | |||
| DistrhoUI3BandEQ::DistrhoUI3BandEQ() | |||
| : UI(Art::backgroundWidth, Art::backgroundHeight), | |||
| : UI(Art::backgroundWidth, Art::backgroundHeight, true), | |||
| fImgBackground(Art::backgroundData, Art::backgroundWidth, Art::backgroundHeight, kImageFormatBGR), | |||
| fAboutWindow(this) | |||
| { | |||
| @@ -24,7 +24,7 @@ namespace Art = DistrhoArtwork3BandSplitter; | |||
| // ----------------------------------------------------------------------- | |||
| DistrhoUI3BandSplitter::DistrhoUI3BandSplitter() | |||
| : UI(Art::backgroundWidth, Art::backgroundHeight), | |||
| : UI(Art::backgroundWidth, Art::backgroundHeight, true), | |||
| fImgBackground(Art::backgroundData, Art::backgroundWidth, Art::backgroundHeight, kImageFormatBGR), | |||
| fAboutWindow(this) | |||
| { | |||
| @@ -1,7 +1,7 @@ | |||
| /* | |||
| * DISTRHO AmplitudeImposer, a DPF'ied AmplitudeImposer. | |||
| * Copyright (C) 2004 Niall Moody | |||
| * Copyright (C) 2015 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2015-2021 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * Permission is hereby granted, free of charge, to any person obtaining a | |||
| * copy of this software and associated documentation files (the "Software"), | |||
| @@ -32,7 +32,7 @@ namespace Art = DistrhoArtworkAmplitudeImposer; | |||
| // ----------------------------------------------------------------------- | |||
| DistrhoUIAmplitudeImposer::DistrhoUIAmplitudeImposer() | |||
| : UI(Art::backWidth, Art::backHeight), | |||
| : UI(Art::backWidth, Art::backHeight, true), | |||
| fImgBackground(Art::backData, Art::backWidth, Art::backHeight, kImageFormatGrayscale) | |||
| { | |||
| // sliders | |||
| @@ -1,5 +1,5 @@ | |||
| Copyright (C) 2004-2006 Niall Moody | |||
| Copyright (C) 2015 Filipe Coelho | |||
| Copyright (C) 2015-2021 Filipe Coelho | |||
| Permission is hereby granted, free of charge, to any person obtaining a | |||
| copy of this software and associated documentation files (the "Software"), | |||
| @@ -1,7 +1,7 @@ | |||
| /* | |||
| * DISTRHO CycleShifter, a DPF'ied CycleShifter. | |||
| * Copyright (C) 2004 Niall Moody | |||
| * Copyright (C) 2015 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2015-2021 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * Permission is hereby granted, free of charge, to any person obtaining a | |||
| * copy of this software and associated documentation files (the "Software"), | |||
| @@ -32,7 +32,7 @@ namespace Art = DistrhoArtworkCycleShifter; | |||
| // ----------------------------------------------------------------------- | |||
| DistrhoUICycleShifter::DistrhoUICycleShifter() | |||
| : UI(Art::backWidth, Art::backHeight), | |||
| : UI(Art::backWidth, Art::backHeight, true), | |||
| fImgBackground(Art::backData, Art::backWidth, Art::backHeight, kImageFormatGrayscale) | |||
| { | |||
| // sliders | |||
| @@ -1,5 +1,5 @@ | |||
| Copyright (C) 2004-2006 Niall Moody | |||
| Copyright (C) 2015 Filipe Coelho | |||
| Copyright (C) 2015-2021 Filipe Coelho | |||
| Permission is hereby granted, free of charge, to any person obtaining a | |||
| copy of this software and associated documentation files (the "Software"), | |||
| @@ -1,7 +1,7 @@ | |||
| /* | |||
| * DISTRHO MVerb, a DPF'ied MVerb. | |||
| * Copyright (c) 2010 Martin Eastwood | |||
| * Copyright (C) 2015 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2015-2021 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 | |||
| @@ -28,7 +28,7 @@ using DGL::Color; | |||
| // ----------------------------------------------------------------------- | |||
| DistrhoUIMVerb::DistrhoUIMVerb() | |||
| : UI(Art::backgroundWidth, Art::backgroundHeight), | |||
| : UI(Art::backgroundWidth, Art::backgroundHeight, true), | |||
| fImgBackground(Art::backgroundData, Art::backgroundWidth, Art::backgroundHeight, kImageFormatBGR) | |||
| { | |||
| // text | |||
| @@ -122,9 +122,6 @@ DistrhoUIMVerb::DistrhoUIMVerb() | |||
| // set initial values | |||
| programLoaded(0); | |||
| // TODO auto-scale but non-resizable | |||
| // setGeometryConstraints(Art::backgroundWidth, Art::backgroundHeight, true, true); | |||
| } | |||
| DistrhoUIMVerb::~DistrhoUIMVerb() | |||
| @@ -25,7 +25,7 @@ namespace Art = DistrhoArtworkNekobi; | |||
| // ----------------------------------------------------------------------- | |||
| DistrhoUINekobi::DistrhoUINekobi() | |||
| : UI(Art::backgroundWidth, Art::backgroundHeight), | |||
| : UI(Art::backgroundWidth, Art::backgroundHeight, true), | |||
| fImgBackground(Art::backgroundData, Art::backgroundWidth, Art::backgroundHeight, kImageFormatBGR), | |||
| fAboutWindow(this) | |||
| { | |||
| @@ -24,7 +24,7 @@ namespace Art = DistrhoArtworkPingPongPan; | |||
| // ----------------------------------------------------------------------- | |||
| DistrhoUIPingPongPan::DistrhoUIPingPongPan() | |||
| : UI(Art::backgroundWidth, Art::backgroundHeight), | |||
| : UI(Art::backgroundWidth, Art::backgroundHeight, true), | |||
| fImgBackground(Art::backgroundData, Art::backgroundWidth, Art::backgroundHeight, kImageFormatBGR), | |||
| fAboutWindow(this) | |||
| { | |||
| @@ -1,7 +1,7 @@ | |||
| /* | |||
| * DISTRHO SoulForce, a DPF'ied SoulForce. | |||
| * Copyright (C) 2006 Niall Moody | |||
| * Copyright (C) 2015 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2015-2021 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * Permission is hereby granted, free of charge, to any person obtaining a | |||
| * copy of this software and associated documentation files (the "Software"), | |||
| @@ -32,7 +32,7 @@ namespace Art = DistrhoArtworkSoulForce; | |||
| // ----------------------------------------------------------------------- | |||
| DistrhoUISoulForce::DistrhoUISoulForce() | |||
| : UI(Art::backgroundWidth, Art::backgroundHeight), | |||
| : UI(Art::backgroundWidth, Art::backgroundHeight, true), | |||
| fImgBackground(Art::backgroundData, Art::backgroundWidth, Art::backgroundHeight, kImageFormatBGR), | |||
| fImgLedOff(Art::led_offData, Art::led_offWidth, Art::led_offHeight, kImageFormatBGR), | |||
| fImgLedOn(Art::led_onData, Art::led_onWidth, Art::led_onHeight, kImageFormatBGR), | |||
| @@ -1,5 +1,5 @@ | |||
| Copyright (C) 2004-2006 Niall Moody | |||
| Copyright (C) 2015 Filipe Coelho | |||
| Copyright (C) 2015-2021 Filipe Coelho | |||
| Permission is hereby granted, free of charge, to any person obtaining a | |||
| copy of this software and associated documentation files (the "Software"), | |||