From fa353203958ae610aff6f33e7317a3acbb82611d Mon Sep 17 00:00:00 2001 From: falkTX Date: Tue, 26 Feb 2019 09:05:05 +0100 Subject: [PATCH] Update DPF and plugins Signed-off-by: falkTX --- dpf/LICENSE | 2 +- dpf/Makefile.plugins.mk | 4 +- dpf/README.md | 3 + dpf/dgl/ImageWidgets.hpp | 2 +- dpf/dgl/Window.hpp | 9 + dpf/dgl/src/Geometry.cpp | 2 +- dpf/dgl/src/NanoVG.cpp | 6 +- dpf/dgl/src/WidgetPrivateData.hpp | 35 +- dpf/dgl/src/Window.cpp | 105 ++++- dpf/dgl/src/pugl/common.h | 121 ----- dpf/dgl/src/pugl/event.h | 41 -- dpf/dgl/src/pugl/gl.h | 32 -- dpf/dgl/src/pugl/glu.h | 32 -- dpf/dgl/src/pugl/pugl.h | 176 +++++-- dpf/dgl/src/pugl/pugl_internal.h | 192 ++------ dpf/dgl/src/pugl/pugl_osx.m | 25 +- dpf/dgl/src/pugl/pugl_win.cpp | 39 +- dpf/dgl/src/pugl/pugl_x11.c | 454 +++++++++---------- dpf/distrho/DistrhoPlugin.hpp | 30 +- dpf/distrho/DistrhoUI.hpp | 30 +- dpf/distrho/extra/ExternalWindow.hpp | 50 +- dpf/distrho/src/DistrhoDefines.h | 9 + dpf/distrho/src/DistrhoPluginChecks.h | 3 +- dpf/distrho/src/DistrhoPluginJack.cpp | 5 - dpf/distrho/src/DistrhoPluginLADSPA+DSSI.cpp | 4 +- dpf/distrho/src/DistrhoPluginLV2.cpp | 16 +- dpf/distrho/src/DistrhoPluginLV2export.cpp | 9 +- dpf/distrho/src/DistrhoPluginVST.cpp | 14 +- dpf/distrho/src/DistrhoUI.cpp | 56 ++- dpf/distrho/src/DistrhoUIDSSI.cpp | 2 +- dpf/distrho/src/DistrhoUIInternal.hpp | 214 ++++++--- dpf/distrho/src/lv2/atom-util.h | 12 +- dpf/utils/png2c.py | 113 +++++ dpf/utils/png2rgba.py | 9 +- plugins/MVerb/MVerb.h | 4 +- 35 files changed, 1006 insertions(+), 854 deletions(-) delete mode 100644 dpf/dgl/src/pugl/common.h delete mode 100644 dpf/dgl/src/pugl/event.h delete mode 100644 dpf/dgl/src/pugl/gl.h delete mode 100644 dpf/dgl/src/pugl/glu.h create mode 100755 dpf/utils/png2c.py diff --git a/dpf/LICENSE b/dpf/LICENSE index 6ecc24c..6bd93e1 100644 --- a/dpf/LICENSE +++ b/dpf/LICENSE @@ -1,5 +1,5 @@ DISTRHO Plugin Framework (DPF) -Copyright (C) 2012-2014 Filipe Coelho +Copyright (C) 2012-2018 Filipe Coelho 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 diff --git a/dpf/Makefile.plugins.mk b/dpf/Makefile.plugins.mk index 47c7fc7..aa69a91 100644 --- a/dpf/Makefile.plugins.mk +++ b/dpf/Makefile.plugins.mk @@ -77,12 +77,12 @@ all: # Common $(BUILD_DIR)/%.c.o: %.c - -@mkdir -p $(BUILD_DIR) + -@mkdir -p "$(shell dirname $(BUILD_DIR)/$<)" @echo "Compiling $<" @$(CC) $< $(BUILD_C_FLAGS) -c -o $@ $(BUILD_DIR)/%.cpp.o: %.cpp - -@mkdir -p $(BUILD_DIR) + -@mkdir -p "$(shell dirname $(BUILD_DIR)/$<)" @echo "Compiling $<" @$(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@ diff --git a/dpf/README.md b/dpf/README.md index 6d0dbd5..b8788fc 100644 --- a/dpf/README.md +++ b/dpf/README.md @@ -27,6 +27,9 @@ List of plugins made with DPF:
- [DISTRHO ndc Plugs](https://github.com/DISTRHO/ndc-Plugs) - [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) + - [YK Chorus](https://github.com/SpotlightKid/ykchorus) Plugin examples are available in the `example/` folder inside this repo.
diff --git a/dpf/dgl/ImageWidgets.hpp b/dpf/dgl/ImageWidgets.hpp index e5a2142..0e1e1dd 100644 --- a/dpf/dgl/ImageWidgets.hpp +++ b/dpf/dgl/ImageWidgets.hpp @@ -240,7 +240,7 @@ public: { public: virtual ~Callback() {} - virtual void imageSwitchClicked(ImageSwitch* imageButton, bool down) = 0; + virtual void imageSwitchClicked(ImageSwitch* imageSwitch, bool down) = 0; }; explicit ImageSwitch(Window& parent, const Image& imageNormal, const Image& imageDown) noexcept; diff --git a/dpf/dgl/Window.hpp b/dpf/dgl/Window.hpp index 182ae97..bc686c2 100644 --- a/dpf/dgl/Window.hpp +++ b/dpf/dgl/Window.hpp @@ -92,6 +92,8 @@ public: bool openFileBrowser(const FileBrowserOptions& options); #endif + bool isEmbed() const noexcept; + bool isVisible() const noexcept; void setVisible(bool yesNo); @@ -107,8 +109,15 @@ public: const char* getTitle() const noexcept; void setTitle(const char* title); + void setGeometryConstraints(uint width, uint height, bool aspect); void setTransientWinId(uintptr_t winId); + double getScaling() const noexcept; + void setScaling(double scaling) noexcept; + + bool getIgnoringKeyRepeat() const noexcept; + void setIgnoringKeyRepeat(bool ignore) noexcept; + Application& getApp() const noexcept; intptr_t getWindowId() const noexcept; diff --git a/dpf/dgl/src/Geometry.cpp b/dpf/dgl/src/Geometry.cpp index 7ea3af3..c76809d 100644 --- a/dpf/dgl/src/Geometry.cpp +++ b/dpf/dgl/src/Geometry.cpp @@ -237,7 +237,7 @@ bool Size::isNotNull() const noexcept template bool Size::isValid() const noexcept { - return fWidth > 1 && fHeight > 1; + return fWidth > 0 && fHeight > 0; } template diff --git a/dpf/dgl/src/NanoVG.cpp b/dpf/dgl/src/NanoVG.cpp index 3ef7b35..3c29222 100644 --- a/dpf/dgl/src/NanoVG.cpp +++ b/dpf/dgl/src/NanoVG.cpp @@ -447,10 +447,8 @@ void NanoVG::translate(float x, float y) void NanoVG::rotate(float angle) { - if (fContext == nullptr) return; - DISTRHO_SAFE_ASSERT_RETURN(angle > 0.0f,); - - nvgRotate(fContext, angle); + if (fContext != nullptr) + nvgRotate(fContext, angle); } void NanoVG::skewX(float angle) diff --git a/dpf/dgl/src/WidgetPrivateData.hpp b/dpf/dgl/src/WidgetPrivateData.hpp index bf836b7..5dbe2ac 100644 --- a/dpf/dgl/src/WidgetPrivateData.hpp +++ b/dpf/dgl/src/WidgetPrivateData.hpp @@ -63,7 +63,7 @@ struct Widget::PrivateData { subWidgets.clear(); } - void display(const uint width, const uint height, const bool renderingSubWidget) + void display(const uint width, const uint height, const double scaling, const bool renderingSubWidget) { if ((skipDisplay && ! renderingSubWidget) || size.isInvalid() || ! visible) return; @@ -76,29 +76,32 @@ struct Widget::PrivateData { if (needsFullViewport || (absolutePos.isZero() && size == Size(width, height))) { // full viewport size - glViewport(0, 0, static_cast(width), static_cast(height)); + glViewport(0, + -(height * scaling - height), + width * scaling, + height * scaling); } else if (needsScaling) { // limit viewport to widget bounds glViewport(absolutePos.getX(), - static_cast(height - self->getHeight()) - absolutePos.getY(), - static_cast(self->getWidth()), - static_cast(self->getHeight())); + height - self->getHeight() - absolutePos.getY(), + self->getWidth(), + self->getHeight()); } else { // only set viewport pos - glViewport(absolutePos.getX(), - /*static_cast(height - self->getHeight())*/ - absolutePos.getY(), - static_cast(width), - static_cast(height)); + 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(), - static_cast(height - self->getHeight()) - absolutePos.getY(), - static_cast(self->getWidth()), - static_cast(self->getHeight())); + 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; @@ -113,17 +116,17 @@ struct Widget::PrivateData { needsDisableScissor = false; } - displaySubWidgets(width, height); + displaySubWidgets(width, height, scaling); } - void displaySubWidgets(const uint width, const uint height) + void displaySubWidgets(const uint width, const uint height, const double scaling) { for (std::vector::iterator it = subWidgets.begin(); it != subWidgets.end(); ++it) { Widget* const widget(*it); DISTRHO_SAFE_ASSERT_CONTINUE(widget->pData != this); - widget->pData->display(width, height, true); + widget->pData->display(width, height, scaling, true); } } diff --git a/dpf/dgl/src/Window.cpp b/dpf/dgl/src/Window.cpp index c03ee75..d155f3b 100644 --- a/dpf/dgl/src/Window.cpp +++ b/dpf/dgl/src/Window.cpp @@ -19,10 +19,6 @@ #include "../Base.hpp" -#undef PUGL_HAVE_CAIRO -#undef PUGL_HAVE_GL -#define PUGL_HAVE_GL 1 - #include "pugl/pugl.h" #if defined(__GNUC__) && (__GNUC__ >= 7) @@ -61,7 +57,7 @@ extern "C" { #define FOR_EACH_WIDGET_INV(rit) \ for (std::list::reverse_iterator rit = fWidgets.rbegin(); rit != fWidgets.rend(); ++rit) -#ifdef DEBUG +#if defined(DEBUG) && defined(DGL_DEBUG_EVENTS) # define DBG(msg) std::fprintf(stderr, "%s", msg); # define DBGp(...) std::fprintf(stderr, __VA_ARGS__); # define DBGF std::fflush(stderr); @@ -87,6 +83,7 @@ struct Window::PrivateData { fUsingEmbed(false), fWidth(1), fHeight(1), + fScaling(1.0), fTitle(nullptr), fWidgets(), fModal(), @@ -117,6 +114,7 @@ struct Window::PrivateData { fUsingEmbed(false), fWidth(1), fHeight(1), + fScaling(1.0), fTitle(nullptr), fWidgets(), fModal(parent.pData), @@ -159,6 +157,7 @@ struct Window::PrivateData { fUsingEmbed(parentId != 0), fWidth(1), fHeight(1), + fScaling(1.0), fTitle(nullptr), fWidgets(), fModal(), @@ -204,7 +203,6 @@ struct Window::PrivateData { return; } - puglInitContextType(fView, PUGL_GL); puglInitUserResizable(fView, fResizable); puglInitWindowSize(fView, static_cast(fWidth), static_cast(fHeight)); @@ -539,6 +537,7 @@ struct Window::PrivateData { DBG("Window setResizable called\n"); fResizable = yesNo; + fView->user_resizable = yesNo; #if defined(DISTRHO_OS_WINDOWS) const int winFlags = fResizable ? GetWindowLong(hwnd, GWL_STYLE) | WS_SIZEBOX @@ -554,6 +553,17 @@ struct Window::PrivateData { // ------------------------------------------------------------------- + void setGeometryConstraints(uint width, uint height, bool aspect) + { + DISTRHO_SAFE_ASSERT_RETURN(fResizable,); + + fView->min_width = width; + fView->min_height = height; + puglUpdateGeometryConstraints(fView, width, height, aspect); + } + + // ------------------------------------------------------------------- + void setSize(uint width, uint height, const bool forced = false) { if (width <= 1 || height <= 1) @@ -605,7 +615,6 @@ struct Window::PrivateData { } } #else - XResizeWindow(xDisplay, xWindow, width, height); if (! fResizable) { @@ -620,9 +629,11 @@ struct Window::PrivateData { sizeHints.max_width = static_cast(width); sizeHints.max_height = static_cast(height); - XSetNormalHints(xDisplay, xWindow, &sizeHints); + XSetWMNormalHints(xDisplay, xWindow, &sizeHints); } + XResizeWindow(xDisplay, xWindow, width, height); + if (! forced) XFlush(xDisplay); #endif @@ -685,6 +696,32 @@ struct Window::PrivateData { // ------------------------------------------------------------------- + double getScaling() const noexcept + { + return fScaling; + } + + void setScaling(double scaling) noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(scaling > 0.0,); + + fScaling = scaling; + } + + // ------------------------------------------------------------------- + + bool getIgnoringKeyRepeat() const noexcept + { + return fView->ignoreKeyRepeat; + } + + void setIgnoringKeyRepeat(bool ignore) noexcept + { + puglIgnoreKeyRepeat(fView, ignore); + } + + // ------------------------------------------------------------------- + void addWidget(Widget* const widget) { fWidgets.push_back(widget); @@ -736,7 +773,7 @@ struct Window::PrivateData { FOR_EACH_WIDGET(it) { Widget* const widget(*it); - widget->pData->display(fWidth, fHeight, false); + widget->pData->display(fWidth, fHeight, fScaling, false); } fSelf->onDisplayAfter(); @@ -796,7 +833,7 @@ struct Window::PrivateData { return 1; } - void onPuglMouse(const int button, const bool press, const int x, const int y) + void onPuglMouse(const int button, const bool press, int x, int y) { DBGp("PUGL: onMouse : %i %i %i %i\n", button, press, x, y); @@ -806,6 +843,9 @@ struct Window::PrivateData { if (fModal.childFocus != nullptr) return fModal.childFocus->focus(); + x /= fScaling; + y /= fScaling; + Widget::MouseEvent ev; ev.button = button; ev.press = press; @@ -823,13 +863,16 @@ struct Window::PrivateData { } } - void onPuglMotion(const int x, const int y) + void onPuglMotion(int x, int y) { - DBGp("PUGL: onMotion : %i %i\n", x, y); + // DBGp("PUGL: onMotion : %i %i\n", x, y); if (fModal.childFocus != nullptr) return; + x /= fScaling; + y /= fScaling; + Widget::MotionEvent ev; ev.mod = static_cast(puglGetModifiers(fView)); ev.time = puglGetEventTimestamp(fView); @@ -845,13 +888,18 @@ struct Window::PrivateData { } } - void onPuglScroll(const int x, const int y, const float dx, const float dy) + void onPuglScroll(int x, int y, float dx, float dy) { DBGp("PUGL: onScroll : %i %i %f %f\n", x, y, dx, dy); if (fModal.childFocus != nullptr) return; + x /= fScaling; + y /= fScaling; + dx /= fScaling; + dy /= fScaling; + Widget::ScrollEvent ev; ev.delta = Point(dx, dy); ev.mod = static_cast(puglGetModifiers(fView)); @@ -1000,6 +1048,7 @@ struct Window::PrivateData { bool fUsingEmbed; uint fWidth; uint fHeight; + double fScaling; char* fTitle; std::list fWidgets; @@ -1221,6 +1270,11 @@ bool Window::openFileBrowser(const FileBrowserOptions& options) } #endif +bool Window::isEmbed() const noexcept +{ + return pData->fUsingEmbed; +} + bool Window::isVisible() const noexcept { return pData->fVisible; @@ -1241,6 +1295,11 @@ void Window::setResizable(bool yesNo) pData->setResizable(yesNo); } +void Window::setGeometryConstraints(uint width, uint height, bool aspect) +{ + pData->setGeometryConstraints(width, height, aspect); +} + uint Window::getWidth() const noexcept { return pData->fWidth; @@ -1281,6 +1340,26 @@ void Window::setTransientWinId(uintptr_t winId) pData->setTransientWinId(winId); } +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(); +} + +void Window::setIgnoringKeyRepeat(bool ignore) noexcept +{ + pData->setIgnoringKeyRepeat(ignore); +} + Application& Window::getApp() const noexcept { return pData->fApp; diff --git a/dpf/dgl/src/pugl/common.h b/dpf/dgl/src/pugl/common.h deleted file mode 100644 index afda61e..0000000 --- a/dpf/dgl/src/pugl/common.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - Copyright 2014 David Robillard - - 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. - - THIS 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 PUGL_COMMON_H_INCLUDED -#define PUGL_COMMON_H_INCLUDED - -#ifdef __cplusplus -extern "C" { -#endif - -/** - @addtogroup pugl - @{ -*/ - -/** - A Pugl view. -*/ -typedef struct PuglViewImpl PuglView; - -/** - A native window handle. - - On X11, this is a Window. - On OSX, this is an NSView*. - On Windows, this is a HWND. -*/ -typedef intptr_t PuglNativeWindow; - -/** - Handle for opaque user data. -*/ -typedef void* PuglHandle; - -/** - Return status code. -*/ -typedef enum { - PUGL_SUCCESS = 0 -} PuglStatus; - -/** - Drawing context type. -*/ -typedef enum { - PUGL_GL, - PUGL_CAIRO -} PuglContextType; - -/** - Convenience symbols for ASCII control characters. -*/ -typedef enum { - PUGL_CHAR_BACKSPACE = 0x08, - PUGL_CHAR_ESCAPE = 0x1B, - PUGL_CHAR_DELETE = 0x7F -} PuglChar; - -/** - Keyboard modifier flags. -*/ -typedef enum { - PUGL_MOD_SHIFT = 1 << 0, /**< Shift key */ - PUGL_MOD_CTRL = 1 << 1, /**< Control key */ - PUGL_MOD_ALT = 1 << 2, /**< Alt/Option key */ - PUGL_MOD_SUPER = 1 << 3 /**< Mod4/Command/Windows key */ -} PuglMod; - -/** - Special (non-Unicode) keyboard keys. -*/ -typedef enum { - PUGL_KEY_F1 = 1, - PUGL_KEY_F2, - PUGL_KEY_F3, - PUGL_KEY_F4, - PUGL_KEY_F5, - PUGL_KEY_F6, - PUGL_KEY_F7, - PUGL_KEY_F8, - PUGL_KEY_F9, - PUGL_KEY_F10, - PUGL_KEY_F11, - PUGL_KEY_F12, - PUGL_KEY_LEFT, - PUGL_KEY_UP, - PUGL_KEY_RIGHT, - PUGL_KEY_DOWN, - PUGL_KEY_PAGE_UP, - PUGL_KEY_PAGE_DOWN, - PUGL_KEY_HOME, - PUGL_KEY_END, - PUGL_KEY_INSERT, - PUGL_KEY_SHIFT, - PUGL_KEY_CTRL, - PUGL_KEY_ALT, - PUGL_KEY_SUPER -} PuglKey; - -/** - @} -*/ - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* PUGL_COMMON_H_INCLUDED */ diff --git a/dpf/dgl/src/pugl/event.h b/dpf/dgl/src/pugl/event.h deleted file mode 100644 index 7314e48..0000000 --- a/dpf/dgl/src/pugl/event.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - Copyright 2014 David Robillard - - 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. - - THIS 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 PUGL_EVENT_H_INCLUDED -#define PUGL_EVENT_H_INCLUDED - -#ifdef __cplusplus -extern "C" { -#else -# include -#endif - -#include "pugl/common.h" - -/** - @addtogroup pugl - @{ -*/ - -/** - @} -*/ - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* PUGL_EVENT_H_INCLUDED */ diff --git a/dpf/dgl/src/pugl/gl.h b/dpf/dgl/src/pugl/gl.h deleted file mode 100644 index 9a6aeef..0000000 --- a/dpf/dgl/src/pugl/gl.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - Copyright 2012-2014 David Robillard - - 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. - - THIS 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. -*/ - -/** - @file gl.h Portable header wrapper for gl.h. - - Unfortunately, GL includes vary across platforms so this header allows for - pure portable programs. -*/ - -#ifdef __APPLE__ -# include "OpenGL/gl.h" -#else -# ifdef _WIN32 -# include /* Broken Windows GL headers require this */ -# endif -# include "GL/gl.h" -#endif - diff --git a/dpf/dgl/src/pugl/glu.h b/dpf/dgl/src/pugl/glu.h deleted file mode 100644 index 4be79c7..0000000 --- a/dpf/dgl/src/pugl/glu.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - Copyright 2012-2014 David Robillard - - 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. - - THIS 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. -*/ - -/** - @file glu.h Portable header wrapper for glu.h. - - Unfortunately, GL includes vary across platforms so this header allows for - pure portable programs. -*/ - -#ifdef __APPLE__ -# include "OpenGL/glu.h" -#else -# ifdef _WIN32 -# include /* Broken Windows GL headers require this */ -# endif -# include "GL/glu.h" -#endif - diff --git a/dpf/dgl/src/pugl/pugl.h b/dpf/dgl/src/pugl/pugl.h index 42518e1..32a10a2 100644 --- a/dpf/dgl/src/pugl/pugl.h +++ b/dpf/dgl/src/pugl/pugl.h @@ -23,28 +23,25 @@ #include -#include "pugl/common.h" -#include "pugl/event.h" - -#ifdef PUGL_SHARED -# ifdef _WIN32 -# define PUGL_LIB_IMPORT __declspec(dllimport) -# define PUGL_LIB_EXPORT __declspec(dllexport) -# else -# define PUGL_LIB_IMPORT __attribute__((visibility("default"))) -# define PUGL_LIB_EXPORT __attribute__((visibility("default"))) -# endif -# ifdef PUGL_INTERNAL -# define PUGL_API PUGL_LIB_EXPORT -# else -# define PUGL_API PUGL_LIB_IMPORT -# endif +/* + This API is pure portable C and contains no platform specific elements, or + even a GL dependency. However, unfortunately GL includes vary across + platforms so they are included here to allow for pure portable programs. +*/ +#ifdef __APPLE__ +# include "OpenGL/gl.h" #else # ifdef _WIN32 -# define PUGL_API -# else -# define PUGL_API __attribute__((visibility("hidden"))) +# include +# include /* Broken Windows GL headers require this */ # endif +# include "GL/gl.h" +#endif + +#ifdef _WIN32 +# define PUGL_API +#else +# define PUGL_API __attribute__((visibility("hidden"))) #endif #ifdef __cplusplus @@ -59,6 +56,82 @@ extern "C" { @{ */ +/** + A Pugl view. +*/ +typedef struct PuglViewImpl PuglView; + +/** + A native window handle. + + On X11, this is a Window. + On OSX, this is an NSView*. + On Windows, this is a HWND. +*/ +typedef intptr_t PuglNativeWindow; + +/** + Return status code. +*/ +typedef enum { + PUGL_SUCCESS = 0 +} PuglStatus; + +/** + Convenience symbols for ASCII control characters. +*/ +typedef enum { + PUGL_CHAR_BACKSPACE = 0x08, + PUGL_CHAR_ESCAPE = 0x1B, + PUGL_CHAR_DELETE = 0x7F +} PuglChar; + +/** + Special (non-Unicode) keyboard keys. +*/ +typedef enum { + PUGL_KEY_F1 = 1, + PUGL_KEY_F2, + PUGL_KEY_F3, + PUGL_KEY_F4, + PUGL_KEY_F5, + PUGL_KEY_F6, + PUGL_KEY_F7, + PUGL_KEY_F8, + PUGL_KEY_F9, + PUGL_KEY_F10, + PUGL_KEY_F11, + PUGL_KEY_F12, + PUGL_KEY_LEFT, + PUGL_KEY_UP, + PUGL_KEY_RIGHT, + PUGL_KEY_DOWN, + PUGL_KEY_PAGE_UP, + PUGL_KEY_PAGE_DOWN, + PUGL_KEY_HOME, + PUGL_KEY_END, + PUGL_KEY_INSERT, + PUGL_KEY_SHIFT, + PUGL_KEY_CTRL, + PUGL_KEY_ALT, + PUGL_KEY_SUPER +} PuglKey; + +/** + Keyboard modifier flags. +*/ +typedef enum { + PUGL_MOD_SHIFT = 1 << 0, /**< Shift key */ + PUGL_MOD_CTRL = 1 << 1, /**< Control key */ + PUGL_MOD_ALT = 1 << 2, /**< Alt/Option key */ + PUGL_MOD_SUPER = 1 << 3 /**< Mod4/Command/Windows key */ +} PuglMod; + +/** + Handle for opaque user data. +*/ +typedef void* PuglHandle; + /** A function called when the window is closed. */ @@ -105,6 +178,16 @@ typedef void (*PuglMouseFunc)( */ typedef void (*PuglReshapeFunc)(PuglView* view, int width, int height); +/** + A function called outside of gl-context when the plugin schedules a resize via puglPostResize. + + @param view The view being resized. + @param width The new width to resize to (variable is initialized to current size) + @param height The new height to resize to (variable is initialized to current size) + @param set_hints If not null, set window-hints + */ +typedef void (*PuglResizeFunc)(PuglView* view, int *width, int *height, int *set_hints); + /** A function called on scrolling (e.g. mouse wheel or track pad). @@ -190,12 +273,6 @@ puglInitUserResizable(PuglView* view, bool resizable); PUGL_API void puglInitTransientFor(PuglView* view, uintptr_t parent); -/** - Set the context type before creating a window. -*/ -PUGL_API void -puglInitContextType(PuglView* view, PuglContextType type); - /** @} */ @@ -215,13 +292,31 @@ PUGL_API int puglCreateWindow(PuglView* view, const char* title); /** - Show the current window. + Create a new GL window. + @param parent Parent window, or 0 for top level. + @param title Window title, or NULL. + @param width Window width in pixels. + @param height Window height in pixels. + @param resizable Whether window should be user resizable. +*/ +PUGL_API PuglView* +puglCreate(PuglNativeWindow parent, + const char* title, + int min_width, + int min_height, + int width, + int height, + bool resizable, + unsigned long transientId); + +/** + Show Window (external ui) */ PUGL_API void puglShowWindow(PuglView* view); /** - Hide the current window. + Hide Window (external ui) */ PUGL_API void puglHideWindow(PuglView* view); @@ -254,15 +349,6 @@ puglSetHandle(PuglView* view, PuglHandle handle); PUGL_API PuglHandle puglGetHandle(PuglView* view); -/** - Get the drawing context. - - For PUGL_GL contexts, this is unused and returns NULL. - For PUGL_CAIRO contexts, this returns a pointer to a cairo_t. -*/ -PUGL_API void* -puglGetContext(PuglView* view); - /** Return the timestamp (if any) of the currently-processing event. */ @@ -337,6 +423,12 @@ puglSetSpecialFunc(PuglView* view, PuglSpecialFunc specialFunc); PUGL_API void puglSetReshapeFunc(PuglView* view, PuglReshapeFunc reshapeFunc); +/** + Set callback function to change window size. +*/ +PUGL_API void +puglSetResizeFunc(PuglView* view, PuglResizeFunc resizeFunc); + /** Set the function to call on file-browser selections. */ @@ -347,6 +439,12 @@ puglSetFileSelectedFunc(PuglView* view, PuglFileSelectedFunc fileSelectedFunc); @} */ +/** + TODO document this. + */ +PUGL_API int +puglUpdateGeometryConstraints(PuglView* view, int min_width, int min_height, bool aspect); + /** Grab the input focus. */ @@ -368,6 +466,12 @@ puglProcessEvents(PuglView* view); PUGL_API void puglPostRedisplay(PuglView* view); +/** + Request a resize on the next call to puglProcessEvents(). +*/ +PUGL_API void +puglPostResize(PuglView* view); + /** Destroy a GL window. */ diff --git a/dpf/dgl/src/pugl/pugl_internal.h b/dpf/dgl/src/pugl/pugl_internal.h index 3ca59ca..fa52df4 100644 --- a/dpf/dgl/src/pugl/pugl_internal.h +++ b/dpf/dgl/src/pugl/pugl_internal.h @@ -20,27 +20,9 @@ Note this file contains function definitions, so it must be compiled into the final binary exactly once. Each platform specific implementation file including it once should achieve this. - - If you are copying the pugl code into your source tree, the following - symbols can be defined to tweak pugl behaviour: - - PUGL_HAVE_CAIRO: Include Cairo support code. - PUGL_HAVE_GL: Include OpenGL support code. - PUGL_GRAB_FOCUS: Work around reparent keyboard issues by grabbing focus. - PUGL_VERBOSE: Print GL information to console. */ -#include "pugl/pugl.h" -#include "pugl/event.h" - -#ifdef PUGL_VERBOSE -# include -# define PUGL_LOG(str) fprintf(stderr, "pugl: " str) -# define PUGL_LOGF(fmt, ...) fprintf(stderr, "pugl: " fmt, __VA_ARGS__) -#else -# define PUGL_LOG(str) -# define PUGL_LOGF(fmt, ...) -#endif +#include "pugl.h" typedef struct PuglInternalsImpl PuglInternals; @@ -52,14 +34,13 @@ struct PuglViewImpl { PuglMotionFunc motionFunc; PuglMouseFunc mouseFunc; PuglReshapeFunc reshapeFunc; + PuglResizeFunc resizeFunc; PuglScrollFunc scrollFunc; PuglSpecialFunc specialFunc; PuglFileSelectedFunc fileSelectedFunc; - PuglInternals* impl; - + PuglInternals* impl; PuglNativeWindow parent; - PuglContextType ctx_type; uintptr_t transient_parent; int width; @@ -70,7 +51,8 @@ struct PuglViewImpl { bool mouse_in_view; bool ignoreKeyRepeat; bool redisplay; - bool resizable; + bool user_resizable; + bool pending_resize; uint32_t event_timestamp_ms; }; @@ -120,7 +102,7 @@ puglInitWindowParent(PuglView* view, PuglNativeWindow parent) void puglInitUserResizable(PuglView* view, bool resizable) { - view->resizable = resizable; + view->user_resizable = resizable; } void @@ -129,10 +111,33 @@ puglInitTransientFor(PuglView* view, uintptr_t parent) view->transient_parent = parent; } -void -puglInitContextType(PuglView* view, PuglContextType type) +PuglView* +puglCreate(PuglNativeWindow parent, + const char* title, + int min_width, + int min_height, + int width, + int height, + bool resizable, + unsigned long transientId) { - view->ctx_type = type; + PuglView* view = puglInit(); + if (!view) { + return NULL; + } + + puglInitWindowParent(view, parent); + puglInitWindowMinSize(view, min_width, min_height); + puglInitWindowSize(view, width, height); + puglInitUserResizable(view, resizable); + puglInitTransientFor(view, transientId); + + if (!puglCreateWindow(view, title)) { + free(view); + return NULL; + } + + return view; } void @@ -201,6 +206,12 @@ puglSetReshapeFunc(PuglView* view, PuglReshapeFunc reshapeFunc) view->reshapeFunc = reshapeFunc; } +void +puglSetResizeFunc(PuglView* view, PuglResizeFunc resizeFunc) +{ + view->resizeFunc = resizeFunc; +} + void puglSetScrollFunc(PuglView* view, PuglScrollFunc scrollFunc) { @@ -225,45 +236,19 @@ puglEnterContext(PuglView* view); void puglLeaveContext(PuglView* view, bool flush); -#if 0 -/** Return the code point for buf, or the replacement character on error. */ -static uint32_t -puglDecodeUTF8(const uint8_t* buf) -{ -#define FAIL_IF(cond) { if (cond) return 0xFFFD; } - - /* http://en.wikipedia.org/wiki/UTF-8 */ - - if (buf[0] < 0x80) { - return buf[0]; - } else if (buf[0] < 0xC2) { - return 0xFFFD; - } else if (buf[0] < 0xE0) { - FAIL_IF((buf[1] & 0xC0) != 0x80); - return (buf[0] << 6) + buf[1] - 0x3080; - } else if (buf[0] < 0xF0) { - FAIL_IF((buf[1] & 0xC0) != 0x80); - FAIL_IF(buf[0] == 0xE0 && buf[1] < 0xA0); - FAIL_IF((buf[2] & 0xC0) != 0x80); - return (buf[0] << 12) + (buf[1] << 6) + buf[2] - 0xE2080; - } else if (buf[0] < 0xF5) { - FAIL_IF((buf[1] & 0xC0) != 0x80); - FAIL_IF(buf[0] == 0xF0 && buf[1] < 0x90); - FAIL_IF(buf[0] == 0xF4 && buf[1] >= 0x90); - FAIL_IF((buf[2] & 0xC0) != 0x80); - FAIL_IF((buf[3] & 0xC0) != 0x80); - return ((buf[0] << 18) + - (buf[1] << 12) + - (buf[2] << 6) + - buf[3] - 0x3C82080); - } - return 0xFFFD; -} -#endif - static void -puglDefaultReshape(PuglView* view, int width, int height) +puglDefaultReshape(int width, int height) { +#ifdef ROBTK_HERE + glViewport(0, 0, width, height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); +#else glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, width, height, 0, 0, 1); @@ -271,82 +256,5 @@ puglDefaultReshape(PuglView* view, int width, int height) glMatrixMode(GL_MODELVIEW); glLoadIdentity(); - return; - - // unused - (void)view; -} - -#if 0 -static void -puglDispatchEvent(PuglView* view, const PuglEvent* event) -{ - if (view->eventFunc) { - view->eventFunc(view, event); - } - - switch (event->type) { - case PUGL_CONFIGURE: - puglEnterContext(view); - view->width = event->configure.width; - view->height = event->configure.height; - if (view->reshapeFunc) { - view->reshapeFunc(view, view->width, view->height); - } - puglLeaveContext(view, false); - break; - case PUGL_EXPOSE: - if (event->expose.count == 0) { - puglEnterContext(view); - if (view->displayFunc) { - view->displayFunc(view); - } - view->redisplay = false; - puglLeaveContext(view, true); - } - break; - case PUGL_MOTION_NOTIFY: - view->event_timestamp_ms = event->motion.time; - view->mods = event->motion.state; - if (view->motionFunc) { - view->motionFunc(view, event->motion.x, event->motion.y); - } - break; - case PUGL_SCROLL: - if (view->scrollFunc) { - view->scrollFunc(view, - event->scroll.x, event->scroll.y, - event->scroll.dx, event->scroll.dy); - } - break; - case PUGL_BUTTON_PRESS: - case PUGL_BUTTON_RELEASE: - view->event_timestamp_ms = event->button.time; - view->mods = event->button.state; - if (view->mouseFunc) { - view->mouseFunc(view, - event->button.button, - event->type == PUGL_BUTTON_PRESS, - event->button.x, - event->button.y); - } - break; - case PUGL_KEY_PRESS: - case PUGL_KEY_RELEASE: - view->event_timestamp_ms = event->key.time; - view->mods = event->key.state; - if (event->key.special && view->specialFunc) { - view->specialFunc(view, - event->type == PUGL_KEY_PRESS, - event->key.special); - } else if (event->key.character && view->keyboardFunc) { - view->keyboardFunc(view, - event->type == PUGL_KEY_PRESS, - event->key.character); - } - break; - default: - break; - } -} #endif +} diff --git a/dpf/dgl/src/pugl/pugl_osx.m b/dpf/dgl/src/pugl/pugl_osx.m index 02c6301..738103f 100644 --- a/dpf/dgl/src/pugl/pugl_osx.m +++ b/dpf/dgl/src/pugl/pugl_osx.m @@ -218,7 +218,7 @@ puglDisplay(PuglView* view) if (puglview->reshapeFunc) { puglview->reshapeFunc(puglview, width, height); } else { - puglDefaultReshape(puglview, width, height); + puglDefaultReshape(width, height); } puglLeaveContext(puglview, false); @@ -427,18 +427,13 @@ puglInitInternals() void puglEnterContext(PuglView* view) { -#ifdef PUGL_HAVE_GL - if (view->ctx_type == PUGL_GL) { - [[view->impl->glview openGLContext] makeCurrentContext]; - } -#endif + [[view->impl->glview openGLContext] makeCurrentContext]; } void puglLeaveContext(PuglView* view, bool flush) { -#ifdef PUGL_HAVE_GL - if (view->ctx_type == PUGL_GL && flush) { + if (flush) { if (view->impl->glview->doubleBuffered) { [[view->impl->glview openGLContext] flushBuffer]; } else { @@ -446,7 +441,6 @@ puglLeaveContext(PuglView* view, bool flush) } //[NSOpenGLContext clearCurrentContext]; } -#endif } int @@ -465,7 +459,7 @@ puglCreateWindow(PuglView* view, const char* title) impl->glview->puglview = view; - if (view->resizable) { + if (view->user_resizable) { [impl->glview setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable]; } @@ -566,11 +560,14 @@ puglGetNativeWindow(PuglView* view) return (PuglNativeWindow)view->impl->glview; } -void* -puglGetContext(PuglView* view) +int +puglUpdateGeometryConstraints(PuglView* view, int min_width, int min_height, bool aspect) { - return NULL; + // TODO + return 1; - // unused (void)view; + (void)min_width; + (void)min_height; + (void)aspect; } diff --git a/dpf/dgl/src/pugl/pugl_win.cpp b/dpf/dgl/src/pugl/pugl_win.cpp index c87af85..9990b8e 100644 --- a/dpf/dgl/src/pugl/pugl_win.cpp +++ b/dpf/dgl/src/pugl/pugl_win.cpp @@ -76,25 +76,17 @@ puglInitInternals() void puglEnterContext(PuglView* view) { -#ifdef PUGL_HAVE_GL - if (view->ctx_type == PUGL_GL) { - wglMakeCurrent(view->impl->hdc, view->impl->hglrc); - } -#endif + wglMakeCurrent(view->impl->hdc, view->impl->hglrc); } void puglLeaveContext(PuglView* view, bool flush) { -#ifdef PUGL_HAVE_GL - if (view->ctx_type == PUGL_GL) { - if (flush) { - glFlush(); - SwapBuffers(view->impl->hdc); - } - wglMakeCurrent(NULL, NULL); + if (flush) { + glFlush(); + SwapBuffers(view->impl->hdc); } -#endif + wglMakeCurrent(NULL, NULL); } int @@ -137,7 +129,7 @@ puglCreateWindow(PuglView* view, const char* title) } int winFlags = WS_POPUPWINDOW | WS_CAPTION; - if (view->resizable) { + if (view->user_resizable) { winFlags |= WS_SIZEBOX; if (view->min_width > 0 && view->min_height > 0) { // Adjust the minimum window size to accomodate requested view size @@ -231,7 +223,7 @@ puglReshape(PuglView* view, int width, int height) if (view->reshapeFunc) { view->reshapeFunc(view, width, height); } else { - puglDefaultReshape(view, width, height); + puglDefaultReshape(width, height); } view->width = width; @@ -477,13 +469,14 @@ puglGetNativeWindow(PuglView* view) return (PuglNativeWindow)view->impl->hwnd; } -void* -puglGetContext(PuglView* /*view*/) +int +puglUpdateGeometryConstraints(PuglView* view, int min_width, int min_height, bool aspect) { -#ifdef PUGL_HAVE_CAIRO - if (view->ctx_type == PUGL_CAIRO) { - // TODO - } -#endif - return NULL; + // TODO + return 1; + + (void)view; + (void)min_width; + (void)min_height; + (void)aspect; } diff --git a/dpf/dgl/src/pugl/pugl_x11.c b/dpf/dgl/src/pugl/pugl_x11.c index 2243248..ea70db1 100644 --- a/dpf/dgl/src/pugl/pugl_x11.c +++ b/dpf/dgl/src/pugl/pugl_x11.c @@ -1,7 +1,7 @@ /* Copyright 2012-2014 David Robillard - Copyright 2013 Robin Gareus Copyright 2011-2012 Ben Loftis, Harrison Consoles + Copyright 2013,2015 Robin Gareus 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,22 +24,14 @@ #include #include +#include +#include #include #include #include #include -#ifdef PUGL_HAVE_GL -#include -#include -#endif - -#ifdef PUGL_HAVE_CAIRO -#include -#include -#endif - -#include "pugl/pugl_internal.h" +#include "pugl_internal.h" #ifndef DGL_FILE_BROWSER_DISABLED #define SOFD_HAVE_X11 @@ -47,212 +39,145 @@ #include "../sofd/libsofd.c" #endif +/* work around buggy re-parent & focus issues on some systems + * where no keyboard events are passed through even if the + * app has mouse-focus and all other events are working. + */ +//#define PUGL_GRAB_FOCUS + +/* show messages during initalization + */ +//#define PUGL_VERBOSE + struct PuglInternalsImpl { Display* display; int screen; Window win; - XIM xim; - XIC xic; -#ifdef PUGL_HAVE_CAIRO - cairo_t* cr; - cairo_surface_t* surface; -#endif -#ifdef PUGL_HAVE_GL GLXContext ctx; Bool doubleBuffered; -#endif }; -PuglInternals* -puglInitInternals(void) -{ - return (PuglInternals*)calloc(1, sizeof(PuglInternals)); -} - -static XVisualInfo* -getVisual(PuglView* view) -{ - PuglInternals* const impl = view->impl; - XVisualInfo* vi = NULL; - -#ifdef PUGL_HAVE_GL - if (view->ctx_type == PUGL_GL) { - /** - Attributes for single-buffered RGBA with at least - 4 bits per color and a 16 bit depth buffer. - */ - int attrListSgl[] = { - GLX_RGBA, - GLX_RED_SIZE, 4, - GLX_GREEN_SIZE, 4, - GLX_BLUE_SIZE, 4, - GLX_DEPTH_SIZE, 16, - GLX_ARB_multisample, 1, - None - }; - - /** - Attributes for double-buffered RGBA with at least - 4 bits per color and a 16 bit depth buffer. - */ - int attrListDbl[] = { - GLX_RGBA, - GLX_DOUBLEBUFFER, - GLX_RED_SIZE, 4, - GLX_GREEN_SIZE, 4, - GLX_BLUE_SIZE, 4, - GLX_DEPTH_SIZE, 16, - GLX_ARB_multisample, 1, - None - }; - - /** - Attributes for double-buffered RGBA with multi-sampling - (antialiasing) - */ - int attrListDblMS[] = { - GLX_RGBA, - GLX_DOUBLEBUFFER, - GLX_RED_SIZE, 4, - GLX_GREEN_SIZE, 4, - GLX_BLUE_SIZE, 4, - GLX_ALPHA_SIZE, 4, - GLX_DEPTH_SIZE, 16, - GLX_SAMPLE_BUFFERS, 1, - GLX_SAMPLES, 4, - None - }; - - impl->doubleBuffered = True; - - vi = glXChooseVisual(impl->display, impl->screen, attrListDblMS); - - if (vi == NULL) { - vi = glXChooseVisual(impl->display, impl->screen, attrListDbl); - PUGL_LOG("multisampling (antialiasing) is not available\n"); - } - - if (vi == NULL) { - vi = glXChooseVisual(impl->display, impl->screen, attrListSgl); - impl->doubleBuffered = False; - PUGL_LOG("singlebuffered rendering will be used, no doublebuffering available\n"); - } - } -#endif -#ifdef PUGL_HAVE_CAIRO - if (view->ctx_type == PUGL_CAIRO) { - XVisualInfo pat; - int n; - pat.screen = impl->screen; - vi = XGetVisualInfo(impl->display, VisualScreenMask, &pat, &n); - } -#endif - - return vi; -} - -static bool -createContext(PuglView* view, XVisualInfo* vi) -{ - PuglInternals* const impl = view->impl; +/** + Attributes for single-buffered RGBA with at least + 4 bits per color and a 16 bit depth buffer. +*/ +static int attrListSgl[] = { + GLX_RGBA, + GLX_RED_SIZE, 4, + GLX_GREEN_SIZE, 4, + GLX_BLUE_SIZE, 4, + GLX_DEPTH_SIZE, 16, + GLX_ARB_multisample, 1, + None +}; -#ifdef PUGL_HAVE_GL - if (view->ctx_type == PUGL_GL) { - impl->ctx = glXCreateContext(impl->display, vi, 0, GL_TRUE); - return (impl->ctx != NULL); - } -#endif -#ifdef PUGL_HAVE_CAIRO - if (view->ctx_type == PUGL_CAIRO) { - impl->surface = cairo_xlib_surface_create( - impl->display, impl->win, vi->visual, view->width, view->height); - if (impl->surface == NULL) { - PUGL_LOG("failed to create cairo surface\n"); - return false; - } - impl->cr = cairo_create(impl->surface); - if (impl->cr == NULL) { - cairo_surface_destroy(impl->surface); - impl->surface = NULL; - PUGL_LOG("failed to create cairo context\n"); - return false; - } - return true; - } -#endif +/** + Attributes for double-buffered RGBA with at least + 4 bits per color and a 16 bit depth buffer. +*/ +static int attrListDbl[] = { + GLX_RGBA, + GLX_DOUBLEBUFFER, True, + GLX_RED_SIZE, 4, + GLX_GREEN_SIZE, 4, + GLX_BLUE_SIZE, 4, + GLX_DEPTH_SIZE, 16, + GLX_ARB_multisample, 1, + None +}; - return false; -} +/** + Attributes for double-buffered RGBA with multi-sampling + (antialiasing) +*/ +static int attrListDblMS[] = { + GLX_RGBA, + GLX_DOUBLEBUFFER, True, + GLX_RED_SIZE, 4, + GLX_GREEN_SIZE, 4, + GLX_BLUE_SIZE, 4, + GLX_ALPHA_SIZE, 4, + GLX_DEPTH_SIZE, 16, + GLX_SAMPLE_BUFFERS, 1, + GLX_SAMPLES, 4, + None +}; -static void -destroyContext(PuglView* view) +PuglInternals* +puglInitInternals(void) { - PuglInternals* const impl = view->impl; - -#ifdef PUGL_HAVE_GL - if (view->ctx_type == PUGL_GL) { - glXDestroyContext(impl->display, impl->ctx); - impl->ctx = NULL; - } -#endif -#ifdef PUGL_HAVE_CAIRO - if (view->ctx_type == PUGL_CAIRO) { - cairo_destroy(impl->cr); - impl->cr = NULL; - - cairo_surface_destroy(impl->surface); - impl->surface = NULL; - } -#endif + return (PuglInternals*)calloc(1, sizeof(PuglInternals)); } void puglEnterContext(PuglView* view) { -#ifdef PUGL_HAVE_GL - if (view->ctx_type == PUGL_GL) { - glXMakeCurrent(view->impl->display, view->impl->win, view->impl->ctx); - } -#endif + glXMakeCurrent(view->impl->display, view->impl->win, view->impl->ctx); } void puglLeaveContext(PuglView* view, bool flush) { -#ifdef PUGL_HAVE_GL - if (view->ctx_type == PUGL_GL) { - if (flush) { - glFlush(); - if (view->impl->doubleBuffered) { - glXSwapBuffers(view->impl->display, view->impl->win); - } + if (flush) { + glFlush(); + if (view->impl->doubleBuffered) { + glXSwapBuffers(view->impl->display, view->impl->win); } - glXMakeCurrent(view->impl->display, None, NULL); } -#endif + glXMakeCurrent(view->impl->display, None, NULL); } int puglCreateWindow(PuglView* view, const char* title) { - PuglInternals* const impl = view->impl; + PuglInternals* impl = (PuglInternals*)calloc(1, sizeof(PuglInternals)); + if (!impl) { + return 1; + } + view->impl = impl; impl->display = XOpenDisplay(NULL); - impl->screen = DefaultScreen(impl->display); + if (!impl->display) { + free(impl); + return 1; + } + impl->screen = DefaultScreen(impl->display); + impl->doubleBuffered = True; + + XVisualInfo* vi = glXChooseVisual(impl->display, impl->screen, attrListDblMS); + + if (!vi) { + vi = glXChooseVisual(impl->display, impl->screen, attrListDbl); +#ifdef PUGL_VERBOSE + printf("puGL: multisampling (antialiasing) is not available\n"); +#endif + } + + if (!vi) { + vi = glXChooseVisual(impl->display, impl->screen, attrListSgl); + impl->doubleBuffered = False; + } - XVisualInfo* const vi = getVisual(view); if (!vi) { XCloseDisplay(impl->display); - impl->display = NULL; + free(impl); return 1; } -#ifdef PUGL_HAVE_GL +#ifdef PUGL_VERBOSE int glxMajor, glxMinor; glXQueryVersion(impl->display, &glxMajor, &glxMinor); - PUGL_LOGF("GLX Version %d.%d\n", glxMajor, glxMinor); + printf("puGL: GLX-Version : %d.%d\n", glxMajor, glxMinor); #endif + impl->ctx = glXCreateContext(impl->display, vi, 0, GL_TRUE); + + if (!impl->ctx) { + XCloseDisplay(impl->display); + free(impl); + return 1; + } + Window xParent = view->parent ? (Window)view->parent : RootWindow(impl->display, impl->screen); @@ -262,76 +187,55 @@ puglCreateWindow(PuglView* view, const char* title) XSetWindowAttributes attr; memset(&attr, 0, sizeof(XSetWindowAttributes)); - attr.background_pixel = BlackPixel(impl->display, impl->screen); - attr.border_pixel = BlackPixel(impl->display, impl->screen); - attr.colormap = cmap; - attr.event_mask = (ExposureMask | StructureNotifyMask | - EnterWindowMask | LeaveWindowMask | - KeyPressMask | KeyReleaseMask | - ButtonPressMask | ButtonReleaseMask | - PointerMotionMask | FocusChangeMask); + attr.border_pixel = BlackPixel(impl->display, impl->screen); + attr.colormap = cmap; + attr.event_mask = (ExposureMask | StructureNotifyMask | + EnterWindowMask | LeaveWindowMask | + KeyPressMask | KeyReleaseMask | + ButtonPressMask | ButtonReleaseMask | + PointerMotionMask | FocusChangeMask); impl->win = XCreateWindow( impl->display, xParent, 0, 0, view->width, view->height, 0, vi->depth, InputOutput, vi->visual, - CWBackPixel | CWBorderPixel | CWColormap | CWEventMask, &attr); - - if (!createContext(view, vi)) { - XDestroyWindow(impl->display, impl->win); - impl->win = 0; + CWBorderPixel | CWColormap | CWEventMask, &attr); + if (!impl->win) { XCloseDisplay(impl->display); - impl->display = NULL; - + free(impl); return 1; } - XSizeHints sizeHints; - memset(&sizeHints, 0, sizeof(sizeHints)); - if (!view->resizable) { - sizeHints.flags = PMinSize|PMaxSize; - sizeHints.min_width = view->width; - sizeHints.min_height = view->height; - sizeHints.max_width = view->width; - sizeHints.max_height = view->height; - XSetNormalHints(impl->display, impl->win, &sizeHints); - } else if (view->min_width > 0 && view->min_height > 0) { - sizeHints.flags = PMinSize; - sizeHints.min_width = view->min_width; - sizeHints.min_height = view->min_height; - XSetNormalHints(impl->display, impl->win, &sizeHints); + 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); } if (title) { XStoreName(impl->display, impl->win, title); } - if (!view->parent) { + if (view->transient_parent > 0) { + XSetTransientForHint(impl->display, impl->win, (Window)view->transient_parent); + } + + if (view->parent) { + XMapRaised(impl->display, impl->win); + } else { Atom wmDelete = XInternAtom(impl->display, "WM_DELETE_WINDOW", True); XSetWMProtocols(impl->display, impl->win, &wmDelete, 1); } +#ifdef PUGL_VERBOSE if (glXIsDirect(impl->display, impl->ctx)) { - PUGL_LOG("DRI enabled (to disable, set LIBGL_ALWAYS_INDIRECT=1\n"); + printf("puGL: DRI enabled (to disable, set LIBGL_ALWAYS_INDIRECT=1\n"); } else { - PUGL_LOG("No DRI available\n"); + printf("puGL: No DRI available\n"); } +#endif XFree(vi); - - return PUGL_SUCCESS; -} - -void -puglShowWindow(PuglView* view) -{ - XMapRaised(view->impl->display, view->impl->win); -} - -void -puglHideWindow(PuglView* view) -{ - XUnmapWindow(view->impl->display, view->impl->win); + return 0; } void @@ -340,18 +244,29 @@ puglDestroy(PuglView* view) if (!view) { return; } - #ifndef DGL_FILE_BROWSER_DISABLED x_fib_close(view->impl->display); #endif - destroyContext(view); + glXDestroyContext(view->impl->display, view->impl->ctx); XDestroyWindow(view->impl->display, view->impl->win); XCloseDisplay(view->impl->display); free(view->impl); free(view); } +void +puglShowWindow(PuglView* view) +{ + XMapRaised(view->impl->display, view->impl->win); +} + +void +puglHideWindow(PuglView* view) +{ + XUnmapWindow(view->impl->display, view->impl->win); +} + static void puglReshape(PuglView* view, int width, int height) { @@ -360,7 +275,7 @@ puglReshape(PuglView* view, int width, int height) if (view->reshapeFunc) { view->reshapeFunc(view, width, height); } else { - puglDefaultReshape(view, width, height); + puglDefaultReshape(width, height); } puglLeaveContext(view, false); @@ -375,7 +290,6 @@ puglDisplay(PuglView* view) puglEnterContext(view); view->redisplay = false; - if (view->displayFunc) { view->displayFunc(view); } @@ -383,6 +297,36 @@ puglDisplay(PuglView* view) puglLeaveContext(view, true); } +static void +puglResize(PuglView* view) +{ + int set_hints = 1; + view->pending_resize = false; + if (!view->resizeFunc) { return; } + /* ask the plugin about the new size */ + view->resizeFunc(view, &view->width, &view->height, &set_hints); + + if (set_hints) { + XSizeHints sizeHints; + memset(&sizeHints, 0, sizeof(sizeHints)); + sizeHints.flags = PMinSize|PMaxSize; + sizeHints.min_width = view->width; + sizeHints.min_height = view->height; + sizeHints.max_width = view->user_resizable ? 4096 : view->width; + sizeHints.max_height = view->user_resizable ? 4096 : view->height; + XSetWMNormalHints(view->impl->display, view->impl->win, &sizeHints); + } + XResizeWindow(view->impl->display, view->impl->win, view->width, view->height); + XFlush(view->impl->display); + +#ifdef PUGL_VERBOSE + printf("puGL: window resize (%dx%d)\n", view->width, view->height); +#endif + + /* and call Reshape in glX context */ + puglReshape(view, view->width, view->height); +} + static PuglKey keySymToSpecial(KeySym sym) { @@ -477,6 +421,9 @@ send_event: PuglStatus puglProcessEvents(PuglView* view) { + int conf_width = -1; + int conf_height = -1; + XEvent event; while (XPending(view->impl->display) > 0) { XNextEvent(view->impl->display, &event); @@ -511,22 +458,26 @@ puglProcessEvents(PuglView* view) } switch (event.type) { + case UnmapNotify: + if (view->motionFunc) { + view->motionFunc(view, -1, -1); + } + break; case MapNotify: puglReshape(view, view->width, view->height); break; case ConfigureNotify: if ((event.xconfigure.width != view->width) || (event.xconfigure.height != view->height)) { - puglReshape(view, - event.xconfigure.width, - event.xconfigure.height); + conf_width = event.xconfigure.width; + conf_height = event.xconfigure.height; } break; case Expose: if (event.xexpose.count != 0) { break; } - puglDisplay(view); + view->redisplay = true; break; case MotionNotify: setModifiers(view, event.xmotion.state, event.xmotion.time); @@ -602,6 +553,14 @@ puglProcessEvents(PuglView* view) } } + if (conf_width != -1) { + puglReshape(view, conf_width, conf_height); + } + + if (view->pending_resize) { + puglResize(view); + } + if (view->redisplay) { puglDisplay(view); } @@ -615,22 +574,35 @@ puglPostRedisplay(PuglView* view) view->redisplay = true; } +void +puglPostResize(PuglView* view) +{ + view->pending_resize = true; +} + PuglNativeWindow puglGetNativeWindow(PuglView* view) { return view->impl->win; } -void* -puglGetContext(PuglView* view) +int +puglUpdateGeometryConstraints(PuglView* view, int min_width, int min_height, bool aspect) { -#ifdef PUGL_HAVE_CAIRO - if (view->ctx_type == PUGL_CAIRO) { - return view->impl->cr; + XSizeHints sizeHints; + memset(&sizeHints, 0, sizeof(sizeHints)); + sizeHints.flags = PMinSize|PMaxSize; + sizeHints.min_width = min_width; + sizeHints.min_height = min_height; + sizeHints.max_width = view->user_resizable ? 4096 : min_width; + sizeHints.max_height = view->user_resizable ? 4096 : min_height; + if (aspect) { + sizeHints.flags |= PAspect; + sizeHints.min_aspect.x = min_width; + sizeHints.min_aspect.y = min_height; + sizeHints.max_aspect.x = min_width; + sizeHints.max_aspect.y = min_height; } -#endif - return NULL; - - // may be unused - (void)view; + XSetWMNormalHints(view->impl->display, view->impl->win, &sizeHints); + return 0; } diff --git a/dpf/distrho/DistrhoPlugin.hpp b/dpf/distrho/DistrhoPlugin.hpp index 2fb9ec6..1da2bdb 100644 --- a/dpf/distrho/DistrhoPlugin.hpp +++ b/dpf/distrho/DistrhoPlugin.hpp @@ -546,7 +546,7 @@ struct TimePosition { /** Current tick within beat.@n - Should always be > 0 and <= @a ticksPerBeat.@n + Should always be >= 0 and < @a ticksPerBeat.@n The first tick is tick '0'. */ int32_t tick; @@ -567,7 +567,7 @@ struct TimePosition { float beatType; /** - Number of ticks within a bar.@n + Number of ticks within a beat.@n Usually a moderately large integer with many denominators, such as 1920.0. */ double ticksPerBeat; @@ -590,6 +590,22 @@ struct TimePosition { beatType(0.0f), ticksPerBeat(0.0), beatsPerMinute(0.0) {} + + /** + Reinitialize this position using the default null initialization. + */ + void clear() noexcept + { + valid = false; + bar = 0; + beat = 0; + tick = 0; + barStartTick = 0.0; + beatsPerBar = 0.0f; + beatType = 0.0f; + ticksPerBeat = 0.0; + beatsPerMinute = 0.0; + } } bbt; /** @@ -599,6 +615,16 @@ struct TimePosition { : playing(false), frame(0), bbt() {} + + /** + Reinitialize this position using the default null initialization. + */ + void clear() noexcept + { + playing = false; + frame = 0; + bbt.clear(); + } }; /** @} */ diff --git a/dpf/distrho/DistrhoUI.hpp b/dpf/distrho/DistrhoUI.hpp index a4ec9e6..244b25b 100644 --- a/dpf/distrho/DistrhoUI.hpp +++ b/dpf/distrho/DistrhoUI.hpp @@ -1,6 +1,6 @@ /* * DISTRHO Plugin Framework (DPF) - * Copyright (C) 2012-2016 Filipe Coelho + * Copyright (C) 2012-2018 Filipe Coelho * * 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 @@ -20,7 +20,8 @@ #include "extra/LeakDetector.hpp" #include "src/DistrhoPluginChecks.h" -#ifndef HAVE_DGL +#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI +# include "../dgl/Base.hpp" # include "extra/ExternalWindow.hpp" typedef DISTRHO_NAMESPACE::ExternalWindow UIWidget; #elif DISTRHO_UI_USE_NANOVG @@ -54,13 +55,28 @@ public: UI class constructor. The UI should be initialized to a default state that matches the plugin side. */ - UI(uint width = 0, uint height = 0); + UI(uint width = 0, uint height = 0, bool userResizable = false); /** Destructor. */ virtual ~UI(); + /** + Wherever this UI is resizable by the user. + This simply returns the value passed in the constructor. + */ + bool isUserResizable() const noexcept; + +#if !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) + @see Window::setScaling(double) + */ + void setGeometryConstraints(uint minWidth, uint minHeight, bool keepAspectRatio, bool automaticallyScale = false); +#endif + /* -------------------------------------------------------------------------------------------------------- * Host state */ @@ -166,7 +182,7 @@ protected: */ virtual void sampleRateChanged(double newSampleRate); -#ifdef HAVE_DGL +#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI /* -------------------------------------------------------------------------------------------------------- * UI Callbacks (optional) */ @@ -176,13 +192,13 @@ protected: */ virtual void uiIdle() {} -#ifndef DGL_FILE_BROWSER_DISABLED +# ifndef DGL_FILE_BROWSER_DISABLED /** File browser selected function. @see Window::fileBrowserSelected(const char*) */ virtual void uiFileBrowserSelected(const char* filename); -#endif +# endif /** OpenGL window reshape function, called when parent window is resized. @@ -210,7 +226,7 @@ private: friend class UIExporter; friend class UIExporterWindow; -#ifdef HAVE_DGL +#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI // these should not be used void setAbsoluteX(int) const noexcept {} void setAbsoluteY(int) const noexcept {} diff --git a/dpf/distrho/extra/ExternalWindow.hpp b/dpf/distrho/extra/ExternalWindow.hpp index 8ad2df0..c39f55c 100644 --- a/dpf/distrho/extra/ExternalWindow.hpp +++ b/dpf/distrho/extra/ExternalWindow.hpp @@ -40,6 +40,8 @@ public: : width(w), height(h), title(t), + transientWinId(0), + visible(false), pid(0) {} virtual ~ExternalWindow() @@ -62,9 +64,14 @@ public: return title; } - void setTitle(const char* const t) noexcept + uintptr_t getTransientWinId() const noexcept { - title = t; + return transientWinId; + } + + bool isVisible() const noexcept + { + return visible; } bool isRunning() noexcept @@ -84,6 +91,27 @@ public: return true; } + virtual void setSize(uint w, uint h) + { + width = w; + height = h; + } + + virtual void setTitle(const char* const t) + { + title = t; + } + + virtual void setTransientWinId(const uintptr_t winId) + { + transientWinId = winId; + } + + virtual void setVisible(const bool yesNo) + { + visible = yesNo; + } + protected: bool startExternalProcess(const char* args[]) { @@ -107,14 +135,6 @@ protected: } } -private: - uint width; - uint height; - String title; - pid_t pid; - - friend class UIExporter; - void terminateAndWaitForProcess() { if (pid <= 0) @@ -162,6 +182,16 @@ private: } } +private: + uint width; + uint height; + String title; + uintptr_t transientWinId; + bool visible; + pid_t pid; + + friend class UIExporter; + DISTRHO_DECLARE_NON_COPY_CLASS(ExternalWindow) }; diff --git a/dpf/distrho/src/DistrhoDefines.h b/dpf/distrho/src/DistrhoDefines.h index c14cfb8..f16e44d 100644 --- a/dpf/distrho/src/DistrhoDefines.h +++ b/dpf/distrho/src/DistrhoDefines.h @@ -66,6 +66,15 @@ # define nullptr NULL #endif +/* Define DISTRHO_DEPRECATED */ +#if defined(__GNUC__) +# define DISTRHO_DEPRECATED __attribute__((deprecated)) +#elif defined(_MSC_VER) +# define DISTRHO_DEPRECATED __declspec(deprecated) +#else +# define DISTRHO_DEPRECATED +#endif + /* Define DISTRHO_SAFE_ASSERT* */ #define DISTRHO_SAFE_ASSERT(cond) if (! (cond)) d_safe_assert(#cond, __FILE__, __LINE__); #define DISTRHO_SAFE_ASSERT_BREAK(cond) if (! (cond)) { d_safe_assert(#cond, __FILE__, __LINE__); break; } diff --git a/dpf/distrho/src/DistrhoPluginChecks.h b/dpf/distrho/src/DistrhoPluginChecks.h index a3690b0..24f25d8 100644 --- a/dpf/distrho/src/DistrhoPluginChecks.h +++ b/dpf/distrho/src/DistrhoPluginChecks.h @@ -126,7 +126,8 @@ // ----------------------------------------------------------------------- // Enable full state if plugin exports presets -#if DISTRHO_PLUGIN_WANT_PROGRAMS && DISTRHO_PLUGIN_WANT_STATE +#if DISTRHO_PLUGIN_WANT_PROGRAMS && DISTRHO_PLUGIN_WANT_STATE && ! DISTRHO_PLUGIN_WANT_FULL_STATE +# warning Plugins with programs and state need to implement full state API # undef DISTRHO_PLUGIN_WANT_FULL_STATE # define DISTRHO_PLUGIN_WANT_FULL_STATE 1 #endif diff --git a/dpf/distrho/src/DistrhoPluginJack.cpp b/dpf/distrho/src/DistrhoPluginJack.cpp index 98ce73c..edafaf6 100644 --- a/dpf/distrho/src/DistrhoPluginJack.cpp +++ b/dpf/distrho/src/DistrhoPluginJack.cpp @@ -16,11 +16,6 @@ #include "DistrhoPluginInternal.hpp" -#if DISTRHO_PLUGIN_HAS_UI && ! DISTRHO_PLUGIN_HAS_EMBED_UI -# undef DISTRHO_PLUGIN_HAS_UI -# define DISTRHO_PLUGIN_HAS_UI 0 -#endif - #if DISTRHO_PLUGIN_HAS_UI # include "DistrhoUIInternal.hpp" #else diff --git a/dpf/distrho/src/DistrhoPluginLADSPA+DSSI.cpp b/dpf/distrho/src/DistrhoPluginLADSPA+DSSI.cpp index 6f45dec..79dcf40 100644 --- a/dpf/distrho/src/DistrhoPluginLADSPA+DSSI.cpp +++ b/dpf/distrho/src/DistrhoPluginLADSPA+DSSI.cpp @@ -286,9 +286,9 @@ public: # if DISTRHO_PLUGIN_WANT_STATE char* dssi_configure(const char* const key, const char* const value) { - if (std::strncmp(key, DSSI_RESERVED_CONFIGURE_PREFIX, std::strlen(DSSI_RESERVED_CONFIGURE_PREFIX) == 0)) + if (std::strncmp(key, DSSI_RESERVED_CONFIGURE_PREFIX, std::strlen(DSSI_RESERVED_CONFIGURE_PREFIX)) == 0) return nullptr; - if (std::strncmp(key, DSSI_GLOBAL_CONFIGURE_PREFIX, std::strlen(DSSI_GLOBAL_CONFIGURE_PREFIX) == 0)) + if (std::strncmp(key, DSSI_GLOBAL_CONFIGURE_PREFIX, std::strlen(DSSI_GLOBAL_CONFIGURE_PREFIX)) == 0) return nullptr; fPlugin.setState(key, value); diff --git a/dpf/distrho/src/DistrhoPluginLV2.cpp b/dpf/distrho/src/DistrhoPluginLV2.cpp index 6eb8be9..e66ec1d 100644 --- a/dpf/distrho/src/DistrhoPluginLV2.cpp +++ b/dpf/distrho/src/DistrhoPluginLV2.cpp @@ -169,7 +169,7 @@ public: void lv2_activate() { #if DISTRHO_PLUGIN_WANT_TIMEPOS - std::memset(&fTimePosition, 0, sizeof(TimePosition)); + fTimePosition.clear(); // hosts may not send all values, resulting on some invalid data fTimePosition.bbt.bar = 1; @@ -613,7 +613,6 @@ public: fEventsOutData.initIfNeeded(fURIDs.atomSequence); LV2_Atom_Event* aev; - uint32_t offset = fEventsOutData.offset; const uint32_t capacity = fEventsOutData.capacity; for (uint32_t i=0, count=fPlugin.getStateCount(); i < count; ++i) @@ -635,8 +634,11 @@ public: // set msg size (key + value + separator + 2x null terminator) const size_t msgSize(key.length()+value.length()+3); - if (sizeof(LV2_Atom_Event) + msgSize > capacity - offset) + if (sizeof(LV2_Atom_Event) + msgSize > capacity - fEventsOutData.offset) + { + d_stdout("Sending key '%s' to UI failed, out of space", key.buffer()); break; + } // reserve msg space // FIXME create a large enough buffer beforehand @@ -644,15 +646,15 @@ public: std::memset(msgBuf, 0, msgSize); // write key and value in atom bufer - std::memcpy(msgBuf, key.buffer(), key.length()); - std::memcpy(msgBuf+(key.length()+1), value.buffer(), value.length()); + std::memcpy(msgBuf, key.buffer(), key.length()+1); + std::memcpy(msgBuf+(key.length()+1), value.buffer(), value.length()+1); // put data - aev = (LV2_Atom_Event*)(LV2_ATOM_CONTENTS(LV2_Atom_Sequence, fEventsOutData.port) + offset); + aev = (LV2_Atom_Event*)(LV2_ATOM_CONTENTS(LV2_Atom_Sequence, fEventsOutData.port) + fEventsOutData.offset); aev->time.frames = 0; aev->body.type = fURIDs.distrhoState; aev->body.size = msgSize; - std::memcpy(LV2_ATOM_BODY(&aev->body), msgBuf, msgSize-1); + std::memcpy(LV2_ATOM_BODY(&aev->body), msgBuf, msgSize); fEventsOutData.growBy(lv2_atom_pad_size(sizeof(LV2_Atom_Event) + msgSize)); diff --git a/dpf/distrho/src/DistrhoPluginLV2export.cpp b/dpf/distrho/src/DistrhoPluginLV2export.cpp index 6ed2f7c..9d2c7a7 100644 --- a/dpf/distrho/src/DistrhoPluginLV2export.cpp +++ b/dpf/distrho/src/DistrhoPluginLV2export.cpp @@ -139,6 +139,7 @@ void lv2_generate_ttl(const char* const basename) # endif manifestString += "\n"; # if DISTRHO_PLUGIN_HAS_EMBED_UI + // TODO: pluginUI.isUserResizable() manifestString += " lv2:optionalFeature ui:noUserResize ,\n"; manifestString += " ui:resize ,\n"; manifestString += " ui:touch ;\n"; @@ -148,9 +149,10 @@ void lv2_generate_ttl(const char* const basename) manifestString += " <" LV2_INSTANCE_ACCESS_URI "> ,\n"; manifestString += " <" LV2_OPTIONS__options "> ,\n"; manifestString += " <" LV2_URID__map "> .\n"; -# else + manifestString += " opts:supportedOption <" LV2_PARAMETERS__sampleRate "> .\n"; +# else // DISTRHO_PLUGIN_WANT_DIRECT_ACCESS manifestString += " rdfs:seeAlso <" + uiTTL + "> .\n"; -# endif +# endif // DISTRHO_PLUGIN_WANT_DIRECT_ACCESS manifestString += "\n"; #endif @@ -192,7 +194,7 @@ void lv2_generate_ttl(const char* const basename) String pluginString; // header -#if DISTRHO_LV2_USE_EVENTS_IN +#if DISTRHO_LV2_USE_EVENTS_IN || DISTRHO_LV2_USE_EVENTS_OUT pluginString += "@prefix atom: <" LV2_ATOM_PREFIX "> .\n"; #endif pluginString += "@prefix doap: .\n"; @@ -628,6 +630,7 @@ void lv2_generate_ttl(const char* const basename) # endif uiString += "\n"; # if DISTRHO_PLUGIN_HAS_EMBED_UI + // TODO: pluginUI.isUserResizable() uiString += " lv2:optionalFeature ui:noUserResize ,\n"; uiString += " ui:resize ,\n"; uiString += " ui:touch ;\n"; diff --git a/dpf/distrho/src/DistrhoPluginVST.cpp b/dpf/distrho/src/DistrhoPluginVST.cpp index 4553233..f8a133f 100644 --- a/dpf/distrho/src/DistrhoPluginVST.cpp +++ b/dpf/distrho/src/DistrhoPluginVST.cpp @@ -72,8 +72,16 @@ static const writeMidiFunc writeMidiCallback = nullptr; void strncpy(char* const dst, const char* const src, const size_t size) { DISTRHO_SAFE_ASSERT_RETURN(size > 0,); - std::memcpy(dst, src, std::min(std::strlen(src), size-1)); - dst[size-1] = '\0'; + + if (const size_t len = std::min(std::strlen(src), size-1U)) + { + std::memcpy(dst, src, len); + dst[len] = '\0'; + } + else + { + dst[0] = '\0'; + } } void snprintf_param(char* const dst, const float value, const size_t size) @@ -965,7 +973,7 @@ public: if (vstTimeInfo->flags & (kVstPpqPosValid|kVstTimeSigValid)) { const int ppqPerBar = vstTimeInfo->timeSigNumerator * 4 / vstTimeInfo->timeSigDenominator; - const double barBeats = (std::fmod(vstTimeInfo->ppqPos, ppqPerBar) / ppqPerBar) * vstTimeInfo->timeSigDenominator; + const double barBeats = (std::fmod(vstTimeInfo->ppqPos, ppqPerBar) / ppqPerBar) * vstTimeInfo->timeSigNumerator; const double rest = std::fmod(barBeats, 1.0); fTimePosition.bbt.bar = int(vstTimeInfo->ppqPos)/ppqPerBar + 1; diff --git a/dpf/distrho/src/DistrhoUI.cpp b/dpf/distrho/src/DistrhoUI.cpp index f180ee2..a950216 100644 --- a/dpf/distrho/src/DistrhoUI.cpp +++ b/dpf/distrho/src/DistrhoUI.cpp @@ -1,6 +1,6 @@ /* * DISTRHO Plugin Framework (DPF) - * Copyright (C) 2012-2016 Filipe Coelho + * Copyright (C) 2012-2018 Filipe Coelho * * 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 @@ -15,8 +15,7 @@ */ #include "DistrhoUIInternal.hpp" - -#ifdef HAVE_DGL +#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI # include "src/WidgetPrivateData.hpp" #endif @@ -27,29 +26,30 @@ START_NAMESPACE_DISTRHO double d_lastUiSampleRate = 0.0; void* d_lastUiDspPtr = nullptr; -#ifdef HAVE_DGL -Window* d_lastUiWindow = nullptr; -#endif +#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI uintptr_t g_nextWindowId = 0; const char* g_nextBundlePath = nullptr; +#else +Window* d_lastUiWindow = nullptr; +#endif /* ------------------------------------------------------------------------------------------------------------ * UI */ -#ifdef HAVE_DGL -UI::UI(uint width, uint height) +#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI +UI::UI(uint width, uint height, bool userResizable) + : UIWidget(width, height), + pData(new PrivateData(userResizable)) {} +#else +UI::UI(uint width, uint height, bool userResizable) : UIWidget(*d_lastUiWindow), - pData(new PrivateData()) + pData(new PrivateData(userResizable)) { ((UIWidget*)this)->pData->needsFullViewport = false; if (width > 0 && height > 0) setSize(width, height); } -#else -UI::UI(uint width, uint height) - : UIWidget(width, height), - pData(new PrivateData()) {} #endif UI::~UI() @@ -57,6 +57,25 @@ UI::~UI() delete pData; } +bool UI::isUserResizable() const noexcept +{ + return pData->userResizable; +} + +#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI +void UI::setGeometryConstraints(uint minWidth, uint minHeight, bool keepAspectRatio, bool automaticallyScale) +{ + DISTRHO_SAFE_ASSERT_RETURN(minWidth > 0,); + DISTRHO_SAFE_ASSERT_RETURN(minHeight > 0,); + + pData->automaticallyScale = automaticallyScale; + pData->minWidth = minWidth; + pData->minHeight = minHeight; + + getParentWindow().setGeometryConstraints(minWidth, minHeight, keepAspectRatio); +} +#endif + /* ------------------------------------------------------------------------------------------------------------ * Host state */ @@ -121,15 +140,15 @@ uintptr_t UI::getNextWindowId() noexcept void UI::sampleRateChanged(double) {} -#ifdef HAVE_DGL +#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI /* ------------------------------------------------------------------------------------------------------------ * UI Callbacks (optional) */ -#ifndef DGL_FILE_BROWSER_DISABLED +# ifndef DGL_FILE_BROWSER_DISABLED void UI::uiFileBrowserSelected(const char*) { } -#endif +# endif void UI::uiReshape(uint width, uint height) { @@ -148,9 +167,12 @@ void UI::uiReshape(uint width, uint height) void UI::onResize(const ResizeEvent& ev) { + if (pData->resizeInProgress) + return; + pData->setSizeCallback(ev.size.getWidth(), ev.size.getHeight()); } -#endif +#endif // !DISTRHO_PLUGIN_HAS_EXTERNAL_UI // ----------------------------------------------------------------------------------------------------------- diff --git a/dpf/distrho/src/DistrhoUIDSSI.cpp b/dpf/distrho/src/DistrhoUIDSSI.cpp index 5f23b83..b11e1d0 100644 --- a/dpf/distrho/src/DistrhoUIDSSI.cpp +++ b/dpf/distrho/src/DistrhoUIDSSI.cpp @@ -194,7 +194,7 @@ protected: uint8_t mdata[4] = { 0, - channel + (velocity != 0 ? 0x90 : 0x80), + static_cast(channel + (velocity != 0 ? 0x90 : 0x80)), note, velocity }; diff --git a/dpf/distrho/src/DistrhoUIInternal.hpp b/dpf/distrho/src/DistrhoUIInternal.hpp index 8a045a9..4ea2658 100644 --- a/dpf/distrho/src/DistrhoUIInternal.hpp +++ b/dpf/distrho/src/DistrhoUIInternal.hpp @@ -19,7 +19,10 @@ #include "../DistrhoUI.hpp" -#ifdef HAVE_DGL +#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI +# include "../extra/Sleep.hpp" +using DGL_NAMESPACE::IdleCallback; +#else # include "../../dgl/Application.hpp" # include "../../dgl/Window.hpp" using DGL_NAMESPACE::Application; @@ -34,7 +37,7 @@ START_NAMESPACE_DISTRHO extern double d_lastUiSampleRate; extern void* d_lastUiDspPtr; -#ifdef HAVE_DGL +#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI extern Window* d_lastUiWindow; #endif extern uintptr_t g_nextWindowId; @@ -60,6 +63,13 @@ struct UI::PrivateData { void* dspPtr; #endif + // UI + const bool userResizable; + bool automaticallyScale; + bool resizeInProgress; + uint minWidth; + uint minHeight; + // Callbacks void* callbacksPtr; editParamFunc editParamCallbackFunc; @@ -68,12 +78,17 @@ struct UI::PrivateData { sendNoteFunc sendNoteCallbackFunc; setSizeFunc setSizeCallbackFunc; - PrivateData() noexcept + PrivateData(const bool resizable) noexcept : sampleRate(d_lastUiSampleRate), parameterOffset(0), #if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS dspPtr(d_lastUiDspPtr), #endif + userResizable(resizable), + automaticallyScale(false), + resizeInProgress(false), + minWidth(0), + minHeight(0), callbacksPtr(nullptr), editParamCallbackFunc(nullptr), setParamCallbackFunc(nullptr), @@ -134,7 +149,20 @@ struct UI::PrivateData { // ----------------------------------------------------------------------- // Plugin Window, needed to take care of resize properly -#ifdef HAVE_DGL +#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI +static inline +UI* createUiWrapper(void* const dspPtr, const uintptr_t winId, 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; + return ret; +} +#else // DISTRHO_PLUGIN_HAS_EXTERNAL_UI static inline UI* createUiWrapper(void* const dspPtr, Window* const window) { @@ -155,9 +183,9 @@ public: fIsReady(false) { DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,); + DISTRHO_SAFE_ASSERT_RETURN(fUI->pData != nullptr,); - // set window size - setResizable(false); + setResizable(fUI->pData->userResizable); setSize(fUI->getWidth(), fUI->getHeight()); } @@ -182,11 +210,25 @@ protected: { DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,); + UI::PrivateData* const pData = fUI->pData; + DISTRHO_SAFE_ASSERT_RETURN(pData != nullptr,); + + if (pData->automaticallyScale) + { + const double scaleHorizontal = static_cast(width) / static_cast(pData->minWidth); + const double scaleVertical = static_cast(height) / static_cast(pData->minHeight); + setScaling(scaleHorizontal < scaleVertical ? scaleHorizontal : scaleVertical); + } + + pData->resizeInProgress = true; + fUI->setSize(width, height); + pData->resizeInProgress = false; + fUI->uiReshape(width, height); fIsReady = true; } -#ifndef DGL_FILE_BROWSER_DISABLED +# ifndef DGL_FILE_BROWSER_DISABLED // custom file-browser selected void fileBrowserSelected(const char* filename) override { @@ -194,26 +236,13 @@ protected: fUI->uiFileBrowserSelected(filename); } -#endif +# endif private: UI* const fUI; bool fIsReady; }; -#else -static inline -UI* createUiWrapper(void* const dspPtr, const uintptr_t winId, 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; - return ret; -} -#endif +#endif // DISTRHO_PLUGIN_HAS_EXTERNAL_UI // ----------------------------------------------------------------------- // UI exporter class @@ -230,13 +259,13 @@ public: const setSizeFunc setSizeCall, void* const dspPtr = nullptr, const char* const bundlePath = nullptr) -#ifdef HAVE_DGL +#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI + : fUI(createUiWrapper(dspPtr, winId, bundlePath)), +#else : glApp(), glWindow(glApp, winId, dspPtr), fChangingSize(false), fUI(glWindow.getUI()), -#else - : fUI(createUiWrapper(dspPtr, winId, bundlePath)), #endif fData((fUI != nullptr) ? fUI->pData : nullptr) { @@ -250,54 +279,65 @@ public: fData->sendNoteCallbackFunc = sendNoteCall; fData->setSizeCallbackFunc = setSizeCall; -#ifdef HAVE_DGL +#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI // unused return; (void)bundlePath; #endif } +#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI + ~UIExporter() + { + delete fUI; + } +#endif + // ------------------------------------------------------------------- +#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI uint getWidth() const noexcept { -#ifdef HAVE_DGL - return glWindow.getWidth(); -#else DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr, 1); return fUI->getWidth(); -#endif } uint getHeight() const noexcept { -#ifdef HAVE_DGL - return glWindow.getHeight(); -#else DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr, 1); return fUI->getHeight(); -#endif } bool isVisible() const noexcept { -#ifdef HAVE_DGL - return glWindow.isVisible(); -#else DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr, false); return fUI->isRunning(); -#endif } - // ------------------------------------------------------------------- + intptr_t getWindowId() const noexcept + { + return 0; + } +#else + uint getWidth() const noexcept + { + return glWindow.getWidth(); + } + + uint getHeight() const noexcept + { + return glWindow.getHeight(); + } + + bool isVisible() const noexcept + { + return glWindow.isVisible(); + } intptr_t getWindowId() const noexcept { -#ifdef HAVE_DGL return glWindow.getWindowId(); -#else - return 0; -#endif } +#endif // ------------------------------------------------------------------- @@ -339,7 +379,39 @@ public: // ------------------------------------------------------------------- -#ifdef HAVE_DGL +#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI + void exec(IdleCallback* const cb) + { + DISTRHO_SAFE_ASSERT_RETURN(cb != nullptr,); + DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,); + + fUI->setVisible(true); + cb->idleCallback(); + + while (fUI->isRunning()) + { + d_msleep(10); + cb->idleCallback(); + } + } + + void exec_idle() + { + } + + bool idle() + { + return true; + } + + void quit() + { + DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,); + + fUI->setVisible(false); + fUI->terminateAndWaitForProcess(); + } +#else void exec(IdleCallback* const cb) { DISTRHO_SAFE_ASSERT_RETURN(cb != nullptr,); @@ -355,48 +427,64 @@ public: if (glWindow.isReady()) fUI->uiIdle(); } -#endif bool idle() { DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr, false); -#ifdef HAVE_DGL glApp.idle(); if (glWindow.isReady()) fUI->uiIdle(); return ! glApp.isQuiting(); -#else - return fUI->isRunning(); -#endif } void quit() { -#ifdef HAVE_DGL glWindow.close(); glApp.quit(); -#else - DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,); - fUI->terminateAndWaitForProcess(); -#endif } +#endif // ------------------------------------------------------------------- +#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI void setWindowTitle(const char* const uiTitle) { -#ifdef HAVE_DGL - glWindow.setTitle(uiTitle); -#else DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,); + fUI->setTitle(uiTitle); -#endif } -#ifdef HAVE_DGL + void setWindowSize(const uint width, const uint height, const bool = false) + { + DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,); + + fUI->setSize(width, height); + } + + void setWindowTransientWinId(const uintptr_t winId) + { + DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,); + + fUI->setTransientWinId(winId); + } + + bool setWindowVisible(const bool yesNo) + { + DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr, false); + + fUI->setVisible(yesNo); + + return fUI->isRunning(); + } +#else + void setWindowTitle(const char* const uiTitle) + { + glWindow.setTitle(uiTitle); + } + void setWindowSize(const uint width, const uint height, const bool updateUI = false) { DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,); @@ -431,12 +519,8 @@ public: bool handlePluginSpecial(const bool press, const Key key) { - return glWindow.handlePluginKeyboard(press, key); + return glWindow.handlePluginSpecial(press, key); } -#else - void setWindowSize(const uint, const uint, const bool) {} - void setWindowTransientWinId(const uintptr_t) {} - bool setWindowVisible(const bool) { return true; } #endif // ------------------------------------------------------------------- @@ -457,7 +541,7 @@ public: } private: -#ifdef HAVE_DGL +#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI // ------------------------------------------------------------------- // DGL Application and Window for this widget diff --git a/dpf/distrho/src/lv2/atom-util.h b/dpf/distrho/src/lv2/atom-util.h index c47c0f6..cad90f8 100644 --- a/dpf/distrho/src/lv2/atom-util.h +++ b/dpf/distrho/src/lv2/atom-util.h @@ -117,13 +117,13 @@ lv2_atom_sequence_next(const LV2_Atom_Event* i) @endcode */ #define LV2_ATOM_SEQUENCE_FOREACH(seq, iter) \ - for (const LV2_Atom_Event* (iter) = lv2_atom_sequence_begin(&(seq)->body); \ + for (const LV2_Atom_Event* iter = lv2_atom_sequence_begin(&(seq)->body); \ !lv2_atom_sequence_is_end(&(seq)->body, (seq)->atom.size, (iter)); \ (iter) = lv2_atom_sequence_next(iter)) /** Like LV2_ATOM_SEQUENCE_FOREACH but for a headerless sequence body. */ #define LV2_ATOM_SEQUENCE_BODY_FOREACH(body, size, iter) \ - for (const LV2_Atom_Event* (iter) = lv2_atom_sequence_begin(body); \ + for (const LV2_Atom_Event* iter = lv2_atom_sequence_begin(body); \ !lv2_atom_sequence_is_end(body, size, (iter)); \ (iter) = lv2_atom_sequence_next(iter)) @@ -214,13 +214,13 @@ lv2_atom_tuple_next(const LV2_Atom* i) @endcode */ #define LV2_ATOM_TUPLE_FOREACH(tuple, iter) \ - for (const LV2_Atom* (iter) = lv2_atom_tuple_begin(tuple); \ + for (const LV2_Atom* iter = lv2_atom_tuple_begin(tuple); \ !lv2_atom_tuple_is_end(LV2_ATOM_BODY_CONST(tuple), (tuple)->size, (iter)); \ (iter) = lv2_atom_tuple_next(iter)) /** Like LV2_ATOM_TUPLE_FOREACH but for a headerless tuple body. */ #define LV2_ATOM_TUPLE_BODY_FOREACH(body, size, iter) \ - for (const LV2_Atom* (iter) = (const LV2_Atom*)body; \ + for (const LV2_Atom* iter = (const LV2_Atom*)body; \ !lv2_atom_tuple_is_end(body, size, (iter)); \ (iter) = lv2_atom_tuple_next(iter)) @@ -270,13 +270,13 @@ lv2_atom_object_next(const LV2_Atom_Property_Body* i) @endcode */ #define LV2_ATOM_OBJECT_FOREACH(obj, iter) \ - for (const LV2_Atom_Property_Body* (iter) = lv2_atom_object_begin(&(obj)->body); \ + for (const LV2_Atom_Property_Body* iter = lv2_atom_object_begin(&(obj)->body); \ !lv2_atom_object_is_end(&(obj)->body, (obj)->atom.size, (iter)); \ (iter) = lv2_atom_object_next(iter)) /** Like LV2_ATOM_OBJECT_FOREACH but for a headerless object body. */ #define LV2_ATOM_OBJECT_BODY_FOREACH(body, size, iter) \ - for (const LV2_Atom_Property_Body* (iter) = lv2_atom_object_begin(body); \ + for (const LV2_Atom_Property_Body* iter = lv2_atom_object_begin(body); \ !lv2_atom_object_is_end(body, size, (iter)); \ (iter) = lv2_atom_object_next(iter)) diff --git a/dpf/utils/png2c.py b/dpf/utils/png2c.py new file mode 100755 index 0000000..ab02365 --- /dev/null +++ b/dpf/utils/png2c.py @@ -0,0 +1,113 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# DISTRHO Plugin Framework (DPF) +# Copyright (C) 2012-2019 Filipe Coelho +# +# 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. + +import os, sys + +# ----------------------------------------------------- + +def png2c(namespace, filenames): + + fdH = open("%s.hpp" % namespace, "w") + fdH.write("/* (Auto-generated binary data file). */\n") + fdH.write("\n") + fdH.write("#ifndef BINARY_%s_HPP\n" % namespace.upper()) + fdH.write("#define BINARY_%s_HPP\n" % namespace.upper()) + fdH.write("\n") + fdH.write("namespace %s\n" % namespace) + fdH.write("{\n") + + fdC = open("%s.cpp" % namespace, "w") + fdC.write("/* (Auto-generated binary data file). */\n") + fdC.write("\n") + fdC.write("#include \"%s.hpp\"\n" % namespace) + fdC.write("\n") + + tempIndex = 1 + + for filename in filenames: + shortFilename = filename.rsplit(os.sep, 1)[-1].split(".", 1)[0] + shortFilename = shortFilename.replace("-", "_") + + pngData = 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))) + + if tempIndex != len(filenames): + fdH.write("\n") + + fdC.write("static const unsigned char temp_%s_%i[] = {\n" % (shortFilename, tempIndex)) + + curColumn = 1 + fdC.write(" ") + + for data in pngData: + if curColumn == 0: + fdC.write(" ") + + fdC.write(" %3u," % data) + + if curColumn > 20: + fdC.write("\n ") + curColumn = 1 + else: + curColumn += 1 + + fdC.write("};\n") + fdC.write("const char* %s::%sData = (const char*)temp_%s_%i;\n" % (namespace, shortFilename, shortFilename, tempIndex)) + + if tempIndex != len(filenames): + fdC.write("\n") + + tempIndex += 1 + + fdH.write("}\n") + fdH.write("\n") + fdH.write("#endif // BINARY_%s_HPP\n" % namespace.upper()) + fdH.write("\n") + fdH.close() + + fdC.write("\n") + fdC.close() + +# ----------------------------------------------------- + +if __name__ == '__main__': + if len(sys.argv) != 3: + print("Usage: %s " % sys.argv[0]) + quit() + + namespace = sys.argv[1].replace("-","_") + artFolder = sys.argv[2] + + if not os.path.exists(artFolder): + print("Folder '%s' does not exist" % artFolder) + quit() + + # find png files + pngFiles = [] + + 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)) + + pngFiles.sort() + + # create code now + png2c(namespace, pngFiles) diff --git a/dpf/utils/png2rgba.py b/dpf/utils/png2rgba.py index 3575db7..99a5089 100755 --- a/dpf/utils/png2rgba.py +++ b/dpf/utils/png2rgba.py @@ -1,8 +1,8 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # -*- coding: utf-8 -*- # DISTRHO Plugin Framework (DPF) -# Copyright (C) 2012-2016 Filipe Coelho +# Copyright (C) 2012-2019 Filipe Coelho # # 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 @@ -52,7 +52,10 @@ def png2rgba(namespace, filenames): shortFilename = filename.rsplit(os.sep, 1)[-1].split(".", 1)[0] shortFilename = shortFilename.replace("-", "_") - png = Image.open(filename) + png = Image.open(filename) + if png.getpalette(): + png = png.convert() + pngNumpy = numpy.array(png) pngData = pngNumpy.tolist() #pngData.reverse() diff --git a/plugins/MVerb/MVerb.h b/plugins/MVerb/MVerb.h index dc0ad07..097e97b 100644 --- a/plugins/MVerb/MVerb.h +++ b/plugins/MVerb/MVerb.h @@ -60,8 +60,8 @@ public: }; MVerb(){ - DampingFreq = 18000.; - BandwidthFreq = 18000.; + DampingFreq = 0.9; + BandwidthFreq = 0.9; SampleRate = 44100.; Decay = 0.5; Gain = 1.;