Browse Source

Update DPF and plugins

Signed-off-by: falkTX <falktx@falktx.com>
tags/v1.2
falkTX 6 years ago
parent
commit
fa35320395
Signed by: falkTX <falktx@falktx.com> GPG Key ID: CDBAA37ABC74FBA0
35 changed files with 1006 additions and 854 deletions
  1. +1
    -1
      dpf/LICENSE
  2. +2
    -2
      dpf/Makefile.plugins.mk
  3. +3
    -0
      dpf/README.md
  4. +1
    -1
      dpf/dgl/ImageWidgets.hpp
  5. +9
    -0
      dpf/dgl/Window.hpp
  6. +1
    -1
      dpf/dgl/src/Geometry.cpp
  7. +2
    -4
      dpf/dgl/src/NanoVG.cpp
  8. +19
    -16
      dpf/dgl/src/WidgetPrivateData.hpp
  9. +92
    -13
      dpf/dgl/src/Window.cpp
  10. +0
    -121
      dpf/dgl/src/pugl/common.h
  11. +0
    -41
      dpf/dgl/src/pugl/event.h
  12. +0
    -32
      dpf/dgl/src/pugl/gl.h
  13. +0
    -32
      dpf/dgl/src/pugl/glu.h
  14. +140
    -36
      dpf/dgl/src/pugl/pugl.h
  15. +50
    -142
      dpf/dgl/src/pugl/pugl_internal.h
  16. +11
    -14
      dpf/dgl/src/pugl/pugl_osx.m
  17. +16
    -23
      dpf/dgl/src/pugl/pugl_win.cpp
  18. +213
    -241
      dpf/dgl/src/pugl/pugl_x11.c
  19. +28
    -2
      dpf/distrho/DistrhoPlugin.hpp
  20. +23
    -7
      dpf/distrho/DistrhoUI.hpp
  21. +40
    -10
      dpf/distrho/extra/ExternalWindow.hpp
  22. +9
    -0
      dpf/distrho/src/DistrhoDefines.h
  23. +2
    -1
      dpf/distrho/src/DistrhoPluginChecks.h
  24. +0
    -5
      dpf/distrho/src/DistrhoPluginJack.cpp
  25. +2
    -2
      dpf/distrho/src/DistrhoPluginLADSPA+DSSI.cpp
  26. +9
    -7
      dpf/distrho/src/DistrhoPluginLV2.cpp
  27. +6
    -3
      dpf/distrho/src/DistrhoPluginLV2export.cpp
  28. +11
    -3
      dpf/distrho/src/DistrhoPluginVST.cpp
  29. +39
    -17
      dpf/distrho/src/DistrhoUI.cpp
  30. +1
    -1
      dpf/distrho/src/DistrhoUIDSSI.cpp
  31. +149
    -65
      dpf/distrho/src/DistrhoUIInternal.hpp
  32. +6
    -6
      dpf/distrho/src/lv2/atom-util.h
  33. +113
    -0
      dpf/utils/png2c.py
  34. +6
    -3
      dpf/utils/png2rgba.py
  35. +2
    -2
      plugins/MVerb/MVerb.h

+ 1
- 1
dpf/LICENSE View File

@@ -1,5 +1,5 @@
DISTRHO Plugin Framework (DPF)
Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
Copyright (C) 2012-2018 Filipe Coelho <falktx@falktx.com>

Permission to use, copy, modify, and/or distribute this software for any purpose with
or without fee is hereby granted, provided that the above copyright notice and this


+ 2
- 2
dpf/Makefile.plugins.mk View File

@@ -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 $@



+ 3
- 0
dpf/README.md View File

@@ -27,6 +27,9 @@ List of plugins made with DPF:<br/>
- [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.<br/>


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

@@ -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;


+ 9
- 0
dpf/dgl/Window.hpp View File

@@ -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;



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

@@ -237,7 +237,7 @@ bool Size<T>::isNotNull() const noexcept
template<typename T>
bool Size<T>::isValid() const noexcept
{
return fWidth > 1 && fHeight > 1;
return fWidth > 0 && fHeight > 0;
}

template<typename T>


+ 2
- 4
dpf/dgl/src/NanoVG.cpp View File

@@ -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)


+ 19
- 16
dpf/dgl/src/WidgetPrivateData.hpp View File

@@ -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<uint>(width, height)))
{
// full viewport size
glViewport(0, 0, static_cast<GLsizei>(width), static_cast<GLsizei>(height));
glViewport(0,
-(height * scaling - height),
width * scaling,
height * scaling);
}
else if (needsScaling)
{
// limit viewport to widget bounds
glViewport(absolutePos.getX(),
static_cast<int>(height - self->getHeight()) - absolutePos.getY(),
static_cast<GLsizei>(self->getWidth()),
static_cast<GLsizei>(self->getHeight()));
height - self->getHeight() - absolutePos.getY(),
self->getWidth(),
self->getHeight());
}
else
{
// only set viewport pos
glViewport(absolutePos.getX(),
/*static_cast<int>(height - self->getHeight())*/ - absolutePos.getY(),
static_cast<GLsizei>(width),
static_cast<GLsizei>(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<int>(height - self->getHeight()) - absolutePos.getY(),
static_cast<GLsizei>(self->getWidth()),
static_cast<GLsizei>(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<Widget*>::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);
}
}



+ 92
- 13
dpf/dgl/src/Window.cpp View File

@@ -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<Widget*>::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<int>(fWidth), static_cast<int>(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<int>(width);
sizeHints.max_height = static_cast<int>(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<Modifier>(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<float>(dx, dy);
ev.mod = static_cast<Modifier>(puglGetModifiers(fView));
@@ -1000,6 +1048,7 @@ struct Window::PrivateData {
bool fUsingEmbed;
uint fWidth;
uint fHeight;
double fScaling;
char* fTitle;
std::list<Widget*> 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;


+ 0
- 121
dpf/dgl/src/pugl/common.h View File

@@ -1,121 +0,0 @@
/*
Copyright 2014 David Robillard <http://drobilla.net>

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 */

+ 0
- 41
dpf/dgl/src/pugl/event.h View File

@@ -1,41 +0,0 @@
/*
Copyright 2014 David Robillard <http://drobilla.net>

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 <stdbool.h>
#endif

#include "pugl/common.h"

/**
@addtogroup pugl
@{
*/

/**
@}
*/

#ifdef __cplusplus
} /* extern "C" */
#endif

#endif /* PUGL_EVENT_H_INCLUDED */

+ 0
- 32
dpf/dgl/src/pugl/gl.h View File

@@ -1,32 +0,0 @@
/*
Copyright 2012-2014 David Robillard <http://drobilla.net>

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 <windows.h> /* Broken Windows GL headers require this */
# endif
# include "GL/gl.h"
#endif


+ 0
- 32
dpf/dgl/src/pugl/glu.h View File

@@ -1,32 +0,0 @@
/*
Copyright 2012-2014 David Robillard <http://drobilla.net>

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 <windows.h> /* Broken Windows GL headers require this */
# endif
# include "GL/glu.h"
#endif


+ 140
- 36
dpf/dgl/src/pugl/pugl.h View File

@@ -23,28 +23,25 @@

#include <stdint.h>

#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 <winsock2.h>
# include <windows.h> /* Broken Windows GL headers require this */
# endif
# include "GL/gl.h"
#endif

#ifdef _WIN32
# define PUGL_API
#else
# define PUGL_API __attribute__((visibility("hidden")))
#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.
*/


+ 50
- 142
dpf/dgl/src/pugl/pugl_internal.h View File

@@ -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 <stdio.h>
# 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
}

+ 11
- 14
dpf/dgl/src/pugl/pugl_osx.m View File

@@ -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;
}

+ 16
- 23
dpf/dgl/src/pugl/pugl_win.cpp View File

@@ -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;
}

+ 213
- 241
dpf/dgl/src/pugl/pugl_x11.c View File

@@ -1,7 +1,7 @@
/*
Copyright 2012-2014 David Robillard <http://drobilla.net>
Copyright 2013 Robin Gareus <robin@gareus.org>
Copyright 2011-2012 Ben Loftis, Harrison Consoles
Copyright 2013,2015 Robin Gareus <robin@gareus.org>

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 <stdlib.h>
#include <string.h>

#include <GL/gl.h>
#include <GL/glx.h>
#include <X11/Xatom.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/keysym.h>

#ifdef PUGL_HAVE_GL
#include <GL/gl.h>
#include <GL/glx.h>
#endif

#ifdef PUGL_HAVE_CAIRO
#include <cairo/cairo.h>
#include <cairo/cairo-xlib.h>
#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;
}

+ 28
- 2
dpf/distrho/DistrhoPlugin.hpp View File

@@ -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();
}
};

/** @} */


+ 23
- 7
dpf/distrho/DistrhoUI.hpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2016 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2018 Filipe Coelho <falktx@falktx.com>
*
* Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this
@@ -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 {}


+ 40
- 10
dpf/distrho/extra/ExternalWindow.hpp View File

@@ -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)
};



+ 9
- 0
dpf/distrho/src/DistrhoDefines.h View File

@@ -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; }


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

@@ -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


+ 0
- 5
dpf/distrho/src/DistrhoPluginJack.cpp View File

@@ -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


+ 2
- 2
dpf/distrho/src/DistrhoPluginLADSPA+DSSI.cpp View File

@@ -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);


+ 9
- 7
dpf/distrho/src/DistrhoPluginLV2.cpp View File

@@ -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));



+ 6
- 3
dpf/distrho/src/DistrhoPluginLV2export.cpp View File

@@ -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: <http://usefulinc.com/ns/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";


+ 11
- 3
dpf/distrho/src/DistrhoPluginVST.cpp View File

@@ -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;


+ 39
- 17
dpf/distrho/src/DistrhoUI.cpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2016 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2018 Filipe Coelho <falktx@falktx.com>
*
* Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this
@@ -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

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



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

@@ -194,7 +194,7 @@ protected:

uint8_t mdata[4] = {
0,
channel + (velocity != 0 ? 0x90 : 0x80),
static_cast<uint8_t>(channel + (velocity != 0 ? 0x90 : 0x80)),
note,
velocity
};


+ 149
- 65
dpf/distrho/src/DistrhoUIInternal.hpp View File

@@ -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<double>(width) / static_cast<double>(pData->minWidth);
const double scaleVertical = static_cast<double>(height) / static_cast<double>(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



+ 6
- 6
dpf/distrho/src/lv2/atom-util.h View File

@@ -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))



+ 113
- 0
dpf/utils/png2c.py View File

@@ -0,0 +1,113 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# DISTRHO Plugin Framework (DPF)
# Copyright (C) 2012-2019 Filipe Coelho <falktx@falktx.com>
#
# Permission to use, copy, modify, and/or distribute this software for any purpose with
# or without fee is hereby granted, provided that the above copyright notice and this
# permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
# TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
# NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
# DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

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 <namespace> <artwork-folder>" % 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)

+ 6
- 3
dpf/utils/png2rgba.py View File

@@ -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 <falktx@falktx.com>
# Copyright (C) 2012-2019 Filipe Coelho <falktx@falktx.com>
#
# Permission to use, copy, modify, and/or distribute this software for any purpose with
# or without fee is hereby granted, provided that the above copyright notice and this
@@ -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()


+ 2
- 2
plugins/MVerb/MVerb.h View File

@@ -60,8 +60,8 @@ public:
};

MVerb(){
DampingFreq = 18000.;
BandwidthFreq = 18000.;
DampingFreq = 0.9;
BandwidthFreq = 0.9;
SampleRate = 44100.;
Decay = 0.5;
Gain = 1.;


Loading…
Cancel
Save