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) 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 Permission to use, copy, modify, and/or distribute this software for any purpose with
or without fee is hereby granted, provided that the above copyright notice and this or without fee is hereby granted, provided that the above copyright notice and this


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

@@ -77,12 +77,12 @@ all:
# Common # Common


$(BUILD_DIR)/%.c.o: %.c $(BUILD_DIR)/%.c.o: %.c
-@mkdir -p $(BUILD_DIR)
-@mkdir -p "$(shell dirname $(BUILD_DIR)/$<)"
@echo "Compiling $<" @echo "Compiling $<"
@$(CC) $< $(BUILD_C_FLAGS) -c -o $@ @$(CC) $< $(BUILD_C_FLAGS) -c -o $@


$(BUILD_DIR)/%.cpp.o: %.cpp $(BUILD_DIR)/%.cpp.o: %.cpp
-@mkdir -p $(BUILD_DIR)
-@mkdir -p "$(shell dirname $(BUILD_DIR)/$<)"
@echo "Compiling $<" @echo "Compiling $<"
@$(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@ @$(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) - [DISTRHO ndc Plugs](https://github.com/DISTRHO/ndc-Plugs)
- [Juice Plugins](https://github.com/DISTRHO/JuicePlugins) (work in progress) - [Juice Plugins](https://github.com/DISTRHO/JuicePlugins) (work in progress)
- [ZamAudio Suite](https://github.com/zamaudio/zam-plugins) - [ZamAudio Suite](https://github.com/zamaudio/zam-plugins)
- [DragonFly-Reverb](https://github.com/michaelwillis/dragonfly-reverb)
- [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/> 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: public:
virtual ~Callback() {} 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; 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); bool openFileBrowser(const FileBrowserOptions& options);
#endif #endif


bool isEmbed() const noexcept;

bool isVisible() const noexcept; bool isVisible() const noexcept;
void setVisible(bool yesNo); void setVisible(bool yesNo);


@@ -107,8 +109,15 @@ public:
const char* getTitle() const noexcept; const char* getTitle() const noexcept;
void setTitle(const char* title); void setTitle(const char* title);


void setGeometryConstraints(uint width, uint height, bool aspect);
void setTransientWinId(uintptr_t winId); 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; Application& getApp() const noexcept;
intptr_t getWindowId() 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> template<typename T>
bool Size<T>::isValid() const noexcept bool Size<T>::isValid() const noexcept
{ {
return fWidth > 1 && fHeight > 1;
return fWidth > 0 && fHeight > 0;
} }


template<typename T> 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) 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) void NanoVG::skewX(float angle)


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

@@ -63,7 +63,7 @@ struct Widget::PrivateData {
subWidgets.clear(); 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) if ((skipDisplay && ! renderingSubWidget) || size.isInvalid() || ! visible)
return; return;
@@ -76,29 +76,32 @@ struct Widget::PrivateData {
if (needsFullViewport || (absolutePos.isZero() && size == Size<uint>(width, height))) if (needsFullViewport || (absolutePos.isZero() && size == Size<uint>(width, height)))
{ {
// full viewport size // 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) else if (needsScaling)
{ {
// limit viewport to widget bounds // limit viewport to widget bounds
glViewport(absolutePos.getX(), 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 else
{ {
// only set viewport pos // 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 // 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); glEnable(GL_SCISSOR_TEST);
needsDisableScissor = true; needsDisableScissor = true;
@@ -113,17 +116,17 @@ struct Widget::PrivateData {
needsDisableScissor = false; 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) for (std::vector<Widget*>::iterator it = subWidgets.begin(); it != subWidgets.end(); ++it)
{ {
Widget* const widget(*it); Widget* const widget(*it);
DISTRHO_SAFE_ASSERT_CONTINUE(widget->pData != this); 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" #include "../Base.hpp"


#undef PUGL_HAVE_CAIRO
#undef PUGL_HAVE_GL
#define PUGL_HAVE_GL 1

#include "pugl/pugl.h" #include "pugl/pugl.h"


#if defined(__GNUC__) && (__GNUC__ >= 7) #if defined(__GNUC__) && (__GNUC__ >= 7)
@@ -61,7 +57,7 @@ extern "C" {
#define FOR_EACH_WIDGET_INV(rit) \ #define FOR_EACH_WIDGET_INV(rit) \
for (std::list<Widget*>::reverse_iterator rit = fWidgets.rbegin(); rit != fWidgets.rend(); ++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 DBG(msg) std::fprintf(stderr, "%s", msg);
# define DBGp(...) std::fprintf(stderr, __VA_ARGS__); # define DBGp(...) std::fprintf(stderr, __VA_ARGS__);
# define DBGF std::fflush(stderr); # define DBGF std::fflush(stderr);
@@ -87,6 +83,7 @@ struct Window::PrivateData {
fUsingEmbed(false), fUsingEmbed(false),
fWidth(1), fWidth(1),
fHeight(1), fHeight(1),
fScaling(1.0),
fTitle(nullptr), fTitle(nullptr),
fWidgets(), fWidgets(),
fModal(), fModal(),
@@ -117,6 +114,7 @@ struct Window::PrivateData {
fUsingEmbed(false), fUsingEmbed(false),
fWidth(1), fWidth(1),
fHeight(1), fHeight(1),
fScaling(1.0),
fTitle(nullptr), fTitle(nullptr),
fWidgets(), fWidgets(),
fModal(parent.pData), fModal(parent.pData),
@@ -159,6 +157,7 @@ struct Window::PrivateData {
fUsingEmbed(parentId != 0), fUsingEmbed(parentId != 0),
fWidth(1), fWidth(1),
fHeight(1), fHeight(1),
fScaling(1.0),
fTitle(nullptr), fTitle(nullptr),
fWidgets(), fWidgets(),
fModal(), fModal(),
@@ -204,7 +203,6 @@ struct Window::PrivateData {
return; return;
} }


puglInitContextType(fView, PUGL_GL);
puglInitUserResizable(fView, fResizable); puglInitUserResizable(fView, fResizable);
puglInitWindowSize(fView, static_cast<int>(fWidth), static_cast<int>(fHeight)); puglInitWindowSize(fView, static_cast<int>(fWidth), static_cast<int>(fHeight));


@@ -539,6 +537,7 @@ struct Window::PrivateData {
DBG("Window setResizable called\n"); DBG("Window setResizable called\n");


fResizable = yesNo; fResizable = yesNo;
fView->user_resizable = yesNo;


#if defined(DISTRHO_OS_WINDOWS) #if defined(DISTRHO_OS_WINDOWS)
const int winFlags = fResizable ? GetWindowLong(hwnd, GWL_STYLE) | WS_SIZEBOX 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) void setSize(uint width, uint height, const bool forced = false)
{ {
if (width <= 1 || height <= 1) if (width <= 1 || height <= 1)
@@ -605,7 +615,6 @@ struct Window::PrivateData {
} }
} }
#else #else
XResizeWindow(xDisplay, xWindow, width, height);


if (! fResizable) if (! fResizable)
{ {
@@ -620,9 +629,11 @@ struct Window::PrivateData {
sizeHints.max_width = static_cast<int>(width); sizeHints.max_width = static_cast<int>(width);
sizeHints.max_height = static_cast<int>(height); sizeHints.max_height = static_cast<int>(height);


XSetNormalHints(xDisplay, xWindow, &sizeHints);
XSetWMNormalHints(xDisplay, xWindow, &sizeHints);
} }


XResizeWindow(xDisplay, xWindow, width, height);

if (! forced) if (! forced)
XFlush(xDisplay); XFlush(xDisplay);
#endif #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) void addWidget(Widget* const widget)
{ {
fWidgets.push_back(widget); fWidgets.push_back(widget);
@@ -736,7 +773,7 @@ struct Window::PrivateData {
FOR_EACH_WIDGET(it) FOR_EACH_WIDGET(it)
{ {
Widget* const widget(*it); Widget* const widget(*it);
widget->pData->display(fWidth, fHeight, false);
widget->pData->display(fWidth, fHeight, fScaling, false);
} }


fSelf->onDisplayAfter(); fSelf->onDisplayAfter();
@@ -796,7 +833,7 @@ struct Window::PrivateData {
return 1; 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); DBGp("PUGL: onMouse : %i %i %i %i\n", button, press, x, y);


@@ -806,6 +843,9 @@ struct Window::PrivateData {
if (fModal.childFocus != nullptr) if (fModal.childFocus != nullptr)
return fModal.childFocus->focus(); return fModal.childFocus->focus();


x /= fScaling;
y /= fScaling;

Widget::MouseEvent ev; Widget::MouseEvent ev;
ev.button = button; ev.button = button;
ev.press = press; 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) if (fModal.childFocus != nullptr)
return; return;


x /= fScaling;
y /= fScaling;

Widget::MotionEvent ev; Widget::MotionEvent ev;
ev.mod = static_cast<Modifier>(puglGetModifiers(fView)); ev.mod = static_cast<Modifier>(puglGetModifiers(fView));
ev.time = puglGetEventTimestamp(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); DBGp("PUGL: onScroll : %i %i %f %f\n", x, y, dx, dy);


if (fModal.childFocus != nullptr) if (fModal.childFocus != nullptr)
return; return;


x /= fScaling;
y /= fScaling;
dx /= fScaling;
dy /= fScaling;

Widget::ScrollEvent ev; Widget::ScrollEvent ev;
ev.delta = Point<float>(dx, dy); ev.delta = Point<float>(dx, dy);
ev.mod = static_cast<Modifier>(puglGetModifiers(fView)); ev.mod = static_cast<Modifier>(puglGetModifiers(fView));
@@ -1000,6 +1048,7 @@ struct Window::PrivateData {
bool fUsingEmbed; bool fUsingEmbed;
uint fWidth; uint fWidth;
uint fHeight; uint fHeight;
double fScaling;
char* fTitle; char* fTitle;
std::list<Widget*> fWidgets; std::list<Widget*> fWidgets;


@@ -1221,6 +1270,11 @@ bool Window::openFileBrowser(const FileBrowserOptions& options)
} }
#endif #endif


bool Window::isEmbed() const noexcept
{
return pData->fUsingEmbed;
}

bool Window::isVisible() const noexcept bool Window::isVisible() const noexcept
{ {
return pData->fVisible; return pData->fVisible;
@@ -1241,6 +1295,11 @@ void Window::setResizable(bool yesNo)
pData->setResizable(yesNo); pData->setResizable(yesNo);
} }


void Window::setGeometryConstraints(uint width, uint height, bool aspect)
{
pData->setGeometryConstraints(width, height, aspect);
}

uint Window::getWidth() const noexcept uint Window::getWidth() const noexcept
{ {
return pData->fWidth; return pData->fWidth;
@@ -1281,6 +1340,26 @@ void Window::setTransientWinId(uintptr_t winId)
pData->setTransientWinId(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 Application& Window::getApp() const noexcept
{ {
return pData->fApp; 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 <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 #else
# ifdef _WIN32 # 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 # endif
# include "GL/gl.h"
#endif

#ifdef _WIN32
# define PUGL_API
#else
# define PUGL_API __attribute__((visibility("hidden")))
#endif #endif


#ifdef __cplusplus #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. A function called when the window is closed.
*/ */
@@ -105,6 +178,16 @@ typedef void (*PuglMouseFunc)(
*/ */
typedef void (*PuglReshapeFunc)(PuglView* view, int width, int height); 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). A function called on scrolling (e.g. mouse wheel or track pad).


@@ -190,12 +273,6 @@ puglInitUserResizable(PuglView* view, bool resizable);
PUGL_API void PUGL_API void
puglInitTransientFor(PuglView* view, uintptr_t parent); 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); 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 PUGL_API void
puglShowWindow(PuglView* view); puglShowWindow(PuglView* view);


/** /**
Hide the current window.
Hide Window (external ui)
*/ */
PUGL_API void PUGL_API void
puglHideWindow(PuglView* view); puglHideWindow(PuglView* view);
@@ -254,15 +349,6 @@ puglSetHandle(PuglView* view, PuglHandle handle);
PUGL_API PuglHandle PUGL_API PuglHandle
puglGetHandle(PuglView* view); 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. Return the timestamp (if any) of the currently-processing event.
*/ */
@@ -337,6 +423,12 @@ puglSetSpecialFunc(PuglView* view, PuglSpecialFunc specialFunc);
PUGL_API void PUGL_API void
puglSetReshapeFunc(PuglView* view, PuglReshapeFunc reshapeFunc); 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. 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. Grab the input focus.
*/ */
@@ -368,6 +466,12 @@ puglProcessEvents(PuglView* view);
PUGL_API void PUGL_API void
puglPostRedisplay(PuglView* view); puglPostRedisplay(PuglView* view);


/**
Request a resize on the next call to puglProcessEvents().
*/
PUGL_API void
puglPostResize(PuglView* view);

/** /**
Destroy a GL window. 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 Note this file contains function definitions, so it must be compiled into
the final binary exactly once. Each platform specific implementation file the final binary exactly once. Each platform specific implementation file
including it once should achieve this. 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; typedef struct PuglInternalsImpl PuglInternals;


@@ -52,14 +34,13 @@ struct PuglViewImpl {
PuglMotionFunc motionFunc; PuglMotionFunc motionFunc;
PuglMouseFunc mouseFunc; PuglMouseFunc mouseFunc;
PuglReshapeFunc reshapeFunc; PuglReshapeFunc reshapeFunc;
PuglResizeFunc resizeFunc;
PuglScrollFunc scrollFunc; PuglScrollFunc scrollFunc;
PuglSpecialFunc specialFunc; PuglSpecialFunc specialFunc;
PuglFileSelectedFunc fileSelectedFunc; PuglFileSelectedFunc fileSelectedFunc;


PuglInternals* impl;

PuglInternals* impl;
PuglNativeWindow parent; PuglNativeWindow parent;
PuglContextType ctx_type;
uintptr_t transient_parent; uintptr_t transient_parent;


int width; int width;
@@ -70,7 +51,8 @@ struct PuglViewImpl {
bool mouse_in_view; bool mouse_in_view;
bool ignoreKeyRepeat; bool ignoreKeyRepeat;
bool redisplay; bool redisplay;
bool resizable;
bool user_resizable;
bool pending_resize;
uint32_t event_timestamp_ms; uint32_t event_timestamp_ms;
}; };


@@ -120,7 +102,7 @@ puglInitWindowParent(PuglView* view, PuglNativeWindow parent)
void void
puglInitUserResizable(PuglView* view, bool resizable) puglInitUserResizable(PuglView* view, bool resizable)
{ {
view->resizable = resizable;
view->user_resizable = resizable;
} }


void void
@@ -129,10 +111,33 @@ puglInitTransientFor(PuglView* view, uintptr_t parent)
view->transient_parent = 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 void
@@ -201,6 +206,12 @@ puglSetReshapeFunc(PuglView* view, PuglReshapeFunc reshapeFunc)
view->reshapeFunc = reshapeFunc; view->reshapeFunc = reshapeFunc;
} }


void
puglSetResizeFunc(PuglView* view, PuglResizeFunc resizeFunc)
{
view->resizeFunc = resizeFunc;
}

void void
puglSetScrollFunc(PuglView* view, PuglScrollFunc scrollFunc) puglSetScrollFunc(PuglView* view, PuglScrollFunc scrollFunc)
{ {
@@ -225,45 +236,19 @@ puglEnterContext(PuglView* view);
void void
puglLeaveContext(PuglView* view, bool flush); 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 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); glMatrixMode(GL_PROJECTION);
glLoadIdentity(); glLoadIdentity();
glOrtho(0, width, height, 0, 0, 1); glOrtho(0, width, height, 0, 0, 1);
@@ -271,82 +256,5 @@ puglDefaultReshape(PuglView* view, int width, int height)


glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
glLoadIdentity(); 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 #endif
}

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

@@ -218,7 +218,7 @@ puglDisplay(PuglView* view)
if (puglview->reshapeFunc) { if (puglview->reshapeFunc) {
puglview->reshapeFunc(puglview, width, height); puglview->reshapeFunc(puglview, width, height);
} else { } else {
puglDefaultReshape(puglview, width, height);
puglDefaultReshape(width, height);
} }


puglLeaveContext(puglview, false); puglLeaveContext(puglview, false);
@@ -427,18 +427,13 @@ puglInitInternals()
void void
puglEnterContext(PuglView* view) 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 void
puglLeaveContext(PuglView* view, bool flush) puglLeaveContext(PuglView* view, bool flush)
{ {
#ifdef PUGL_HAVE_GL
if (view->ctx_type == PUGL_GL && flush) {
if (flush) {
if (view->impl->glview->doubleBuffered) { if (view->impl->glview->doubleBuffered) {
[[view->impl->glview openGLContext] flushBuffer]; [[view->impl->glview openGLContext] flushBuffer];
} else { } else {
@@ -446,7 +441,6 @@ puglLeaveContext(PuglView* view, bool flush)
} }
//[NSOpenGLContext clearCurrentContext]; //[NSOpenGLContext clearCurrentContext];
} }
#endif
} }


int int
@@ -465,7 +459,7 @@ puglCreateWindow(PuglView* view, const char* title)
impl->glview->puglview = view; impl->glview->puglview = view;


if (view->resizable) {
if (view->user_resizable) {
[impl->glview setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable]; [impl->glview setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable];
} }


@@ -566,11 +560,14 @@ puglGetNativeWindow(PuglView* view)
return (PuglNativeWindow)view->impl->glview; 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)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 void
puglEnterContext(PuglView* view) 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 void
puglLeaveContext(PuglView* view, bool flush) 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 int
@@ -137,7 +129,7 @@ puglCreateWindow(PuglView* view, const char* title)
} }


int winFlags = WS_POPUPWINDOW | WS_CAPTION; int winFlags = WS_POPUPWINDOW | WS_CAPTION;
if (view->resizable) {
if (view->user_resizable) {
winFlags |= WS_SIZEBOX; winFlags |= WS_SIZEBOX;
if (view->min_width > 0 && view->min_height > 0) { if (view->min_width > 0 && view->min_height > 0) {
// Adjust the minimum window size to accomodate requested view size // Adjust the minimum window size to accomodate requested view size
@@ -231,7 +223,7 @@ puglReshape(PuglView* view, int width, int height)
if (view->reshapeFunc) { if (view->reshapeFunc) {
view->reshapeFunc(view, width, height); view->reshapeFunc(view, width, height);
} else { } else {
puglDefaultReshape(view, width, height);
puglDefaultReshape(width, height);
} }


view->width = width; view->width = width;
@@ -477,13 +469,14 @@ puglGetNativeWindow(PuglView* view)
return (PuglNativeWindow)view->impl->hwnd; 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 2012-2014 David Robillard <http://drobilla.net>
Copyright 2013 Robin Gareus <robin@gareus.org>
Copyright 2011-2012 Ben Loftis, Harrison Consoles 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 Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above purpose with or without fee is hereby granted, provided that the above
@@ -24,22 +24,14 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>


#include <GL/gl.h>
#include <GL/glx.h>
#include <X11/Xatom.h> #include <X11/Xatom.h>
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <X11/Xutil.h> #include <X11/Xutil.h>
#include <X11/keysym.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 #ifndef DGL_FILE_BROWSER_DISABLED
#define SOFD_HAVE_X11 #define SOFD_HAVE_X11
@@ -47,212 +39,145 @@
#include "../sofd/libsofd.c" #include "../sofd/libsofd.c"
#endif #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 { struct PuglInternalsImpl {
Display* display; Display* display;
int screen; int screen;
Window win; Window win;
XIM xim;
XIC xic;
#ifdef PUGL_HAVE_CAIRO
cairo_t* cr;
cairo_surface_t* surface;
#endif
#ifdef PUGL_HAVE_GL
GLXContext ctx; GLXContext ctx;
Bool doubleBuffered; 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 void
puglEnterContext(PuglView* view) 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 void
puglLeaveContext(PuglView* view, bool flush) 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 int
puglCreateWindow(PuglView* view, const char* title) 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->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) { if (!vi) {
XCloseDisplay(impl->display); XCloseDisplay(impl->display);
impl->display = NULL;
free(impl);
return 1; return 1;
} }


#ifdef PUGL_HAVE_GL
#ifdef PUGL_VERBOSE
int glxMajor, glxMinor; int glxMajor, glxMinor;
glXQueryVersion(impl->display, &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 #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 xParent = view->parent
? (Window)view->parent ? (Window)view->parent
: RootWindow(impl->display, impl->screen); : RootWindow(impl->display, impl->screen);
@@ -262,76 +187,55 @@ puglCreateWindow(PuglView* view, const char* title)


XSetWindowAttributes attr; XSetWindowAttributes attr;
memset(&attr, 0, sizeof(XSetWindowAttributes)); 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->win = XCreateWindow(
impl->display, xParent, impl->display, xParent,
0, 0, view->width, view->height, 0, vi->depth, InputOutput, vi->visual, 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); XCloseDisplay(impl->display);
impl->display = NULL;

free(impl);
return 1; 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) { if (title) {
XStoreName(impl->display, impl->win, 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); Atom wmDelete = XInternAtom(impl->display, "WM_DELETE_WINDOW", True);
XSetWMProtocols(impl->display, impl->win, &wmDelete, 1); XSetWMProtocols(impl->display, impl->win, &wmDelete, 1);
} }


#ifdef PUGL_VERBOSE
if (glXIsDirect(impl->display, impl->ctx)) { 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 { } else {
PUGL_LOG("No DRI available\n");
printf("puGL: No DRI available\n");
} }
#endif


XFree(vi); 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 void
@@ -340,18 +244,29 @@ puglDestroy(PuglView* view)
if (!view) { if (!view) {
return; return;
} }

#ifndef DGL_FILE_BROWSER_DISABLED #ifndef DGL_FILE_BROWSER_DISABLED
x_fib_close(view->impl->display); x_fib_close(view->impl->display);
#endif #endif


destroyContext(view);
glXDestroyContext(view->impl->display, view->impl->ctx);
XDestroyWindow(view->impl->display, view->impl->win); XDestroyWindow(view->impl->display, view->impl->win);
XCloseDisplay(view->impl->display); XCloseDisplay(view->impl->display);
free(view->impl); free(view->impl);
free(view); 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 static void
puglReshape(PuglView* view, int width, int height) puglReshape(PuglView* view, int width, int height)
{ {
@@ -360,7 +275,7 @@ puglReshape(PuglView* view, int width, int height)
if (view->reshapeFunc) { if (view->reshapeFunc) {
view->reshapeFunc(view, width, height); view->reshapeFunc(view, width, height);
} else { } else {
puglDefaultReshape(view, width, height);
puglDefaultReshape(width, height);
} }


puglLeaveContext(view, false); puglLeaveContext(view, false);
@@ -375,7 +290,6 @@ puglDisplay(PuglView* view)
puglEnterContext(view); puglEnterContext(view);


view->redisplay = false; view->redisplay = false;

if (view->displayFunc) { if (view->displayFunc) {
view->displayFunc(view); view->displayFunc(view);
} }
@@ -383,6 +297,36 @@ puglDisplay(PuglView* view)
puglLeaveContext(view, true); 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 static PuglKey
keySymToSpecial(KeySym sym) keySymToSpecial(KeySym sym)
{ {
@@ -477,6 +421,9 @@ send_event:
PuglStatus PuglStatus
puglProcessEvents(PuglView* view) puglProcessEvents(PuglView* view)
{ {
int conf_width = -1;
int conf_height = -1;

XEvent event; XEvent event;
while (XPending(view->impl->display) > 0) { while (XPending(view->impl->display) > 0) {
XNextEvent(view->impl->display, &event); XNextEvent(view->impl->display, &event);
@@ -511,22 +458,26 @@ puglProcessEvents(PuglView* view)
} }


switch (event.type) { switch (event.type) {
case UnmapNotify:
if (view->motionFunc) {
view->motionFunc(view, -1, -1);
}
break;
case MapNotify: case MapNotify:
puglReshape(view, view->width, view->height); puglReshape(view, view->width, view->height);
break; break;
case ConfigureNotify: case ConfigureNotify:
if ((event.xconfigure.width != view->width) || if ((event.xconfigure.width != view->width) ||
(event.xconfigure.height != view->height)) { (event.xconfigure.height != view->height)) {
puglReshape(view,
event.xconfigure.width,
event.xconfigure.height);
conf_width = event.xconfigure.width;
conf_height = event.xconfigure.height;
} }
break; break;
case Expose: case Expose:
if (event.xexpose.count != 0) { if (event.xexpose.count != 0) {
break; break;
} }
puglDisplay(view);
view->redisplay = true;
break; break;
case MotionNotify: case MotionNotify:
setModifiers(view, event.xmotion.state, event.xmotion.time); 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) { if (view->redisplay) {
puglDisplay(view); puglDisplay(view);
} }
@@ -615,22 +574,35 @@ puglPostRedisplay(PuglView* view)
view->redisplay = true; view->redisplay = true;
} }


void
puglPostResize(PuglView* view)
{
view->pending_resize = true;
}

PuglNativeWindow PuglNativeWindow
puglGetNativeWindow(PuglView* view) puglGetNativeWindow(PuglView* view)
{ {
return view->impl->win; 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 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'. The first tick is tick '0'.
*/ */
int32_t tick; int32_t tick;
@@ -567,7 +567,7 @@ struct TimePosition {
float beatType; 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. Usually a moderately large integer with many denominators, such as 1920.0.
*/ */
double ticksPerBeat; double ticksPerBeat;
@@ -590,6 +590,22 @@ struct TimePosition {
beatType(0.0f), beatType(0.0f),
ticksPerBeat(0.0), ticksPerBeat(0.0),
beatsPerMinute(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; } bbt;


/** /**
@@ -599,6 +615,16 @@ struct TimePosition {
: playing(false), : playing(false),
frame(0), frame(0),
bbt() {} 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) * 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 * Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this * or without fee is hereby granted, provided that the above copyright notice and this
@@ -20,7 +20,8 @@
#include "extra/LeakDetector.hpp" #include "extra/LeakDetector.hpp"
#include "src/DistrhoPluginChecks.h" #include "src/DistrhoPluginChecks.h"


#ifndef HAVE_DGL
#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI
# include "../dgl/Base.hpp"
# include "extra/ExternalWindow.hpp" # include "extra/ExternalWindow.hpp"
typedef DISTRHO_NAMESPACE::ExternalWindow UIWidget; typedef DISTRHO_NAMESPACE::ExternalWindow UIWidget;
#elif DISTRHO_UI_USE_NANOVG #elif DISTRHO_UI_USE_NANOVG
@@ -54,13 +55,28 @@ public:
UI class constructor. UI class constructor.
The UI should be initialized to a default state that matches the plugin side. 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. Destructor.
*/ */
virtual ~UI(); 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 */ * Host state */


@@ -166,7 +182,7 @@ protected:
*/ */
virtual void sampleRateChanged(double newSampleRate); virtual void sampleRateChanged(double newSampleRate);


#ifdef HAVE_DGL
#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI
/* -------------------------------------------------------------------------------------------------------- /* --------------------------------------------------------------------------------------------------------
* UI Callbacks (optional) */ * UI Callbacks (optional) */


@@ -176,13 +192,13 @@ protected:
*/ */
virtual void uiIdle() {} virtual void uiIdle() {}


#ifndef DGL_FILE_BROWSER_DISABLED
# ifndef DGL_FILE_BROWSER_DISABLED
/** /**
File browser selected function. File browser selected function.
@see Window::fileBrowserSelected(const char*) @see Window::fileBrowserSelected(const char*)
*/ */
virtual void uiFileBrowserSelected(const char* filename); virtual void uiFileBrowserSelected(const char* filename);
#endif
# endif


/** /**
OpenGL window reshape function, called when parent window is resized. OpenGL window reshape function, called when parent window is resized.
@@ -210,7 +226,7 @@ private:
friend class UIExporter; friend class UIExporter;
friend class UIExporterWindow; friend class UIExporterWindow;


#ifdef HAVE_DGL
#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI
// these should not be used // these should not be used
void setAbsoluteX(int) const noexcept {} void setAbsoluteX(int) const noexcept {}
void setAbsoluteY(int) const noexcept {} void setAbsoluteY(int) const noexcept {}


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

@@ -40,6 +40,8 @@ public:
: width(w), : width(w),
height(h), height(h),
title(t), title(t),
transientWinId(0),
visible(false),
pid(0) {} pid(0) {}


virtual ~ExternalWindow() virtual ~ExternalWindow()
@@ -62,9 +64,14 @@ public:
return title; 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 bool isRunning() noexcept
@@ -84,6 +91,27 @@ public:
return true; 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: protected:
bool startExternalProcess(const char* args[]) 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() void terminateAndWaitForProcess()
{ {
if (pid <= 0) 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) DISTRHO_DECLARE_NON_COPY_CLASS(ExternalWindow)
}; };




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

@@ -66,6 +66,15 @@
# define nullptr NULL # define nullptr NULL
#endif #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* */
#define DISTRHO_SAFE_ASSERT(cond) if (! (cond)) d_safe_assert(#cond, __FILE__, __LINE__); #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; } #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 // 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 # undef DISTRHO_PLUGIN_WANT_FULL_STATE
# define DISTRHO_PLUGIN_WANT_FULL_STATE 1 # define DISTRHO_PLUGIN_WANT_FULL_STATE 1
#endif #endif


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

@@ -16,11 +16,6 @@


#include "DistrhoPluginInternal.hpp" #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 #if DISTRHO_PLUGIN_HAS_UI
# include "DistrhoUIInternal.hpp" # include "DistrhoUIInternal.hpp"
#else #else


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

@@ -286,9 +286,9 @@ public:
# if DISTRHO_PLUGIN_WANT_STATE # if DISTRHO_PLUGIN_WANT_STATE
char* dssi_configure(const char* const key, const char* const value) 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; 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; return nullptr;


fPlugin.setState(key, value); fPlugin.setState(key, value);


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

@@ -169,7 +169,7 @@ public:
void lv2_activate() void lv2_activate()
{ {
#if DISTRHO_PLUGIN_WANT_TIMEPOS #if DISTRHO_PLUGIN_WANT_TIMEPOS
std::memset(&fTimePosition, 0, sizeof(TimePosition));
fTimePosition.clear();


// hosts may not send all values, resulting on some invalid data // hosts may not send all values, resulting on some invalid data
fTimePosition.bbt.bar = 1; fTimePosition.bbt.bar = 1;
@@ -613,7 +613,6 @@ public:
fEventsOutData.initIfNeeded(fURIDs.atomSequence); fEventsOutData.initIfNeeded(fURIDs.atomSequence);


LV2_Atom_Event* aev; LV2_Atom_Event* aev;
uint32_t offset = fEventsOutData.offset;
const uint32_t capacity = fEventsOutData.capacity; const uint32_t capacity = fEventsOutData.capacity;


for (uint32_t i=0, count=fPlugin.getStateCount(); i < count; ++i) 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) // set msg size (key + value + separator + 2x null terminator)
const size_t msgSize(key.length()+value.length()+3); 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; break;
}


// reserve msg space // reserve msg space
// FIXME create a large enough buffer beforehand // FIXME create a large enough buffer beforehand
@@ -644,15 +646,15 @@ public:
std::memset(msgBuf, 0, msgSize); std::memset(msgBuf, 0, msgSize);


// write key and value in atom bufer // 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 // 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->time.frames = 0;
aev->body.type = fURIDs.distrhoState; aev->body.type = fURIDs.distrhoState;
aev->body.size = msgSize; 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)); 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 # endif
manifestString += "\n"; manifestString += "\n";
# if DISTRHO_PLUGIN_HAS_EMBED_UI # if DISTRHO_PLUGIN_HAS_EMBED_UI
// TODO: pluginUI.isUserResizable()
manifestString += " lv2:optionalFeature ui:noUserResize ,\n"; manifestString += " lv2:optionalFeature ui:noUserResize ,\n";
manifestString += " ui:resize ,\n"; manifestString += " ui:resize ,\n";
manifestString += " ui:touch ;\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_INSTANCE_ACCESS_URI "> ,\n";
manifestString += " <" LV2_OPTIONS__options "> ,\n"; manifestString += " <" LV2_OPTIONS__options "> ,\n";
manifestString += " <" LV2_URID__map "> .\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"; manifestString += " rdfs:seeAlso <" + uiTTL + "> .\n";
# endif
# endif // DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
manifestString += "\n"; manifestString += "\n";
#endif #endif


@@ -192,7 +194,7 @@ void lv2_generate_ttl(const char* const basename)
String pluginString; String pluginString;


// header // 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"; pluginString += "@prefix atom: <" LV2_ATOM_PREFIX "> .\n";
#endif #endif
pluginString += "@prefix doap: <http://usefulinc.com/ns/doap#> .\n"; pluginString += "@prefix doap: <http://usefulinc.com/ns/doap#> .\n";
@@ -628,6 +630,7 @@ void lv2_generate_ttl(const char* const basename)
# endif # endif
uiString += "\n"; uiString += "\n";
# if DISTRHO_PLUGIN_HAS_EMBED_UI # if DISTRHO_PLUGIN_HAS_EMBED_UI
// TODO: pluginUI.isUserResizable()
uiString += " lv2:optionalFeature ui:noUserResize ,\n"; uiString += " lv2:optionalFeature ui:noUserResize ,\n";
uiString += " ui:resize ,\n"; uiString += " ui:resize ,\n";
uiString += " ui:touch ;\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) void strncpy(char* const dst, const char* const src, const size_t size)
{ {
DISTRHO_SAFE_ASSERT_RETURN(size > 0,); 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) void snprintf_param(char* const dst, const float value, const size_t size)
@@ -965,7 +973,7 @@ public:
if (vstTimeInfo->flags & (kVstPpqPosValid|kVstTimeSigValid)) if (vstTimeInfo->flags & (kVstPpqPosValid|kVstTimeSigValid))
{ {
const int ppqPerBar = vstTimeInfo->timeSigNumerator * 4 / vstTimeInfo->timeSigDenominator; 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); const double rest = std::fmod(barBeats, 1.0);


fTimePosition.bbt.bar = int(vstTimeInfo->ppqPos)/ppqPerBar + 1; 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) * 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 * Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this * or without fee is hereby granted, provided that the above copyright notice and this
@@ -15,8 +15,7 @@
*/ */


#include "DistrhoUIInternal.hpp" #include "DistrhoUIInternal.hpp"

#ifdef HAVE_DGL
#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI
# include "src/WidgetPrivateData.hpp" # include "src/WidgetPrivateData.hpp"
#endif #endif


@@ -27,29 +26,30 @@ START_NAMESPACE_DISTRHO


double d_lastUiSampleRate = 0.0; double d_lastUiSampleRate = 0.0;
void* d_lastUiDspPtr = nullptr; void* d_lastUiDspPtr = nullptr;
#ifdef HAVE_DGL
Window* d_lastUiWindow = nullptr;
#endif
#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI
uintptr_t g_nextWindowId = 0; uintptr_t g_nextWindowId = 0;
const char* g_nextBundlePath = nullptr; const char* g_nextBundlePath = nullptr;
#else
Window* d_lastUiWindow = nullptr;
#endif


/* ------------------------------------------------------------------------------------------------------------ /* ------------------------------------------------------------------------------------------------------------
* UI */ * 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), : UIWidget(*d_lastUiWindow),
pData(new PrivateData())
pData(new PrivateData(userResizable))
{ {
((UIWidget*)this)->pData->needsFullViewport = false; ((UIWidget*)this)->pData->needsFullViewport = false;


if (width > 0 && height > 0) if (width > 0 && height > 0)
setSize(width, height); setSize(width, height);
} }
#else
UI::UI(uint width, uint height)
: UIWidget(width, height),
pData(new PrivateData()) {}
#endif #endif


UI::~UI() UI::~UI()
@@ -57,6 +57,25 @@ UI::~UI()
delete pData; 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 */ * Host state */


@@ -121,15 +140,15 @@ uintptr_t UI::getNextWindowId() noexcept


void UI::sampleRateChanged(double) {} void UI::sampleRateChanged(double) {}


#ifdef HAVE_DGL
#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI
/* ------------------------------------------------------------------------------------------------------------ /* ------------------------------------------------------------------------------------------------------------
* UI Callbacks (optional) */ * UI Callbacks (optional) */


#ifndef DGL_FILE_BROWSER_DISABLED
# ifndef DGL_FILE_BROWSER_DISABLED
void UI::uiFileBrowserSelected(const char*) void UI::uiFileBrowserSelected(const char*)
{ {
} }
#endif
# endif


void UI::uiReshape(uint width, uint height) void UI::uiReshape(uint width, uint height)
{ {
@@ -148,9 +167,12 @@ void UI::uiReshape(uint width, uint height)


void UI::onResize(const ResizeEvent& ev) void UI::onResize(const ResizeEvent& ev)
{ {
if (pData->resizeInProgress)
return;

pData->setSizeCallback(ev.size.getWidth(), ev.size.getHeight()); 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] = { uint8_t mdata[4] = {
0, 0,
channel + (velocity != 0 ? 0x90 : 0x80),
static_cast<uint8_t>(channel + (velocity != 0 ? 0x90 : 0x80)),
note, note,
velocity velocity
}; };


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

@@ -19,7 +19,10 @@


#include "../DistrhoUI.hpp" #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/Application.hpp"
# include "../../dgl/Window.hpp" # include "../../dgl/Window.hpp"
using DGL_NAMESPACE::Application; using DGL_NAMESPACE::Application;
@@ -34,7 +37,7 @@ START_NAMESPACE_DISTRHO


extern double d_lastUiSampleRate; extern double d_lastUiSampleRate;
extern void* d_lastUiDspPtr; extern void* d_lastUiDspPtr;
#ifdef HAVE_DGL
#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI
extern Window* d_lastUiWindow; extern Window* d_lastUiWindow;
#endif #endif
extern uintptr_t g_nextWindowId; extern uintptr_t g_nextWindowId;
@@ -60,6 +63,13 @@ struct UI::PrivateData {
void* dspPtr; void* dspPtr;
#endif #endif


// UI
const bool userResizable;
bool automaticallyScale;
bool resizeInProgress;
uint minWidth;
uint minHeight;

// Callbacks // Callbacks
void* callbacksPtr; void* callbacksPtr;
editParamFunc editParamCallbackFunc; editParamFunc editParamCallbackFunc;
@@ -68,12 +78,17 @@ struct UI::PrivateData {
sendNoteFunc sendNoteCallbackFunc; sendNoteFunc sendNoteCallbackFunc;
setSizeFunc setSizeCallbackFunc; setSizeFunc setSizeCallbackFunc;


PrivateData() noexcept
PrivateData(const bool resizable) noexcept
: sampleRate(d_lastUiSampleRate), : sampleRate(d_lastUiSampleRate),
parameterOffset(0), parameterOffset(0),
#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS #if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
dspPtr(d_lastUiDspPtr), dspPtr(d_lastUiDspPtr),
#endif #endif
userResizable(resizable),
automaticallyScale(false),
resizeInProgress(false),
minWidth(0),
minHeight(0),
callbacksPtr(nullptr), callbacksPtr(nullptr),
editParamCallbackFunc(nullptr), editParamCallbackFunc(nullptr),
setParamCallbackFunc(nullptr), setParamCallbackFunc(nullptr),
@@ -134,7 +149,20 @@ struct UI::PrivateData {
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
// Plugin Window, needed to take care of resize properly // 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 static inline
UI* createUiWrapper(void* const dspPtr, Window* const window) UI* createUiWrapper(void* const dspPtr, Window* const window)
{ {
@@ -155,9 +183,9 @@ public:
fIsReady(false) fIsReady(false)
{ {
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,); 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()); setSize(fUI->getWidth(), fUI->getHeight());
} }


@@ -182,11 +210,25 @@ protected:
{ {
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,); 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); fUI->uiReshape(width, height);
fIsReady = true; fIsReady = true;
} }


#ifndef DGL_FILE_BROWSER_DISABLED
# ifndef DGL_FILE_BROWSER_DISABLED
// custom file-browser selected // custom file-browser selected
void fileBrowserSelected(const char* filename) override void fileBrowserSelected(const char* filename) override
{ {
@@ -194,26 +236,13 @@ protected:


fUI->uiFileBrowserSelected(filename); fUI->uiFileBrowserSelected(filename);
} }
#endif
# endif


private: private:
UI* const fUI; UI* const fUI;
bool fIsReady; 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 // UI exporter class
@@ -230,13 +259,13 @@ public:
const setSizeFunc setSizeCall, const setSizeFunc setSizeCall,
void* const dspPtr = nullptr, void* const dspPtr = nullptr,
const char* const bundlePath = nullptr) const char* const bundlePath = nullptr)
#ifdef HAVE_DGL
#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI
: fUI(createUiWrapper(dspPtr, winId, bundlePath)),
#else
: glApp(), : glApp(),
glWindow(glApp, winId, dspPtr), glWindow(glApp, winId, dspPtr),
fChangingSize(false), fChangingSize(false),
fUI(glWindow.getUI()), fUI(glWindow.getUI()),
#else
: fUI(createUiWrapper(dspPtr, winId, bundlePath)),
#endif #endif
fData((fUI != nullptr) ? fUI->pData : nullptr) fData((fUI != nullptr) ? fUI->pData : nullptr)
{ {
@@ -250,54 +279,65 @@ public:
fData->sendNoteCallbackFunc = sendNoteCall; fData->sendNoteCallbackFunc = sendNoteCall;
fData->setSizeCallbackFunc = setSizeCall; fData->setSizeCallbackFunc = setSizeCall;


#ifdef HAVE_DGL
#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI
// unused // unused
return; (void)bundlePath; return; (void)bundlePath;
#endif #endif
} }


#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI
~UIExporter()
{
delete fUI;
}
#endif

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


#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI
uint getWidth() const noexcept uint getWidth() const noexcept
{ {
#ifdef HAVE_DGL
return glWindow.getWidth();
#else
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr, 1); DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr, 1);
return fUI->getWidth(); return fUI->getWidth();
#endif
} }


uint getHeight() const noexcept uint getHeight() const noexcept
{ {
#ifdef HAVE_DGL
return glWindow.getHeight();
#else
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr, 1); DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr, 1);
return fUI->getHeight(); return fUI->getHeight();
#endif
} }


bool isVisible() const noexcept bool isVisible() const noexcept
{ {
#ifdef HAVE_DGL
return glWindow.isVisible();
#else
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr, false); DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr, false);
return fUI->isRunning(); 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 intptr_t getWindowId() const noexcept
{ {
#ifdef HAVE_DGL
return glWindow.getWindowId(); 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) void exec(IdleCallback* const cb)
{ {
DISTRHO_SAFE_ASSERT_RETURN(cb != nullptr,); DISTRHO_SAFE_ASSERT_RETURN(cb != nullptr,);
@@ -355,48 +427,64 @@ public:
if (glWindow.isReady()) if (glWindow.isReady())
fUI->uiIdle(); fUI->uiIdle();
} }
#endif


bool idle() bool idle()
{ {
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr, false); DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr, false);


#ifdef HAVE_DGL
glApp.idle(); glApp.idle();


if (glWindow.isReady()) if (glWindow.isReady())
fUI->uiIdle(); fUI->uiIdle();


return ! glApp.isQuiting(); return ! glApp.isQuiting();
#else
return fUI->isRunning();
#endif
} }


void quit() void quit()
{ {
#ifdef HAVE_DGL
glWindow.close(); glWindow.close();
glApp.quit(); 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) void setWindowTitle(const char* const uiTitle)
{ {
#ifdef HAVE_DGL
glWindow.setTitle(uiTitle);
#else
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,); DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,);

fUI->setTitle(uiTitle); 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) void setWindowSize(const uint width, const uint height, const bool updateUI = false)
{ {
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,); DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,);
@@ -431,12 +519,8 @@ public:


bool handlePluginSpecial(const bool press, const Key key) 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 #endif


// ------------------------------------------------------------------- // -------------------------------------------------------------------
@@ -457,7 +541,7 @@ public:
} }


private: private:
#ifdef HAVE_DGL
#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// DGL Application and Window for this widget // 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 @endcode
*/ */
#define LV2_ATOM_SEQUENCE_FOREACH(seq, iter) \ #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)); \ !lv2_atom_sequence_is_end(&(seq)->body, (seq)->atom.size, (iter)); \
(iter) = lv2_atom_sequence_next(iter)) (iter) = lv2_atom_sequence_next(iter))


/** Like LV2_ATOM_SEQUENCE_FOREACH but for a headerless sequence body. */ /** Like LV2_ATOM_SEQUENCE_FOREACH but for a headerless sequence body. */
#define LV2_ATOM_SEQUENCE_BODY_FOREACH(body, size, iter) \ #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)); \ !lv2_atom_sequence_is_end(body, size, (iter)); \
(iter) = lv2_atom_sequence_next(iter)) (iter) = lv2_atom_sequence_next(iter))


@@ -214,13 +214,13 @@ lv2_atom_tuple_next(const LV2_Atom* i)
@endcode @endcode
*/ */
#define LV2_ATOM_TUPLE_FOREACH(tuple, iter) \ #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)); \ !lv2_atom_tuple_is_end(LV2_ATOM_BODY_CONST(tuple), (tuple)->size, (iter)); \
(iter) = lv2_atom_tuple_next(iter)) (iter) = lv2_atom_tuple_next(iter))


/** Like LV2_ATOM_TUPLE_FOREACH but for a headerless tuple body. */ /** Like LV2_ATOM_TUPLE_FOREACH but for a headerless tuple body. */
#define LV2_ATOM_TUPLE_BODY_FOREACH(body, size, iter) \ #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)); \ !lv2_atom_tuple_is_end(body, size, (iter)); \
(iter) = lv2_atom_tuple_next(iter)) (iter) = lv2_atom_tuple_next(iter))


@@ -270,13 +270,13 @@ lv2_atom_object_next(const LV2_Atom_Property_Body* i)
@endcode @endcode
*/ */
#define LV2_ATOM_OBJECT_FOREACH(obj, iter) \ #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)); \ !lv2_atom_object_is_end(&(obj)->body, (obj)->atom.size, (iter)); \
(iter) = lv2_atom_object_next(iter)) (iter) = lv2_atom_object_next(iter))


/** Like LV2_ATOM_OBJECT_FOREACH but for a headerless object body. */ /** Like LV2_ATOM_OBJECT_FOREACH but for a headerless object body. */
#define LV2_ATOM_OBJECT_BODY_FOREACH(body, size, iter) \ #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)); \ !lv2_atom_object_is_end(body, size, (iter)); \
(iter) = lv2_atom_object_next(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 -*- # -*- coding: utf-8 -*-


# DISTRHO Plugin Framework (DPF) # DISTRHO Plugin Framework (DPF)
# Copyright (C) 2012-2016 Filipe Coelho <falktx@falktx.com>
# Copyright (C) 2012-2019 Filipe Coelho <falktx@falktx.com>
# #
# Permission to use, copy, modify, and/or distribute this software for any purpose with # Permission to use, copy, modify, and/or distribute this software for any purpose with
# or without fee is hereby granted, provided that the above copyright notice and this # or without fee is hereby granted, provided that the above copyright notice and this
@@ -52,7 +52,10 @@ def png2rgba(namespace, filenames):
shortFilename = filename.rsplit(os.sep, 1)[-1].split(".", 1)[0] shortFilename = filename.rsplit(os.sep, 1)[-1].split(".", 1)[0]
shortFilename = shortFilename.replace("-", "_") shortFilename = shortFilename.replace("-", "_")


png = Image.open(filename)
png = Image.open(filename)
if png.getpalette():
png = png.convert()

pngNumpy = numpy.array(png) pngNumpy = numpy.array(png)
pngData = pngNumpy.tolist() pngData = pngNumpy.tolist()
#pngData.reverse() #pngData.reverse()


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

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


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


Loading…
Cancel
Save