Browse Source

Update to latest dgl and distrho

tags/1.9.7
falkTX 10 years ago
parent
commit
947854e292
92 changed files with 130608 additions and 8721 deletions
  1. +6
    -6
      source/modules/dgl/Application.hpp
  2. +43
    -35
      source/modules/dgl/Base.hpp
  3. +3
    -5
      source/modules/dgl/Color.hpp
  4. +1
    -1
      source/modules/dgl/Geometry.hpp
  5. +5
    -5
      source/modules/dgl/Image.hpp
  6. +3
    -34
      source/modules/dgl/ImageAboutWindow.hpp
  7. +3
    -47
      source/modules/dgl/ImageButton.hpp
  8. +3
    -83
      source/modules/dgl/ImageKnob.hpp
  9. +3
    -78
      source/modules/dgl/ImageSlider.hpp
  10. +3
    -45
      source/modules/dgl/ImageSwitch.hpp
  11. +271
    -0
      source/modules/dgl/ImageWidgets.hpp
  12. +6
    -6
      source/modules/dgl/Makefile
  13. +181
    -62
      source/modules/dgl/NanoVG.hpp
  14. +67
    -0
      source/modules/dgl/NanoWidgets.hpp
  15. +18
    -38
      source/modules/dgl/StandaloneWindow.hpp
  16. +25
    -27
      source/modules/dgl/Widget.hpp
  17. +7
    -7
      source/modules/dgl/Window.hpp
  18. +9
    -10
      source/modules/dgl/src/Application.cpp
  19. +4
    -4
      source/modules/dgl/src/ApplicationPrivateData.hpp
  20. +1
    -1
      source/modules/dgl/src/Color.cpp
  21. +129
    -0
      source/modules/dgl/src/Common.hpp
  22. +1
    -1
      source/modules/dgl/src/Geometry.cpp
  23. +1
    -1
      source/modules/dgl/src/Image.cpp
  24. +0
    -89
      source/modules/dgl/src/ImageAboutWindow.cpp
  25. +0
    -190
      source/modules/dgl/src/ImageButton.cpp
  26. +0
    -459
      source/modules/dgl/src/ImageKnob.cpp
  27. +0
    -399
      source/modules/dgl/src/ImageSlider.cpp
  28. +0
    -122
      source/modules/dgl/src/ImageSwitch.cpp
  29. +1078
    -0
      source/modules/dgl/src/ImageWidgets.cpp
  30. +234
    -90
      source/modules/dgl/src/NanoVG.cpp
  31. +144
    -0
      source/modules/dgl/src/NanoWidgets.cpp
  32. +58
    -63
      source/modules/dgl/src/Widget.cpp
  33. +133
    -0
      source/modules/dgl/src/WidgetPrivateData.hpp
  34. +97
    -89
      source/modules/dgl/src/Window.cpp
  35. +194
    -176
      source/modules/dgl/src/nanovg/fontstash.h
  36. +789
    -512
      source/modules/dgl/src/nanovg/nanovg.c
  37. +171
    -141
      source/modules/dgl/src/nanovg/nanovg.h
  38. +529
    -297
      source/modules/dgl/src/nanovg/nanovg_gl.h
  39. +132
    -0
      source/modules/dgl/src/nanovg/nanovg_gl_utils.h
  40. +4648
    -4676
      source/modules/dgl/src/nanovg/stb_image.h
  41. +33
    -16
      source/modules/dgl/src/nanovg/stb_truetype.h
  42. +21
    -0
      source/modules/dgl/src/oui-blendish/LICENSE
  43. +2399
    -0
      source/modules/dgl/src/oui-blendish/blendish.h
  44. +24815
    -0
      source/modules/dgl/src/oui-blendish/blendish_resources.cpp
  45. +15
    -0
      source/modules/dgl/src/oui-blendish/blendish_resources.h
  46. +2025
    -0
      source/modules/dgl/src/oui-blendish/oui.h
  47. BIN
      source/modules/dgl/src/oui-blendish/resources/DejaVuSans.ttf
  48. +97
    -0
      source/modules/dgl/src/oui-blendish/resources/LICENSE-DejaVuSans.ttf.txt
  49. +280
    -0
      source/modules/dgl/src/oui-blendish/resources/LICENSE-blender_icons.svg.txt
  50. +88974
    -0
      source/modules/dgl/src/oui-blendish/resources/blender_icons.svg
  51. BIN
      source/modules/dgl/src/oui-blendish/resources/blender_icons16.png
  52. +121
    -0
      source/modules/dgl/src/pugl/common.h
  53. +41
    -0
      source/modules/dgl/src/pugl/event.h
  54. +32
    -0
      source/modules/dgl/src/pugl/gl.h
  55. +32
    -0
      source/modules/dgl/src/pugl/glu.h
  56. +71
    -92
      source/modules/dgl/src/pugl/pugl.h
  57. +162
    -19
      source/modules/dgl/src/pugl/pugl_internal.h
  58. +39
    -12
      source/modules/dgl/src/pugl/pugl_osx.m
  59. +79
    -25
      source/modules/dgl/src/pugl/pugl_win.cpp
  60. +241
    -90
      source/modules/dgl/src/pugl/pugl_x11.c
  61. +5
    -5
      source/modules/dgl/src/sofd/libsofd.h
  62. +571
    -0
      source/modules/distrho/DistrhoInfo.hpp
  63. +213
    -129
      source/modules/distrho/DistrhoPlugin.hpp
  64. +1
    -1
      source/modules/distrho/DistrhoPluginMain.cpp
  65. +35
    -22
      source/modules/distrho/DistrhoUI.hpp
  66. +1
    -1
      source/modules/distrho/DistrhoUIMain.cpp
  67. +32
    -1
      source/modules/distrho/DistrhoUtils.hpp
  68. +127
    -0
      source/modules/distrho/extra/Base64.hpp
  69. +11
    -4
      source/modules/distrho/extra/LeakDetector.hpp
  70. +57
    -13
      source/modules/distrho/extra/Mutex.hpp
  71. +4
    -21
      source/modules/distrho/extra/ScopedPointer.hpp
  72. +7
    -1
      source/modules/distrho/extra/Sleep.hpp
  73. +187
    -97
      source/modules/distrho/extra/String.hpp
  74. +11
    -12
      source/modules/distrho/extra/Thread.hpp
  75. +1
    -1
      source/modules/distrho/src/DistrhoDefines.h
  76. +40
    -14
      source/modules/distrho/src/DistrhoPlugin.cpp
  77. +3
    -3
      source/modules/distrho/src/DistrhoPluginCarla.cpp
  78. +41
    -37
      source/modules/distrho/src/DistrhoPluginChecks.h
  79. +119
    -37
      source/modules/distrho/src/DistrhoPluginInternal.hpp
  80. +97
    -8
      source/modules/distrho/src/DistrhoPluginJack.cpp
  81. +12
    -14
      source/modules/distrho/src/DistrhoPluginLADSPA+DSSI.cpp
  82. +185
    -119
      source/modules/distrho/src/DistrhoPluginLV2.cpp
  83. +241
    -60
      source/modules/distrho/src/DistrhoPluginLV2export.cpp
  84. +89
    -35
      source/modules/distrho/src/DistrhoPluginVST.cpp
  85. +16
    -12
      source/modules/distrho/src/DistrhoUI.cpp
  86. +3
    -3
      source/modules/distrho/src/DistrhoUIDSSI.cpp
  87. +14
    -14
      source/modules/distrho/src/DistrhoUIInternal.hpp
  88. +4
    -4
      source/modules/distrho/src/DistrhoUILV2.cpp
  89. +1
    -0
      source/modules/distrho/src/dssi
  90. +1
    -0
      source/modules/distrho/src/ladspa
  91. +1
    -0
      source/modules/distrho/src/lv2
  92. +1
    -0
      source/modules/distrho/src/vestige

source/modules/dgl/App.hpp → source/modules/dgl/Application.hpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2015 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
@@ -38,18 +38,18 @@ class Window;
In standalone mode an application will automatically quit its
event-loop when all its windows are closed.
*/
class App
class Application
{
public:
/**
Constructor.
*/
App();
Application();

/**
Destructor.
*/
~App();
~Application();

/**
Idle function.
@@ -60,7 +60,7 @@ public:
/**
Run the application event-loop until all Windows are closed.
idle() is called at regular intervals.
@note: This function is meant for standalones only, *never* call this from plugins.
@note This function is meant for standalones only, *never* call this from plugins.
*/
void exec();

@@ -81,7 +81,7 @@ private:
PrivateData* const pData;
friend class Window;

DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(App)
DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(Application)
};

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

+ 43
- 35
source/modules/dgl/Base.hpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2015 Filipe Coelho <falktx@falktx.com>
*
* Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this
@@ -17,8 +17,8 @@
#ifndef DGL_BASE_HPP_INCLUDED
#define DGL_BASE_HPP_INCLUDED

#include "../distrho/extra/d_leakdetector.hpp"
#include "../distrho/extra/d_scopedpointer.hpp"
#include "../distrho/extra/LeakDetector.hpp"
#include "../distrho/extra/ScopedPointer.hpp"

// -----------------------------------------------------------------------
// Define namespace
@@ -121,50 +121,50 @@ START_NAMESPACE_DGL
Convenience symbols for ASCII control characters.
*/
enum Char {
CHAR_BACKSPACE = 0x08,
CHAR_ESCAPE = 0x1B,
CHAR_DELETE = 0x7F
kCharBackspace = 0x08,
kCharEscape = 0x1B,
kCharDelete = 0x7F
};

/**
Keyboard modifier flags.
*/
enum Modifier {
MODIFIER_SHIFT = 1 << 0, /**< Shift key */
MODIFIER_CTRL = 1 << 1, /**< Control key */
MODIFIER_ALT = 1 << 2, /**< Alt/Option key */
MODIFIER_SUPER = 1 << 3 /**< Mod4/Command/Windows key */
kModifierShift = 1 << 0, /**< Shift key */
kModifierControl = 1 << 1, /**< Control key */
kModifierAlt = 1 << 2, /**< Alt/Option key */
kModifierSuper = 1 << 3 /**< Mod4/Command/Windows key */
};

/**
Special (non-Unicode) keyboard keys.
*/
enum Key {
KEY_F1 = 1,
KEY_F2,
KEY_F3,
KEY_F4,
KEY_F5,
KEY_F6,
KEY_F7,
KEY_F8,
KEY_F9,
KEY_F10,
KEY_F11,
KEY_F12,
KEY_LEFT,
KEY_UP,
KEY_RIGHT,
KEY_DOWN,
KEY_PAGE_UP,
KEY_PAGE_DOWN,
KEY_HOME,
KEY_END,
KEY_INSERT,
KEY_SHIFT,
KEY_CTRL,
KEY_ALT,
KEY_SUPER
kKeyF1 = 1,
kKeyF2,
kKeyF3,
kKeyF4,
kKeyF5,
kKeyF6,
kKeyF7,
kKeyF8,
kKeyF9,
kKeyF10,
kKeyF11,
kKeyF12,
kKeyLeft,
kKeyUp,
kKeyRight,
kKeyDown,
kKeyPageUp,
kKeyPageDown,
kKeyHome,
kKeyEnd,
kKeyInsert,
kKeyShift,
kKeyControl,
kKeyAlt,
kKeySuper
};

// -----------------------------------------------------------------------
@@ -184,4 +184,12 @@ public:

END_NAMESPACE_DGL

#ifndef DONT_SET_USING_DGL_NAMESPACE
// If your code uses a lot of DGL classes, then this will obviously save you
// a lot of typing, but can be disabled by setting DONT_SET_USING_DGL_NAMESPACE.
using namespace DGL_NAMESPACE;
#endif

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

#endif // DGL_BASE_HPP_INCLUDED

+ 3
- 5
source/modules/dgl/Color.hpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2015 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
@@ -25,8 +25,6 @@ START_NAMESPACE_DGL

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

// TODO: create color from "#333" and "#112233" like strings

/**
A color made from red, green, blue and alpha floating-point values in [0..1] range.
*/
@@ -40,7 +38,7 @@ struct Color {
};

/**
Create black color.
Create solid black color.
*/
Color() noexcept;

@@ -85,7 +83,7 @@ struct Color {

/**
Check if this color matches another.
@note: Comparison is forced within 8-bit color values.
@note Comparison is forced within 8-bit color values.
*/
bool isEqual(const Color& color, bool withAlpha = true) noexcept;
bool isNotEqual(const Color& color, bool withAlpha = true) noexcept;


+ 1
- 1
source/modules/dgl/Geometry.hpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2015 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


+ 5
- 5
source/modules/dgl/Image.hpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2015 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
@@ -45,13 +45,13 @@ public:

/**
Constructor using raw image data.
@note: @a rawData must remain valid for the lifetime of this Image.
@note @a rawData must remain valid for the lifetime of this Image.
*/
Image(const char* const rawData, const uint width, const uint height, const GLenum format = GL_BGRA, const GLenum type = GL_UNSIGNED_BYTE);

/**
Constructor using raw image data.
@note: @a rawData must remain valid for the lifetime of this Image.
@note @a rawData must remain valid for the lifetime of this Image.
*/
Image(const char* const rawData, const Size<uint>& size, const GLenum format = GL_BGRA, const GLenum type = GL_UNSIGNED_BYTE);

@@ -67,13 +67,13 @@ public:

/**
Load image data from memory.
@note: @a rawData must remain valid for the lifetime of this Image.
@note @a rawData must remain valid for the lifetime of this Image.
*/
void loadFromMemory(const char* const rawData, const uint width, const uint height, const GLenum format = GL_BGRA, const GLenum type = GL_UNSIGNED_BYTE) noexcept;

/**
Load image data from memory.
@note: @a rawData must remain valid for the lifetime of this Image.
@note @a rawData must remain valid for the lifetime of this Image.
*/
void loadFromMemory(const char* const rawData, const Size<uint>& size, const GLenum format = GL_BGRA, const GLenum type = GL_UNSIGNED_BYTE) noexcept;



+ 3
- 34
source/modules/dgl/ImageAboutWindow.hpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2015 Filipe Coelho <falktx@falktx.com>
*
* Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this
@@ -17,38 +17,7 @@
#ifndef DGL_IMAGE_ABOUT_WINDOW_HPP_INCLUDED
#define DGL_IMAGE_ABOUT_WINDOW_HPP_INCLUDED

#include "Image.hpp"
#include "Widget.hpp"
#include "Window.hpp"

START_NAMESPACE_DGL

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

class ImageAboutWindow : public Window,
public Widget
{
public:
explicit ImageAboutWindow(Window& parent, const Image& image = Image());
explicit ImageAboutWindow(Widget* widget, const Image& image = Image());

void setImage(const Image& image);

protected:
void onDisplay() override;
bool onKeyboard(const KeyboardEvent&) override;
bool onMouse(const MouseEvent&) override;
void onReshape(uint width, uint height) override;

private:
Image fImgBackground;

DISTRHO_DECLARE_NON_COPY_CLASS(ImageAboutWindow)
//DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ImageAboutWindow)
};

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

END_NAMESPACE_DGL
#warning This is a deprecated file, please include ImageWidgets.hpp instead.
#include "ImageWidgets.hpp"

#endif // DGL_IMAGE_ABOUT_WINDOW_HPP_INCLUDED

+ 3
- 47
source/modules/dgl/ImageButton.hpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2015 Filipe Coelho <falktx@falktx.com>
*
* Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this
@@ -17,51 +17,7 @@
#ifndef DGL_IMAGE_BUTTON_HPP_INCLUDED
#define DGL_IMAGE_BUTTON_HPP_INCLUDED

#include "Image.hpp"
#include "Widget.hpp"

START_NAMESPACE_DGL

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

class ImageButton : public Widget
{
public:
class Callback
{
public:
virtual ~Callback() {}
virtual void imageButtonClicked(ImageButton* imageButton, int button) = 0;
};

explicit ImageButton(Window& parent, const Image& image) noexcept;
explicit ImageButton(Window& parent, const Image& imageNormal, const Image& imageHover, const Image& imageDown) noexcept;
explicit ImageButton(Widget* widget, const Image& image) noexcept;
explicit ImageButton(Widget* widget, const Image& imageNormal, const Image& imageHover, const Image& imageDown) noexcept;
explicit ImageButton(const ImageButton& imageButton) noexcept;
ImageButton& operator=(const ImageButton& imageButton) noexcept;

void setCallback(Callback* callback) noexcept;

protected:
void onDisplay() override;
bool onMouse(const MouseEvent&) override;
bool onMotion(const MotionEvent&) override;

private:
Image fImageNormal;
Image fImageHover;
Image fImageDown;
Image* fCurImage;
int fCurButton;

Callback* fCallback;

DISTRHO_LEAK_DETECTOR(ImageButton)
};

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

END_NAMESPACE_DGL
#warning This is a deprecated file, please include ImageWidgets.hpp instead.
#include "ImageWidgets.hpp"

#endif // DGL_IMAGE_BUTTON_HPP_INCLUDED

+ 3
- 83
source/modules/dgl/ImageKnob.hpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2015 Filipe Coelho <falktx@falktx.com>
*
* Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this
@@ -17,87 +17,7 @@
#ifndef DGL_IMAGE_KNOB_HPP_INCLUDED
#define DGL_IMAGE_KNOB_HPP_INCLUDED

#include "Image.hpp"
#include "Widget.hpp"

START_NAMESPACE_DGL

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

class ImageKnob : public Widget
{
public:
enum Orientation {
Horizontal,
Vertical
};

class Callback
{
public:
virtual ~Callback() {}
virtual void imageKnobDragStarted(ImageKnob* imageKnob) = 0;
virtual void imageKnobDragFinished(ImageKnob* imageKnob) = 0;
virtual void imageKnobValueChanged(ImageKnob* imageKnob, float value) = 0;
};

explicit ImageKnob(Window& parent, const Image& image, Orientation orientation = Vertical) noexcept;
explicit ImageKnob(Widget* widget, const Image& image, Orientation orientation = Vertical) noexcept;
explicit ImageKnob(const ImageKnob& imageKnob);
ImageKnob& operator=(const ImageKnob& imageKnob);
~ImageKnob() override;

float getValue() const noexcept;

void setDefault(float def) noexcept;
void setRange(float min, float max) noexcept;
void setStep(float step) noexcept;
void setValue(float value, bool sendCallback = false) noexcept;
void setUsingLogScale(bool yesNo) noexcept;

void setCallback(Callback* callback) noexcept;
void setOrientation(Orientation orientation) noexcept;
void setRotationAngle(int angle);

protected:
void onDisplay() override;
bool onMouse(const MouseEvent&) override;
bool onMotion(const MotionEvent&) override;
bool onScroll(const ScrollEvent&) override;

private:
Image fImage;
float fMinimum;
float fMaximum;
float fStep;
float fValue;
float fValueDef;
float fValueTmp;
bool fUsingDefault;
bool fUsingLog;
Orientation fOrientation;

int fRotationAngle;
bool fDragging;
int fLastX;
int fLastY;

Callback* fCallback;

bool fIsImgVertical;
uint fImgLayerSize;
uint fImgLayerCount;
bool fIsReady;
GLuint fTextureId;

float _logscale(float value) const;
float _invlogscale(float value) const;

DISTRHO_LEAK_DETECTOR(ImageKnob)
};

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

END_NAMESPACE_DGL
#warning This is a deprecated file, please include ImageWidgets.hpp instead.
#include "ImageWidgets.hpp"

#endif // DGL_IMAGE_KNOB_HPP_INCLUDED

+ 3
- 78
source/modules/dgl/ImageSlider.hpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2015 Filipe Coelho <falktx@falktx.com>
*
* Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this
@@ -17,82 +17,7 @@
#ifndef DGL_IMAGE_SLIDER_HPP_INCLUDED
#define DGL_IMAGE_SLIDER_HPP_INCLUDED

#include "Image.hpp"
#include "Widget.hpp"

START_NAMESPACE_DGL

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

class ImageSlider : public Widget
{
public:
class Callback
{
public:
virtual ~Callback() {}
virtual void imageSliderDragStarted(ImageSlider* imageSlider) = 0;
virtual void imageSliderDragFinished(ImageSlider* imageSlider) = 0;
virtual void imageSliderValueChanged(ImageSlider* imageSlider, float value) = 0;
};

explicit ImageSlider(Window& parent, const Image& image) noexcept;
explicit ImageSlider(Widget* widget, const Image& image) noexcept;
explicit ImageSlider(const ImageSlider& imageSlider) noexcept;
ImageSlider& operator=(const ImageSlider& imageSlider) noexcept;

float getValue() const noexcept;

void setStartPos(const Point<int>& startPos) noexcept;
void setStartPos(int x, int y) noexcept;
void setEndPos(const Point<int>& endPos) noexcept;
void setEndPos(int x, int y) noexcept;

void setInverted(bool inverted) noexcept;
void setRange(float min, float max) noexcept;
void setStep(float step) noexcept;
void setValue(float value, bool sendCallback = false) noexcept;

void setCallback(Callback* callback) noexcept;

protected:
void onDisplay() override;
bool onMouse(const MouseEvent&) override;
bool onMotion(const MotionEvent&) override;

private:
Image fImage;
float fMinimum;
float fMaximum;
float fStep;
float fValue;
float fValueTmp;

bool fDragging;
bool fInverted;
int fStartedX;
int fStartedY;

Callback* fCallback;

Point<int> fStartPos;
Point<int> fEndPos;
Rectangle<int> fSliderArea;

void _recheckArea() noexcept;

// these should not be used
void setAbsoluteX(int) const noexcept {}
void setAbsoluteY(int) const noexcept {}
void setAbsolutePos(int, int) const noexcept {}
void setAbsolutePos(const Point<int>&) const noexcept {}
void setNeedsFullViewport(bool) const noexcept {}

DISTRHO_LEAK_DETECTOR(ImageSlider)
};

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

END_NAMESPACE_DGL
#warning This is a deprecated file, please include ImageWidgets.hpp instead.
#include "ImageWidgets.hpp"

#endif // DGL_IMAGE_SLIDER_HPP_INCLUDED

+ 3
- 45
source/modules/dgl/ImageSwitch.hpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2015 Filipe Coelho <falktx@falktx.com>
*
* Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this
@@ -17,49 +17,7 @@
#ifndef DGL_IMAGE_SWITCH_HPP_INCLUDED
#define DGL_IMAGE_SWITCH_HPP_INCLUDED

#include "Image.hpp"
#include "Widget.hpp"

START_NAMESPACE_DGL

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

class ImageSwitch : public Widget
{
public:
class Callback
{
public:
virtual ~Callback() {}
virtual void imageSwitchClicked(ImageSwitch* imageButton, bool down) = 0;
};

explicit ImageSwitch(Window& parent, const Image& imageNormal, const Image& imageDown) noexcept;
explicit ImageSwitch(Widget* widget, const Image& imageNormal, const Image& imageDown) noexcept;
explicit ImageSwitch(const ImageSwitch& imageSwitch) noexcept;
ImageSwitch& operator=(const ImageSwitch& imageSwitch) noexcept;

bool isDown() const noexcept;
void setDown(bool down) noexcept;

void setCallback(Callback* callback) noexcept;

protected:
void onDisplay() override;
bool onMouse(const MouseEvent&) override;

private:
Image fImageNormal;
Image fImageDown;
bool fIsDown;

Callback* fCallback;

DISTRHO_LEAK_DETECTOR(ImageSwitch)
};

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

END_NAMESPACE_DGL
#warning This is a deprecated file, please include ImageWidgets.hpp instead.
#include "ImageWidgets.hpp"

#endif // DGL_IMAGE_SWITCH_HPP_INCLUDED

+ 271
- 0
source/modules/dgl/ImageWidgets.hpp View File

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

#ifndef DGL_IMAGE_WIDGETS_HPP_INCLUDED
#define DGL_IMAGE_WIDGETS_HPP_INCLUDED

#include "Image.hpp"
#include "Widget.hpp"
#include "Window.hpp"

START_NAMESPACE_DGL

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

class ImageAboutWindow : public Window,
public Widget
{
public:
explicit ImageAboutWindow(Window& parent, const Image& image = Image());
explicit ImageAboutWindow(Widget* widget, const Image& image = Image());

void setImage(const Image& image);

protected:
void onDisplay() override;
bool onKeyboard(const KeyboardEvent&) override;
bool onMouse(const MouseEvent&) override;
void onReshape(uint width, uint height) override;

private:
Image fImgBackground;

DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ImageAboutWindow)
};

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

class ImageButton : public Widget
{
public:
class Callback
{
public:
virtual ~Callback() {}
virtual void imageButtonClicked(ImageButton* imageButton, int button) = 0;
};

explicit ImageButton(Window& parent, const Image& image);
explicit ImageButton(Window& parent, const Image& imageNormal, const Image& imageDown);
explicit ImageButton(Window& parent, const Image& imageNormal, const Image& imageHover, const Image& imageDown);

explicit ImageButton(Widget* widget, const Image& image);
explicit ImageButton(Widget* widget, const Image& imageNormal, const Image& imageDown);
explicit ImageButton(Widget* widget, const Image& imageNormal, const Image& imageHover, const Image& imageDown);

~ImageButton() override;

void setCallback(Callback* callback) noexcept;

protected:
void onDisplay() override;
bool onMouse(const MouseEvent&) override;
bool onMotion(const MotionEvent&) override;

private:
struct PrivateData;
PrivateData* const pData;

DISTRHO_LEAK_DETECTOR(ImageButton)
};

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

class ImageKnob : public Widget
{
public:
enum Orientation {
Horizontal,
Vertical
};

class Callback
{
public:
virtual ~Callback() {}
virtual void imageKnobDragStarted(ImageKnob* imageKnob) = 0;
virtual void imageKnobDragFinished(ImageKnob* imageKnob) = 0;
virtual void imageKnobValueChanged(ImageKnob* imageKnob, float value) = 0;
};

explicit ImageKnob(Window& parent, const Image& image, Orientation orientation = Vertical) noexcept;
explicit ImageKnob(Widget* widget, const Image& image, Orientation orientation = Vertical) noexcept;
explicit ImageKnob(const ImageKnob& imageKnob);
ImageKnob& operator=(const ImageKnob& imageKnob);
~ImageKnob() override;

float getValue() const noexcept;

void setDefault(float def) noexcept;
void setRange(float min, float max) noexcept;
void setStep(float step) noexcept;
void setValue(float value, bool sendCallback = false) noexcept;
void setUsingLogScale(bool yesNo) noexcept;

void setCallback(Callback* callback) noexcept;
void setOrientation(Orientation orientation) noexcept;
void setRotationAngle(int angle);

void setImageLayerCount(uint count) noexcept;

protected:
void onDisplay() override;
bool onMouse(const MouseEvent&) override;
bool onMotion(const MotionEvent&) override;
bool onScroll(const ScrollEvent&) override;

private:
Image fImage;
float fMinimum;
float fMaximum;
float fStep;
float fValue;
float fValueDef;
float fValueTmp;
bool fUsingDefault;
bool fUsingLog;
Orientation fOrientation;

int fRotationAngle;
bool fDragging;
int fLastX;
int fLastY;

Callback* fCallback;

bool fIsImgVertical;
uint fImgLayerWidth;
uint fImgLayerHeight;
uint fImgLayerCount;
bool fIsReady;
GLuint fTextureId;

float _logscale(float value) const;
float _invlogscale(float value) const;

DISTRHO_LEAK_DETECTOR(ImageKnob)
};

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

// note set range and step before setting the value

class ImageSlider : public Widget
{
public:
class Callback
{
public:
virtual ~Callback() {}
virtual void imageSliderDragStarted(ImageSlider* imageSlider) = 0;
virtual void imageSliderDragFinished(ImageSlider* imageSlider) = 0;
virtual void imageSliderValueChanged(ImageSlider* imageSlider, float value) = 0;
};

explicit ImageSlider(Window& parent, const Image& image) noexcept;
explicit ImageSlider(Widget* widget, const Image& image) noexcept;

float getValue() const noexcept;
void setValue(float value, bool sendCallback = false) noexcept;

void setStartPos(const Point<int>& startPos) noexcept;
void setStartPos(int x, int y) noexcept;
void setEndPos(const Point<int>& endPos) noexcept;
void setEndPos(int x, int y) noexcept;

void setInverted(bool inverted) noexcept;
void setRange(float min, float max) noexcept;
void setStep(float step) noexcept;

void setCallback(Callback* callback) noexcept;

protected:
void onDisplay() override;
bool onMouse(const MouseEvent&) override;
bool onMotion(const MotionEvent&) override;

private:
Image fImage;
float fMinimum;
float fMaximum;
float fStep;
float fValue;
float fValueTmp;

bool fDragging;
bool fInverted;
bool fValueIsSet;
int fStartedX;
int fStartedY;

Callback* fCallback;

Point<int> fStartPos;
Point<int> fEndPos;
Rectangle<int> fSliderArea;

void _recheckArea() noexcept;

// these should not be used
void setAbsoluteX(int) const noexcept {}
void setAbsoluteY(int) const noexcept {}
void setAbsolutePos(int, int) const noexcept {}
void setAbsolutePos(const Point<int>&) const noexcept {}

DISTRHO_LEAK_DETECTOR(ImageSlider)
};

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

class ImageSwitch : public Widget
{
public:
class Callback
{
public:
virtual ~Callback() {}
virtual void imageSwitchClicked(ImageSwitch* imageButton, bool down) = 0;
};

explicit ImageSwitch(Window& parent, const Image& imageNormal, const Image& imageDown) noexcept;
explicit ImageSwitch(Widget* widget, const Image& imageNormal, const Image& imageDown) noexcept;
explicit ImageSwitch(const ImageSwitch& imageSwitch) noexcept;
ImageSwitch& operator=(const ImageSwitch& imageSwitch) noexcept;

bool isDown() const noexcept;
void setDown(bool down) noexcept;

void setCallback(Callback* callback) noexcept;

protected:
void onDisplay() override;
bool onMouse(const MouseEvent&) override;

private:
Image fImageNormal;
Image fImageDown;
bool fIsDown;

Callback* fCallback;

DISTRHO_LEAK_DETECTOR(ImageSwitch)
};

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

END_NAMESPACE_DGL

#endif // DGL_IMAGE_WIDGETS_HPP_INCLUDED

+ 6
- 6
source/modules/dgl/Makefile View File

@@ -15,19 +15,19 @@ BUILD_CXX_FLAGS += $(DGL_FLAGS) -Isrc
# needed by sofd right now, fix later
BUILD_CXX_FLAGS += -fpermissive

# needed by oui-blendish
BUILD_CXX_FLAGS += -Wno-unused-parameter

# ----------------------------------------------------------------------------------------------------------------------------

OBJS = \
$(OBJDIR)/App.cpp.o \
$(OBJDIR)/Application.cpp.o \
$(OBJDIR)/Color.cpp.o \
$(OBJDIR)/Geometry.cpp.o \
$(OBJDIR)/Image.cpp.o \
$(OBJDIR)/ImageAboutWindow.cpp.o \
$(OBJDIR)/ImageButton.cpp.o \
$(OBJDIR)/ImageKnob.cpp.o \
$(OBJDIR)/ImageSlider.cpp.o \
$(OBJDIR)/ImageSwitch.cpp.o \
$(OBJDIR)/ImageWidgets.cpp.o \
$(OBJDIR)/NanoVG.cpp.o \
$(OBJDIR)/NanoWidgets.cpp.o \
$(OBJDIR)/Widget.cpp.o

ifeq ($(MACOS),true)


+ 181
- 62
source/modules/dgl/NanoVG.hpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2015 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
@@ -25,6 +25,11 @@ struct NVGpaint;

START_NAMESPACE_DGL

// -----------------------------------------------------------------------
// Forward class names

class NanoVG;

// -----------------------------------------------------------------------
// NanoImage

@@ -36,35 +41,62 @@ START_NAMESPACE_DGL
*/
class NanoImage
{
private:
struct Handle {
NVGcontext* context;
int imageId;

Handle() noexcept
: context(nullptr),
imageId(0) {}

Handle(NVGcontext* c, int id) noexcept
: context(c),
imageId(id) {}
};

public:
/**
Constructor for an invalid/null image.
*/
NanoImage();

/**
Constructor.
*/
NanoImage(const Handle& handle);

/**
Destructor.
*/
~NanoImage();

/**
Get size.
Create a new image without recreating the C++ class.
*/
Size<uint> getSize() const noexcept;
NanoImage& operator=(const Handle& handle);

/**
Update image data.
Wherever this image is valid.
*/
void updateImage(const uchar* const data);
bool isValid() const noexcept;

/**
Get size.
*/
Size<uint> getSize() const noexcept;

protected:
/**
Constructors are protected.
NanoImages must be created within a NanoVG or NanoWidget class.
Get the OpenGL texture handle.
*/
NanoImage(NVGcontext* const context, const int imageId) noexcept;
GLuint getTextureHandle() const;

private:
NVGcontext* fContext;
int fImageId;
Handle fHandle;
Size<uint> fSize;
friend class NanoVG;

/** @internal */
void _updateSize();

DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(NanoImage)
@@ -114,7 +146,7 @@ private:
These can be used as paints for strokes and fills.

@section Scissoring
Scissoring allows you to clip the rendering into a rectangle. This is useful for varius
Scissoring allows you to clip the rendering into a rectangle. This is useful for various
user interface cases like rendering a text edit or a timeline.

@section Paths
@@ -168,6 +200,32 @@ private:
class NanoVG
{
public:
enum CreateFlags {
/**
Flag indicating if geometry based anti-aliasing is used (may not be needed when using MSAA).
*/
CREATE_ANTIALIAS = 1 << 0,

/**
Flag indicating if strokes should be drawn using stencil buffer. The rendering will be a little
slower, but path overlaps (i.e. self-intersecting or sharp turns) will be drawn just once.
*/
CREATE_STENCIL_STROKES = 1 << 1,

/**
Flag indicating that additional debug checks are done.
*/
CREATE_DEBUG = 1 << 2,
};

enum ImageFlags {
IMAGE_GENERATE_MIPMAPS = 1 << 0, // Generate mipmaps during creation of the image.
IMAGE_REPEAT_X = 1 << 1, // Repeat image in X direction.
IMAGE_REPEAT_Y = 1 << 2, // Repeat image in Y direction.
IMAGE_FLIP_Y = 1 << 3, // Flips (inverses) image in Y direction when rendered.
IMAGE_PREMULTIPLIED = 1 << 4 // Image data has premultiplied alpha.
};

enum Align {
// Horizontal align
ALIGN_LEFT = 1 << 0, // Align horizontally to left (default).
@@ -180,11 +238,6 @@ public:
ALIGN_BASELINE = 1 << 6 // Align vertically to baseline (default).
};

enum Alpha {
STRAIGHT_ALPHA,
PREMULTIPLIED_ALPHA
};

enum LineCap {
BUTT,
ROUND,
@@ -193,12 +246,6 @@ public:
MITER
};

enum PatternRepeat {
REPEAT_NONE = 0x0, // No repeat
REPEAT_X = 0x1, // Repeat in X direction
REPEAT_Y = 0x2 // Repeat in Y direction
};

enum Solidity {
SOLID = 1, // CCW
HOLE = 2 // CW
@@ -217,7 +264,6 @@ public:
Color innerColor;
Color outerColor;
int imageId;
PatternRepeat repeat;

Paint() noexcept;

@@ -246,14 +292,14 @@ public:

/**
Constructor.
Uses 512x512 as default atlas size.
@see CreateFlags
*/
NanoVG();
NanoVG(int flags = CREATE_ANTIALIAS);

/**
Constructor using custom text atlas size.
Constructor reusing a NanoVG context, used for subwidgets.
*/
NanoVG(const int textAtlasWidth, const int textAtlasHeight);
NanoVG(NanoWidget* groupWidget);

/**
Destructor.
@@ -271,15 +317,19 @@ public:

/**
Begin drawing a new frame.
@param withAlha Controls if drawing the shapes to the render target should be done using straight or pre-multiplied alpha.
*/
void beginFrame(const uint width, const uint height, const float scaleFactor = 1.0f, const Alpha alpha = PREMULTIPLIED_ALPHA);
void beginFrame(const uint width, const uint height, const float scaleFactor = 1.0f);

/**
Begin drawing a new frame inside a widget.
*/
void beginFrame(Widget* const widget);

/**
Cancels drawing the current frame.
*/
void cancelFrame();

/**
Ends drawing flushing remaining render state.
*/
@@ -374,6 +424,12 @@ public:
*/
void lineJoin(LineCap join = MITER);

/**
Sets the transparency applied to all rendered shapes.
Already transparent paths will get proportionally more transparent as well.
*/
void globalAlpha(float alpha);

/* --------------------------------------------------------------------
* Transforms */

@@ -495,17 +551,50 @@ public:
/**
Creates image by loading it from the disk from specified file name.
*/
NanoImage* createImage(const char* filename);
NanoImage::Handle createImageFromFile(const char* filename, ImageFlags imageFlags);

/**
Creates image by loading it from the disk from specified file name.
Overloaded function for convenience.
@see ImageFlags
*/
NanoImage::Handle createImageFromFile(const char* filename, int imageFlags);

/**
Creates image by loading it from the specified chunk of memory.
*/
NanoImage::Handle createImageFromMemory(uchar* data, uint dataSize, ImageFlags imageFlags);

/**
Creates image by loading it from the specified chunk of memory.
Overloaded function for convenience.
@see ImageFlags
*/
NanoImage* createImageMem(uchar* data, int ndata);
NanoImage::Handle createImageFromMemory(uchar* data, uint dataSize, int imageFlags);

/**
Creates image from specified image data.
*/
NanoImage* createImageRGBA(uint w, uint h, const uchar* data);
NanoImage::Handle createImageFromRGBA(uint w, uint h, const uchar* data, ImageFlags imageFlags);

/**
Creates image from specified image data.
Overloaded function for convenience.
@see ImageFlags
*/
NanoImage::Handle createImageFromRGBA(uint w, uint h, const uchar* data, int imageFlags);

/**
Creates image from an OpenGL texture handle.
*/
NanoImage::Handle createImageFromTextureHandle(GLuint textureId, uint w, uint h, ImageFlags imageFlags, bool deleteTexture = false);

/**
Creates image from an OpenGL texture handle.
Overloaded function for convenience.
@see ImageFlags
*/
NanoImage::Handle createImageFromTextureHandle(GLuint textureId, uint w, uint h, int imageFlags, bool deleteTexture = false);

/* --------------------------------------------------------------------
* Paints */
@@ -535,21 +624,30 @@ public:

/**
Creates and returns an image pattern. Parameters (ox,oy) specify the left-top location of the image pattern,
(ex,ey) the size of one image, angle rotation around the top-left corner, image is handle to the image to render,
and repeat tells if the image should be repeated across x or y.
(ex,ey) the size of one image, angle rotation around the top-left corner, image is handle to the image to render.
The gradient is transformed by the current transform when it is passed to fillPaint() or strokePaint().
*/
Paint imagePattern(float ox, float oy, float ex, float ey, float angle, const NanoImage* image, PatternRepeat repeat);
Paint imagePattern(float ox, float oy, float ex, float ey, float angle, const NanoImage& image, float alpha);

/* --------------------------------------------------------------------
* Scissoring */

/**
Sets the current
Sets the current scissor rectangle.
The scissor rectangle is transformed by the current transform.
*/
void scissor(float x, float y, float w, float h);

/**
Intersects current scissor rectangle with the specified rectangle.
The scissor rectangle is transformed by the current transform.
Note: in case the rotation of previous scissor rect differs from
the current one, the intersection will be done between the specified
rectangle and the previous scissor rectangle transformed in the current
transform space. The resulting shape is always rectangle.
*/
void intersectScissor(float x, float y, float w, float h);

/**
Reset and disables scissoring.
*/
@@ -574,10 +672,15 @@ public:
void lineTo(float x, float y);

/**
Adds bezier segment from last point in the path via two control points to the specified point.
Adds cubic bezier segment from last point in the path via two control points to the specified point.
*/
void bezierTo(float c1x, float c1y, float c2x, float c2y, float x, float y);

/**
Adds quadratic bezier segment from last point in the path via a control point to the specified point.
*/
void quadTo(float cx, float cy, float x, float y);

/**
Adds an arc segment at the corner defined by the last path point, and two specified points.
*/
@@ -594,7 +697,9 @@ public:
void pathWinding(Winding dir);

/**
Creates new arc shaped sub-path.
Creates new circle arc shaped sub-path. The arc center is at cx,cy, the arc radius is r,
and the arc is drawn from angle a0 to a1, and swept in direction dir (NVG_CCW or NVG_CW).
Angles are specified in radians.
*/
void arc(float cx, float cy, float r, float a0, float a1, Winding dir);

@@ -635,13 +740,13 @@ public:
Creates font by loading it from the disk from specified file name.
Returns handle to the font.
*/
FontId createFont(const char* name, const char* filename);
FontId createFontFromFile(const char* name, const char* filename);

/**
Creates font by loading it from the specified memory chunk.
Returns handle to the font.
*/
FontId createFontMem(const char* name, const uchar* data, int ndata, bool freeData);
FontId createFontFromMemory(const char* name, const uchar* data, uint dataSize, bool freeData);

/**
Finds a loaded font of specified name, and returns handle to it, or -1 if the font is not found.
@@ -696,11 +801,12 @@ public:
float text(float x, float y, const char* string, const char* end);

/**
Draws multi-line text string at specified location wrapped at the specified width. If end is specified only the sub-string up to the end is drawn.
Draws multi-line text string at specified location wrapped at the specified width.
If end is specified only the sub-string up to the end is drawn.
White space is stripped at the beginning of the rows, the text is split at word boundaries or when new-line characters are encountered.
Words longer than the max width are slit at nearest character (i.e. no hyphenation).
*/
void textBox(float x, float y, float breakRowWidth, const char* string, const char* end);
void textBox(float x, float y, float breakRowWidth, const char* string, const char* end = nullptr);

/**
Measures the specified text string. The bounds value are [xmin,ymin, xmax,ymax].
@@ -714,13 +820,13 @@ public:
if the bounding box of the text should be returned. The bounds value are [xmin,ymin, xmax,ymax]
Measured values are returned in local coordinate space.
*/
void textBoxBounds(float x, float y, float breakRowWidth, const char* string, const char* end, float* bounds);
void textBoxBounds(float x, float y, float breakRowWidth, const char* string, const char* end, float bounds[4]);

/**
Calculates the glyph x positions of the specified text. If end is specified only the sub-string will be used.
Measured values are returned in local coordinate space.
*/
int textGlyphPositions(float x, float y, const char* string, const char* end, GlyphPosition* positions, int maxPositions);
int textGlyphPositions(float x, float y, const char* string, const char* end, GlyphPosition& positions, int maxPositions);

/**
Returns the vertical metrics based on the current text style.
@@ -733,11 +839,12 @@ public:
White space is stripped at the beginning of the rows, the text is split at word boundaries or when new-line characters are encountered.
Words longer than the max width are slit at nearest character (i.e. no hyphenation).
*/
int textBreakLines(const char* string, const char* end, float breakRowWidth, TextRow* rows, int maxRows);
int textBreakLines(const char* string, const char* end, float breakRowWidth, TextRow& rows, int maxRows);

private:
NVGcontext* const fContext;
bool fInFrame;
bool fIsSubWidget;

DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(NanoVG)
};
@@ -758,14 +865,24 @@ class NanoWidget : public Widget,
public:
/**
Constructor.
@see CreateFlags
*/
NanoWidget(Window& parent)
: Widget(parent),
NanoVG(),
leakDetector_NanoWidget()
{
setNeedsScaling(true);
}
explicit NanoWidget(Window& parent, int flags = CREATE_ANTIALIAS);

/**
Constructor for a subwidget.
*/
explicit NanoWidget(Widget* groupWidget, int flags = CREATE_ANTIALIAS);

/**
Constructor for a subwidget, reusing a NanoVG context.
*/
explicit NanoWidget(NanoWidget* groupWidget);

/**
Destructor.
*/
virtual ~NanoWidget();

protected:
/**
@@ -775,19 +892,21 @@ protected:
virtual void onNanoDisplay() = 0;

private:
struct PrivateData;
PrivateData* const nData;

/**
Widget display function.
Implemented internally to wrap begin/endFrame() automatically.
*/
void onDisplay() override
{
//glPushAttrib(GL_PIXEL_MODE_BIT|GL_STENCIL_BUFFER_BIT|GL_ENABLE_BIT);
beginFrame(getWidth(), getHeight());
onNanoDisplay();
endFrame();
//glPopAttrib();
glDisable(GL_CULL_FACE);
}
void onDisplay() override;

// these should not be used
void beginFrame(uint,uint) {}
void beginFrame(uint,uint,float) {}
void beginFrame(Widget*) {}
void cancelFrame() {}
void endFrame() {}

DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(NanoWidget)
};


+ 67
- 0
source/modules/dgl/NanoWidgets.hpp View File

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

#ifndef DGL_NANO_WIDGETS_HPP_INCLUDED
#define DGL_NANO_WIDGETS_HPP_INCLUDED

#include "NanoVG.hpp"
#include "../distrho/extra/String.hpp"

START_NAMESPACE_DGL

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

class BlendishButton : public NanoWidget
{
public:
class Callback
{
public:
virtual ~Callback() {}
virtual void blendishButtonClicked(BlendishButton* blendishButton, int button) = 0;
};

explicit BlendishButton(Window& parent, const char* text = "", int iconId = -1);
explicit BlendishButton(NanoWidget* widget, const char* text = "", int iconId = -1);
~BlendishButton() override;

int getIconId() const noexcept;
void setIconId(int iconId) noexcept;

const char* getText() const noexcept;
void setText(const char* text) noexcept;

void setCallback(Callback* callback) noexcept;

protected:
void onNanoDisplay() override;
bool onMouse(const MouseEvent&) override;
bool onMotion(const MotionEvent&) override;

private:
struct PrivateData;
PrivateData* const pData;

void _updateBounds();

DISTRHO_LEAK_DETECTOR(BlendishButton)
};

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

END_NAMESPACE_DGL

#endif // DGL_NANO_WIDGETS_HPP_INCLUDED

+ 18
- 38
source/modules/dgl/StandaloneWindow.hpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2015 Filipe Coelho <falktx@falktx.com>
*
* Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this
@@ -17,7 +17,7 @@
#ifndef DGL_STANDALONE_WINDOW_HPP_INCLUDED
#define DGL_STANDALONE_WINDOW_HPP_INCLUDED

#include "App.hpp"
#include "Application.hpp"
#include "Widget.hpp"
#include "Window.hpp"

@@ -25,51 +25,31 @@ START_NAMESPACE_DGL

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

class StandaloneWindow : public App,
class StandaloneWindow : public Application,
public Window
{
public:
StandaloneWindow()
: App(),
Window((App&)*this),
fWidget(nullptr) {}
/**
Constructor.
*/
StandaloneWindow();

void exec()
{
Window::show();
App::exec();
}

protected:
void onReshape(uint width, uint height) override
{
if (fWidget != nullptr)
fWidget->setSize(width, height);
Window::onReshape(width, height);
}
/**
Show window and execute application.
*/
void exec();

private:
Widget* fWidget;

void _addWidget(Widget* widget) override
{
if (fWidget == nullptr)
{
fWidget = widget;
fWidget->setNeedsFullViewport(true);
}
Window::_addWidget(widget);
}
/** @internal */
void onReshape(uint width, uint height) override;

/** @internal */
void _addWidget(Widget* widget) override;

void _removeWidget(Widget* widget) override
{
if (fWidget == widget)
{
fWidget->setNeedsFullViewport(false);
fWidget = nullptr;
}
Window::_removeWidget(widget);
}
/** @internal */
void _removeWidget(Widget* widget) override;

DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(StandaloneWindow)
};


+ 25
- 27
source/modules/dgl/Widget.hpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2015 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
@@ -19,12 +19,20 @@

#include "Geometry.hpp"

START_NAMESPACE_DGL
#include <vector>

// -----------------------------------------------------------------------
// Forward class names

class App;
START_NAMESPACE_DISTRHO
class UI;
END_NAMESPACE_DISTRHO

START_NAMESPACE_DGL

class Application;
class ImageSlider;
class NanoWidget;
class Window;
class StandaloneWindow;

@@ -172,6 +180,11 @@ public:
*/
explicit Widget(Window& parent);

/**
Constructor for a subwidget.
*/
explicit Widget(Widget* groupWidget);

/**
Destructor.
*/
@@ -274,7 +287,7 @@ public:
Get this widget's window application.
Same as calling getParentWindow().getApp().
*/
App& getParentApp() const noexcept;
Application& getParentApp() const noexcept;

/**
Get parent window, as passed in the constructor.
@@ -349,33 +362,18 @@ protected:
*/
virtual void onResize(const ResizeEvent&);

/**
Tell the parent window this widget needs the full viewport.
When enabled, the local widget coordinates are ignored.
@note: This is an internal function;
You do not need it under normal circumstances.
*/
void setNeedsFullViewport(bool yesNo) noexcept;

/**
Tell the parent window this widget needs scaling.
When enabled, the widget viewport is scaled to match width and height.
@note: This is an internal function;
You do not need it under normal circumstances.
*/
void setNeedsScaling(bool yesNo) noexcept;

private:
Window& fParent;
bool fNeedsFullViewport;
bool fNeedsScaling;
bool fVisible;
uint fId;
Point<int> fAbsolutePos;
Size<uint> fSize;
struct PrivateData;
PrivateData* const pData;

/** @internal */
explicit Widget(Widget* groupWidget, bool addToSubWidgets);

friend class ImageSlider;
friend class NanoWidget;
friend class Window;
friend class StandaloneWindow;
friend class DISTRHO_NAMESPACE::UI;

DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(Widget)
};


+ 7
- 7
source/modules/dgl/Window.hpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2015 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
@@ -23,7 +23,7 @@ START_NAMESPACE_DGL

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

class App;
class Application;
class Widget;
class StandaloneWindow;

@@ -67,9 +67,9 @@ public:
buttons() {}
};

explicit Window(App& app);
explicit Window(App& app, Window& parent);
explicit Window(App& app, intptr_t parentId);
explicit Window(Application& app);
explicit Window(Application& app, Window& parent);
explicit Window(Application& app, intptr_t parentId);
virtual ~Window();

void show();
@@ -99,7 +99,7 @@ public:

void setTransientWinId(uintptr_t winId);

App& getApp() const noexcept;
Application& getApp() const noexcept;
intptr_t getWindowId() const noexcept;

void addIdleCallback(IdleCallback* const callback);
@@ -116,7 +116,7 @@ protected:
private:
struct PrivateData;
PrivateData* const pData;
friend class App;
friend class Application;
friend class Widget;
friend class StandaloneWindow;



source/modules/dgl/src/App.cpp → source/modules/dgl/src/Application.cpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2015 Filipe Coelho <falktx@falktx.com>
*
* Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this
@@ -14,23 +14,22 @@
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

#include "AppPrivateData.hpp"
#include "ApplicationPrivateData.hpp"
#include "../Window.hpp"

START_NAMESPACE_DGL

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

App::App()
: pData(new PrivateData()),
leakDetector_App() {}
Application::Application()
: pData(new PrivateData()) {}

App::~App()
Application::~Application()
{
delete pData;
}

void App::idle()
void Application::idle()
{
for (std::list<Window*>::iterator it = pData->windows.begin(), ite = pData->windows.end(); it != ite; ++it)
{
@@ -45,7 +44,7 @@ void App::idle()
}
}

void App::exec()
void Application::exec()
{
for (; pData->doLoop;)
{
@@ -54,7 +53,7 @@ void App::exec()
}
}

void App::quit()
void Application::quit()
{
pData->doLoop = false;

@@ -65,7 +64,7 @@ void App::quit()
}
}

bool App::isQuiting() const noexcept
bool Application::isQuiting() const noexcept
{
return !pData->doLoop;
}

source/modules/dgl/src/AppPrivateData.hpp → source/modules/dgl/src/ApplicationPrivateData.hpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2015 Filipe Coelho <falktx@falktx.com>
*
* Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this
@@ -17,8 +17,8 @@
#ifndef DGL_APP_PRIVATE_DATA_HPP_INCLUDED
#define DGL_APP_PRIVATE_DATA_HPP_INCLUDED

#include "../App.hpp"
#include "../../distrho/extra/d_sleep.hpp"
#include "../Application.hpp"
#include "../../distrho/extra/Sleep.hpp"

#include <list>

@@ -26,7 +26,7 @@ START_NAMESPACE_DGL

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

struct App::PrivateData {
struct Application::PrivateData {
bool doLoop;
uint visibleWindows;
std::list<Window*> windows;

+ 1
- 1
source/modules/dgl/src/Color.cpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2015 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


+ 129
- 0
source/modules/dgl/src/Common.hpp View File

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

#ifndef DGL_COMMON_HPP_INCLUDED
#define DGL_COMMON_HPP_INCLUDED

#include "../ImageWidgets.hpp"
#include "../NanoWidgets.hpp"

START_NAMESPACE_DGL

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

struct ButtonImpl {
enum State {
kStateNormal = 0,
kStateHover,
kStateDown
};

int button;
int state;
Widget* self;

BlendishButton::Callback* callback_b;
ImageButton::Callback* callback_i;

ButtonImpl(Widget* const s) noexcept
: button(-1),
state(kStateNormal),
self(s),
callback_b(nullptr),
callback_i(nullptr) {}

bool onMouse(const Widget::MouseEvent& ev)
{
// button was released, handle it now
if (button != -1 && ! ev.press)
{
DISTRHO_SAFE_ASSERT(state == kStateDown);

// release button
const int button2 = button;
button = -1;

// cursor was moved outside the button bounds, ignore click
if (! self->contains(ev.pos))
{
state = kStateNormal;
self->repaint();
return true;
}

// still on bounds, register click
state = kStateHover;
self->repaint();

if (callback_b != nullptr)
callback_b->blendishButtonClicked((BlendishButton*)self, button2);
if (callback_i != nullptr)
callback_i->imageButtonClicked((ImageButton*)self, button2);

return true;
}

// button was pressed, wait for release
if (ev.press && self->contains(ev.pos))
{
button = ev.button;
state = kStateDown;
self->repaint();
return true;
}

return false;
}

bool onMotion(const Widget::MotionEvent& ev)
{
// keep pressed
if (button != -1)
return true;

if (self->contains(ev.pos))
{
// check if entering hover
if (state == kStateNormal)
{
state = kStateHover;
self->repaint();
return true;
}
}
else
{
// check if exiting hover
if (state == kStateHover)
{
state = kStateNormal;
self->repaint();
return true;
}
}

return false;
}

DISTRHO_PREVENT_HEAP_ALLOCATION
DISTRHO_DECLARE_NON_COPY_STRUCT(ButtonImpl)
};

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

END_NAMESPACE_DGL

#endif // DGL_APP_PRIVATE_DATA_HPP_INCLUDED

+ 1
- 1
source/modules/dgl/src/Geometry.cpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2015 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


+ 1
- 1
source/modules/dgl/src/Image.cpp View File

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


+ 0
- 89
source/modules/dgl/src/ImageAboutWindow.cpp View File

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

#include "../ImageAboutWindow.hpp"

START_NAMESPACE_DGL

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

ImageAboutWindow::ImageAboutWindow(Window& parent, const Image& image)
: Window(parent.getApp(), parent),
Widget((Window&)*this),
fImgBackground(image)/*,
leakDetector_ImageAboutWindow()*/
{
Window::setResizable(false);
Window::setSize(static_cast<uint>(image.getWidth()), static_cast<uint>(image.getHeight()));
Window::setTitle("About");
}

ImageAboutWindow::ImageAboutWindow(Widget* widget, const Image& image)
: Window(widget->getParentApp(), widget->getParentWindow()),
Widget((Window&)*this),
fImgBackground(image)/*,
leakDetector_ImageAboutWindow()*/
{
Window::setResizable(false);
Window::setSize(static_cast<uint>(image.getWidth()), static_cast<uint>(image.getHeight()));
Window::setTitle("About");
}

void ImageAboutWindow::setImage(const Image& image)
{
if (fImgBackground == image)
return;

fImgBackground = image;
Window::setSize(static_cast<uint>(image.getWidth()), static_cast<uint>(image.getHeight()));
}

void ImageAboutWindow::onDisplay()
{
fImgBackground.draw();
}

bool ImageAboutWindow::onKeyboard(const KeyboardEvent& ev)
{
if (ev.press && ev.key == CHAR_ESCAPE)
{
Window::close();
return true;
}

return false;
}

bool ImageAboutWindow::onMouse(const MouseEvent& ev)
{
if (ev.press)
{
Window::close();
return true;
}

return false;
}

void ImageAboutWindow::onReshape(uint width, uint height)
{
Widget::setSize(width, height);
Window::onReshape(width, height);
}

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

END_NAMESPACE_DGL

+ 0
- 190
source/modules/dgl/src/ImageButton.cpp View File

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

#include "../ImageButton.hpp"

START_NAMESPACE_DGL

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

ImageButton::ImageButton(Window& parent, const Image& image) noexcept
: Widget(parent),
fImageNormal(image),
fImageHover(image),
fImageDown(image),
fCurImage(&fImageNormal),
fCurButton(-1),
fCallback(nullptr),
leakDetector_ImageButton() {}

ImageButton::ImageButton(Window& parent, const Image& imageNormal, const Image& imageHover, const Image& imageDown) noexcept
: Widget(parent),
fImageNormal(imageNormal),
fImageHover(imageHover),
fImageDown(imageDown),
fCurImage(&fImageNormal),
fCurButton(-1),
fCallback(nullptr),
leakDetector_ImageButton()
{
DISTRHO_SAFE_ASSERT(fImageNormal.getSize() == fImageHover.getSize() && fImageHover.getSize() == fImageDown.getSize());

setSize(fCurImage->getSize());
}

ImageButton::ImageButton(Widget* widget, const Image& image) noexcept
: Widget(widget->getParentWindow()),
fImageNormal(image),
fImageHover(image),
fImageDown(image),
fCurImage(&fImageNormal),
fCurButton(-1),
fCallback(nullptr),
leakDetector_ImageButton() {}

ImageButton::ImageButton(Widget* widget, const Image& imageNormal, const Image& imageHover, const Image& imageDown) noexcept
: Widget(widget->getParentWindow()),
fImageNormal(imageNormal),
fImageHover(imageHover),
fImageDown(imageDown),
fCurImage(&fImageNormal),
fCurButton(-1),
fCallback(nullptr),
leakDetector_ImageButton()
{
DISTRHO_SAFE_ASSERT(fImageNormal.getSize() == fImageHover.getSize() && fImageHover.getSize() == fImageDown.getSize());

setSize(fCurImage->getSize());
}

ImageButton::ImageButton(const ImageButton& imageButton) noexcept
: Widget(imageButton.getParentWindow()),
fImageNormal(imageButton.fImageNormal),
fImageHover(imageButton.fImageHover),
fImageDown(imageButton.fImageDown),
fCurImage(&fImageNormal),
fCurButton(-1),
fCallback(imageButton.fCallback),
leakDetector_ImageButton()
{
DISTRHO_SAFE_ASSERT(fImageNormal.getSize() == fImageHover.getSize() && fImageHover.getSize() == fImageDown.getSize());

setSize(fCurImage->getSize());
}

ImageButton& ImageButton::operator=(const ImageButton& imageButton) noexcept
{
fImageNormal = imageButton.fImageNormal;
fImageHover = imageButton.fImageHover;
fImageDown = imageButton.fImageDown;
fCurImage = &fImageNormal;
fCurButton = -1;
fCallback = imageButton.fCallback;

DISTRHO_SAFE_ASSERT(fImageNormal.getSize() == fImageHover.getSize() && fImageHover.getSize() == fImageDown.getSize());

setSize(fCurImage->getSize());

return *this;
}

void ImageButton::setCallback(Callback* callback) noexcept
{
fCallback = callback;
}

void ImageButton::onDisplay()
{
fCurImage->draw();
}

bool ImageButton::onMouse(const MouseEvent& ev)
{
if (fCurButton != -1 && ! ev.press)
{
if (fCurImage != &fImageNormal)
{
fCurImage = &fImageNormal;
repaint();
}

if (! contains(ev.pos))
{
fCurButton = -1;
return false;
}

if (fCallback != nullptr)
fCallback->imageButtonClicked(this, fCurButton);

#if 0
if (contains(ev.pos))
{
fCurImage = &fImageHover;
repaint();
}
#endif

fCurButton = -1;

return true;
}

if (ev.press && contains(ev.pos))
{
if (fCurImage != &fImageDown)
{
fCurImage = &fImageDown;
repaint();
}

fCurButton = ev.button;
return true;
}

return false;
}

bool ImageButton::onMotion(const MotionEvent& ev)
{
if (fCurButton != -1)
return true;

if (contains(ev.pos))
{
if (fCurImage != &fImageHover)
{
fCurImage = &fImageHover;
repaint();
}

return true;
}
else
{
if (fCurImage != &fImageNormal)
{
fCurImage = &fImageNormal;
repaint();
}

return false;
}
}

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

END_NAMESPACE_DGL

+ 0
- 459
source/modules/dgl/src/ImageKnob.cpp View File

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

#include "../ImageKnob.hpp"

#include <cmath>

START_NAMESPACE_DGL

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

ImageKnob::ImageKnob(Window& parent, const Image& image, Orientation orientation) noexcept
: Widget(parent),
fImage(image),
fMinimum(0.0f),
fMaximum(1.0f),
fStep(0.0f),
fValue(0.5f),
fValueDef(fValue),
fValueTmp(fValue),
fUsingDefault(false),
fUsingLog(false),
fOrientation(orientation),
fRotationAngle(0),
fDragging(false),
fLastX(0),
fLastY(0),
fCallback(nullptr),
fIsImgVertical(image.getHeight() > image.getWidth()),
fImgLayerSize(fIsImgVertical ? image.getWidth() : image.getHeight()),
fImgLayerCount(fIsImgVertical ? image.getHeight()/fImgLayerSize : image.getWidth()/fImgLayerSize),
fIsReady(false),
fTextureId(0),
leakDetector_ImageKnob()
{
glGenTextures(1, &fTextureId);
setSize(fImgLayerSize, fImgLayerSize);
}

ImageKnob::ImageKnob(Widget* widget, const Image& image, Orientation orientation) noexcept
: Widget(widget->getParentWindow()),
fImage(image),
fMinimum(0.0f),
fMaximum(1.0f),
fStep(0.0f),
fValue(0.5f),
fValueDef(fValue),
fValueTmp(fValue),
fUsingDefault(false),
fUsingLog(false),
fOrientation(orientation),
fRotationAngle(0),
fDragging(false),
fLastX(0),
fLastY(0),
fCallback(nullptr),
fIsImgVertical(image.getHeight() > image.getWidth()),
fImgLayerSize(fIsImgVertical ? image.getWidth() : image.getHeight()),
fImgLayerCount(fIsImgVertical ? image.getHeight()/fImgLayerSize : image.getWidth()/fImgLayerSize),
fIsReady(false),
fTextureId(0),
leakDetector_ImageKnob()
{
glGenTextures(1, &fTextureId);
setSize(fImgLayerSize, fImgLayerSize);
}

ImageKnob::ImageKnob(const ImageKnob& imageKnob)
: Widget(imageKnob.getParentWindow()),
fImage(imageKnob.fImage),
fMinimum(imageKnob.fMinimum),
fMaximum(imageKnob.fMaximum),
fStep(imageKnob.fStep),
fValue(imageKnob.fValue),
fValueDef(imageKnob.fValueDef),
fValueTmp(fValue),
fUsingDefault(imageKnob.fUsingDefault),
fUsingLog(imageKnob.fUsingLog),
fOrientation(imageKnob.fOrientation),
fRotationAngle(imageKnob.fRotationAngle),
fDragging(false),
fLastX(0),
fLastY(0),
fCallback(imageKnob.fCallback),
fIsImgVertical(imageKnob.fIsImgVertical),
fImgLayerSize(imageKnob.fImgLayerSize),
fImgLayerCount(imageKnob.fImgLayerCount),
fIsReady(false),
fTextureId(0),
leakDetector_ImageKnob()
{
glGenTextures(1, &fTextureId);
setSize(fImgLayerSize, fImgLayerSize);
}

ImageKnob& ImageKnob::operator=(const ImageKnob& imageKnob)
{
fImage = imageKnob.fImage;
fMinimum = imageKnob.fMinimum;
fMaximum = imageKnob.fMaximum;
fStep = imageKnob.fStep;
fValue = imageKnob.fValue;
fValueDef = imageKnob.fValueDef;
fValueTmp = fValue;
fUsingDefault = imageKnob.fUsingDefault;
fUsingLog = imageKnob.fUsingLog;
fOrientation = imageKnob.fOrientation;
fRotationAngle = imageKnob.fRotationAngle;
fDragging = false;
fLastX = 0;
fLastY = 0;
fCallback = imageKnob.fCallback;
fIsImgVertical = imageKnob.fIsImgVertical;
fImgLayerSize = imageKnob.fImgLayerSize;
fImgLayerCount = imageKnob.fImgLayerCount;
fIsReady = false;

if (fTextureId != 0)
{
glDeleteTextures(1, &fTextureId);
fTextureId = 0;
}

glGenTextures(1, &fTextureId);
setSize(fImgLayerSize, fImgLayerSize);

return *this;
}

ImageKnob::~ImageKnob()
{
if (fTextureId != 0)
{
glDeleteTextures(1, &fTextureId);
fTextureId = 0;
}
}

float ImageKnob::getValue() const noexcept
{
return fValue;
}

// NOTE: value is assumed to be scaled if using log
void ImageKnob::setDefault(float value) noexcept
{
fValueDef = value;
fUsingDefault = true;
}

void ImageKnob::setRange(float min, float max) noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(max > min,);

if (fValue < min)
{
fValue = min;
repaint();

if (fCallback != nullptr)
{
try {
fCallback->imageKnobValueChanged(this, fValue);
} DISTRHO_SAFE_EXCEPTION("ImageKnob::setRange < min");
}
}
else if (fValue > max)
{
fValue = max;
repaint();

if (fCallback != nullptr)
{
try {
fCallback->imageKnobValueChanged(this, fValue);
} DISTRHO_SAFE_EXCEPTION("ImageKnob::setRange > max");
}
}

fMinimum = min;
fMaximum = max;
}

void ImageKnob::setStep(float step) noexcept
{
fStep = step;
}

// NOTE: value is assumed to be scaled if using log
void ImageKnob::setValue(float value, bool sendCallback) noexcept
{
if (d_isEqual(fValue, value))
return;

fValue = value;

if (d_isZero(fStep))
fValueTmp = value;

if (fRotationAngle == 0)
fIsReady = false;

repaint();

if (sendCallback && fCallback != nullptr)
{
try {
fCallback->imageKnobValueChanged(this, fValue);
} DISTRHO_SAFE_EXCEPTION("ImageKnob::setValue");
}
}

void ImageKnob::setUsingLogScale(bool yesNo) noexcept
{
fUsingLog = yesNo;
}

void ImageKnob::setCallback(Callback* callback) noexcept
{
fCallback = callback;
}

void ImageKnob::setOrientation(Orientation orientation) noexcept
{
if (fOrientation == orientation)
return;

fOrientation = orientation;
}

void ImageKnob::setRotationAngle(int angle)
{
if (fRotationAngle == angle)
return;

fRotationAngle = angle;
fIsReady = false;
}

void ImageKnob::onDisplay()
{
const float normValue = ((fUsingLog ? _invlogscale(fValue) : fValue) - fMinimum) / (fMaximum - fMinimum);

glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, fTextureId);

if (! fIsReady)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);

static const float trans[] = { 0.0f, 0.0f, 0.0f, 0.0f };
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, trans);

glPixelStorei(GL_PACK_ALIGNMENT, 1);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

uint imageDataOffset = 0;

if (fRotationAngle == 0)
{
DISTRHO_SAFE_ASSERT_RETURN(fImgLayerCount > 0,);
DISTRHO_SAFE_ASSERT_RETURN(normValue >= 0.0f,);

const uint layerDataSize = fImgLayerSize * fImgLayerSize * ((fImage.getFormat() == GL_BGRA || fImage.getFormat() == GL_RGBA) ? 4 : 3);
/* */ imageDataOffset = layerDataSize * uint(normValue * float(fImgLayerCount-1));
}

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
static_cast<GLsizei>(getWidth()), static_cast<GLsizei>(getHeight()), 0,
fImage.getFormat(), fImage.getType(), fImage.getRawData() + imageDataOffset);

fIsReady = true;
}

const int w = static_cast<int>(getWidth());
const int h = static_cast<int>(getHeight());

if (fRotationAngle != 0)
{
glPushMatrix();

const int w2 = w/2;
const int h2 = h/2;

glTranslatef(static_cast<float>(w2), static_cast<float>(h2), 0.0f);
glRotatef(normValue*static_cast<float>(fRotationAngle), 0.0f, 0.0f, 1.0f);

Rectangle<int>(-w2, -h2, w, h).draw();

glPopMatrix();
}
else
{
Rectangle<int>(0, 0, w, h).draw();
}

glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
}

bool ImageKnob::onMouse(const MouseEvent& ev)
{
if (ev.button != 1)
return false;

if (ev.press)
{
if (! contains(ev.pos))
return false;

if ((ev.mod & MODIFIER_SHIFT) != 0 && fUsingDefault)
{
setValue(fValueDef, true);
fValueTmp = fValue;
return true;
}

fDragging = true;
fLastX = ev.pos.getX();
fLastY = ev.pos.getY();

if (fCallback != nullptr)
fCallback->imageKnobDragStarted(this);

return true;
}
else if (fDragging)
{
if (fCallback != nullptr)
fCallback->imageKnobDragFinished(this);

fDragging = false;
return true;
}

return false;
}

bool ImageKnob::onMotion(const MotionEvent& ev)
{
if (! fDragging)
return false;

bool doVal = false;
float d, value = 0.0f;

if (fOrientation == ImageKnob::Horizontal)
{
if (const int movX = ev.pos.getX() - fLastX)
{
d = (ev.mod & MODIFIER_CTRL) ? 2000.0f : 200.0f;
value = (fUsingLog ? _invlogscale(fValueTmp) : fValueTmp) + (float(fMaximum - fMinimum) / d * float(movX));
doVal = true;
}
}
else if (fOrientation == ImageKnob::Vertical)
{
if (const int movY = fLastY - ev.pos.getY())
{
d = (ev.mod & MODIFIER_CTRL) ? 2000.0f : 200.0f;
value = (fUsingLog ? _invlogscale(fValueTmp) : fValueTmp) + (float(fMaximum - fMinimum) / d * float(movY));
doVal = true;
}
}

if (! doVal)
return false;

if (fUsingLog)
value = _logscale(value);

if (value < fMinimum)
{
fValueTmp = value = fMinimum;
}
else if (value > fMaximum)
{
fValueTmp = value = fMaximum;
}
else if (d_isNotZero(fStep))
{
fValueTmp = value;
const float rest = std::fmod(value, fStep);
value = value - rest + (rest > fStep/2.0f ? fStep : 0.0f);
}

setValue(value, true);

fLastX = ev.pos.getX();
fLastY = ev.pos.getY();

return true;
}

bool ImageKnob::onScroll(const ScrollEvent& ev)
{
if (! contains(ev.pos))
return false;

const float d = (ev.mod & MODIFIER_CTRL) ? 2000.0f : 200.0f;
float value = (fUsingLog ? _invlogscale(fValueTmp) : fValueTmp) + (float(fMaximum - fMinimum) / d * 10.f * ev.delta.getY());

if (fUsingLog)
value = _logscale(value);

if (value < fMinimum)
{
fValueTmp = value = fMinimum;
}
else if (value > fMaximum)
{
fValueTmp = value = fMaximum;
}
else if (d_isNotZero(fStep))
{
fValueTmp = value;
const float rest = std::fmod(value, fStep);
value = value - rest + (rest > fStep/2.0f ? fStep : 0.0f);
}

setValue(value, true);
return true;
}

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

float ImageKnob::_logscale(float value) const
{
const float b = std::log(fMaximum/fMinimum)/(fMaximum-fMinimum);
const float a = fMaximum/std::exp(fMaximum*b);
return a * std::exp(b*value);
}

float ImageKnob::_invlogscale(float value) const
{
const float b = std::log(fMaximum/fMinimum)/(fMaximum-fMinimum);
const float a = fMaximum/std::exp(fMaximum*b);
return std::log(value/a)/b;
}

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

END_NAMESPACE_DGL

+ 0
- 399
source/modules/dgl/src/ImageSlider.cpp View File

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

#include "../ImageSlider.hpp"

#include <cmath>

START_NAMESPACE_DGL

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

ImageSlider::ImageSlider(Window& parent, const Image& image) noexcept
: Widget(parent),
fImage(image),
fMinimum(0.0f),
fMaximum(1.0f),
fStep(0.0f),
fValue(0.5f),
fValueTmp(fValue),
fDragging(false),
fInverted(false),
fStartedX(0),
fStartedY(0),
fCallback(nullptr),
fStartPos(),
fEndPos(),
fSliderArea(),
leakDetector_ImageSlider()
{
Widget::setNeedsFullViewport(true);
}

ImageSlider::ImageSlider(Widget* widget, const Image& image) noexcept
: Widget(widget->getParentWindow()),
fImage(image),
fMinimum(0.0f),
fMaximum(1.0f),
fStep(0.0f),
fValue(0.5f),
fValueTmp(fValue),
fDragging(false),
fInverted(false),
fStartedX(0),
fStartedY(0),
fCallback(nullptr),
fStartPos(),
fEndPos(),
fSliderArea(),
leakDetector_ImageSlider()
{
Widget::setNeedsFullViewport(true);
}

ImageSlider::ImageSlider(const ImageSlider& imageSlider) noexcept
: Widget(imageSlider.getParentWindow()),
fImage(imageSlider.fImage),
fMinimum(imageSlider.fMinimum),
fMaximum(imageSlider.fMaximum),
fStep(imageSlider.fStep),
fValue(imageSlider.fValue),
fValueTmp(fValue),
fDragging(false),
fInverted(imageSlider.fInverted),
fStartedX(0),
fStartedY(0),
fCallback(imageSlider.fCallback),
fStartPos(imageSlider.fStartPos),
fEndPos(imageSlider.fEndPos),
fSliderArea(imageSlider.fSliderArea),
leakDetector_ImageSlider()
{
Widget::setNeedsFullViewport(true);
}

ImageSlider& ImageSlider::operator=(const ImageSlider& imageSlider) noexcept
{
fImage = imageSlider.fImage;
fMinimum = imageSlider.fMinimum;
fMaximum = imageSlider.fMaximum;
fStep = imageSlider.fStep;
fValue = imageSlider.fValue;
fValueTmp = fValue;
fDragging = false;
fInverted = imageSlider.fInverted;
fStartedX = 0;
fStartedY = 0;
fCallback = imageSlider.fCallback;
fStartPos = imageSlider.fStartPos;
fEndPos = imageSlider.fEndPos;
fSliderArea = imageSlider.fSliderArea;

return *this;
}

float ImageSlider::getValue() const noexcept
{
return fValue;
}

void ImageSlider::setStartPos(const Point<int>& startPos) noexcept
{
fStartPos = startPos;
_recheckArea();
}

void ImageSlider::setStartPos(int x, int y) noexcept
{
setStartPos(Point<int>(x, y));
}

void ImageSlider::setEndPos(const Point<int>& endPos) noexcept
{
fEndPos = endPos;
_recheckArea();
}

void ImageSlider::setEndPos(int x, int y) noexcept
{
setEndPos(Point<int>(x, y));
}

void ImageSlider::setInverted(bool inverted) noexcept
{
if (fInverted == inverted)
return;

fInverted = inverted;
repaint();
}

void ImageSlider::setRange(float min, float max) noexcept
{
if (fValue < min)
{
fValue = min;
repaint();

if (fCallback != nullptr)
{
try {
fCallback->imageSliderValueChanged(this, fValue);
} DISTRHO_SAFE_EXCEPTION("ImageSlider::setRange < min");
}
}
else if (fValue > max)
{
fValue = max;
repaint();

if (fCallback != nullptr)
{
try {
fCallback->imageSliderValueChanged(this, fValue);
} DISTRHO_SAFE_EXCEPTION("ImageSlider::setRange > max");
}
}

fMinimum = min;
fMaximum = max;
}

void ImageSlider::setStep(float step) noexcept
{
fStep = step;
}

void ImageSlider::setValue(float value, bool sendCallback) noexcept
{
if (d_isEqual(fValue, value))
return;

fValue = value;

if (d_isZero(fStep))
fValueTmp = value;

repaint();

if (sendCallback && fCallback != nullptr)
{
try {
fCallback->imageSliderValueChanged(this, fValue);
} DISTRHO_SAFE_EXCEPTION("ImageSlider::setValue");
}
}

void ImageSlider::setCallback(Callback* callback) noexcept
{
fCallback = callback;
}

void ImageSlider::onDisplay()
{
#if 0 // DEBUG, paints slider area
glColor3f(0.4f, 0.5f, 0.1f);
glRecti(fSliderArea.getX(), fSliderArea.getY(), fSliderArea.getX()+fSliderArea.getWidth(), fSliderArea.getY()+fSliderArea.getHeight());
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
#endif

const float normValue = (fValue - fMinimum) / (fMaximum - fMinimum);

int x, y;

if (fStartPos.getY() == fEndPos.getY())
{
// horizontal
if (fInverted)
x = fEndPos.getX() - static_cast<int>(normValue*static_cast<float>(fEndPos.getX()-fStartPos.getX()));
else
x = fStartPos.getX() + static_cast<int>(normValue*static_cast<float>(fEndPos.getX()-fStartPos.getX()));

y = fStartPos.getY();
}
else
{
// vertical
x = fStartPos.getX();

if (fInverted)
y = fEndPos.getY() - static_cast<int>(normValue*static_cast<float>(fEndPos.getY()-fStartPos.getY()));
else
y = fStartPos.getY() + static_cast<int>(normValue*static_cast<float>(fEndPos.getY()-fStartPos.getY()));
}

fImage.drawAt(x, y);
}

bool ImageSlider::onMouse(const MouseEvent& ev)
{
if (ev.button != 1)
return false;

if (ev.press)
{
if (! fSliderArea.contains(ev.pos))
return false;

float vper;
const int x = ev.pos.getX();
const int y = ev.pos.getY();

if (fStartPos.getY() == fEndPos.getY())
{
// horizontal
vper = float(x - fSliderArea.getX()) / float(fSliderArea.getWidth());
}
else
{
// vertical
vper = float(y - fSliderArea.getY()) / float(fSliderArea.getHeight());
}

float value;

if (fInverted)
value = fMaximum - vper * (fMaximum - fMinimum);
else
value = fMinimum + vper * (fMaximum - fMinimum);

if (value < fMinimum)
{
fValueTmp = value = fMinimum;
}
else if (value > fMaximum)
{
fValueTmp = value = fMaximum;
}
else if (d_isNotZero(fStep))
{
fValueTmp = value;
const float rest = std::fmod(value, fStep);
value = value - rest + (rest > fStep/2.0f ? fStep : 0.0f);
}

fDragging = true;
fStartedX = x;
fStartedY = y;

if (fCallback != nullptr)
fCallback->imageSliderDragStarted(this);

setValue(value, true);

return true;
}
else if (fDragging)
{
if (fCallback != nullptr)
fCallback->imageSliderDragFinished(this);

fDragging = false;
return true;
}

return false;
}

bool ImageSlider::onMotion(const MotionEvent& ev)
{
if (! fDragging)
return false;

const bool horizontal = fStartPos.getY() == fEndPos.getY();
const int x = ev.pos.getX();
const int y = ev.pos.getY();

if ((horizontal && fSliderArea.containsX(x)) || (fSliderArea.containsY(y) && ! horizontal))
{
float vper;

if (horizontal)
{
// horizontal
vper = float(x - fSliderArea.getX()) / float(fSliderArea.getWidth());
}
else
{
// vertical
vper = float(y - fSliderArea.getY()) / float(fSliderArea.getHeight());
}

float value;

if (fInverted)
value = fMaximum - vper * (fMaximum - fMinimum);
else
value = fMinimum + vper * (fMaximum - fMinimum);

if (value < fMinimum)
{
fValueTmp = value = fMinimum;
}
else if (value > fMaximum)
{
fValueTmp = value = fMaximum;
}
else if (d_isNotZero(fStep))
{
fValueTmp = value;
const float rest = std::fmod(value, fStep);
value = value - rest + (rest > fStep/2.0f ? fStep : 0.0f);
}

setValue(value, true);
}
else if (horizontal)
{
if (x < fSliderArea.getX())
setValue(fInverted ? fMaximum : fMinimum, true);
else
setValue(fInverted ? fMinimum : fMaximum, true);
}
else
{
if (y < fSliderArea.getY())
setValue(fInverted ? fMaximum : fMinimum, true);
else
setValue(fInverted ? fMinimum : fMaximum, true);
}

return true;
}

void ImageSlider::_recheckArea() noexcept
{
if (fStartPos.getY() == fEndPos.getY())
{
// horizontal
fSliderArea = Rectangle<int>(fStartPos.getX(),
fStartPos.getY(),
fEndPos.getX() + static_cast<int>(fImage.getWidth()) - fStartPos.getX(),
static_cast<int>(fImage.getHeight()));
}
else
{
// vertical
fSliderArea = Rectangle<int>(fStartPos.getX(),
fStartPos.getY(),
static_cast<int>(fImage.getWidth()),
fEndPos.getY() + static_cast<int>(fImage.getHeight()) - fStartPos.getY());
}
}

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

END_NAMESPACE_DGL

+ 0
- 122
source/modules/dgl/src/ImageSwitch.cpp View File

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

#include "../ImageSwitch.hpp"

START_NAMESPACE_DGL

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

ImageSwitch::ImageSwitch(Window& parent, const Image& imageNormal, const Image& imageDown) noexcept
: Widget(parent),
fImageNormal(imageNormal),
fImageDown(imageDown),
fIsDown(false),
fCallback(nullptr),
leakDetector_ImageSwitch()
{
DISTRHO_SAFE_ASSERT(fImageNormal.getSize() == fImageDown.getSize());

setSize(fImageNormal.getSize());
}

ImageSwitch::ImageSwitch(Widget* widget, const Image& imageNormal, const Image& imageDown) noexcept
: Widget(widget->getParentWindow()),
fImageNormal(imageNormal),
fImageDown(imageDown),
fIsDown(false),
fCallback(nullptr),
leakDetector_ImageSwitch()
{
DISTRHO_SAFE_ASSERT(fImageNormal.getSize() == fImageDown.getSize());

setSize(fImageNormal.getSize());
}

ImageSwitch::ImageSwitch(const ImageSwitch& imageSwitch) noexcept
: Widget(imageSwitch.getParentWindow()),
fImageNormal(imageSwitch.fImageNormal),
fImageDown(imageSwitch.fImageDown),
fIsDown(imageSwitch.fIsDown),
fCallback(imageSwitch.fCallback),
leakDetector_ImageSwitch()
{
DISTRHO_SAFE_ASSERT(fImageNormal.getSize() == fImageDown.getSize());

setSize(fImageNormal.getSize());
}

ImageSwitch& ImageSwitch::operator=(const ImageSwitch& imageSwitch) noexcept
{
fImageNormal = imageSwitch.fImageNormal;
fImageDown = imageSwitch.fImageDown;
fIsDown = imageSwitch.fIsDown;
fCallback = imageSwitch.fCallback;

DISTRHO_SAFE_ASSERT(fImageNormal.getSize() == fImageDown.getSize());

setSize(fImageNormal.getSize());

return *this;
}

bool ImageSwitch::isDown() const noexcept
{
return fIsDown;
}

void ImageSwitch::setDown(bool down) noexcept
{
if (fIsDown == down)
return;

fIsDown = down;
repaint();
}

void ImageSwitch::setCallback(Callback* callback) noexcept
{
fCallback = callback;
}

void ImageSwitch::onDisplay()
{
if (fIsDown)
fImageNormal.draw();
else
fImageDown.draw();
}

bool ImageSwitch::onMouse(const MouseEvent& ev)
{
if (ev.press && contains(ev.pos))
{
fIsDown = !fIsDown;

repaint();

if (fCallback != nullptr)
fCallback->imageSwitchClicked(this, fIsDown);

return true;
}

return false;
}

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

END_NAMESPACE_DGL

+ 1078
- 0
source/modules/dgl/src/ImageWidgets.cpp
File diff suppressed because it is too large
View File


+ 234
- 90
source/modules/dgl/src/NanoVG.cpp View File

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

#include "../NanoVG.hpp"
#include "../Window.hpp"
#include "WidgetPrivateData.hpp"

// -----------------------------------------------------------------------
// Ignore some warnings if debugging
@@ -43,7 +43,8 @@
// -----------------------------------------------------------------------
// Include NanoVG OpenGL implementation

#define NANOVG_GL2_IMPLEMENTATION 1
//#define STB_IMAGE_STATIC
#define NANOVG_GL2_IMPLEMENTATION
#include "nanovg/nanovg_gl.h"

#if defined(NANOVG_GL2)
@@ -76,52 +77,41 @@
START_NAMESPACE_DGL

// -----------------------------------------------------------------------
// Paint
// NanoImage

NanoVG::Paint::Paint() noexcept
: radius(0.0f), feather(0.0f), innerColor(), outerColor(), imageId(0), repeat(REPEAT_NONE)
NanoImage::NanoImage()
: fHandle(),
fSize() {}

NanoImage::NanoImage(const Handle& handle)
: fHandle(handle),
fSize()
{
std::memset(xform, 0, sizeof(float)*6);
std::memset(extent, 0, sizeof(float)*2);
DISTRHO_SAFE_ASSERT_RETURN(fHandle.context != nullptr && fHandle.imageId != 0,);

_updateSize();
}

NanoVG::Paint::Paint(const NVGpaint& p) noexcept
: radius(p.radius), feather(p.feather), innerColor(p.innerColor), outerColor(p.outerColor), imageId(p.image), repeat(static_cast<PatternRepeat>(p.repeat))
NanoImage::~NanoImage()
{
std::memcpy(xform, p.xform, sizeof(float)*6);
std::memcpy(extent, p.extent, sizeof(float)*2);
if (fHandle.context != nullptr && fHandle.imageId != 0)
nvgDeleteImage(fHandle.context, fHandle.imageId);
}

NanoVG::Paint::operator NVGpaint() const noexcept
NanoImage& NanoImage::operator=(const Handle& handle)
{
NVGpaint p;
p.radius = radius;
p.feather = feather;
p.innerColor = innerColor;
p.outerColor = outerColor;
p.image = imageId;
p.repeat = repeat;
std::memcpy(p.xform, xform, sizeof(float)*6);
std::memcpy(p.extent, extent, sizeof(float)*2);
return p;
}
if (fHandle.context != nullptr && fHandle.imageId != 0)
nvgDeleteImage(fHandle.context, fHandle.imageId);

// -----------------------------------------------------------------------
// NanoImage
fHandle.context = handle.context;
fHandle.imageId = handle.imageId;

NanoImage::NanoImage(NVGcontext* const context, const int imageId) noexcept
: fContext(context),
fImageId(imageId),
fSize(),
leakDetector_NanoImage()
{
_updateSize();
return *this;
}

NanoImage::~NanoImage()
bool NanoImage::isValid() const noexcept
{
if (fContext != nullptr && fImageId != 0)
nvgDeleteImage(fContext, fImageId);
return (fHandle.context != nullptr && fHandle.imageId != 0);
}

Size<uint> NanoImage::getSize() const noexcept
@@ -129,69 +119,91 @@ Size<uint> NanoImage::getSize() const noexcept
return fSize;
}

void NanoImage::updateImage(const uchar* const data)
GLuint NanoImage::getTextureHandle() const
{
DISTRHO_SAFE_ASSERT_RETURN(data != nullptr,);
DISTRHO_SAFE_ASSERT_RETURN(fHandle.context != nullptr && fHandle.imageId != 0, 0);

if (fContext != nullptr && fImageId != 0)
{
nvgUpdateImage(fContext, fImageId, data);
_updateSize();
}
return nvglImageHandle(fHandle.context, fHandle.imageId);
}

void NanoImage::_updateSize()
{
int w=0, h=0;

if (fContext != nullptr && fImageId != 0)
{
nvgImageSize(fContext, fImageId, &w, &h);
nvgImageSize(fHandle.context, fHandle.imageId, &w, &h);

if (w < 0) w = 0;
if (h < 0) h = 0;
}
if (w < 0) w = 0;
if (h < 0) h = 0;

fSize.setSize(static_cast<uint>(w), static_cast<uint>(h));
}

// -----------------------------------------------------------------------
// Paint

NanoVG::Paint::Paint() noexcept
: radius(0.0f), feather(0.0f), innerColor(), outerColor(), imageId(0)
{
std::memset(xform, 0, sizeof(float)*6);
std::memset(extent, 0, sizeof(float)*2);
}

NanoVG::Paint::Paint(const NVGpaint& p) noexcept
: radius(p.radius), feather(p.feather), innerColor(p.innerColor), outerColor(p.outerColor), imageId(p.image)
{
std::memcpy(xform, p.xform, sizeof(float)*6);
std::memcpy(extent, p.extent, sizeof(float)*2);
}

NanoVG::Paint::operator NVGpaint() const noexcept
{
NVGpaint p;
p.radius = radius;
p.feather = feather;
p.innerColor = innerColor;
p.outerColor = outerColor;
p.image = imageId;
std::memcpy(p.xform, xform, sizeof(float)*6);
std::memcpy(p.extent, extent, sizeof(float)*2);
return p;
}

// -----------------------------------------------------------------------
// NanoVG

NanoVG::NanoVG()
: fContext(nvgCreateGL(512, 512, NVG_ANTIALIAS)),
NanoVG::NanoVG(int flags)
: fContext(nvgCreateGL(flags)),
fInFrame(false),
leakDetector_NanoVG()
fIsSubWidget(false)
{
DISTRHO_SAFE_ASSERT_RETURN(fContext != nullptr,);
}

NanoVG::NanoVG(const int textAtlasWidth, const int textAtlasHeight)
: fContext(nvgCreateGL(textAtlasWidth, textAtlasHeight, NVG_ANTIALIAS)),
NanoVG::NanoVG(NanoWidget* groupWidget)
: fContext(groupWidget->fContext),
fInFrame(false),
leakDetector_NanoVG()
fIsSubWidget(true)
{
DISTRHO_SAFE_ASSERT_RETURN(fContext != nullptr,);
}

NanoVG::~NanoVG()
{
DISTRHO_SAFE_ASSERT(! fInFrame);

if (fContext != nullptr)
if (fContext != nullptr && ! fIsSubWidget)
nvgDeleteGL(fContext);
}

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

void NanoVG::beginFrame(const uint width, const uint height, const float scaleFactor, const Alpha alpha)
void NanoVG::beginFrame(const uint width, const uint height, const float scaleFactor)
{
if (fContext == nullptr) return;
DISTRHO_SAFE_ASSERT_RETURN(scaleFactor > 0.0f,);
DISTRHO_SAFE_ASSERT_RETURN(! fInFrame,);

fInFrame = true;
nvgBeginFrame(fContext, static_cast<int>(width), static_cast<int>(height), scaleFactor, static_cast<NVGalpha>(alpha));
nvgBeginFrame(fContext, static_cast<int>(width), static_cast<int>(height), scaleFactor);
}

void NanoVG::beginFrame(Widget* const widget)
@@ -203,16 +215,41 @@ void NanoVG::beginFrame(Widget* const widget)
Window& window(widget->getParentWindow());

fInFrame = true;
nvgBeginFrame(fContext, static_cast<int>(window.getWidth()), static_cast<int>(window.getHeight()), 1.0f, NVG_PREMULTIPLIED_ALPHA);
nvgBeginFrame(fContext, static_cast<int>(window.getWidth()), static_cast<int>(window.getHeight()), 1.0f);
}

void NanoVG::cancelFrame()
{
DISTRHO_SAFE_ASSERT_RETURN(fInFrame,);

if (fContext != nullptr)
nvgCancelFrame(fContext);

fInFrame = false;
}

void NanoVG::endFrame()
{
DISTRHO_SAFE_ASSERT_RETURN(fInFrame,);

// Save current blend state
GLboolean blendEnabled;
GLint blendSrc, blendDst;
glGetBooleanv(GL_BLEND, &blendEnabled);
glGetIntegerv(GL_BLEND_SRC_ALPHA, &blendSrc);
glGetIntegerv(GL_BLEND_DST_ALPHA, &blendDst);

if (fContext != nullptr)
nvgEndFrame(fContext);

// Restore blend state
if (blendEnabled)
glEnable(GL_BLEND);
else
glDisable(GL_BLEND);

glBlendFunc(blendSrc, blendDst);

fInFrame = false;
}

@@ -336,6 +373,12 @@ void NanoVG::lineJoin(NanoVG::LineCap join)
nvgLineJoin(fContext, join);
}

void NanoVG::globalAlpha(float alpha)
{
if (fContext != nullptr)
nvgGlobalAlpha(fContext, alpha);
}

// -----------------------------------------------------------------------
// Transforms

@@ -459,38 +502,65 @@ float NanoVG::radToDeg(float rad)
// -----------------------------------------------------------------------
// Images

NanoImage* NanoVG::createImage(const char* filename)
NanoImage::Handle NanoVG::createImageFromFile(const char* filename, ImageFlags imageFlags)
{
return createImageFromFile(filename, static_cast<int>(imageFlags));
}

NanoImage::Handle NanoVG::createImageFromFile(const char* filename, int imageFlags)
{
if (fContext == nullptr) return NanoImage::Handle();
DISTRHO_SAFE_ASSERT_RETURN(filename != nullptr && filename[0] != '\0', NanoImage::Handle());

return NanoImage::Handle(fContext, nvgCreateImage(fContext, filename, imageFlags));
}

NanoImage::Handle NanoVG::createImageFromMemory(uchar* data, uint dataSize, ImageFlags imageFlags)
{
return createImageFromMemory(data, dataSize, static_cast<int>(imageFlags));
}

NanoImage::Handle NanoVG::createImageFromMemory(uchar* data, uint dataSize, int imageFlags)
{
if (fContext == nullptr) return nullptr;
DISTRHO_SAFE_ASSERT_RETURN(filename != nullptr && filename[0] != '\0', nullptr);
if (fContext == nullptr) return NanoImage::Handle();
DISTRHO_SAFE_ASSERT_RETURN(data != nullptr, NanoImage::Handle());
DISTRHO_SAFE_ASSERT_RETURN(dataSize > 0, NanoImage::Handle());

if (const int imageId = nvgCreateImage(fContext, filename))
return new NanoImage(fContext, imageId);
return NanoImage::Handle(fContext, nvgCreateImageMem(fContext, imageFlags, data,static_cast<int>(dataSize)));
}

return nullptr;
NanoImage::Handle NanoVG::createImageFromRGBA(uint w, uint h, const uchar* data, ImageFlags imageFlags)
{
return createImageFromRGBA(w, h, data, static_cast<int>(imageFlags));
}

NanoImage* NanoVG::createImageMem(uchar* data, int ndata)
NanoImage::Handle NanoVG::createImageFromRGBA(uint w, uint h, const uchar* data, int imageFlags)
{
if (fContext == nullptr) return nullptr;
DISTRHO_SAFE_ASSERT_RETURN(data != nullptr, nullptr);
DISTRHO_SAFE_ASSERT_RETURN(ndata > 0, nullptr);
if (fContext == nullptr) return NanoImage::Handle();
DISTRHO_SAFE_ASSERT_RETURN(data != nullptr, NanoImage::Handle());

if (const int imageId = nvgCreateImageMem(fContext, data, ndata))
return new NanoImage(fContext, imageId);
return NanoImage::Handle(fContext, nvgCreateImageRGBA(fContext,
static_cast<int>(w),
static_cast<int>(h), imageFlags, data));
}

return nullptr;
NanoImage::Handle NanoVG::createImageFromTextureHandle(GLuint textureId, uint w, uint h, ImageFlags imageFlags, bool deleteTexture)
{
return createImageFromTextureHandle(textureId, w, h, static_cast<int>(imageFlags), deleteTexture);
}

NanoImage* NanoVG::createImageRGBA(uint w, uint h, const uchar* data)
NanoImage::Handle NanoVG::createImageFromTextureHandle(GLuint textureId, uint w, uint h, int imageFlags, bool deleteTexture)
{
if (fContext == nullptr) return nullptr;
DISTRHO_SAFE_ASSERT_RETURN(data != nullptr, nullptr);
if (fContext == nullptr) return NanoImage::Handle();
DISTRHO_SAFE_ASSERT_RETURN(textureId != 0, NanoImage::Handle());

if (const int imageId = nvgCreateImageRGBA(fContext, static_cast<int>(w), static_cast<int>(h), data))
return new NanoImage(fContext, imageId);
if (! deleteTexture)
imageFlags |= NVG_IMAGE_NODELETE;

return nullptr;
return NanoImage::Handle(fContext, nvglCreateImageFromHandle(fContext,
textureId,
static_cast<int>(w),
static_cast<int>(h), imageFlags));
}

// -----------------------------------------------------------------------
@@ -514,12 +584,14 @@ NanoVG::Paint NanoVG::radialGradient(float cx, float cy, float inr, float outr,
return nvgRadialGradient(fContext, cx, cy, inr, outr, icol, ocol);
}

NanoVG::Paint NanoVG::imagePattern(float ox, float oy, float ex, float ey, float angle, const NanoImage* image, NanoVG::PatternRepeat repeat)
NanoVG::Paint NanoVG::imagePattern(float ox, float oy, float ex, float ey, float angle, const NanoImage& image, float alpha)
{
if (fContext == nullptr) return Paint();
DISTRHO_SAFE_ASSERT_RETURN(image != nullptr, Paint());

return nvgImagePattern(fContext, ox, oy, ex, ey, angle, image->fImageId, repeat);
const int imageId(image.fHandle.imageId);
DISTRHO_SAFE_ASSERT_RETURN(imageId != 0, Paint());

return nvgImagePattern(fContext, ox, oy, ex, ey, angle, imageId, alpha);
}

// -----------------------------------------------------------------------
@@ -531,6 +603,12 @@ void NanoVG::scissor(float x, float y, float w, float h)
nvgScissor(fContext, x, y, w, h);
}

void NanoVG::intersectScissor(float x, float y, float w, float h)
{
if (fContext != nullptr)
nvgIntersectScissor(fContext, x, y, w, h);
}

void NanoVG::resetScissor()
{
if (fContext != nullptr)
@@ -564,6 +642,12 @@ void NanoVG::bezierTo(float c1x, float c1y, float c2x, float c2y, float x, float
nvgBezierTo(fContext, c1x, c1y, c2x, c2y, x, y);
}

void NanoVG::quadTo(float cx, float cy, float x, float y)
{
if (fContext != nullptr)
nvgQuadTo(fContext, cx, cy, x, y);
}

void NanoVG::arcTo(float x1, float y1, float x2, float y2, float radius)
{
if (fContext != nullptr)
@@ -627,7 +711,7 @@ void NanoVG::stroke()
// -----------------------------------------------------------------------
// Text

NanoVG::FontId NanoVG::createFont(const char* name, const char* filename)
NanoVG::FontId NanoVG::createFontFromFile(const char* name, const char* filename)
{
if (fContext == nullptr) return -1;
DISTRHO_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0', -1);
@@ -636,13 +720,13 @@ NanoVG::FontId NanoVG::createFont(const char* name, const char* filename)
return nvgCreateFont(fContext, name, filename);
}

NanoVG::FontId NanoVG::createFontMem(const char* name, const uchar* data, int ndata, bool freeData)
NanoVG::FontId NanoVG::createFontFromMemory(const char* name, const uchar* data, uint dataSize, bool freeData)
{
if (fContext == nullptr) return -1;
DISTRHO_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0', -1);
DISTRHO_SAFE_ASSERT_RETURN(data != nullptr, -1);

return nvgCreateFontMem(fContext, name, const_cast<uchar*>(data), ndata, freeData);
return nvgCreateFontMem(fContext, name, const_cast<uchar*>(data), static_cast<int>(dataSize), freeData);
}

NanoVG::FontId NanoVG::findFont(const char* name)
@@ -740,7 +824,7 @@ float NanoVG::textBounds(float x, float y, const char* string, const char* end,
return ret;
}

void NanoVG::textBoxBounds(float x, float y, float breakRowWidth, const char* string, const char* end, float* bounds)
void NanoVG::textBoxBounds(float x, float y, float breakRowWidth, const char* string, const char* end, float bounds[4])
{
if (fContext == nullptr) return;
DISTRHO_SAFE_ASSERT_RETURN(string != nullptr && string[0] != '\0',);
@@ -748,12 +832,12 @@ void NanoVG::textBoxBounds(float x, float y, float breakRowWidth, const char* st
nvgTextBoxBounds(fContext, x, y, breakRowWidth, string, end, bounds);
}

int NanoVG::textGlyphPositions(float x, float y, const char* string, const char* end, NanoVG::GlyphPosition* positions, int maxPositions)
int NanoVG::textGlyphPositions(float x, float y, const char* string, const char* end, NanoVG::GlyphPosition& positions, int maxPositions)
{
if (fContext == nullptr) return 0;
DISTRHO_SAFE_ASSERT_RETURN(string != nullptr && string[0] != '\0', 0);

return nvgTextGlyphPositions(fContext, x, y, string, end, (NVGglyphPosition*)positions, maxPositions);
return nvgTextGlyphPositions(fContext, x, y, string, end, (NVGglyphPosition*)&positions, maxPositions);
}

void NanoVG::textMetrics(float* ascender, float* descender, float* lineh)
@@ -762,15 +846,75 @@ void NanoVG::textMetrics(float* ascender, float* descender, float* lineh)
nvgTextMetrics(fContext, ascender, descender, lineh);
}

int NanoVG::textBreakLines(const char* string, const char* end, float breakRowWidth, NanoVG::TextRow* rows, int maxRows)
int NanoVG::textBreakLines(const char* string, const char* end, float breakRowWidth, NanoVG::TextRow& rows, int maxRows)
{
if (fContext != nullptr)
return nvgTextBreakLines(fContext, string, end, breakRowWidth, (NVGtextRow*)rows, maxRows);
return nvgTextBreakLines(fContext, string, end, breakRowWidth, (NVGtextRow*)&rows, maxRows);
return 0;
}

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

struct NanoWidget::PrivateData {
NanoWidget* const self;
std::vector<NanoWidget*> subWidgets;

PrivateData(NanoWidget* const s)
: self(s),
subWidgets() {}

~PrivateData()
{
subWidgets.clear();
}
};

NanoWidget::NanoWidget(Window& parent, int flags)
: Widget(parent),
NanoVG(flags),
nData(new PrivateData(this))
{
pData->needsScaling = true;
}

NanoWidget::NanoWidget(Widget* groupWidget, int flags)
: Widget(groupWidget, true),
NanoVG(flags),
nData(new PrivateData(this))
{
pData->needsScaling = true;
}

NanoWidget::NanoWidget(NanoWidget* groupWidget)
: Widget(groupWidget, false),
NanoVG(groupWidget),
nData(new PrivateData(this))
{
pData->needsScaling = true;
groupWidget->nData->subWidgets.push_back(this);
}

NanoWidget::~NanoWidget()
{
delete nData;
}

void NanoWidget::onDisplay()
{
NanoVG::beginFrame(getWidth(), getHeight());
onNanoDisplay();

for (std::vector<NanoWidget*>::iterator it = nData->subWidgets.begin(); it != nData->subWidgets.end(); ++it)
{
NanoWidget* const widget(*it);
widget->onNanoDisplay();
}

NanoVG::endFrame();
}

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

END_NAMESPACE_DGL

extern "C" {


+ 144
- 0
source/modules/dgl/src/NanoWidgets.cpp View File

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

#include "../NanoWidgets.hpp"
#include "Common.hpp"

#define BLENDISH_IMPLEMENTATION
#include "nanovg/nanovg.h"
#include "oui-blendish/blendish.h"
#include "oui-blendish/blendish_resources.h"

START_NAMESPACE_DGL

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

static void registerBlendishResourcesIfNeeded(NVGcontext* const context)
{
if (nvgFindFont(context, "__dpf_blendish__") >= 0)
return;

using namespace blendish_resources;

bndSetFont(nvgCreateFontMem(context, "__dpf_blendish__", (const uchar*)dejavusans_ttf, dejavusans_ttf_size, 0));
bndSetIconImage(nvgCreateImageMem(context, 0, (const uchar*)blender_icons16_png, blender_icons16_png_size));
}

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

struct BlendishButton::PrivateData {
ButtonImpl impl;
int iconId;
DISTRHO_NAMESPACE::String text;

PrivateData(Widget* const s, const char* const t, const int i) noexcept
: impl(s),
iconId(i),
text(t) {}

DISTRHO_DECLARE_NON_COPY_STRUCT(PrivateData)
};

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

BlendishButton::BlendishButton(Window& parent, const char* text, int iconId)
: NanoWidget(parent),
pData(new PrivateData(this, text, iconId))
{
registerBlendishResourcesIfNeeded(getContext());
_updateBounds();
}

BlendishButton::BlendishButton(NanoWidget* widget, const char* text, int iconId)
: NanoWidget(widget),
pData(new PrivateData(this, text, iconId))
{
registerBlendishResourcesIfNeeded(getContext());
_updateBounds();
}

BlendishButton::~BlendishButton()
{
delete pData;
}

int BlendishButton::getIconId() const noexcept
{
return pData->iconId;
}

void BlendishButton::setIconId(int iconId) noexcept
{
if (pData->iconId == iconId)
return;

pData->iconId = iconId;
_updateBounds();
repaint();
}

const char* BlendishButton::getText() const noexcept
{
return pData->text;
}

void BlendishButton::setText(const char* text) noexcept
{
if (pData->text == text)
return;

pData->text = text;
_updateBounds();
repaint();
}

void BlendishButton::setCallback(Callback* callback) noexcept
{
pData->impl.callback_b = callback;
}

void BlendishButton::onNanoDisplay()
{
bndToolButton(getContext(),
getAbsoluteX(), getAbsoluteY(), getWidth(), getHeight(),
0, static_cast<BNDwidgetState>(pData->impl.state), pData->iconId, pData->text);
}

bool BlendishButton::onMouse(const MouseEvent& ev)
{
return pData->impl.onMouse(ev);
}

bool BlendishButton::onMotion(const MotionEvent& ev)
{
return pData->impl.onMotion(ev);
}

void BlendishButton::_updateBounds()
{
const float width = bndLabelWidth (getContext(), pData->iconId, pData->text);
const float height = bndLabelHeight(getContext(), pData->iconId, pData->text, width);

setSize(width, height);
}

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

END_NAMESPACE_DGL

#include "oui-blendish/blendish_resources.cpp"

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

+ 58
- 63
source/modules/dgl/src/Widget.cpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2015 Filipe Coelho <falktx@falktx.com>
*
* Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this
@@ -14,8 +14,7 @@
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

#include "../Widget.hpp"
#include "../Window.hpp"
#include "WidgetPrivateData.hpp"

START_NAMESPACE_DGL

@@ -23,35 +22,41 @@ START_NAMESPACE_DGL
// Widget

Widget::Widget(Window& parent)
: fParent(parent),
fNeedsFullViewport(false),
fNeedsScaling(false),
fVisible(true),
fId(0),
fAbsolutePos(0, 0),
fSize(0, 0),
leakDetector_Widget()
: pData(new PrivateData(this, parent, nullptr, false))
{
fParent._addWidget(this);
parent._addWidget(this);
}

Widget::Widget(Widget* groupWidget)
: pData(new PrivateData(this, groupWidget->getParentWindow(), groupWidget, true))
{
pData->parent._addWidget(this);
}

Widget::Widget(Widget* groupWidget, bool addToSubWidgets)
: pData(new PrivateData(this, groupWidget->getParentWindow(), groupWidget, addToSubWidgets))
{
pData->parent._addWidget(this);
}

Widget::~Widget()
{
fParent._removeWidget(this);
pData->parent._removeWidget(this);
delete pData;
}

bool Widget::isVisible() const noexcept
{
return fVisible;
return pData->visible;
}

void Widget::setVisible(bool yesNo)
{
if (fVisible == yesNo)
if (pData->visible == yesNo)
return;

fVisible = yesNo;
fParent.repaint();
pData->visible = yesNo;
pData->parent.repaint();
}

void Widget::show()
@@ -66,47 +71,47 @@ void Widget::hide()

uint Widget::getWidth() const noexcept
{
return fSize.getWidth();
return pData->size.getWidth();
}

uint Widget::getHeight() const noexcept
{
return fSize.getHeight();
return pData->size.getHeight();
}

const Size<uint>& Widget::getSize() const noexcept
{
return fSize;
return pData->size;
}

void Widget::setWidth(uint width) noexcept
{
if (fSize.getWidth() == width)
if (pData->size.getWidth() == width)
return;

ResizeEvent ev;
ev.oldSize = fSize;
ev.size = Size<uint>(width, fSize.getHeight());
ev.oldSize = pData->size;
ev.size = Size<uint>(width, pData->size.getHeight());

fSize.setWidth(width);
pData->size.setWidth(width);
onResize(ev);

fParent.repaint();
pData->parent.repaint();
}

void Widget::setHeight(uint height) noexcept
{
if (fSize.getHeight() == height)
if (pData->size.getHeight() == height)
return;

ResizeEvent ev;
ev.oldSize = fSize;
ev.size = Size<uint>(fSize.getWidth(), height);
ev.oldSize = pData->size;
ev.size = Size<uint>(pData->size.getWidth(), height);

fSize.setHeight(height);
pData->size.setHeight(height);
onResize(ev);

fParent.repaint();
pData->parent.repaint();
}

void Widget::setSize(uint width, uint height) noexcept
@@ -116,50 +121,50 @@ void Widget::setSize(uint width, uint height) noexcept

void Widget::setSize(const Size<uint>& size) noexcept
{
if (fSize == size)
if (pData->size == size)
return;

ResizeEvent ev;
ev.oldSize = fSize;
ev.oldSize = pData->size;
ev.size = size;

fSize = size;
pData->size = size;
onResize(ev);

fParent.repaint();
pData->parent.repaint();
}

int Widget::getAbsoluteX() const noexcept
{
return fAbsolutePos.getX();
return pData->absolutePos.getX();
}

int Widget::getAbsoluteY() const noexcept
{
return fAbsolutePos.getY();
return pData->absolutePos.getY();
}

const Point<int>& Widget::getAbsolutePos() const noexcept
{
return fAbsolutePos;
return pData->absolutePos;
}

void Widget::setAbsoluteX(int x) noexcept
{
if (fAbsolutePos.getX() == x)
if (pData->absolutePos.getX() == x)
return;

fAbsolutePos.setX(x);
fParent.repaint();
pData->absolutePos.setX(x);
pData->parent.repaint();
}

void Widget::setAbsoluteY(int y) noexcept
{
if (fAbsolutePos.getY() == y)
if (pData->absolutePos.getY() == y)
return;

fAbsolutePos.setY(y);
fParent.repaint();
pData->absolutePos.setY(y);
pData->parent.repaint();
}

void Widget::setAbsolutePos(int x, int y) noexcept
@@ -169,26 +174,26 @@ void Widget::setAbsolutePos(int x, int y) noexcept

void Widget::setAbsolutePos(const Point<int>& pos) noexcept
{
if (fAbsolutePos == pos)
if (pData->absolutePos == pos)
return;

fAbsolutePos = pos;
fParent.repaint();
pData->absolutePos = pos;
pData->parent.repaint();
}

App& Widget::getParentApp() const noexcept
Application& Widget::getParentApp() const noexcept
{
return fParent.getApp();
return pData->parent.getApp();
}

Window& Widget::getParentWindow() const noexcept
{
return fParent;
return pData->parent;
}

bool Widget::contains(int x, int y) const noexcept
{
return (x >= 0 && y >= 0 && static_cast<uint>(x) < fSize.getWidth() && static_cast<uint>(y) < fSize.getHeight());
return (x >= 0 && y >= 0 && static_cast<uint>(x) < pData->size.getWidth() && static_cast<uint>(y) < pData->size.getHeight());
}

bool Widget::contains(const Point<int>& pos) const noexcept
@@ -198,17 +203,17 @@ bool Widget::contains(const Point<int>& pos) const noexcept

void Widget::repaint() noexcept
{
fParent.repaint();
pData->parent.repaint();
}

uint Widget::getId() const noexcept
{
return fId;
return pData->id;
}

void Widget::setId(uint id) noexcept
{
fId = id;
pData->id = id;
}

bool Widget::onKeyboard(const KeyboardEvent&)
@@ -240,16 +245,6 @@ void Widget::onResize(const ResizeEvent&)
{
}

void Widget::setNeedsFullViewport(bool yesNo) noexcept
{
fNeedsFullViewport = yesNo;
}

void Widget::setNeedsScaling(bool yesNo) noexcept
{
fNeedsScaling = yesNo;
}

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

END_NAMESPACE_DGL

+ 133
- 0
source/modules/dgl/src/WidgetPrivateData.hpp View File

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

#ifndef DGL_WIDGET_PRIVATE_DATA_HPP_INCLUDED
#define DGL_WIDGET_PRIVATE_DATA_HPP_INCLUDED

#include "../Widget.hpp"
#include "../Window.hpp"

#include <vector>

START_NAMESPACE_DGL

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

struct Widget::PrivateData {
Widget* const self;
Window& parent;
Point<int> absolutePos;
Size<uint> size;
std::vector<Widget*> subWidgets;

uint id;
bool needsFullViewport;
bool needsScaling;
bool skipDisplay;
bool visible;

PrivateData(Widget* const s, Window& p, Widget* groupWidget, bool addToSubWidgets)
: self(s),
parent(p),
absolutePos(0, 0),
size(0, 0),
id(0),
needsFullViewport(false),
needsScaling(false),
skipDisplay(false),
visible(true)
{
if (addToSubWidgets && groupWidget != nullptr)
groupWidget->pData->subWidgets.push_back(self);
}

~PrivateData()
{
subWidgets.clear();
}

void display(const uint width, const uint height)
{
if (skipDisplay || ! visible)
return;

bool needsDisableScissor = false;

// reset color
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);

if (needsFullViewport || (absolutePos.isZero() && size == Size<uint>(width, height)))
{
// full viewport size
glViewport(0, 0, static_cast<GLsizei>(width), static_cast<GLsizei>(height));
}
else if (needsScaling)
{
// limit viewport to widget bounds
glViewport(absolutePos.getX(),
height - static_cast<int>(self->getHeight()) - absolutePos.getY(),
static_cast<GLsizei>(self->getWidth()),
static_cast<GLsizei>(self->getHeight()));
}
else
{
// only set viewport pos
glViewport(absolutePos.getX(),
/*height - static_cast<int>(self->getHeight())*/ - absolutePos.getY(),
static_cast<GLsizei>(width),
static_cast<GLsizei>(height));

// then cut the outer bounds
glScissor(absolutePos.getX(),
height - static_cast<int>(self->getHeight()) - absolutePos.getY(),
static_cast<GLsizei>(self->getWidth()),
static_cast<GLsizei>(self->getHeight()));

glEnable(GL_SCISSOR_TEST);
needsDisableScissor = true;
}

// display widget
self->onDisplay();

if (needsDisableScissor)
{
glDisable(GL_SCISSOR_TEST);
needsDisableScissor = false;
}

displaySubWidgets(width, height);
}

void displaySubWidgets(const uint width, const uint height)
{
for (std::vector<Widget*>::iterator it = subWidgets.begin(); it != subWidgets.end(); ++it)
{
Widget* const widget(*it);
DISTRHO_SAFE_ASSERT_CONTINUE(widget->pData != this);

widget->pData->display(width, height);
}
}

DISTRHO_DECLARE_NON_COPY_STRUCT(PrivateData)
};

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

END_NAMESPACE_DGL

#endif // DGL_WIDGET_PRIVATE_DATA_HPP_INCLUDED

+ 97
- 89
source/modules/dgl/src/Window.cpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2015 Filipe Coelho <falktx@falktx.com>
*
* Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this
@@ -17,10 +17,11 @@
// we need this for now
//#define PUGL_GRAB_FOCUS 1

#include "AppPrivateData.hpp"
#include "../Widget.hpp"
#include "../Window.hpp"
#include "../../distrho/extra/d_string.hpp"
#include "../../distrho/src/DistrhoDefines.h"

#undef PUGL_HAVE_CAIRO
#undef PUGL_HAVE_GL
#define PUGL_HAVE_GL 1

#include "pugl/pugl.h"

@@ -38,6 +39,11 @@ extern "C" {
# error Unsupported platform
#endif

#include "ApplicationPrivateData.hpp"
#include "WidgetPrivateData.hpp"
#include "../StandaloneWindow.hpp"
#include "../../distrho/extra/String.hpp"

#define FOR_EACH_WIDGET(it) \
for (std::list<Widget*>::iterator it = fWidgets.begin(); it != fWidgets.end(); ++it)

@@ -60,7 +66,7 @@ START_NAMESPACE_DGL
// Window Private

struct Window::PrivateData {
PrivateData(App& app, Window* const self)
PrivateData(Application& app, Window* const self)
: fApp(app),
fSelf(self),
fView(puglInit()),
@@ -74,22 +80,21 @@ struct Window::PrivateData {
fWidgets(),
fModal(),
#if defined(DISTRHO_OS_WINDOWS)
hwnd(0),
hwnd(0)
#elif defined(DISTRHO_OS_LINUX)
xDisplay(nullptr),
xWindow(0),
xWindow(0)
#elif defined(DISTRHO_OS_MAC)
fNeedsIdle(true),
mView(nullptr),
mWindow(nullptr),
mWindow(nullptr)
#endif
leakDetector_PrivateData()
{
DBG("Creating window without parent..."); DBGF;
init();
}

PrivateData(App& app, Window* const self, Window& parent)
PrivateData(Application& app, Window* const self, Window& parent)
: fApp(app),
fSelf(self),
fView(puglInit()),
@@ -103,16 +108,15 @@ struct Window::PrivateData {
fWidgets(),
fModal(parent.pData),
#if defined(DISTRHO_OS_WINDOWS)
hwnd(0),
hwnd(0)
#elif defined(DISTRHO_OS_LINUX)
xDisplay(nullptr),
xWindow(0),
xWindow(0)
#elif defined(DISTRHO_OS_MAC)
fNeedsIdle(false),
mView(nullptr),
mWindow(nullptr),
mWindow(nullptr)
#endif
leakDetector_PrivateData()
{
DBG("Creating window with parent..."); DBGF;
init();
@@ -128,7 +132,7 @@ struct Window::PrivateData {
#endif
}

PrivateData(App& app, Window* const self, const intptr_t parentId)
PrivateData(Application& app, Window* const self, const intptr_t parentId)
: fApp(app),
fSelf(self),
fView(puglInit()),
@@ -142,16 +146,15 @@ struct Window::PrivateData {
fWidgets(),
fModal(),
#if defined(DISTRHO_OS_WINDOWS)
hwnd(0),
hwnd(0)
#elif defined(DISTRHO_OS_LINUX)
xDisplay(nullptr),
xWindow(0),
xWindow(0)
#elif defined(DISTRHO_OS_MAC)
fNeedsIdle(parentId == 0),
mView(nullptr),
mWindow(nullptr),
mWindow(nullptr)
#endif
leakDetector_PrivateData()
{
if (fUsingEmbed)
{
@@ -182,7 +185,8 @@ struct Window::PrivateData {
return;
}

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

puglSetHandle(fView, this);
@@ -223,6 +227,7 @@ struct Window::PrivateData {
XChangeProperty(xDisplay, xWindow, _nwp, XA_CARDINAL, 32, PropModeReplace, (const uchar*)&pid, 1);
}
#endif
puglEnterContext(fView);

fApp.pData->windows.push_back(fSelf);

@@ -349,8 +354,24 @@ struct Window::PrivateData {
fModal.enabled = false;

if (fModal.parent != nullptr)
{
fModal.parent->fModal.childFocus = nullptr;

// the mouse position probably changed since the modal appeared,
// so send a mouse motion event to the modal's parent window
#if defined(DISTRHO_OS_WINDOWS)
// TODO
#elif defined(DISTRHO_OS_MAC)
// TODO
#elif defined(DISTRHO_OS_LINUX)
int i, wx, wy;
uint u;
::Window w;
if (XQueryPointer(fModal.parent->xDisplay, fModal.parent->xWindow, &w, &w, &i, &i, &wx, &wy, &u) == True)
fModal.parent->onPuglMotion(wx, wy);
#endif
}

DBG("Ok\n");
}

@@ -647,60 +668,10 @@ struct Window::PrivateData {
{
fSelf->onDisplayBefore();

bool needsDisableScissor = false;

FOR_EACH_WIDGET(it)
{
Widget* const widget(*it);

if (widget->isVisible())
{
// reset color
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);

if (widget->fNeedsFullViewport || (widget->fAbsolutePos.isZero() && widget->fSize == Size<uint>(fWidth, fHeight)))
{
// full viewport size
glViewport(0,
0,
static_cast<GLsizei>(fWidth),
static_cast<GLsizei>(fHeight));
}
else if (! widget->fNeedsScaling)
{
// only set viewport pos
glViewport(widget->getAbsoluteX(),
/*fView->height - static_cast<int>(widget->getHeight())*/ - widget->getAbsoluteY(),
static_cast<GLsizei>(fWidth),
static_cast<GLsizei>(fHeight));

// then cut the outer bounds
glScissor(widget->getAbsoluteX(),
fView->height - static_cast<int>(widget->getHeight()) - widget->getAbsoluteY(),
static_cast<GLsizei>(widget->getWidth()),
static_cast<GLsizei>(widget->getHeight()));

glEnable(GL_SCISSOR_TEST);
needsDisableScissor = true;
}
else
{
// limit viewport to widget bounds
glViewport(widget->getAbsoluteX(),
fView->height - static_cast<int>(widget->getHeight()) - widget->getAbsoluteY(),
static_cast<GLsizei>(widget->getWidth()),
static_cast<GLsizei>(widget->getHeight()));
}

// display widget
widget->onDisplay();

if (needsDisableScissor)
{
glDisable(GL_SCISSOR_TEST);
needsDisableScissor = false;
}
}
widget->pData->display(fWidth, fHeight);
}

fSelf->onDisplayAfter();
@@ -838,7 +809,7 @@ struct Window::PrivateData {
{
Widget* const widget(*it);

if (widget->fNeedsFullViewport)
if (widget->pData->needsFullViewport)
widget->setSize(fWidth, fHeight);
}
}
@@ -860,9 +831,9 @@ struct Window::PrivateData {

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

App& fApp;
Window* fSelf;
PuglView* fView;
Application& fApp;
Window* fSelf;
PuglView* fView;

bool fFirstInit;
bool fVisible;
@@ -966,17 +937,14 @@ struct Window::PrivateData {
// -----------------------------------------------------------------------
// Window

Window::Window(App& app)
: pData(new PrivateData(app, this)),
leakDetector_Window() {}
Window::Window(Application& app)
: pData(new PrivateData(app, this)) {}

Window::Window(App& app, Window& parent)
: pData(new PrivateData(app, this, parent)),
leakDetector_Window() {}
Window::Window(Application& app, Window& parent)
: pData(new PrivateData(app, this, parent)) {}

Window::Window(App& app, intptr_t parentId)
: pData(new PrivateData(app, this, parentId)),
leakDetector_Window() {}
Window::Window(Application& app, intptr_t parentId)
: pData(new PrivateData(app, this, parentId)) {}

Window::~Window()
{
@@ -1022,7 +990,7 @@ void Window::repaint() noexcept
bool Window::openFileBrowser(const FileBrowserOptions& options)
{
#ifdef SOFD_HAVE_X11
using DISTRHO_NAMESPACE::d_string;
using DISTRHO_NAMESPACE::String;

// --------------------------------------------------------------------------
// configure start dir
@@ -1030,7 +998,7 @@ bool Window::openFileBrowser(const FileBrowserOptions& options)
// TODO: get abspath if needed
// TODO: cross-platform

d_string startDir(options.startDir);
String startDir(options.startDir);

if (startDir.isEmpty())
{
@@ -1051,7 +1019,7 @@ bool Window::openFileBrowser(const FileBrowserOptions& options)
// --------------------------------------------------------------------------
// configure title

d_string title(options.title);
String title(options.title);

if (title.isEmpty())
{
@@ -1145,7 +1113,7 @@ void Window::setTransientWinId(uintptr_t winId)
pData->setTransientWinId(winId);
}

App& Window::getApp() const noexcept
Application& Window::getApp() const noexcept
{
return pData->fApp;
}
@@ -1220,6 +1188,46 @@ void Window::fileBrowserSelected(const char*)

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

StandaloneWindow::StandaloneWindow()
: Application(),
Window((Application&)*this),
fWidget(nullptr) {}

void StandaloneWindow::exec()
{
Window::show();
Application::exec();
}

void StandaloneWindow::onReshape(uint width, uint height)
{
if (fWidget != nullptr)
fWidget->setSize(width, height);
Window::onReshape(width, height);
}

void StandaloneWindow::_addWidget(Widget* widget)
{
if (fWidget == nullptr)
{
fWidget = widget;
fWidget->pData->needsFullViewport = true;
}
Window::_addWidget(widget);
}

void StandaloneWindow::_removeWidget(Widget* widget)
{
if (fWidget == widget)
{
fWidget->pData->needsFullViewport = false;
fWidget = nullptr;
}
Window::_removeWidget(widget);
}

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

END_NAMESPACE_DGL

#undef DBG


+ 194
- 176
source/modules/dgl/src/nanovg/fontstash.h
File diff suppressed because it is too large
View File


+ 789
- 512
source/modules/dgl/src/nanovg/nanovg.c
File diff suppressed because it is too large
View File


+ 171
- 141
source/modules/dgl/src/nanovg/nanovg.h View File

@@ -25,7 +25,12 @@ extern "C" {

#define NVG_PI 3.14159265358979323846264338327f

struct NVGcontext;
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4201) // nonstandard extension used : nameless struct/union
#endif

typedef struct NVGcontext NVGcontext;

struct NVGcolor {
union {
@@ -35,17 +40,18 @@ struct NVGcolor {
};
};
};
typedef struct NVGcolor NVGcolor;

struct NVGpaint {
float xform[6];
float extent[2];
float radius;
float feather;
struct NVGcolor innerColor;
struct NVGcolor outerColor;
NVGcolor innerColor;
NVGcolor outerColor;
int image;
int repeat;
};
typedef struct NVGpaint NVGpaint;

enum NVGwinding {
NVG_CCW = 1, // Winding for solid shapes
@@ -65,11 +71,6 @@ enum NVGlineCap {
NVG_MITER,
};

enum NVGpatternRepeat {
NVG_REPEATX = 0x01, // Repeat image pattern in X direction
NVG_REPEATY = 0x02, // Repeat image pattern in Y direction
};

enum NVGalign {
// Horizontal align
NVG_ALIGN_LEFT = 1<<0, // Default, align text horizontally to left.
@@ -78,13 +79,8 @@ enum NVGalign {
// Vertical align
NVG_ALIGN_TOP = 1<<3, // Align text vertically to top.
NVG_ALIGN_MIDDLE = 1<<4, // Align text vertically to middle.
NVG_ALIGN_BOTTOM = 1<<5, // Align text vertically to bottom.
NVG_ALIGN_BASELINE = 1<<6, // Default, align text vertically to baseline.
};

enum NVGalpha {
NVG_STRAIGHT_ALPHA,
NVG_PREMULTIPLIED_ALPHA,
NVG_ALIGN_BOTTOM = 1<<5, // Align text vertically to bottom.
NVG_ALIGN_BASELINE = 1<<6, // Default, align text vertically to baseline.
};

struct NVGglyphPosition {
@@ -92,6 +88,7 @@ struct NVGglyphPosition {
float x; // The x-coordinate of the logical glyph position.
float minx, maxx; // The bounds of the glyph shape.
};
typedef struct NVGglyphPosition NVGglyphPosition;

struct NVGtextRow {
const char* start; // Pointer to the input text where the row starts.
@@ -100,7 +97,15 @@ struct NVGtextRow {
float width; // Logical width of the row.
float minx, maxx; // Actual bounds of the row. Logical with and bounds can differ because of kerning and some parts over extending.
};

typedef struct NVGtextRow NVGtextRow;

enum NVGimageFlags {
NVG_IMAGE_GENERATE_MIPMAPS = 1<<0, // Generate mipmaps during creation of the image.
NVG_IMAGE_REPEATX = 1<<1, // Repeat image in X direction.
NVG_IMAGE_REPEATY = 1<<2, // Repeat image in Y direction.
NVG_IMAGE_FLIPY = 1<<3, // Flips (inverses) image in Y direction when rendered.
NVG_IMAGE_PREMULTIPLIED = 1<<4, // Image data has premultiplied alpha.
};

// Begin drawing a new frame
// Calls to nanovg drawing API should be wrapped in nvgBeginFrame() & nvgEndFrame()
@@ -110,14 +115,13 @@ struct NVGtextRow {
// For example, GLFW returns two dimension for an opened window: window size and
// frame buffer size. In that case you would set windowWidth/Height to the window size
// devicePixelRatio to: frameBufferWidth / windowWidth.
// AlphaBlend controls if drawing the shapes to the render target should be done using straight or
// premultiplied alpha. If rendering directly to framebuffer you probably want to use NVG_STRAIGHT_ALPHA,
// if rendering to texture which should contain transparent regions NVG_PREMULTIPLIED_ALPHA is the
// right choice.
void nvgBeginFrame(struct NVGcontext* ctx, int windowWidth, int windowHeight, float devicePixelRatio, int alphaBlend);
void nvgBeginFrame(NVGcontext* ctx, int windowWidth, int windowHeight, float devicePixelRatio);

// Cancels drawing the current frame.
void nvgCancelFrame(NVGcontext* ctx);

// Ends drawing flushing remaining render state.
void nvgEndFrame(struct NVGcontext* ctx);
void nvgEndFrame(NVGcontext* ctx);

//
// Color utils
@@ -125,35 +129,35 @@ void nvgEndFrame(struct NVGcontext* ctx);
// Colors in NanoVG are stored as unsigned ints in ABGR format.

// Returns a color value from red, green, blue values. Alpha will be set to 255 (1.0f).
struct NVGcolor nvgRGB(unsigned char r, unsigned char g, unsigned char b);
NVGcolor nvgRGB(unsigned char r, unsigned char g, unsigned char b);

// Returns a color value from red, green, blue values. Alpha will be set to 1.0f.
struct NVGcolor nvgRGBf(float r, float g, float b);
NVGcolor nvgRGBf(float r, float g, float b);


// Returns a color value from red, green, blue and alpha values.
struct NVGcolor nvgRGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a);
NVGcolor nvgRGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a);

// Returns a color value from red, green, blue and alpha values.
struct NVGcolor nvgRGBAf(float r, float g, float b, float a);
NVGcolor nvgRGBAf(float r, float g, float b, float a);


// Linearly interpoaltes from color c0 to c1, and returns resulting color value.
struct NVGcolor nvgLerpRGBA(struct NVGcolor c0, struct NVGcolor c1, float u);
// Linearly interpolates from color c0 to c1, and returns resulting color value.
NVGcolor nvgLerpRGBA(NVGcolor c0, NVGcolor c1, float u);

// Sets transparency of a color value.
struct NVGcolor nvgTransRGBA(struct NVGcolor c0, unsigned char a);
NVGcolor nvgTransRGBA(NVGcolor c0, unsigned char a);

// Sets transparency of a color value.
struct NVGcolor nvgTransRGBAf(struct NVGcolor c0, float a);
NVGcolor nvgTransRGBAf(NVGcolor c0, float a);

// Returns color value specified by hue, saturation and lightness.
// HSL values are all in range [0..1], alpha will be set to 255.
struct NVGcolor nvgHSL(float h, float s, float l);
NVGcolor nvgHSL(float h, float s, float l);

// Returns color value specified by hue, saturation and lightness and alpha.
// HSL values are all in range [0..1], alpha in range [0..255]
struct NVGcolor nvgHSLA(float h, float s, float l, unsigned char a);
NVGcolor nvgHSLA(float h, float s, float l, unsigned char a);

//
// State Handling
@@ -164,13 +168,13 @@ struct NVGcolor nvgHSLA(float h, float s, float l, unsigned char a);

// Pushes and saves the current render state into a state stack.
// A matching nvgRestore() must be used to restore the state.
void nvgSave(struct NVGcontext* ctx);
void nvgSave(NVGcontext* ctx);

// Pops and restores current render state.
void nvgRestore(struct NVGcontext* ctx);
void nvgRestore(NVGcontext* ctx);

// Resets current render state to default values. Does not affect the render state stack.
void nvgReset(struct NVGcontext* ctx);
void nvgReset(NVGcontext* ctx);

//
// Render styles
@@ -179,34 +183,38 @@ void nvgReset(struct NVGcontext* ctx);
// Solid color is simply defined as a color value, different kinds of paints can be created
// using nvgLinearGradient(), nvgBoxGradient(), nvgRadialGradient() and nvgImagePattern().
//
// Current render style can be saved and restored using nvgSave() and nvgRestore().
// Current render style can be saved and restored using nvgSave() and nvgRestore().

// Sets current stroke style to a solid color.
void nvgStrokeColor(struct NVGcontext* ctx, struct NVGcolor color);
void nvgStrokeColor(NVGcontext* ctx, NVGcolor color);

// Sets current stroke style to a paint, which can be a one of the gradients or a pattern.
void nvgStrokePaint(struct NVGcontext* ctx, struct NVGpaint paint);
void nvgStrokePaint(NVGcontext* ctx, NVGpaint paint);

// Sets current fill cstyle to a solid color.
void nvgFillColor(struct NVGcontext* ctx, struct NVGcolor color);
// Sets current fill style to a solid color.
void nvgFillColor(NVGcontext* ctx, NVGcolor color);

// Sets current fill style to a paint, which can be a one of the gradients or a pattern.
void nvgFillPaint(struct NVGcontext* ctx, struct NVGpaint paint);
void nvgFillPaint(NVGcontext* ctx, NVGpaint paint);

// Sets the miter limit of the stroke style.
// Miter limit controls when a sharp corner is beveled.
void nvgMiterLimit(struct NVGcontext* ctx, float limit);
void nvgMiterLimit(NVGcontext* ctx, float limit);

// Sets the stroke witdth of the stroke style.
void nvgStrokeWidth(struct NVGcontext* ctx, float size);
// Sets the stroke width of the stroke style.
void nvgStrokeWidth(NVGcontext* ctx, float size);

// Sets how the end of the line (cap) is drawn,
// Can be one of: NVG_BUTT (default), NVG_ROUND, NVG_SQUARE.
void nvgLineCap(struct NVGcontext* ctx, int cap);
void nvgLineCap(NVGcontext* ctx, int cap);

// Sets how sharp path corners are drawn.
// Can be one of NVG_MITER (default), NVG_ROUND, NVG_BEVEL.
void nvgLineJoin(struct NVGcontext* ctx, int join);
void nvgLineJoin(NVGcontext* ctx, int join);

// Sets the transparency applied to all rendered shapes.
// Already transparent paths will get proportionally more transparent as well.
void nvgGlobalAlpha(NVGcontext* ctx, float alpha);

//
// Transforms
@@ -223,43 +231,43 @@ void nvgLineJoin(struct NVGcontext* ctx, int join);
// Apart from nvgResetTransform(), each transformation function first creates
// specific transformation matrix and pre-multiplies the current transformation by it.
//
// Current coordinate system (transformation) can be saved and restored using nvgSave() and nvgRestore().
// Current coordinate system (transformation) can be saved and restored using nvgSave() and nvgRestore().

// Resets current transform to a identity matrix.
void nvgResetTransform(struct NVGcontext* ctx);
void nvgResetTransform(NVGcontext* ctx);

// Premultiplies current coordinate system by specified matrix.
// The parameters are interpreted as matrix as follows:
// [a c e]
// [b d f]
// [0 0 1]
void nvgTransform(struct NVGcontext* ctx, float a, float b, float c, float d, float e, float f);
void nvgTransform(NVGcontext* ctx, float a, float b, float c, float d, float e, float f);

// Translates current coordinate system.
void nvgTranslate(struct NVGcontext* ctx, float x, float y);
void nvgTranslate(NVGcontext* ctx, float x, float y);

// Rotates current coordinate system. Angle is specifid in radians.
void nvgRotate(struct NVGcontext* ctx, float angle);
// Rotates current coordinate system. Angle is specified in radians.
void nvgRotate(NVGcontext* ctx, float angle);

// Skews the current coordinate system along X axis. Angle is specifid in radians.
void nvgSkewX(struct NVGcontext* ctx, float angle);
// Skews the current coordinate system along X axis. Angle is specified in radians.
void nvgSkewX(NVGcontext* ctx, float angle);

// Skews the current coordinate system along Y axis. Angle is specifid in radians.
void nvgSkewY(struct NVGcontext* ctx, float angle);
// Skews the current coordinate system along Y axis. Angle is specified in radians.
void nvgSkewY(NVGcontext* ctx, float angle);

// Scales the current coordinat system.
void nvgScale(struct NVGcontext* ctx, float x, float y);
// Scales the current coordinate system.
void nvgScale(NVGcontext* ctx, float x, float y);

// Stores the top part (a-f) of the current transformation matrix in to the specified buffer.
// [a c e]
// [b d f]
// [0 0 1]
// There should be space for 6 floats in the return buffer for the values a-f.
void nvgCurrentTransform(struct NVGcontext* ctx, float* xform);
void nvgCurrentTransform(NVGcontext* ctx, float* xform);


// The following functions can be used to make calculations on 2x3 transformation matrices.
// A 2x3 matrix is representated as float[6].
// A 2x3 matrix is represented as float[6].

// Sets the transform to identity matrix.
void nvgTransformIdentity(float* dst);
@@ -270,13 +278,13 @@ void nvgTransformTranslate(float* dst, float tx, float ty);
// Sets the transform to scale matrix.
void nvgTransformScale(float* dst, float sx, float sy);

// Sets the transform to rotate matrix. Angle is specifid in radians.
// Sets the transform to rotate matrix. Angle is specified in radians.
void nvgTransformRotate(float* dst, float a);

// Sets the transform to skew-x matrix. Angle is specifid in radians.
// Sets the transform to skew-x matrix. Angle is specified in radians.
void nvgTransformSkewX(float* dst, float a);

// Sets the transform to skew-y matrix. Angle is specifid in radians.
// Sets the transform to skew-y matrix. Angle is specified in radians.
void nvgTransformSkewY(float* dst, float a);

// Sets the transform to the result of multiplication of two transforms, of A = A*B.
@@ -292,7 +300,7 @@ int nvgTransformInverse(float* dst, const float* src);
// Transform a point by given transform.
void nvgTransformPoint(float* dstx, float* dsty, const float* xform, float srcx, float srcy);

// Converts degress to radians and vice versa.
// Converts degrees to radians and vice versa.
float nvgDegToRad(float deg);
float nvgRadToDeg(float rad);

@@ -301,27 +309,28 @@ float nvgRadToDeg(float rad);
//
// NanoVG allows you to load jpg, png, psd, tga, pic and gif files to be used for rendering.
// In addition you can upload your own image. The image loading is provided by stb_image.
// The parameter imageFlags is combination of flags defined in NVGimageFlags.

// Creates image by loading it from the disk from specified file name.
// Returns handle to the image.
int nvgCreateImage(struct NVGcontext* ctx, const char* filename);
int nvgCreateImage(NVGcontext* ctx, const char* filename, int imageFlags);

// Creates image by loading it from the specified chunk of memory.
// Returns handle to the image.
int nvgCreateImageMem(struct NVGcontext* ctx, unsigned char* data, int ndata);
int nvgCreateImageMem(NVGcontext* ctx, int imageFlags, const unsigned char* data, int ndata);

// Creates image from specified image data.
// Returns handle to the image.
int nvgCreateImageRGBA(struct NVGcontext* ctx, int w, int h, const unsigned char* data);
int nvgCreateImageRGBA(NVGcontext* ctx, int w, int h, int imageFlags, const unsigned char* data);

// Updates image data specified by image handle.
void nvgUpdateImage(struct NVGcontext* ctx, int image, const unsigned char* data);
void nvgUpdateImage(NVGcontext* ctx, int image, const unsigned char* data);

// Returns the domensions of a created image.
void nvgImageSize(struct NVGcontext* ctx, int image, int* w, int* h);
// Returns the dimensions of a created image.
void nvgImageSize(NVGcontext* ctx, int image, int* w, int* h);

// Deletes created image.
void nvgDeleteImage(struct NVGcontext* ctx, int image);
void nvgDeleteImage(NVGcontext* ctx, int image);

//
// Paints
@@ -332,42 +341,49 @@ void nvgDeleteImage(struct NVGcontext* ctx, int image);
// Creates and returns a linear gradient. Parameters (sx,sy)-(ex,ey) specify the start and end coordinates
// of the linear gradient, icol specifies the start color and ocol the end color.
// The gradient is transformed by the current transform when it is passed to nvgFillPaint() or nvgStrokePaint().
struct NVGpaint nvgLinearGradient(struct NVGcontext* ctx, float sx, float sy, float ex, float ey,
struct NVGcolor icol, struct NVGcolor ocol);
NVGpaint nvgLinearGradient(NVGcontext* ctx, float sx, float sy, float ex, float ey,
NVGcolor icol, NVGcolor ocol);

// Creates and returns a box gradient. Box gradient is a feathered rounded rectangle, it is useful for rendering
// drop shadows or hilights for boxes. Parameters (x,y) define the top-left corner of the rectangle,
// drop shadows or highlights for boxes. Parameters (x,y) define the top-left corner of the rectangle,
// (w,h) define the size of the rectangle, r defines the corner radius, and f feather. Feather defines how blurry
// the border of the rectangle is. Parameter icol specifies the inner color and ocol the outer color of the gradient.
// The gradient is transformed by the current transform when it is passed to nvgFillPaint() or nvgStrokePaint().
struct NVGpaint nvgBoxGradient(struct NVGcontext* ctx, float x, float y, float w, float h,
float r, float f, struct NVGcolor icol, struct NVGcolor ocol);
NVGpaint nvgBoxGradient(NVGcontext* ctx, float x, float y, float w, float h,
float r, float f, NVGcolor icol, NVGcolor ocol);

// Creates and returns a radial gradient. Parameters (cx,cy) specify the center, inr and outr specify
// the inner and outer radius of the gradient, icol specifies the start color and ocol the end color.
// The gradient is transformed by the current transform when it is passed to nvgFillPaint() or nvgStrokePaint().
struct NVGpaint nvgRadialGradient(struct NVGcontext* ctx, float cx, float cy, float inr, float outr,
struct NVGcolor icol, struct NVGcolor ocol);
NVGpaint nvgRadialGradient(NVGcontext* ctx, float cx, float cy, float inr, float outr,
NVGcolor icol, NVGcolor ocol);

// Creates and returns an image patter. Parameters (ox,oy) specify the left-top location of the image pattern,
// (ex,ey) the size of one image, angle rotation around the top-left corner, image is handle to the image to render,
// and repeat is combination of NVG_REPEATX and NVG_REPEATY which tells if the image should be repeated across x or y.
// (ex,ey) the size of one image, angle rotation around the top-left corner, image is handle to the image to render.
// The gradient is transformed by the current transform when it is passed to nvgFillPaint() or nvgStrokePaint().
struct NVGpaint nvgImagePattern(struct NVGcontext* ctx, float ox, float oy, float ex, float ey,
float angle, int image, int repeat);
NVGpaint nvgImagePattern(NVGcontext* ctx, float ox, float oy, float ex, float ey,
float angle, int image, float alpha);

//
// Scissoring
//
// Scissoring allows you to clip the rendering into a rectangle. This is useful for varius
// user interface cases like rendering a text edit or a timeline.
// Scissoring allows you to clip the rendering into a rectangle. This is useful for various
// user interface cases like rendering a text edit or a timeline.

// Sets the current scissor rectangle.
// The scissor rectangle is transformed by the current transform.
void nvgScissor(NVGcontext* ctx, float x, float y, float w, float h);

// Sets the current
// Intersects current scissor rectangle with the specified rectangle.
// The scissor rectangle is transformed by the current transform.
void nvgScissor(struct NVGcontext* ctx, float x, float y, float w, float h);
// Note: in case the rotation of previous scissor rect differs from
// the current one, the intersection will be done between the specified
// rectangle and the previous scissor rectangle transformed in the current
// transform space. The resulting shape is always rectangle.
void nvgIntersectScissor(NVGcontext* ctx, float x, float y, float w, float h);

// Reset and disables scissoring.
void nvgResetScissor(struct NVGcontext* ctx);
void nvgResetScissor(NVGcontext* ctx);

//
// Paths
@@ -387,46 +403,51 @@ void nvgResetScissor(struct NVGcontext* ctx);
// The curve segments and sub-paths are transformed by the current transform.

// Clears the current path and sub-paths.
void nvgBeginPath(struct NVGcontext* ctx);
void nvgBeginPath(NVGcontext* ctx);

// Starts new sub-path with specified point as first point.
void nvgMoveTo(struct NVGcontext* ctx, float x, float y);
void nvgMoveTo(NVGcontext* ctx, float x, float y);

// Adds line segment from the last point in the path to the specified point.
void nvgLineTo(struct NVGcontext* ctx, float x, float y);
void nvgLineTo(NVGcontext* ctx, float x, float y);

// Adds bezier segment from last point in the path via two control points to the specified point.
void nvgBezierTo(struct NVGcontext* ctx, float c1x, float c1y, float c2x, float c2y, float x, float y);
// Adds cubic bezier segment from last point in the path via two control points to the specified point.
void nvgBezierTo(NVGcontext* ctx, float c1x, float c1y, float c2x, float c2y, float x, float y);

// Adds quadratic bezier segment from last point in the path via a control point to the specified point.
void nvgQuadTo(NVGcontext* ctx, float cx, float cy, float x, float y);

// Adds an arc segment at the corner defined by the last path point, and two specified points.
void nvgArcTo(struct NVGcontext* ctx, float x1, float y1, float x2, float y2, float radius);
void nvgArcTo(NVGcontext* ctx, float x1, float y1, float x2, float y2, float radius);

// Closes current sub-path with a line segment.
void nvgClosePath(struct NVGcontext* ctx);
void nvgClosePath(NVGcontext* ctx);

// Sets the current sub-path winding, see NVGwinding and NVGsolidity.
void nvgPathWinding(struct NVGcontext* ctx, int dir);
// Sets the current sub-path winding, see NVGwinding and NVGsolidity.
void nvgPathWinding(NVGcontext* ctx, int dir);

// Creates new arc shaped sub-path.
void nvgArc(struct NVGcontext* ctx, float cx, float cy, float r, float a0, float a1, int dir);
// Creates new circle arc shaped sub-path. The arc center is at cx,cy, the arc radius is r,
// and the arc is drawn from angle a0 to a1, and swept in direction dir (NVG_CCW, or NVG_CW).
// Angles are specified in radians.
void nvgArc(NVGcontext* ctx, float cx, float cy, float r, float a0, float a1, int dir);

// Creates new rectangle shaped sub-path.
void nvgRect(struct NVGcontext* ctx, float x, float y, float w, float h);
void nvgRect(NVGcontext* ctx, float x, float y, float w, float h);

// Creates new rounded rectangle shaped sub-path.
void nvgRoundedRect(struct NVGcontext* ctx, float x, float y, float w, float h, float r);
void nvgRoundedRect(NVGcontext* ctx, float x, float y, float w, float h, float r);

// Creates new ellipse shaped sub-path.
void nvgEllipse(struct NVGcontext* ctx, float cx, float cy, float rx, float ry);
void nvgEllipse(NVGcontext* ctx, float cx, float cy, float rx, float ry);

// Creates new circle shaped sub-path.
void nvgCircle(struct NVGcontext* ctx, float cx, float cy, float r);
// Creates new circle shaped sub-path.
void nvgCircle(NVGcontext* ctx, float cx, float cy, float r);

// Fills the current path with current fill style.
void nvgFill(struct NVGcontext* ctx);
void nvgFill(NVGcontext* ctx);

// Fills the current path with current stroke style.
void nvgStroke(struct NVGcontext* ctx);
void nvgStroke(NVGcontext* ctx);


//
@@ -464,67 +485,67 @@ void nvgStroke(struct NVGcontext* ctx);

// Creates font by loading it from the disk from specified file name.
// Returns handle to the font.
int nvgCreateFont(struct NVGcontext* ctx, const char* name, const char* filename);
int nvgCreateFont(NVGcontext* ctx, const char* name, const char* filename);

// Creates image by loading it from the specified memory chunk.
// Returns handle to the font.
int nvgCreateFontMem(struct NVGcontext* ctx, const char* name, unsigned char* data, int ndata, int freeData);
int nvgCreateFontMem(NVGcontext* ctx, const char* name, const unsigned char* data, int ndata, int freeData);

// Finds a loaded font of specified name, and returns handle to it, or -1 if the font is not found.
int nvgFindFont(struct NVGcontext* ctx, const char* name);
int nvgFindFont(NVGcontext* ctx, const char* name);

// Sets the font size of current text style.
void nvgFontSize(struct NVGcontext* ctx, float size);
void nvgFontSize(NVGcontext* ctx, float size);

// Sets the blur of current text style.
void nvgFontBlur(struct NVGcontext* ctx, float blur);
void nvgFontBlur(NVGcontext* ctx, float blur);

// Sets the letter spacing of current text style.
void nvgTextLetterSpacing(struct NVGcontext* ctx, float spacing);
void nvgTextLetterSpacing(NVGcontext* ctx, float spacing);

// Sets the proportional line height of current text style. The line height is specified as multiple of font size.
void nvgTextLineHeight(struct NVGcontext* ctx, float lineHeight);
// Sets the proportional line height of current text style. The line height is specified as multiple of font size.
void nvgTextLineHeight(NVGcontext* ctx, float lineHeight);

// Sets the text align of current text style, see NVGaling for options.
void nvgTextAlign(struct NVGcontext* ctx, int align);
// Sets the text align of current text style, see NVGalign for options.
void nvgTextAlign(NVGcontext* ctx, int align);

// Sets the font face based on specified id of current text style.
void nvgFontFaceId(struct NVGcontext* ctx, int font);
void nvgFontFaceId(NVGcontext* ctx, int font);

// Sets the font face based on specified name of current text style.
void nvgFontFace(struct NVGcontext* ctx, const char* font);
void nvgFontFace(NVGcontext* ctx, const char* font);

// Draws text string at specified location. If end is specified only the sub-string up to the end is drawn.
float nvgText(struct NVGcontext* ctx, float x, float y, const char* string, const char* end);
float nvgText(NVGcontext* ctx, float x, float y, const char* string, const char* end);

// Draws multi-line text string at specified location wrapped at the specified width. If end is specified only the sub-string up to the end is drawn.
// White space is stripped at the beginning of the rows, the text is split at word boundaries or when new-line characters are encountered.
// Words longer than the max width are slit at nearest character (i.e. no hyphenation).
void nvgTextBox(struct NVGcontext* ctx, float x, float y, float breakRowWidth, const char* string, const char* end);
void nvgTextBox(NVGcontext* ctx, float x, float y, float breakRowWidth, const char* string, const char* end);

// Measures the specified text string. Parameter bounds should be a pointer to float[4],
// if the bounding box of the text should be returned. The bounds value are [xmin,ymin, xmax,ymax]
// Returns the horizontal advance of the measured text (i.e. where the next character should drawn).
// Measured values are returned in local coordinate space.
float nvgTextBounds(struct NVGcontext* ctx, float x, float y, const char* string, const char* end, float* bounds);
float nvgTextBounds(NVGcontext* ctx, float x, float y, const char* string, const char* end, float* bounds);

// Measures the specified multi-text string. Parameter bounds should be a pointer to float[4],
// if the bounding box of the text should be returned. The bounds value are [xmin,ymin, xmax,ymax]
// Measured values are returned in local coordinate space.
void nvgTextBoxBounds(struct NVGcontext* ctx, float x, float y, float breakRowWidth, const char* string, const char* end, float* bounds);
void nvgTextBoxBounds(NVGcontext* ctx, float x, float y, float breakRowWidth, const char* string, const char* end, float* bounds);

// Calculates the glyph x positions of the specified text. If end is specified only the sub-string will be used.
// Measured values are returned in local coordinate space.
int nvgTextGlyphPositions(struct NVGcontext* ctx, float x, float y, const char* string, const char* end, struct NVGglyphPosition* positions, int maxPositions);
int nvgTextGlyphPositions(NVGcontext* ctx, float x, float y, const char* string, const char* end, NVGglyphPosition* positions, int maxPositions);

// Returns the vertical metrics based on the current text style.
// Measured values are returned in local coordinate space.
void nvgTextMetrics(struct NVGcontext* ctx, float* ascender, float* descender, float* lineh);
void nvgTextMetrics(NVGcontext* ctx, float* ascender, float* descender, float* lineh);

// Breaks the specified text into lines. If end is specified only the sub-string will be used.
// White space is stripped at the beginning of the rows, the text is split at word boundaries or when new-line characters are encountered.
// Words longer than the max width are slit at nearest character (i.e. no hyphenation).
int nvgTextBreakLines(struct NVGcontext* ctx, const char* string, const char* end, float breakRowWidth, struct NVGtextRow* rows, int maxRows);
int nvgTextBreakLines(NVGcontext* ctx, const char* string, const char* end, float breakRowWidth, NVGtextRow* rows, int maxRows);

//
// Internal Render API
@@ -534,54 +555,63 @@ enum NVGtexture {
NVG_TEXTURE_RGBA = 0x02,
};

struct NVGscissor
{
struct NVGscissor {
float xform[6];
float extent[2];
};
typedef struct NVGscissor NVGscissor;

struct NVGvertex {
float x,y,u,v;
};
typedef struct NVGvertex NVGvertex;

struct NVGpath {
int first;
int count;
unsigned char closed;
int nbevel;
struct NVGvertex* fill;
NVGvertex* fill;
int nfill;
struct NVGvertex* stroke;
NVGvertex* stroke;
int nstroke;
int winding;
int convex;
};
typedef struct NVGpath NVGpath;

struct NVGparams {
void* userPtr;
int atlasWidth, atlasHeight;
int edgeAntiAlias;
int (*renderCreate)(void* uptr);
int (*renderCreateTexture)(void* uptr, int type, int w, int h, const unsigned char* data);
int (*renderCreateTexture)(void* uptr, int type, int w, int h, int imageFlags, const unsigned char* data);
int (*renderDeleteTexture)(void* uptr, int image);
int (*renderUpdateTexture)(void* uptr, int image, int x, int y, int w, int h, const unsigned char* data);
int (*renderGetTextureSize)(void* uptr, int image, int* w, int* h);
void (*renderViewport)(void* uptr, int width, int height, int alphaBlend);
void (*renderFlush)(void* uptr, int alphaBlend);
void (*renderFill)(void* uptr, struct NVGpaint* paint, struct NVGscissor* scissor, float fringe, const float* bounds, const struct NVGpath* paths, int npaths);
void (*renderStroke)(void* uptr, struct NVGpaint* paint, struct NVGscissor* scissor, float fringe, float strokeWidth, const struct NVGpath* paths, int npaths);
void (*renderTriangles)(void* uptr, struct NVGpaint* paint, struct NVGscissor* scissor, const struct NVGvertex* verts, int nverts);
void (*renderViewport)(void* uptr, int width, int height);
void (*renderCancel)(void* uptr);
void (*renderFlush)(void* uptr);
void (*renderFill)(void* uptr, NVGpaint* paint, NVGscissor* scissor, float fringe, const float* bounds, const NVGpath* paths, int npaths);
void (*renderStroke)(void* uptr, NVGpaint* paint, NVGscissor* scissor, float fringe, float strokeWidth, const NVGpath* paths, int npaths);
void (*renderTriangles)(void* uptr, NVGpaint* paint, NVGscissor* scissor, const NVGvertex* verts, int nverts);
void (*renderDelete)(void* uptr);
};
typedef struct NVGparams NVGparams;

// Constructor and destructor, called by the render back-end.
NVGcontext* nvgCreateInternal(NVGparams* params);
void nvgDeleteInternal(NVGcontext* ctx);

// Contructor and destructor, called by the render back-end.
struct NVGcontext* nvgCreateInternal(struct NVGparams* params);
void nvgDeleteInternal(struct NVGcontext* ctx);
NVGparams* nvgInternalParams(NVGcontext* ctx);

// Debug function to dump cached path data.
void nvgDebugDumpPathCache(struct NVGcontext* ctx);
void nvgDebugDumpPathCache(NVGcontext* ctx);

#ifdef _MSC_VER
#pragma warning(pop)
#endif

#define NVG_NOTUSED(v) do { (void)(1 ? (void)0 : ( (void)(v) ) ); } while(0)
#define NVG_NOTUSED(v) for (;;) { (void)(1 ? (void)0 : ( (void)(v) ) ); break; }

#ifdef __cplusplus
}


+ 529
- 297
source/modules/dgl/src/nanovg/nanovg_gl.h
File diff suppressed because it is too large
View File


+ 132
- 0
source/modules/dgl/src/nanovg/nanovg_gl_utils.h View File

@@ -0,0 +1,132 @@
//
// Copyright (c) 2009-2013 Mikko Mononen memon@inside.org
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
//
#ifndef NANOVG_GL_UTILS_H
#define NANOVG_GL_UTILS_H

struct NVGLUframebuffer {
NVGcontext* ctx;
GLuint fbo;
GLuint rbo;
GLuint texture;
int image;
};
typedef struct NVGLUframebuffer NVGLUframebuffer;

// Helper function to create GL frame buffer to render to.
void nvgluBindFramebuffer(NVGLUframebuffer* fb);
NVGLUframebuffer* nvgluCreateFramebuffer(NVGcontext* ctx, int w, int h, int imageFlags);
void nvgluDeleteFramebuffer(NVGcontext* ctx, NVGLUframebuffer* fb);

#endif // NANOVG_GL_UTILS_H

#ifdef NANOVG_GL_IMPLEMENTATION

#if defined(NANOVG_GL3) || defined(NANOVG_GLES2) || defined(NANOVG_GLES3)
// FBO is core in OpenGL 3>.
# define NANOVG_FBO_VALID 1
#elif defined(NANOVG_GL2)
// On OS X including glext defines FBO on GL2 too.
# ifdef __APPLE__
# include <OpenGL/glext.h>
# define NANOVG_FBO_VALID 1
# endif
#endif

static GLint defaultFBO = -1;

NVGLUframebuffer* nvgluCreateFramebuffer(NVGcontext* ctx, int w, int h, int imageFlags)
{
#ifdef NANOVG_FBO_VALID
GLint defaultFBO;
GLint defaultRBO;
NVGLUframebuffer* fb = NULL;

glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFBO);
glGetIntegerv(GL_RENDERBUFFER_BINDING, &defaultRBO);

fb = (NVGLUframebuffer*)malloc(sizeof(NVGLUframebuffer));
if (fb == NULL) goto error;
memset(fb, 0, sizeof(NVGLUframebuffer));

fb->image = nvgCreateImageRGBA(ctx, w, h, imageFlags | NVG_IMAGE_FLIPY | NVG_IMAGE_PREMULTIPLIED, NULL);
fb->texture = nvglImageHandle(ctx, fb->image);

// frame buffer object
glGenFramebuffers(1, &fb->fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fb->fbo);

// render buffer object
glGenRenderbuffers(1, &fb->rbo);
glBindRenderbuffer(GL_RENDERBUFFER, fb->rbo);
glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, w, h);

// combine all
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb->texture, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fb->rbo);

if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) goto error;

glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO);
glBindRenderbuffer(GL_RENDERBUFFER, defaultRBO);
return fb;
error:
glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO);
glBindRenderbuffer(GL_RENDERBUFFER, defaultRBO);
nvgluDeleteFramebuffer(ctx, fb);
return NULL;
#else
NVG_NOTUSED(ctx);
NVG_NOTUSED(w);
NVG_NOTUSED(h);
NVG_NOTUSED(imageFlags);
return NULL;
#endif
}

void nvgluBindFramebuffer(NVGLUframebuffer* fb)
{
#ifdef NANOVG_FBO_VALID
if (defaultFBO == -1) glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFBO);
glBindFramebuffer(GL_FRAMEBUFFER, fb != NULL ? fb->fbo : defaultFBO);
#else
NVG_NOTUSED(fb);
#endif
}

void nvgluDeleteFramebuffer(NVGcontext* ctx, NVGLUframebuffer* fb)
{
#ifdef NANOVG_FBO_VALID
if (fb == NULL) return;
if (fb->fbo != 0)
glDeleteFramebuffers(1, &fb->fbo);
if (fb->rbo != 0)
glDeleteRenderbuffers(1, &fb->rbo);
if (fb->image >= 0)
nvgDeleteImage(ctx, fb->image);
fb->fbo = 0;
fb->rbo = 0;
fb->texture = 0;
fb->image = -1;
free(fb);
#else
NVG_NOTUSED(ctx);
NVG_NOTUSED(fb);
#endif
}

#endif // NANOVG_GL_IMPLEMENTATION

source/modules/dgl/src/nanovg/stb_image.h
File diff suppressed because it is too large
View File


+ 33
- 16
source/modules/dgl/src/nanovg/stb_truetype.h View File

@@ -1,5 +1,5 @@
// stb_truetype.h - v0.6c - public domain
// authored from 2009-2012 by Sean Barrett / RAD Game Tools
// stb_truetype.h - v0.8 - public domain
// authored from 2009-2013 by Sean Barrett / RAD Game Tools
//
// This library processes TrueType files:
// parse files
@@ -27,9 +27,15 @@
// stoiko (Haemimont Games)
// Brian Hook
// Walter van Niftrik
// David Gow
// David Given
// Ivan-Assen Ivanov
// Anthony Pesch
//
// VERSION HISTORY
//
// 0.8 (2014-05-25) fix a few more warnings
// 0.7 (2013-09-25) bugfix: subpixel glyph bug fixed in 0.5 had come back
// 0.6c (2012-07-24) improve documentation
// 0.6b (2012-07-20) fix a few more warnings
// 0.6 (2012-07-17) fix warnings; added stbtt_ScaleForMappingEmToPixels,
@@ -222,7 +228,7 @@ void my_stbtt_print(float x, float y, char *text)
while (*text) {
if (*text >= 32 && *text < 128) {
stbtt_aligned_quad q;
stbtt_GetBakedQuad(cdata, 512,512, *text-32, &x,&y,&q,1);//1=opengl,0=old d3d
stbtt_GetBakedQuad(cdata, 512,512, *text-32, &x,&y,&q,1);//1=opengl & d3d10+,0=d3d9
glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0,q.y0);
glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1,q.y0);
glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1,q.y1);
@@ -291,7 +297,7 @@ int main(int arg, char **argv)
{
stbtt_fontinfo font;
int i,j,ascent,baseline,ch=0;
float scale, xpos=0;
float scale, xpos=2; // leave a little padding in case the character extends left
char *text = "Heljo World!";
fread(buffer, 1, 1000000, fopen("c:/windows/fonts/arialbd.ttf", "rb"));
@@ -363,10 +369,15 @@ int main(int arg, char **argv)
#define STBTT_iceil(x) ((int) ceil(x))
#endif
#ifndef STBTT_sqrt
#include <math.h>
#define STBTT_sqrt(x) sqrt(x)
#endif
// #define your own functions "STBTT_malloc" / "STBTT_free" to avoid malloc.h
#ifndef STBTT_malloc
#include <malloc.h>
#define STBTT_malloc(x,u) malloc(x)
#include <stdlib.h>
#define STBTT_malloc(x,u) ((void)(u),malloc(x))
#define STBTT_free(x,u) free(x)
#endif
@@ -531,7 +542,6 @@ extern void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint
extern int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2);
// an additional amount to add to the 'advance' value between ch1 and ch2
// @TODO; for now always returns 0!
extern int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1);
// Gets the bounding box of the visible part of the glyph, in unscaled coordinates
@@ -573,6 +583,13 @@ extern int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codep
extern int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **vertices);
// returns # of vertices and fills *vertices with the pointer to them
// these are expressed in "unscaled" coordinates
//
// The shape is a series of countours. Each one starts with
// a STBTT_moveto, then consists of a series of mixed
// STBTT_lineto and STBTT_curveto segments. A lineto
// draws a line from previous endpoint to its x,y; a curveto
// draws a quadratic bezier from previous endpoint to
// its x,y, using cx,cy as the bezier control point.
extern void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices);
// frees the data allocated above
@@ -916,8 +933,6 @@ int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint)
search -= 2;
while (entrySelector) {
searchRange >>= 1;
start = ttUSHORT(data + search + 2 + segcount*2 + 2);
end = ttUSHORT(data + search + 2);
start = ttUSHORT(data + search + searchRange*2 + segcount*2 + 2);
end = ttUSHORT(data + search + searchRange*2);
if (unicode_codepoint > end)
@@ -1222,8 +1237,8 @@ int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_verte
}
// Find transformation scales.
m = (float) sqrt(mtx[0]*mtx[0] + mtx[1]*mtx[1]);
n = (float) sqrt(mtx[2]*mtx[2] + mtx[3]*mtx[3]);
m = (float) STBTT_sqrt(mtx[0]*mtx[0] + mtx[1]*mtx[1]);
n = (float) STBTT_sqrt(mtx[2]*mtx[2] + mtx[3]*mtx[3]);
// Get indexed glyph.
comp_num_verts = stbtt_GetGlyphShape(info, gidx, &comp_verts);
@@ -1246,8 +1261,8 @@ int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_verte
if (comp_verts) STBTT_free(comp_verts, info->userdata);
return 0;
}
if (num_vertices > 0) memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex));
memcpy(tmp+num_vertices, comp_verts, comp_num_verts*sizeof(stbtt_vertex));
if (num_vertices > 0) STBTT_memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex));
STBTT_memcpy(tmp+num_vertices, comp_verts, comp_num_verts*sizeof(stbtt_vertex));
if (vertices) STBTT_free(vertices, info->userdata);
vertices = tmp;
STBTT_free(comp_verts, info->userdata);
@@ -1759,7 +1774,7 @@ unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float sc
scale_y = scale_x;
}
stbtt_GetGlyphBitmapBox(info, glyph, scale_x, scale_y, &ix0,&iy0,&ix1,&iy1);
stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,&ix1,&iy1);
// now we get the size
gbm.w = (ix1 - ix0);
@@ -1991,14 +2006,16 @@ static int stbtt__matchpair(stbtt_uint8 *fc, stbtt_uint32 nm, stbtt_uint8 *name,
// is this a Unicode encoding?
if (platform == 0 || (platform == 3 && encoding == 1) || (platform == 3 && encoding == 10)) {
stbtt_int32 slen = ttUSHORT(fc+loc+8), off = ttUSHORT(fc+loc+10);
stbtt_int32 slen = ttUSHORT(fc+loc+8);
stbtt_int32 off = ttUSHORT(fc+loc+10);
// check if there's a prefix match
stbtt_int32 matchlen = stbtt__CompareUTF8toUTF16_bigendian_prefix(name, nlen, fc+stringOffset+off,slen);
if (matchlen >= 0) {
// check for target_id+1 immediately following, with same encoding & language
if (i+1 < count && ttUSHORT(fc+loc+12+6) == next_id && ttUSHORT(fc+loc+12) == platform && ttUSHORT(fc+loc+12+2) == encoding && ttUSHORT(fc+loc+12+4) == language) {
stbtt_int32 slen = ttUSHORT(fc+loc+12+8), off = ttUSHORT(fc+loc+12+10);
slen = ttUSHORT(fc+loc+12+8);
off = ttUSHORT(fc+loc+12+10);
if (slen == 0) {
if (matchlen == nlen)
return 1;


+ 21
- 0
source/modules/dgl/src/oui-blendish/LICENSE View File

@@ -0,0 +1,21 @@
Blendish - Blender 2.5 UI based theming functions for NanoVG

Copyright (c) 2014 Leonard Ritter <leonard.ritter@duangle.com>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

+ 2399
- 0
source/modules/dgl/src/oui-blendish/blendish.h
File diff suppressed because it is too large
View File


+ 24815
- 0
source/modules/dgl/src/oui-blendish/blendish_resources.cpp
File diff suppressed because it is too large
View File


+ 15
- 0
source/modules/dgl/src/oui-blendish/blendish_resources.h View File

@@ -0,0 +1,15 @@
/* (Auto-generated binary data file). */
#ifndef BINARY_BLENDISH_RESOURCES_H
#define BINARY_BLENDISH_RESOURCES_H
namespace blendish_resources
{
extern const char* blender_icons16_png;
const unsigned int blender_icons16_png_size = 250706;
extern const char* dejavusans_ttf;
const unsigned int dejavusans_ttf_size = 741536;
};
#endif

+ 2025
- 0
source/modules/dgl/src/oui-blendish/oui.h
File diff suppressed because it is too large
View File


BIN
source/modules/dgl/src/oui-blendish/resources/DejaVuSans.ttf View File


+ 97
- 0
source/modules/dgl/src/oui-blendish/resources/LICENSE-DejaVuSans.ttf.txt View File

@@ -0,0 +1,97 @@
Fonts are (c) Bitstream (see below). DejaVu changes are in public domain.
Glyphs imported from Arev fonts are (c) Tavmjong Bah (see below)

Bitstream Vera Fonts Copyright
------------------------------

Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is
a trademark of Bitstream, Inc.

Permission is hereby granted, free of charge, to any person obtaining a copy
of the fonts accompanying this license ("Fonts") and associated
documentation files (the "Font Software"), to reproduce and distribute the
Font Software, including without limitation the rights to use, copy, merge,
publish, distribute, and/or sell copies of the Font Software, and to permit
persons to whom the Font Software is furnished to do so, subject to the
following conditions:

The above copyright and trademark notices and this permission notice shall
be included in all copies of one or more of the Font Software typefaces.

The Font Software may be modified, altered, or added to, and in particular
the designs of glyphs or characters in the Fonts may be modified and
additional glyphs or characters may be added to the Fonts, only if the fonts
are renamed to names not containing either the words "Bitstream" or the word
"Vera".

This License becomes null and void to the extent applicable to Fonts or Font
Software that has been modified and is distributed under the "Bitstream
Vera" names.

The Font Software may be sold as part of a larger software package but no
copy of one or more of the Font Software typefaces may be sold by itself.

THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT,
TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME
FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING
ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE
FONT SOFTWARE.

Except as contained in this notice, the names of Gnome, the Gnome
Foundation, and Bitstream Inc., shall not be used in advertising or
otherwise to promote the sale, use or other dealings in this Font Software
without prior written authorization from the Gnome Foundation or Bitstream
Inc., respectively. For further information, contact: fonts at gnome dot
org.

Arev Fonts Copyright
------------------------------

Copyright (c) 2006 by Tavmjong Bah. All Rights Reserved.

Permission is hereby granted, free of charge, to any person obtaining
a copy of the fonts accompanying this license ("Fonts") and
associated documentation files (the "Font Software"), to reproduce
and distribute the modifications to the Bitstream Vera Font Software,
including without limitation the rights to use, copy, merge, publish,
distribute, and/or sell copies of the Font Software, and to permit
persons to whom the Font Software is furnished to do so, subject to
the following conditions:

The above copyright and trademark notices and this permission notice
shall be included in all copies of one or more of the Font Software
typefaces.

The Font Software may be modified, altered, or added to, and in
particular the designs of glyphs or characters in the Fonts may be
modified and additional glyphs or characters may be added to the
Fonts, only if the fonts are renamed to names not containing either
the words "Tavmjong Bah" or the word "Arev".

This License becomes null and void to the extent applicable to Fonts
or Font Software that has been modified and is distributed under the
"Tavmjong Bah Arev" names.

The Font Software may be sold as part of a larger software package but
no copy of one or more of the Font Software typefaces may be sold by
itself.

THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL
TAVMJONG BAH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

Except as contained in this notice, the name of Tavmjong Bah shall not
be used in advertising or otherwise to promote the sale, use or other
dealings in this Font Software without prior written authorization
from Tavmjong Bah. For further information, contact: tavmjong @ free
. fr.

+ 280
- 0
source/modules/dgl/src/oui-blendish/resources/LICENSE-blender_icons.svg.txt View File

@@ -0,0 +1,280 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991

Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.

Preamble

The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.

When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.

To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.

For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.

We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.

Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.

Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.

The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".

Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.

1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.

You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.

2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:

a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.

b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.

c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.

Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.

In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.

3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:

a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,

b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,

c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)

The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.

If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.

5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.

6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.

7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.

If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.

It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.

This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.

9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.

Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.

10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.

NO WARRANTY

11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.

12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.

END OF TERMS AND CONDITIONS

+ 88974
- 0
source/modules/dgl/src/oui-blendish/resources/blender_icons.svg
File diff suppressed because it is too large
View File


BIN
source/modules/dgl/src/oui-blendish/resources/blender_icons16.png View File

Before After
Width: 602  |  Height: 640  |  Size: 245KB

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

@@ -0,0 +1,121 @@
/*
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 */

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

@@ -0,0 +1,41 @@
/*
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 */

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

@@ -0,0 +1,32 @@
/*
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


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

@@ -0,0 +1,32 @@
/*
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


+ 71
- 92
source/modules/dgl/src/pugl/pugl.h View File

@@ -23,19 +23,8 @@

#include <stdint.h>

/*
This API is pure portable C and contains no platform specific elements, or
even a GL dependency. However, unfortunately GL includes vary across
platforms so they are included here to allow for pure portable programs.
*/
#ifdef __APPLE__
# include "OpenGL/gl.h"
#else
# ifdef _WIN32
# include <windows.h> /* Broken Windows GL headers require this */
# endif
# include "GL/gl.h"
#endif
#include "pugl/common.h"
#include "pugl/event.h"

#ifdef PUGL_SHARED
# ifdef _WIN32
@@ -70,82 +59,6 @@ extern "C" {
@{
*/

/**
An OpenGL 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, /**< 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.
*/
@@ -227,6 +140,12 @@ typedef void (*PuglSpecialFunc)(PuglView* view, bool press, PuglKey key);
*/
typedef void (*PuglFileSelectedFunc)(PuglView* view, const char* filename);

/**
@name Initialization
Configuration functions which must be called before creating a window.
@{
*/

/**
Create a Pugl context.

@@ -248,12 +167,43 @@ puglInitWindowParent(PuglView* view, PuglNativeWindow parent);
PUGL_API void
puglInitWindowSize(PuglView* view, int width, int height);

/**
Set the minimum window size before creating a window.
*/
PUGL_API void
puglInitWindowMinSize(PuglView* view, int width, int height);

/**
Enable or disable resizing before creating a window.
*/
PUGL_API void
puglInitUserResizable(PuglView* view, bool resizable);

/**
Set transient parent before creating a window.

On X11, parent_id must be a Window.
On OSX, parent_id must be an NSView*.
*/
PUGL_API void
puglInitTransientFor(PuglView* view, uintptr_t parent);

/**
Set the context type before creating a window.
*/
PUGL_API void
puglInitContextType(PuglView* view, PuglContextType type);

/**
@}
*/

/**
@name Windows
Window management functions.
@{
*/

/**
Create a window with the settings given by the various puglInit functions.

@@ -274,6 +224,16 @@ puglShowWindow(PuglView* view);
PUGL_API void
puglHideWindow(PuglView* view);

/**
Return the native window handle.
*/
PUGL_API PuglNativeWindow
puglGetNativeWindow(PuglView* view);

/**
@}
*/

/**
Set the handle to be passed to all callbacks.

@@ -292,6 +252,15 @@ puglSetHandle(PuglView* view, PuglHandle handle);
PUGL_API PuglHandle
puglGetHandle(PuglView* view);

/**
Get the drawing context.

For PUGL_GL contexts, this is unused and returns NULL.
For PUGL_CAIRO contexts, this returns a pointer to a cairo_t.
*/
PUGL_API void*
puglGetContext(PuglView* view);

/**
Return the timestamp (if any) of the currently-processing event.
*/
@@ -312,6 +281,12 @@ puglGetModifiers(PuglView* view);
PUGL_API void
puglIgnoreKeyRepeat(PuglView* view, bool ignore);

/**
@name Event Callbacks
Functions to set event callbacks for handling user input.
@{
*/

/**
Set the function to call when the window is closed.
*/
@@ -367,10 +342,14 @@ PUGL_API void
puglSetFileSelectedFunc(PuglView* view, PuglFileSelectedFunc fileSelectedFunc);

/**
Return the native window handle.
@}
*/
PUGL_API PuglNativeWindow
puglGetNativeWindow(PuglView* view);

/**
Grab the input focus.
*/
PUGL_API void
puglGrabFocus(PuglView* view);

/**
Process all pending window events.


+ 162
- 19
source/modules/dgl/src/pugl/pugl_internal.h View File

@@ -1,5 +1,5 @@
/*
Copyright 2012 David Robillard <http://drobilla.net>
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
@@ -24,11 +24,14 @@
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.h"
#include "pugl/pugl.h"
#include "pugl/event.h"

#ifdef PUGL_VERBOSE
# include <stdio.h>
@@ -54,10 +57,15 @@ struct PuglViewImpl {
PuglFileSelectedFunc fileSelectedFunc;

PuglInternals* impl;

PuglNativeWindow parent;
PuglContextType ctx_type;
uintptr_t transient_parent;

int width;
int height;
int min_width;
int min_height;
int mods;
bool mouse_in_view;
bool ignoreKeyRepeat;
@@ -96,6 +104,13 @@ puglInitWindowSize(PuglView* view, int width, int height)
view->height = height;
}

void
puglInitWindowMinSize(PuglView* view, int width, int height)
{
view->min_width = width;
view->min_height = height;
}

void
puglInitWindowParent(PuglView* view, PuglNativeWindow parent)
{
@@ -103,11 +118,23 @@ puglInitWindowParent(PuglView* view, PuglNativeWindow parent)
}

void
puglInitResizable(PuglView* view, bool resizable)
puglInitUserResizable(PuglView* view, bool resizable)
{
view->resizable = resizable;
}

void
puglInitTransientFor(PuglView* view, uintptr_t parent)
{
view->transient_parent = parent;
}

void
puglInitContextType(PuglView* view, PuglContextType type)
{
view->ctx_type = type;
}

void
puglSetHandle(PuglView* view, PuglHandle handle)
{
@@ -132,22 +159,6 @@ puglGetModifiers(PuglView* view)
return view->mods;
}

static void
puglDefaultReshape(PuglView* view, int width, int height)
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, width, height, 0, 0, 1);
glViewport(0, 0, width, height);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
return;

// unused
(void)view;
}

void
puglIgnoreKeyRepeat(PuglView* view, bool ignore)
{
@@ -207,3 +218,135 @@ puglSetFileSelectedFunc(PuglView* view, PuglFileSelectedFunc fileSelectedFunc)
{
view->fileSelectedFunc = fileSelectedFunc;
}

void
puglEnterContext(PuglView* view);

void
puglLeaveContext(PuglView* view, bool flush);

#if 0
/** Return the code point for buf, or the replacement character on error. */
static uint32_t
puglDecodeUTF8(const uint8_t* buf)
{
#define FAIL_IF(cond) { if (cond) return 0xFFFD; }

/* http://en.wikipedia.org/wiki/UTF-8 */

if (buf[0] < 0x80) {
return buf[0];
} else if (buf[0] < 0xC2) {
return 0xFFFD;
} else if (buf[0] < 0xE0) {
FAIL_IF((buf[1] & 0xC0) != 0x80);
return (buf[0] << 6) + buf[1] - 0x3080;
} else if (buf[0] < 0xF0) {
FAIL_IF((buf[1] & 0xC0) != 0x80);
FAIL_IF(buf[0] == 0xE0 && buf[1] < 0xA0);
FAIL_IF((buf[2] & 0xC0) != 0x80);
return (buf[0] << 12) + (buf[1] << 6) + buf[2] - 0xE2080;
} else if (buf[0] < 0xF5) {
FAIL_IF((buf[1] & 0xC0) != 0x80);
FAIL_IF(buf[0] == 0xF0 && buf[1] < 0x90);
FAIL_IF(buf[0] == 0xF4 && buf[1] >= 0x90);
FAIL_IF((buf[2] & 0xC0) != 0x80);
FAIL_IF((buf[3] & 0xC0) != 0x80);
return ((buf[0] << 18) +
(buf[1] << 12) +
(buf[2] << 6) +
buf[3] - 0x3C82080);
}
return 0xFFFD;
}
#endif

static void
puglDefaultReshape(PuglView* view, int width, int height)
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, width, height, 0, 0, 1);
glViewport(0, 0, width, height);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
return;

// unused
(void)view;
}

#if 0
static void
puglDispatchEvent(PuglView* view, const PuglEvent* event)
{
if (view->eventFunc) {
view->eventFunc(view, event);
}

switch (event->type) {
case PUGL_CONFIGURE:
puglEnterContext(view);
view->width = event->configure.width;
view->height = event->configure.height;
if (view->reshapeFunc) {
view->reshapeFunc(view, view->width, view->height);
}
puglLeaveContext(view, false);
break;
case PUGL_EXPOSE:
if (event->expose.count == 0) {
puglEnterContext(view);
if (view->displayFunc) {
view->displayFunc(view);
}
view->redisplay = false;
puglLeaveContext(view, true);
}
break;
case PUGL_MOTION_NOTIFY:
view->event_timestamp_ms = event->motion.time;
view->mods = event->motion.state;
if (view->motionFunc) {
view->motionFunc(view, event->motion.x, event->motion.y);
}
break;
case PUGL_SCROLL:
if (view->scrollFunc) {
view->scrollFunc(view,
event->scroll.x, event->scroll.y,
event->scroll.dx, event->scroll.dy);
}
break;
case PUGL_BUTTON_PRESS:
case PUGL_BUTTON_RELEASE:
view->event_timestamp_ms = event->button.time;
view->mods = event->button.state;
if (view->mouseFunc) {
view->mouseFunc(view,
event->button.button,
event->type == PUGL_BUTTON_PRESS,
event->button.x,
event->button.y);
}
break;
case PUGL_KEY_PRESS:
case PUGL_KEY_RELEASE:
view->event_timestamp_ms = event->key.time;
view->mods = event->key.state;
if (event->key.special && view->specialFunc) {
view->specialFunc(view,
event->type == PUGL_KEY_PRESS,
event->key.special);
} else if (event->key.character && view->keyboardFunc) {
view->keyboardFunc(view,
event->type == PUGL_KEY_PRESS,
event->key.character);
}
break;
default:
break;
}
}
#endif

+ 39
- 12
source/modules/dgl/src/pugl/pugl_osx.m View File

@@ -187,12 +187,9 @@ puglDisplay(PuglView* view)
printf("Is doubleBuffered? FALSE\n");
}

if (self) {
NSOpenGLContext* context = [self openGLContext];
[context makeCurrentContext];

if (self) {
GLint swapInterval = 1;
[context setValues:&swapInterval forParameter:NSOpenGLCPSwapInterval];
[[self openGLContext] setValues:&swapInterval forParameter:NSOpenGLCPSwapInterval];

[self reshape];
}
@@ -216,26 +213,25 @@ puglDisplay(PuglView* view)
int width = bounds.size.width;
int height = bounds.size.height;

puglEnterContext(puglview);

if (puglview->reshapeFunc) {
puglview->reshapeFunc(puglview, width, height);
} else {
puglDefaultReshape(puglview, width, height);
}

puglLeaveContext(puglview, false);

puglview->width = width;
puglview->height = height;
}

- (void) drawRect:(NSRect)r
{
puglEnterContext(puglview);
puglDisplay(puglview);

if (doubleBuffered) {
[[self openGLContext] flushBuffer];
} else {
glFlush();
//glSwapAPPLE();
}
puglLeaveContext(puglview, true);

// unused
return; (void)r;
@@ -428,6 +424,31 @@ puglInitInternals()
return (PuglInternals*)calloc(1, sizeof(PuglInternals));
}

void
puglEnterContext(PuglView* view)
{
#ifdef PUGL_HAVE_GL
if (view->ctx_type == PUGL_GL) {
[[view->impl->glview openGLContext] makeCurrentContext];
}
#endif
}

void
puglLeaveContext(PuglView* view, bool flush)
{
#ifdef PUGL_HAVE_GL
if (view->ctx_type == PUGL_GL && flush) {
if (view->impl->glview->doubleBuffered) {
[[view->impl->glview openGLContext] flushBuffer];
} else {
glFlush();
}
//[NSOpenGLContext clearCurrentContext];
}
#endif
}

int
puglCreateWindow(PuglView* view, const char* title)
{
@@ -544,3 +565,9 @@ puglGetNativeWindow(PuglView* view)
{
return (PuglNativeWindow)view->impl->glview;
}

void*
puglGetContext(PuglView* view)
{
return NULL;
}

+ 79
- 25
source/modules/dgl/src/pugl/pugl_win.cpp View File

@@ -1,5 +1,5 @@
/*
Copyright 2012 David Robillard <http://drobilla.net>
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
@@ -18,15 +18,16 @@
@file pugl_win.cpp Windows/WGL Pugl Implementation.
*/

#include <winsock2.h>
#include <windows.h>
#include <windowsx.h>
#include <GL/gl.h>

#include <ctime>
#include <stdio.h>
#include <stdlib.h>
#include <cstdio>
#include <cstdlib>

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

#ifndef WM_MOUSEWHEEL
# define WM_MOUSEWHEEL 0x020A
@@ -37,8 +38,11 @@
#ifndef WHEEL_DELTA
# define WHEEL_DELTA 120
#endif
#ifndef GWLP_USERDATA
# define GWLP_USERDATA (-21)
#endif

const int LOCAL_CLOSE_MSG = WM_USER + 50;
#define PUGL_LOCAL_CLOSE_MSG (WM_USER + 50)

HINSTANCE hInstance = NULL;

@@ -69,6 +73,27 @@ puglInitInternals()
return (PuglInternals*)calloc(1, sizeof(PuglInternals));
}

void
puglEnterContext(PuglView* view)
{
#ifdef PUGL_HAVE_GL
if (view->ctx_type == PUGL_GL) {
wglMakeCurrent(view->impl->hdc, view->impl->hglrc);
}
#endif
}

void
puglLeaveContext(PuglView* view, bool flush)
{
#ifdef PUGL_HAVE_GL
if (view->ctx_type == PUGL_GL && flush) {
glFlush();
SwapBuffers(view->impl->hdc);
}
#endif
}

int
puglCreateWindow(PuglView* view, const char* title)
{
@@ -104,8 +129,19 @@ puglCreateWindow(PuglView* view, const char* title)
return 1;
}

// Adjust the overall window size to accomodate our requested client size
const int winFlags = WS_POPUPWINDOW | WS_CAPTION | (view->resizable ? WS_SIZEBOX : 0x0);
int winFlags = WS_POPUPWINDOW | WS_CAPTION;
if (view->resizable) {
winFlags |= WS_SIZEBOX;
if (view->min_width > 0 && view->min_height > 0) {
// Adjust the minimum window size to accomodate requested view size
RECT mr = { 0, 0, view->min_width, view->min_height };
AdjustWindowRectEx(&mr, view->parent ? WS_CHILD : winFlags, FALSE, WS_EX_TOPMOST);
view->min_width = mr.right - mr.left;
view->min_height = mr.bottom - mr.top;
}
}

// Adjust the window size to accomodate requested view size
RECT wr = { 0, 0, view->width, view->height };
AdjustWindowRectEx(&wr, view->parent ? WS_CHILD : winFlags, FALSE, WS_EX_TOPMOST);

@@ -152,25 +188,19 @@ puglCreateWindow(PuglView* view, const char* title)
return 1;
}

wglMakeCurrent(impl->hdc, impl->hglrc);

return 0;
return PUGL_SUCCESS;
}

void
puglShowWindow(PuglView* view)
{
PuglInternals* impl = view->impl;

ShowWindow(impl->hwnd, SW_SHOWNORMAL);
ShowWindow(view->impl->hwnd, SW_SHOWNORMAL);
}

void
puglHideWindow(PuglView* view)
{
PuglInternals* impl = view->impl;

ShowWindow(impl->hwnd, SW_HIDE);
ShowWindow(view->impl->hwnd, SW_HIDE);
}

void
@@ -189,7 +219,7 @@ puglDestroy(PuglView* view)
static void
puglReshape(PuglView* view, int width, int height)
{
wglMakeCurrent(view->impl->hdc, view->impl->hglrc);
puglEnterContext(view);

if (view->reshapeFunc) {
view->reshapeFunc(view, width, height);
@@ -204,15 +234,14 @@ puglReshape(PuglView* view, int width, int height)
static void
puglDisplay(PuglView* view)
{
wglMakeCurrent(view->impl->hdc, view->impl->hglrc);
puglEnterContext(view);

view->redisplay = false;
if (view->displayFunc) {
view->displayFunc(view);
}

glFlush();
SwapBuffers(view->impl->hdc);
puglLeaveContext(view, true);
}

static PuglKey
@@ -282,18 +311,24 @@ handleMessage(PuglView* view, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
PuglKey key;
RECT rect;
MINMAXINFO* mmi;

setModifiers(view);
switch (message) {
case WM_CREATE:
case WM_SHOWWINDOW:
case WM_SIZE:
RECT rect;
GetClientRect(view->impl->hwnd, &rect);
puglReshape(view, rect.right, rect.bottom);
view->width = rect.right;
view->height = rect.bottom;
break;
case WM_GETMINMAXINFO:
mmi = (MINMAXINFO*)lParam;
mmi->ptMinTrackSize.x = view->min_width;
mmi->ptMinTrackSize.y = view->min_height;
break;
case WM_PAINT:
BeginPaint(view->impl->hwnd, &ps);
puglDisplay(view);
@@ -301,6 +336,7 @@ handleMessage(PuglView* view, UINT message, WPARAM wParam, LPARAM lParam)
break;
case WM_MOUSEMOVE:
if (view->motionFunc) {
view->event_timestamp_ms = GetMessageTime();
view->motionFunc(view, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
}
break;
@@ -329,7 +365,7 @@ handleMessage(PuglView* view, UINT message, WPARAM wParam, LPARAM lParam)
ScreenToClient(view->impl->hwnd, &pt);
view->scrollFunc(
view, pt.x, pt.y,
0, GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA);
0.0f, GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA);
}
break;
case WM_MOUSEHWHEEL:
@@ -339,7 +375,7 @@ handleMessage(PuglView* view, UINT message, WPARAM wParam, LPARAM lParam)
ScreenToClient(view->impl->hwnd, &pt);
view->scrollFunc(
view, pt.x, pt.y,
GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA, 0);
GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA, 0.0f);
}
break;
case WM_KEYDOWN:
@@ -364,9 +400,10 @@ handleMessage(PuglView* view, UINT message, WPARAM wParam, LPARAM lParam)
}
break;
case WM_QUIT:
case LOCAL_CLOSE_MSG:
case PUGL_LOCAL_CLOSE_MSG:
if (view->closeFunc) {
view->closeFunc(view);
view->redisplay = false;
}
break;
default:
@@ -377,6 +414,12 @@ handleMessage(PuglView* view, UINT message, WPARAM wParam, LPARAM lParam)
return 0;
}

void
puglGrabFocus(PuglView* view)
{
// TODO
}

PuglStatus
puglProcessEvents(PuglView* view)
{
@@ -402,7 +445,7 @@ wndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
PostMessage(hwnd, WM_SHOWWINDOW, TRUE, 0);
return 0;
case WM_CLOSE:
PostMessage(hwnd, LOCAL_CLOSE_MSG, wParam, lParam);
PostMessage(hwnd, PUGL_LOCAL_CLOSE_MSG, wParam, lParam);
return 0;
case WM_DESTROY:
return 0;
@@ -426,3 +469,14 @@ puglGetNativeWindow(PuglView* view)
{
return (PuglNativeWindow)view->impl->hwnd;
}

void*
puglGetContext(PuglView* view)
{
#ifdef PUGL_HAVE_CAIRO
if (view->ctx_type == PUGL_CAIRO) {
// TODO
}
#endif
return NULL;
}

+ 241
- 90
source/modules/dgl/src/pugl/pugl_x11.c View File

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

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@@ -24,13 +24,22 @@
#include <stdlib.h>
#include <string.h>

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

#include "pugl_internal.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"

#define SOFD_HAVE_X11
#include "../sofd/libsofd.h"
@@ -40,53 +49,16 @@ struct PuglInternalsImpl {
Display* display;
int screen;
Window win;
XIM xim;
XIC xic;
#ifdef PUGL_HAVE_CAIRO
cairo_t* cr;
cairo_surface_t* surface;
#endif
#ifdef PUGL_HAVE_GL
GLXContext ctx;
Bool doubleBuffered;
};

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

/**
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,
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)
*/
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
#endif
};

PuglInternals*
@@ -95,33 +67,186 @@ 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;

#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

return false;
}

static void
destroyContext(PuglView* view)
{
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
}

void
puglEnterContext(PuglView* view)
{
#ifdef PUGL_HAVE_GL
if (view->ctx_type == PUGL_GL) {
glXMakeCurrent(view->impl->display, view->impl->win, view->impl->ctx);
}
#endif
}

void
puglLeaveContext(PuglView* view, bool flush)
{
#ifdef PUGL_HAVE_GL
if (view->ctx_type == PUGL_GL && flush) {
glFlush();
if (view->impl->doubleBuffered) {
glXSwapBuffers(view->impl->display, view->impl->win);
}
}
#endif
}

int
puglCreateWindow(PuglView* view, const char* title)
{
PuglInternals* impl = view->impl;
PuglInternals* const impl = view->impl;

impl->display = XOpenDisplay(NULL);
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);
PUGL_LOG("multisampling (antialiasing) is not available\n");
}

XVisualInfo* const vi = getVisual(view);
if (!vi) {
vi = glXChooseVisual(impl->display, impl->screen, attrListSgl);
impl->doubleBuffered = False;
PUGL_LOG("singlebuffered rendering will be used, no doublebuffering available\n");
XCloseDisplay(impl->display);
impl->display = NULL;
return 1;
}

#ifdef PUGL_HAVE_GL
int glxMajor, glxMinor;
glXQueryVersion(impl->display, &glxMajor, &glxMinor);
PUGL_LOGF("GLX Version %d.%d\n", glxMajor, glxMinor);

impl->ctx = glXCreateContext(impl->display, vi, 0, GL_TRUE);
#endif

Window xParent = view->parent
? (Window)view->parent
@@ -132,20 +257,29 @@ puglCreateWindow(PuglView* view, const char* title)

XSetWindowAttributes attr;
memset(&attr, 0, sizeof(XSetWindowAttributes));
attr.colormap = cmap;
attr.border_pixel = 0;

attr.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask
| ButtonPressMask | ButtonReleaseMask
#ifdef PUGL_GRAB_FOCUS
| EnterWindowMask
#endif
| PointerMotionMask | StructureNotifyMask;
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);

impl->win = XCreateWindow(
impl->display, xParent,
0, 0, view->width, view->height, 0, vi->depth, InputOutput, vi->visual,
CWBorderPixel | CWColormap | CWEventMask, &attr);
CWBackPixel | CWBorderPixel | CWColormap | CWEventMask, &attr);

if (!createContext(view, vi)) {
XDestroyWindow(impl->display, impl->win);
impl->win = 0;

XCloseDisplay(impl->display);
impl->display = NULL;

return 1;
}

XSizeHints sizeHints;
memset(&sizeHints, 0, sizeof(sizeHints));
@@ -156,6 +290,11 @@ puglCreateWindow(PuglView* view, const char* title)
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 (title) {
@@ -175,25 +314,19 @@ puglCreateWindow(PuglView* view, const char* title)

XFree(vi);

glXMakeCurrent(view->impl->display, view->impl->win, view->impl->ctx);

return 0;
return PUGL_SUCCESS;
}

void
puglShowWindow(PuglView* view)
{
PuglInternals* impl = view->impl;

XMapRaised(impl->display, impl->win);
XMapRaised(view->impl->display, view->impl->win);
}

void
puglHideWindow(PuglView* view)
{
PuglInternals* impl = view->impl;

XUnmapWindow(impl->display, impl->win);
XUnmapWindow(view->impl->display, view->impl->win);
}

void
@@ -203,7 +336,9 @@ puglDestroy(PuglView* view)
return;
}

glXDestroyContext(view->impl->display, view->impl->ctx);
x_fib_close(view->impl->display);

destroyContext(view);
XDestroyWindow(view->impl->display, view->impl->win);
XCloseDisplay(view->impl->display);
free(view->impl);
@@ -213,7 +348,7 @@ puglDestroy(PuglView* view)
static void
puglReshape(PuglView* view, int width, int height)
{
glXMakeCurrent(view->impl->display, view->impl->win, view->impl->ctx);
puglEnterContext(view);

if (view->reshapeFunc) {
view->reshapeFunc(view, width, height);
@@ -221,6 +356,8 @@ puglReshape(PuglView* view, int width, int height)
puglDefaultReshape(view, width, height);
}

puglLeaveContext(view, false);

view->width = width;
view->height = height;
}
@@ -228,7 +365,7 @@ puglReshape(PuglView* view, int width, int height)
static void
puglDisplay(PuglView* view)
{
glXMakeCurrent(view->impl->display, view->impl->win, view->impl->ctx);
puglEnterContext(view);

view->redisplay = false;

@@ -236,11 +373,7 @@ puglDisplay(PuglView* view)
view->displayFunc(view);
}

glFlush();

if (view->impl->doubleBuffered) {
glXSwapBuffers(view->impl->display, view->impl->win);
}
puglLeaveContext(view, true);
}

static PuglKey
@@ -346,6 +479,10 @@ puglProcessEvents(PuglView* view)
break;
}

if (event.xany.window != view->impl->win) {
continue;
}

switch (event.type) {
case MapNotify:
puglReshape(view, view->width, view->height);
@@ -456,3 +593,17 @@ puglGetNativeWindow(PuglView* view)
{
return view->impl->win;
}

void*
puglGetContext(PuglView* view)
{
#ifdef PUGL_HAVE_CAIRO
if (view->ctx_type == PUGL_CAIRO) {
return view->impl->cr;
}
#endif
return NULL;

// may be unused
(void)view;
}

+ 5
- 5
source/modules/dgl/src/sofd/libsofd.h View File

@@ -21,14 +21,14 @@
* THE SOFTWARE.
*/

#ifdef SOFD_HAVE_X11
#ifndef LIBSOFD_H
#define LIBSOFD_H

#include <X11/Xlib.h>

///////////////////////////////////////////////////////////////////////////////
/* public API */

typedef struct FibInternalsImpl FibInternals;

/** open a file select dialog
* @param dpy X Display connection
* @param parent (optional) if not NULL, become transient for given window
@@ -110,8 +110,6 @@ int x_fib_cfg_buttons (int k, int v);
*/
int x_fib_cfg_filter_callback (int (*cb)(const char*));

#endif /* END X11 specific functions */

/* 'recently used' API. x-platform
* NOTE: all functions use a static cache and are not reentrant.
* It is expected that none of these functions are called in
@@ -173,3 +171,5 @@ unsigned int x_fib_recent_count ();
* @return pointer to static string
*/
const char *x_fib_recent_at (unsigned int i);

#endif // LIBSOFD_H

+ 571
- 0
source/modules/distrho/DistrhoInfo.hpp View File

@@ -0,0 +1,571 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2015 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.
*/

#ifdef DOXYGEN

#include "src/DistrhoDefines.h"

START_NAMESPACE_DISTRHO

/* ------------------------------------------------------------------------------------------------------------
* Intro */

/**
@mainpage DISTRHO %Plugin Framework

DISTRHO %Plugin Framework (or @b DPF for short)
is a plugin framework designed to make development of new plugins an easy and enjoyable task.@n
It allows developers to create plugins with custom UIs using a simple C++ API.@n
The framework facilitates exporting various different plugin formats from the same code-base.

DPF can build for LADSPA, DSSI, LV2 and VST2 formats.@n
A JACK/Standalone mode is also available, allowing you to quickly test plugins.

@section Macros
You start by creating a "DistrhoPluginInfo.h" file describing the plugin via macros, see @ref PluginMacros.@n
This file is included in the main DPF code to select which features to activate for each plugin format.

For example, a plugin (with %UI) that use states will require LV2 hosts to support Atom and Worker extensions for
message passing from the %UI to the plugin.@n
If your plugin does not make use of states, the Worker extension is not set as a required feature.

@section Plugin
The next step is to create your plugin code by subclassing DPF's Plugin class.@n
You need to pass the number of parameters in the constructor and also the number of programs and states, if any.

Here's an example of an audio plugin that simply mutes the host output:
@code
class MutePlugin : public Plugin
{
public:
/**
Plugin class constructor.
*/
MutePlugin()
: Plugin(0, 0, 0) // 0 parameters, 0 programs and 0 states
{
}

protected:
/* ----------------------------------------------------------------------------------------
* Information */

/**
Get the plugin label.
This label is a short restricted name consisting of only _, a-z, A-Z and 0-9 characters.
*/
const char* getLabel() const override
{
return "Mute";
}

/**
Get the plugin author/maker.
*/
const char* getMaker() const override
{
return "DPF";
}

/**
Get the plugin license name (a single line of text).
For commercial plugins this should return some short copyright information.
*/
const char* getLicense() const override
{
return "MIT";
}

/**
Get the plugin version, in hexadecimal.
TODO format to be defined
*/
uint32_t getVersion() const override
{
return 0x1000;
}

/**
Get the plugin unique Id.
This value is used by LADSPA, DSSI and VST plugin formats.
*/
int64_t getUniqueId() const override
{
return cconst('M', 'u', 't', 'e');
}

/* ----------------------------------------------------------------------------------------
* This example has no parameters, so skip parameter stuff */

void initParameter(uint32_t, Parameter&) override {}
float getParameterValue(uint32_t) const override { return 0.0f; }
void setParameterValue(uint32_t, float) override {}

/* ----------------------------------------------------------------------------------------
* Audio/MIDI Processing */

/**
Run/process function for plugins without MIDI input.
NOTE: Some parameters might be null if there are no audio inputs or outputs.
*/
void run(const float**, float** outputs, uint32_t frames) override
{
// get the left and right audio outputs
float* const outL = outputs[0];
float* const outR = outputs[1];

// mute audio
std::memset(outL, 0, sizeof(float)*frames);
std::memset(outR, 0, sizeof(float)*frames);
}

};
@endcode

See the Plugin class for more information and to understand what each function does.

@section Parameters
A plugin is nothing without parameters.@n
In DPF parameters can be inputs or outputs.@n
They have hints to describe how they behave plus a name and a symbol identifying them.@n
Parameters also have 'ranges' – a minimum, maximum and default value.

Input parameters are "read-only": the plugin can read them but not change them.
(the exception being when changing programs, more on that below)@n
It's the host responsibility to save, restore and set input parameters.

Output parameters can be changed at anytime by the plugin.@n
The host will simply read their values and not change them.

Here's an example of an audio plugin that has 1 input parameter:
@code
class GainPlugin : public Plugin
{
public:
/**
Plugin class constructor.
You must set all parameter values to their defaults, matching ParameterRanges::def.
*/
GainPlugin()
: Plugin(1, 0, 0), // 1 parameter, 0 programs and 0 states
fGain(1.0f)
{
}

protected:
/* ----------------------------------------------------------------------------------------
* Information */

const char* getLabel() const override
{
return "Gain";
}

const char* getMaker() const override
{
return "DPF";
}

const char* getLicense() const override
{
return "MIT";
}

uint32_t getVersion() const override
{
return 0x1000;
}

int64_t getUniqueId() const override
{
return cconst('G', 'a', 'i', 'n');
}

/* ----------------------------------------------------------------------------------------
* Init */

/**
Initialize a parameter.
This function will be called once, shortly after the plugin is created.
*/
void initParameter(uint32_t index, Parameter& parameter) override
{
// we only have one parameter so we can skip checking the index

parameter.hints = kParameterIsAutomable;
parameter.name = "Gain";
parameter.symbol = "gain";
parameter.ranges.min = 0.0f;
parameter.ranges.max = 2.0f;
parameter.ranges.def = 1.0f;
}

/* ----------------------------------------------------------------------------------------
* Internal data */

/**
Get the current value of a parameter.
*/
float getParameterValue(uint32_t index) const override
{
// same as before, ignore index check

return fGain;
}

/**
Change a parameter value.
*/
void setParameterValue(uint32_t index, float value) override
{
// same as before, ignore index check

fGain = value;
}

/* ----------------------------------------------------------------------------------------
* Audio/MIDI Processing */

void run(const float**, float** outputs, uint32_t frames) override
{
// get the mono input and output
const float* const in = inputs[0];
/* */ float* const out = outputs[0];

// apply gain against all samples
for (uint32_t i=0; i < frames; ++i)
out[i] = in[i] * fGain;
}

private:
float fGain;
};
@endcode

See the Parameter struct for more information about parameters.

@section Programs
Programs in DPF refer to plugin-side presets (usually called "factory presets"),
an initial set of presets provided by plugin authors included in the actual plugin.

To use programs you must first enable them by setting @ref DISTRHO_PLUGIN_WANT_PROGRAMS to 1 in your DistrhoPluginInfo.h file.@n
When enabled you'll need to override 2 new function in your plugin code,
Plugin::initProgramName(uint32_t, String&) and Plugin::loadProgram(uint32_t).

Here's an example of a plugin with a "default" program:
@code
class PluginWithPresets : public Plugin
{
public:
PluginWithPresets()
: Plugin(2, 1, 0), // 2 parameters, 1 program and 0 states
fGainL(1.0f),
fGainR(1.0f),
{
}

protected:
/* ----------------------------------------------------------------------------------------
* Information */

const char* getLabel() const override
{
return "Prog";
}

const char* getMaker() const override
{
return "DPF";
}

const char* getLicense() const override
{
return "MIT";
}

uint32_t getVersion() const override
{
return 0x1000;
}

int64_t getUniqueId() const override
{
return cconst('P', 'r', 'o', 'g');
}

/* ----------------------------------------------------------------------------------------
* Init */

/**
Initialize a parameter.
This function will be called once, shortly after the plugin is created.
*/
void initParameter(uint32_t index, Parameter& parameter) override
{
parameter.hints = kParameterIsAutomable;
parameter.ranges.min = 0.0f;
parameter.ranges.max = 2.0f;
parameter.ranges.def = 1.0f;

switch (index)
{
case 0;
parameter.name = "Gain Right";
parameter.symbol = "gainR";
break;
case 1;
parameter.name = "Gain Left";
parameter.symbol = "gainL";
break;
}
}

/**
Set the name of the program @a index.
This function will be called once, shortly after the plugin is created.
*/
void initProgramName(uint32_t index, String& programName)
{
switch(index)
{
case 0:
programName = "Default";
break;
}
}

/* ----------------------------------------------------------------------------------------
* Internal data */

/**
Get the current value of a parameter.
*/
float getParameterValue(uint32_t index) const override
{
switch (index)
{
case 0;
return fGainL;
case 1;
return fGainR;
}
}

/**
Change a parameter value.
*/
void setParameterValue(uint32_t index, float value) override
{
switch (index)
{
case 0;
fGainL = value;
break;
case 1;
fGainR = value;
break;
}
}

/**
Load a program.
*/
void loadProgram(uint32_t index)
{
switch(index)
{
case 0:
fGainL = 1.0f;
fGainR = 1.0f;
break;
}
}

/* ----------------------------------------------------------------------------------------
* Audio/MIDI Processing */

void run(const float**, float** outputs, uint32_t frames) override
{
// get the left and right audio buffers
const float* const inL = inputs[0];
const float* const inR = inputs[0];
/* */ float* const outL = outputs[0];
/* */ float* const outR = outputs[0];

// apply gain against all samples
for (uint32_t i=0; i < frames; ++i)
{
outL[i] = inL[i] * fGainL;
outR[i] = inR[i] * fGainR;
}
}

private:
float fGainL, fGainR;
};
@endcode

@section States
describe them

@section MIDI
describe them

@section Latency
describe it

@section Time-Position
describe it

@section UI
describe them
*/

/* ------------------------------------------------------------------------------------------------------------
* Plugin Macros */

/**
@defgroup PluginMacros Plugin Macros

C Macros that describe your plugin. (defined in the "DistrhoPluginInfo.h" file)

With these macros you can tell the host what features your plugin requires.@n
Depending on which macros you enable, new functions will be available to call and/or override.

All values are either integer or strings.@n
For boolean-like values 1 means 'on' and 0 means 'off'.

The values defined in this group are for documentation purposes only.@n
All macros are disabled by default.

Only 4 macros are required, they are:
- @ref DISTRHO_PLUGIN_NAME
- @ref DISTRHO_PLUGIN_NUM_INPUTS
- @ref DISTRHO_PLUGIN_NUM_OUTPUTS
- @ref DISTRHO_PLUGIN_URI
@{
*/

/**
The plugin name.@n
This is used to identify your plugin before a Plugin instance can be created.
@note This macro is required.
*/
#define DISTRHO_PLUGIN_NAME "Plugin Name"

/**
Number of audio inputs the plugin has.
@note This macro is required.
*/
#define DISTRHO_PLUGIN_NUM_INPUTS 2

/**
Number of audio outputs the plugin has.
@note This macro is required.
*/
#define DISTRHO_PLUGIN_NUM_OUTPUTS 2

/**
The plugin URI when exporting in LV2 format.
@note This macro is required.
*/
#define DISTRHO_PLUGIN_URI "urn:distrho:name"

/**
Wherever the plugin has a custom %UI.
@see DISTRHO_UI_USE_NANOVG
@see UI
*/
#define DISTRHO_PLUGIN_HAS_UI 1

/**
Wherever the plugin processing is realtime-safe.@n
TODO - list rtsafe requirements
*/
#define DISTRHO_PLUGIN_IS_RT_SAFE 1

/**
Wherever the plugin is a synth.@n
@ref DISTRHO_PLUGIN_WANT_MIDI_INPUT is automatically enabled when this is too.
@see DISTRHO_PLUGIN_WANT_MIDI_INPUT
*/
#define DISTRHO_PLUGIN_IS_SYNTH 1

/**
Enable direct access between the %UI and plugin code.
@see UI::getPluginInstancePointer()
@note DO NOT USE THIS UNLESS STRICTLY NECESSARY!!
Try to avoid it at all costs!
*/
#define DISTRHO_PLUGIN_WANT_DIRECT_ACCESS 0

/**
Wherever the plugin introduces latency during audio or midi processing.
@see Plugin::setLatency(uint32_t)
*/
#define DISTRHO_PLUGIN_WANT_LATENCY 1

/**
Wherever the plugin wants MIDI input.@n
This is automatically enabled if @ref DISTRHO_PLUGIN_IS_SYNTH is true.
*/
#define DISTRHO_PLUGIN_WANT_MIDI_INPUT 1

/**
Wherever the plugin wants MIDI output.
@see Plugin::writeMidiEvent(const MidiEvent&)
*/
#define DISTRHO_PLUGIN_WANT_MIDI_OUTPUT 1

/**
Wherever the plugin provides its own internal programs.
@see Plugin::initProgramName(uint32_t, String&)
@see Plugin::loadProgram(uint32_t)
*/
#define DISTRHO_PLUGIN_WANT_PROGRAMS 1

/**
Wherever the plugin uses internal non-parameter data.
@see Plugin::initState(uint32_t, String&, String&)
@see Plugin::setState(const char*, const char*)
*/
#define DISTRHO_PLUGIN_WANT_STATE 1

/**
Wherever the plugin wants time position information from the host.
@see Plugin::getTimePosition()
*/
#define DISTRHO_PLUGIN_WANT_TIMEPOS 1

/**
Wherever the %UI uses NanoVG for drawing instead of the default raw OpenGL calls.@n
When enabled your %UI instance will subclass @ref NanoWidget instead of @ref Widget.
*/
#define DISTRHO_UI_USE_NANOVG 1

/**
The %UI URI when exporting in LV2 format.@n
By default this is set to @ref DISTRHO_PLUGIN_URI with "#UI" as suffix.
*/
#define DISTRHO_UI_URI DISTRHO_PLUGIN_URI "#UI"

/** @} */

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

END_NAMESPACE_DISTRHO

#endif // DOXYGEN

+ 213
- 129
source/modules/distrho/DistrhoPlugin.hpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2015 Filipe Coelho <falktx@falktx.com>
*
* Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this
@@ -17,22 +17,34 @@
#ifndef DISTRHO_PLUGIN_HPP_INCLUDED
#define DISTRHO_PLUGIN_HPP_INCLUDED

#include "extra/d_string.hpp"
#include "extra/String.hpp"
#include "extra/LeakDetector.hpp"
#include "src/DistrhoPluginChecks.h"

#include <cmath>
START_NAMESPACE_DISTRHO

#ifdef DISTRHO_PROPER_CPP11_SUPPORT
# include <cstdint>
#else
# include <stdint.h>
#endif
/* ------------------------------------------------------------------------------------------------------------
* Audio Port Hints */

#ifndef M_PI
# define M_PI 3.14159265358979323846
#endif
/**
@defgroup AudioPortHints Audio Port Hints

START_NAMESPACE_DISTRHO
Various audio port hints.
@see AudioPort::hints
@{
*/

/**
Audio port can be used as control voltage (LV2 only).
*/
static const uint32_t kAudioPortIsCV = 0x1;

/**
Audio port should be used as sidechan (LV2 only).
*/
static const uint32_t kAudioPortIsSidechain = 0x2;

/** @} */

/* ------------------------------------------------------------------------------------------------------------
* Parameter Hints */
@@ -47,12 +59,12 @@ START_NAMESPACE_DISTRHO

/**
Parameter is automable (real-time safe).
@see Plugin::d_setParameterValue()
@see Plugin::setParameterValue(uint32_t, float)
*/
static const uint32_t kParameterIsAutomable = 0x01;

/**
Parameter value is boolean.
Parameter value is boolean.@n
It's always at either minimum or maximum value.
*/
static const uint32_t kParameterIsBoolean = 0x02;
@@ -68,11 +80,11 @@ static const uint32_t kParameterIsInteger = 0x04;
static const uint32_t kParameterIsLogarithmic = 0x08;

/**
Parameter is of output type.
Parameter is of output type.@n
When unset, parameter is assumed to be of input type.

Parameter inputs are changed by the host and must not be changed by the plugin.
The only exception being when changing programs, see Plugin::d_setProgram().
Parameter inputs are changed by the host and must not be changed by the plugin.@n
The only exception being when changing programs, see Plugin::loadProgram().@n
Outputs are changed by the plugin and never modified by the host.
*/
static const uint32_t kParameterIsOutput = 0x10;
@@ -80,13 +92,52 @@ static const uint32_t kParameterIsOutput = 0x10;
/** @} */

/* ------------------------------------------------------------------------------------------------------------
* DPF Base structs */
* Base Plugin structs */

/**
Parameter ranges.
@defgroup BasePluginStructs Base Plugin Structs
@{
*/

/**
Audio Port.
*/
struct AudioPort {
/**
Hints describing this audio port.
@see AudioPortHints
*/
uint32_t hints;

/**
The name of this audio port.@n
An audio port name can contain any character, but hosts might have a hard time with non-ascii ones.@n
The name doesn't have to be unique within a plugin instance, but it's recommended.
*/
String name;

/**
The symbol of this audio port.@n
An audio port symbol is a short restricted name used as a machine and human readable identifier.@n
The first character must be one of _, a-z or A-Z and subsequent characters can be from _, a-z, A-Z and 0-9.
@note Audio port and parameter symbols MUST be unique within a plugin instance.
*/
String symbol;

/**
Default constructor for a regular audio port.
*/
AudioPort() noexcept
: hints(0x0),
name(),
symbol() {}
};

/**
Parameter ranges.@n
This is used to set the default, minimum and maximum values of a parameter.

By default a parameter has 0.0 as minimum, 1.0 as maximum and 0.0 as default.
By default a parameter has 0.0 as minimum, 1.0 as maximum and 0.0 as default.@n
When changing this struct values you must ensure maximum > minimum and default is within range.
*/
struct ParameterRanges {
@@ -106,7 +157,7 @@ struct ParameterRanges {
float max;

/**
Default constructor.
Default constructor, using 0.0 as minimum, 1.0 as maximum and 0.0 as default.
*/
ParameterRanges() noexcept
: def(0.0f),
@@ -116,7 +167,7 @@ struct ParameterRanges {
/**
Constructor using custom values.
*/
ParameterRanges(const float df, const float mn, const float mx) noexcept
ParameterRanges(float df, float mn, float mx) noexcept
: def(df),
min(mn),
max(mx) {}
@@ -211,29 +262,29 @@ struct Parameter {
uint32_t hints;

/**
The name of this parameter.
A parameter name can contain any character, but hosts might have a hard time with non-ascii ones.
The name of this parameter.@n
A parameter name can contain any character, but hosts might have a hard time with non-ascii ones.@n
The name doesn't have to be unique within a plugin instance, but it's recommended.
*/
d_string name;
String name;

/**
The symbol of this parameter.
A parameter symbol is a short restricted name used as a machine and human readable identifier.
The symbol of this parameter.@n
A parameter symbol is a short restricted name used as a machine and human readable identifier.@n
The first character must be one of _, a-z or A-Z and subsequent characters can be from _, a-z, A-Z and 0-9.
@note: Parameter symbols MUST be unique within a plugin instance.
@note Parameter symbols MUST be unique within a plugin instance.
*/
d_string symbol;
String symbol;

/**
The unit of this parameter.
This means something like "dB", "kHz" and "ms".
Can be left blank if units do not apply to this parameter.
The unit of this parameter.@n
This means something like "dB", "kHz" and "ms".@n
Can be left blank if a unit does not apply to this parameter.
*/
d_string unit;
String unit;

/**
Ranges of this parameter.
Ranges of this parameter.@n
The ranges describe the default, minimum and maximum values.
*/
ParameterRanges ranges;
@@ -247,6 +298,16 @@ struct Parameter {
symbol(),
unit(),
ranges() {}

/**
Constructor using custom values.
*/
Parameter(uint32_t h, const char* n, const char* s, const char* u, float def, float min, float max) noexcept
: hints(h),
name(n),
symbol(s),
unit(u),
ranges(def, min, max) {}
};

/**
@@ -269,7 +330,7 @@ struct MidiEvent {
uint32_t size;

/**
MIDI data.
MIDI data.@n
If size > kDataSize, dataExt is used (otherwise null).
*/
uint8_t data[kDataSize];
@@ -277,8 +338,8 @@ struct MidiEvent {
};

/**
Time position.
The @a playing and @a frame values are always valid.
Time position.@n
The @a playing and @a frame values are always valid.@n
BBT values are only valid when @a bbt.valid is true.

This struct is inspired by the JACK Transport API.
@@ -299,28 +360,28 @@ struct TimePosition {
*/
struct BarBeatTick {
/**
Wherever the host transport is using BBT.
Wherever the host transport is using BBT.@n
If false you must not read from this struct.
*/
bool valid;

/**
Current bar.
Should always be > 0.
Current bar.@n
Should always be > 0.@n
The first bar is bar '1'.
*/
int32_t bar;

/**
Current beat within bar.
Should always be > 0 and <= @a beatsPerBar.
Current beat within bar.@n
Should always be > 0 and <= @a beatsPerBar.@n
The first beat is beat '1'.
*/
int32_t beat;

/**
Current tick within beat.
Should always be > 0 and <= @a ticksPerBeat.
Current tick within beat.@n
Should always be > 0 and <= @a ticksPerBeat.@n
The first tick is tick '0'.
*/
int32_t tick;
@@ -341,7 +402,7 @@ struct TimePosition {
float beatType;

/**
Number of ticks within a bar.
Number of ticks within a bar.@n
Usually a moderately large integer with many denominators, such as 1920.0.
*/
double ticksPerBeat;
@@ -375,44 +436,50 @@ struct TimePosition {
bbt() {}
};

/** @} */

/* ------------------------------------------------------------------------------------------------------------
* DPF Plugin */

/**
@defgroup MainClasses Main Classes
@{
*/

/**
DPF Plugin class from where plugin instances are created.

The public methods (Host state) are called from the plugin to get or set host information.
They can be called from a plugin instance at anytime unless stated otherwise.
The public methods (Host state) are called from the plugin to get or set host information.@n
They can be called from a plugin instance at anytime unless stated otherwise.@n
All other methods are to be implemented by the plugin and will be called by the host.

Shortly after a plugin instance is created, the various d_init* functions will be called by the host.
Host will call d_activate() before d_run(), and d_deactivate() before the plugin instance is destroyed.
The host may call deactivate right after activate and vice-versa, but never activate/deactivate consecutively.
There is no limit on how many times d_run() is called, only that activate/deactivate will be called in between.
Shortly after a plugin instance is created, the various init* functions will be called by the host.@n
Host will call activate() before run(), and deactivate() before the plugin instance is destroyed.@n
The host may call deactivate right after activate and vice-versa, but never activate/deactivate consecutively.@n
There is no limit on how many times run() is called, only that activate/deactivate will be called in between.

The buffer size and sample rate values will remain constant between activate and deactivate.
Buffer size is only a hint though, the host might call d_run() with a higher or lower number of frames.
The buffer size and sample rate values will remain constant between activate and deactivate.@n
Buffer size is only a hint though, the host might call run() with a higher or lower number of frames.

Some of this class functions are only available according to some macros.

DISTRHO_PLUGIN_WANT_PROGRAMS activates program related features.
When enabled you need to implement d_initProgramName() and d_setProgram().
DISTRHO_PLUGIN_WANT_PROGRAMS activates program related features.@n
When enabled you need to implement initProgramName() and loadProgram().

DISTRHO_PLUGIN_WANT_STATE activates internal state features.
When enabled you need to implement d_initStateKey() and d_setState().
DISTRHO_PLUGIN_WANT_STATE activates internal state features.@n
When enabled you need to implement initStateKey() and setState().

The process function d_run() changes wherever DISTRHO_PLUGIN_HAS_MIDI_INPUT is enabled or not.
The process function run() changes wherever DISTRHO_PLUGIN_WANT_MIDI_INPUT is enabled or not.@n
When enabled it provides midi input events.
*/
class Plugin
{
public:
/**
Plugin class constructor.
Plugin class constructor.@n
You must set all parameter values to their defaults, matching ParameterRanges::def.
If you're using states you must also set them to their defaults by calling d_setState().
*/
Plugin(const uint32_t parameterCount, const uint32_t programCount, const uint32_t stateCount);
Plugin(uint32_t parameterCount, uint32_t programCount, uint32_t stateCount);

/**
Destructor.
@@ -423,46 +490,47 @@ public:
* Host state */

/**
Get the current buffer size that will probably be used during processing, in frames.
Get the current buffer size that will probably be used during processing, in frames.@n
This value will remain constant between activate and deactivate.
@note: This value is only a hint!
Hosts might call d_run() with a higher or lower number of frames.
@see d_bufferSizeChanged(uint32_t)
@note This value is only a hint!@n
Hosts might call run() with a higher or lower number of frames.
@see bufferSizeChanged(uint32_t)
*/
uint32_t d_getBufferSize() const noexcept;
uint32_t getBufferSize() const noexcept;

/**
Get the current sample rate that will be used during processing.
Get the current sample rate that will be used during processing.@n
This value will remain constant between activate and deactivate.
@see d_sampleRateChanged(double)
@see sampleRateChanged(double)
*/
double d_getSampleRate() const noexcept;
double getSampleRate() const noexcept;

#if DISTRHO_PLUGIN_WANT_TIMEPOS
/**
Get the current host transport time position.
This function should only be called during d_run().
Get the current host transport time position.@n
This function should only be called during run().@n
You can call this during other times, but the returned position is not guaranteed to be in sync.
@note: TimePos is not supported in LADSPA and DSSI plugin formats.
@note TimePosition is not supported in LADSPA and DSSI plugin formats.
*/
const TimePosition& d_getTimePosition() const noexcept;
const TimePosition& getTimePosition() const noexcept;
#endif

#if DISTRHO_PLUGIN_WANT_LATENCY
/**
Change the plugin audio output latency to @a frames.
This function should only be called in the constructor, d_activate() and d_run().
Change the plugin audio output latency to @a frames.@n
This function should only be called in the constructor, activate() and run().
@note This function is only available if DISTRHO_PLUGIN_WANT_LATENCY is enabled.
*/
void d_setLatency(const uint32_t frames) noexcept;
void setLatency(uint32_t frames) noexcept;
#endif

#if DISTRHO_PLUGIN_HAS_MIDI_OUTPUT
#if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT
/**
Write a MIDI output event.
This function must only be called during d_run().
Returns false when the host buffer is full, in which case do not call this again until the next d_run().
Write a MIDI output event.@n
This function must only be called during run().@n
Returns false when the host buffer is full, in which case do not call this again until the next run().
*/
bool d_writeMidiEvent(const MidiEvent& midiEvent) noexcept;
bool writeMidiEvent(const MidiEvent& midiEvent) noexcept;
#endif

protected:
@@ -470,146 +538,153 @@ protected:
* Information */

/**
Get the plugin name.
Get the plugin name.@n
Returns DISTRHO_PLUGIN_NAME by default.
*/
virtual const char* d_getName() const { return DISTRHO_PLUGIN_NAME; }
virtual const char* getName() const { return DISTRHO_PLUGIN_NAME; }

/**
Get the plugin label.
A plugin label follows the same rules as Parameter::symbol, with the exception that it can start with numbers.
Get the plugin label.@n
This label is a short restricted name consisting of only _, a-z, A-Z and 0-9 characters.
*/
virtual const char* d_getLabel() const = 0;
virtual const char* getLabel() const = 0;

/**
Get the plugin author/maker.
*/
virtual const char* d_getMaker() const = 0;
virtual const char* getMaker() const = 0;

/**
Get the plugin license name (a single line of text).
Get the plugin license name (a single line of text).@n
For commercial plugins this should return some short copyright information.
*/
virtual const char* d_getLicense() const = 0;
virtual const char* getLicense() const = 0;

/**
Get the plugin version, in hexadecimal.
Get the plugin version, in hexadecimal.@n
TODO format to be defined
*/
virtual uint32_t d_getVersion() const = 0;
virtual uint32_t getVersion() const = 0;

/**
Get the plugin unique Id.
Get the plugin unique Id.@n
This value is used by LADSPA, DSSI and VST plugin formats.
*/
virtual int64_t d_getUniqueId() const = 0;
virtual int64_t getUniqueId() const = 0;

/* --------------------------------------------------------------------------------------------------------
* Init */

/**
Initialize the parameter @a index.
Initialize the audio port @a index.@n
This function will be called once, shortly after the plugin is created.
*/
virtual void d_initParameter(uint32_t index, Parameter& parameter) = 0;
virtual void initAudioPort(bool input, uint32_t index, AudioPort& port);

#if DISTRHO_PLUGIN_WANT_PROGRAMS
/**
Set the name of the program @a index.
Initialize the parameter @a index.@n
This function will be called once, shortly after the plugin is created.
*/
virtual void initParameter(uint32_t index, Parameter& parameter) = 0;

#if DISTRHO_PLUGIN_WANT_PROGRAMS
/**
Set the name of the program @a index.@n
This function will be called once, shortly after the plugin is created.@n
Must be implemented by your plugin class only if DISTRHO_PLUGIN_WANT_PROGRAMS is enabled.
*/
virtual void d_initProgramName(uint32_t index, d_string& programName) = 0;
virtual void initProgramName(uint32_t index, String& programName) = 0;
#endif

#if DISTRHO_PLUGIN_WANT_STATE
/**
Set the state key and default value of @a index.
This function will be called once, shortly after the plugin is created.
Set the state key and default value of @a index.@n
This function will be called once, shortly after the plugin is created.@n
Must be implemented by your plugin class only if DISTRHO_PLUGIN_WANT_STATE is enabled.
*/
virtual void d_initState(uint32_t index, d_string& stateKey, d_string& defaultStateValue) = 0;
virtual void initState(uint32_t index, String& stateKey, String& defaultStateValue) = 0;
#endif

/* --------------------------------------------------------------------------------------------------------
* Internal data */

/**
Get the current value of a parameter.
Get the current value of a parameter.@n
The host may call this function from any context, including realtime processing.
*/
virtual float d_getParameterValue(uint32_t index) const = 0;
virtual float getParameterValue(uint32_t index) const = 0;

/**
Change a parameter value.
The host may call this function from any context, including realtime processing.
When a parameter is marked as automable, you must ensure no non-realtime operations are called.
Change a parameter value.@n
The host may call this function from any context, including realtime processing.@n
When a parameter is marked as automable, you must ensure no non-realtime operations are performed.
@note This function will only be called for parameter inputs.
*/
virtual void d_setParameterValue(uint32_t index, float value) = 0;
virtual void setParameterValue(uint32_t index, float value) = 0;

#if DISTRHO_PLUGIN_WANT_PROGRAMS
/**
Change the currently used program to @a index.
The host may call this function from any context, including realtime processing.
Load a program.@n
The host may call this function from any context, including realtime processing.@n
Must be implemented by your plugin class only if DISTRHO_PLUGIN_WANT_PROGRAMS is enabled.
*/
virtual void d_setProgram(uint32_t index) = 0;
virtual void loadProgram(uint32_t index) = 0;
#endif

#if DISTRHO_PLUGIN_WANT_STATE
/**
Change an internal state @a key to @a value.
Change an internal state @a key to @a value.@n
Must be implemented by your plugin class only if DISTRHO_PLUGIN_WANT_STATE is enabled.
*/
virtual void d_setState(const char* key, const char* value) = 0;
virtual void setState(const char* key, const char* value) = 0;
#endif

/* --------------------------------------------------------------------------------------------------------
* Process */
* Audio/MIDI Processing */

/**
Activate this plugin.
*/
virtual void d_activate() {}
virtual void activate() {}

/**
Deactivate this plugin.
*/
virtual void d_deactivate() {}
virtual void deactivate() {}

#if DISTRHO_PLUGIN_HAS_MIDI_INPUT
#if DISTRHO_PLUGIN_WANT_MIDI_INPUT
/**
Run/process function for plugins with MIDI input.
@note: Some parameters might be null if there are no audio inputs/outputs or MIDI events.
@note Some parameters might be null if there are no audio inputs/outputs or MIDI events.
*/
virtual void d_run(const float** inputs, float** outputs, uint32_t frames,
const MidiEvent* midiEvents, uint32_t midiEventCount) = 0;
virtual void run(const float** inputs, float** outputs, uint32_t frames,
const MidiEvent* midiEvents, uint32_t midiEventCount) = 0;
#else
/**
Run/process function for plugins without MIDI input.
@note: Some parameters might be null if there are no audio inputs or outputs.
@note Some parameters might be null if there are no audio inputs or outputs.
*/
virtual void d_run(const float** inputs, float** outputs, uint32_t frames) = 0;
virtual void run(const float** inputs, float** outputs, uint32_t frames) = 0;
#endif

/* --------------------------------------------------------------------------------------------------------
* Callbacks (optional) */

/**
Optional callback to inform the plugin about a buffer size change.
Optional callback to inform the plugin about a buffer size change.@n
This function will only be called when the plugin is deactivated.
@note: This value is only a hint!
Hosts might call d_run() with a higher or lower number of frames.
@see d_getBufferSize()
@note This value is only a hint!@n
Hosts might call run() with a higher or lower number of frames.
@see getBufferSize()
*/
virtual void d_bufferSizeChanged(uint32_t newBufferSize);
virtual void bufferSizeChanged(uint32_t newBufferSize);

/**
Optional callback to inform the plugin about a sample rate change.
Optional callback to inform the plugin about a sample rate change.@n
This function will only be called when the plugin is deactivated.
@see d_getSampleRate()
@see getSampleRate()
*/
virtual void d_sampleRateChanged(double newSampleRate);
virtual void sampleRateChanged(double newSampleRate);

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

@@ -621,14 +696,23 @@ private:
DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(Plugin)
};

/** @} */

/* ------------------------------------------------------------------------------------------------------------
* Create plugin, entry point */

/**
@defgroup EntryPoints Entry Points
@{
*/

/**
TODO.
*/
extern Plugin* createPlugin();

/** @} */

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

END_NAMESPACE_DISTRHO


+ 1
- 1
source/modules/distrho/DistrhoPluginMain.cpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2015 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


+ 35
- 22
source/modules/distrho/DistrhoUI.hpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2015 Filipe Coelho <falktx@falktx.com>
*
* Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this
@@ -17,7 +17,7 @@
#ifndef DISTRHO_UI_HPP_INCLUDED
#define DISTRHO_UI_HPP_INCLUDED

#include "extra/d_leakdetector.hpp"
#include "extra/LeakDetector.hpp"
#include "src/DistrhoPluginChecks.h"

#if DISTRHO_UI_USE_NANOVG
@@ -33,6 +33,11 @@ START_NAMESPACE_DISTRHO
/* ------------------------------------------------------------------------------------------------------------
* DPF UI */

/**
@addtogroup MainClasses
@{
*/

/**
DPF UI class from where UI instances are created.

@@ -47,7 +52,7 @@ public:
UI class constructor.
The UI should be initialized to a default state that matches the plugin side.
*/
UI();
UI(uint width = 0, uint height = 0);

/**
Destructor.
@@ -59,32 +64,32 @@ public:

/**
Get the current sample rate used in plugin processing.
@see d_sampleRateChanged(double)
@see sampleRateChanged(double)
*/
double d_getSampleRate() const noexcept;
double getSampleRate() const noexcept;

/**
TODO: Document this.
*/
void d_editParameter(const uint32_t index, const bool started);
void editParameter(uint32_t index, bool started);

/**
TODO: Document this.
*/
void d_setParameterValue(const uint32_t index, const float value);
void setParameterValue(uint32_t index, float value);

#if DISTRHO_PLUGIN_WANT_STATE
/**
TODO: Document this.
*/
void d_setState(const char* const key, const char* const value);
void setState(const char* key, const char* value);
#endif

#if DISTRHO_PLUGIN_IS_SYNTH
/**
TODO: Document this.
*/
void d_sendNote(const uint8_t channel, const uint8_t note, const uint8_t velocity);
void sendNote(uint8_t channel, uint8_t note, uint8_t velocity);
#endif

#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
@@ -94,7 +99,7 @@ public:
/**
TODO: Document this.
*/
void* d_getPluginInstancePointer() const noexcept;
void* getPluginInstancePointer() const noexcept;
#endif

protected:
@@ -102,25 +107,25 @@ protected:
* DSP/Plugin Callbacks */

/**
A parameter has changed on the plugin side.
A parameter has changed on the plugin side.@n
This is called by the host to inform the UI about parameter changes.
*/
virtual void d_parameterChanged(uint32_t index, float value) = 0;
virtual void parameterChanged(uint32_t index, float value) = 0;

#if DISTRHO_PLUGIN_WANT_PROGRAMS
/**
The current program has changed on the plugin side.
A program has been loaded on the plugin side.@n
This is called by the host to inform the UI about program changes.
*/
virtual void d_programChanged(uint32_t index) = 0;
virtual void programLoaded(uint32_t index) = 0;
#endif

#if DISTRHO_PLUGIN_WANT_STATE
/**
A state has changed on the plugin side.
A state has changed on the plugin side.@n
This is called by the host to inform the UI about state changes.
*/
virtual void d_stateChanged(const char* key, const char* value) = 0;
virtual void stateChanged(const char* key, const char* value) = 0;
#endif

/* --------------------------------------------------------------------------------------------------------
@@ -128,9 +133,9 @@ protected:

/**
Optional callback to inform the UI about a sample rate change on the plugin side.
@see d_getSampleRate()
@see getSampleRate()
*/
virtual void d_sampleRateChanged(double newSampleRate);
virtual void sampleRateChanged(double newSampleRate);

/* --------------------------------------------------------------------------------------------------------
* UI Callbacks (optional) */
@@ -138,20 +143,20 @@ protected:
/**
TODO: Document this.
*/
virtual void d_uiIdle() {}
virtual void uiIdle() {}

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

/**
OpenGL window reshape function, called when parent window is resized.
You can reimplement this function for a custom OpenGL state.
@see Window::onReshape(uint,uint)
*/
virtual void d_uiReshape(uint width, uint height);
virtual void uiReshape(uint width, uint height);

/* --------------------------------------------------------------------------------------------------------
* UI Resize Handling, internal */
@@ -176,19 +181,27 @@ private:
void setAbsoluteY(int) const noexcept {}
void setAbsolutePos(int, int) const noexcept {}
void setAbsolutePos(const DGL::Point<int>&) const noexcept {}
void setNeedsFullViewport(bool) const noexcept {}

DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(UI)
};

/** @} */

/* ------------------------------------------------------------------------------------------------------------
* Create UI, entry point */

/**
@addtogroup EntryPoints
@{
*/

/**
TODO.
*/
extern UI* createUI();

/** @} */

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

END_NAMESPACE_DISTRHO


+ 1
- 1
source/modules/distrho/DistrhoUIMain.cpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2015 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


+ 32
- 1
source/modules/distrho/DistrhoUtils.hpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2015 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
@@ -46,6 +46,10 @@ inline float round(float __x)
}
#endif

#ifndef M_PI
# define M_PI 3.14159265358979323846
#endif

// -----------------------------------------------------------------------
// misc functions

@@ -197,6 +201,33 @@ bool d_isNotZero(const T& value)
return std::abs(value) >= std::numeric_limits<T>::epsilon();
}

/*
* Get next power of 2.
*/
static inline
uint32_t d_nextPowerOf2(uint32_t size) noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(size > 0, 0);

// http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
--size;
size |= size >> 1;
size |= size >> 2;
size |= size >> 4;
size |= size >> 8;
size |= size >> 16;
return ++size;
}

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

#ifndef DONT_SET_USING_DISTRHO_NAMESPACE
// If your code uses a lot of DISTRHO classes, then this will obviously save you
// a lot of typing, but can be disabled by setting DONT_SET_USING_DISTRHO_NAMESPACE.
namespace DISTRHO_NAMESPACE {}
using namespace DISTRHO_NAMESPACE;
#endif

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

#endif // DISTRHO_UTILS_HPP_INCLUDED

+ 127
- 0
source/modules/distrho/extra/Base64.hpp View File

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

#ifndef DISTRHO_BASE64_HPP_INCLUDED
#define DISTRHO_BASE64_HPP_INCLUDED

#include "../DistrhoUtils.hpp"

#include <cctype>
#include <vector>

// -----------------------------------------------------------------------
// base64 stuff, based on http://www.adp-gmbh.ch/cpp/common/base64.html
// Copyright (C) 2004-2008 René Nyffenegger

// -----------------------------------------------------------------------
// Helpers

#ifndef DOXYGEN
namespace DistrhoBase64Helpers {

static const char* const kBase64Chars =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";

static inline
uint8_t findBase64CharIndex(const char c)
{
static const uint8_t kBase64CharsLen(static_cast<uint8_t>(std::strlen(kBase64Chars)));

for (uint8_t i=0; i<kBase64CharsLen; ++i)
{
if (kBase64Chars[i] == c)
return i;
}

d_stderr2("findBase64CharIndex('%c') - failed", c);
return 0;
}

static inline
bool isBase64Char(const char c)
{
return (std::isalnum(c) || (c == '+') || (c == '/'));
}

} // namespace DistrhoBase64Helpers
#endif

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

static inline
std::vector<uint8_t> d_getChunkFromBase64String(const char* const base64string)
{
DISTRHO_SAFE_ASSERT_RETURN(base64string != nullptr, std::vector<uint8_t>());

uint i=0, j=0;
uint charArray3[3], charArray4[4];

std::vector<uint8_t> ret;
ret.reserve(std::strlen(base64string)*3/4 + 4);

for (std::size_t l=0, len=std::strlen(base64string); l<len; ++l)
{
const char c = base64string[l];

if (c == '\0' || c == '=')
break;
if (c == ' ' || c == '\n')
continue;

DISTRHO_SAFE_ASSERT_CONTINUE(CarlaBase64Helpers::isBase64Char(c));

charArray4[i++] = static_cast<uint>(c);

if (i == 4)
{
for (i=0; i<4; ++i)
charArray4[i] = DistrhoBase64Helpers::findBase64CharIndex(static_cast<char>(charArray4[i]));

charArray3[0] = (charArray4[0] << 2) + ((charArray4[1] & 0x30) >> 4);
charArray3[1] = ((charArray4[1] & 0xf) << 4) + ((charArray4[2] & 0x3c) >> 2);
charArray3[2] = ((charArray4[2] & 0x3) << 6) + charArray4[3];

for (i=0; i<3; ++i)
ret.push_back(static_cast<uint8_t>(charArray3[i]));

i = 0;
}
}

if (i != 0)
{
for (j=0; j<i && j<4; ++j)
charArray4[j] = DistrhoBase64Helpers::findBase64CharIndex(static_cast<char>(charArray4[j]));

for (j=i; j<4; ++j)
charArray4[j] = 0;

charArray3[0] = (charArray4[0] << 2) + ((charArray4[1] & 0x30) >> 4);
charArray3[1] = ((charArray4[1] & 0xf) << 4) + ((charArray4[2] & 0x3c) >> 2);
charArray3[2] = ((charArray4[2] & 0x3) << 6) + charArray4[3];

for (j=0; i>0 && j<i-1; j++)
ret.push_back(static_cast<uint8_t>(charArray3[j]));
}

return ret;
}

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

#endif // DISTRHO_BASE64_HPP_INCLUDED

source/modules/distrho/extra/d_leakdetector.hpp → source/modules/distrho/extra/LeakDetector.hpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2015 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
@@ -32,6 +32,7 @@ START_NAMESPACE_DISTRHO
#define DISTRHO_JOIN_MACRO_HELPER(a, b) a ## b
#define DISTRHO_JOIN_MACRO(item1, item2) DISTRHO_JOIN_MACRO_HELPER(item1, item2)

#ifdef DEBUG
/** This macro lets you embed a leak-detecting object inside a class.\n
To use it, simply declare a DISTRHO_LEAK_DETECTOR(YourClassName) inside a private section
of the class declaration. E.g.
@@ -47,14 +48,20 @@ START_NAMESPACE_DISTRHO
};
\endcode
*/
#define DISTRHO_LEAK_DETECTOR(ClassName) \
# define DISTRHO_LEAK_DETECTOR(ClassName) \
friend class DISTRHO_NAMESPACE::LeakedObjectDetector<ClassName>; \
static const char* getLeakedObjectClassName() noexcept { return #ClassName; } \
DISTRHO_NAMESPACE::LeakedObjectDetector<ClassName> DISTRHO_JOIN_MACRO(leakDetector_, ClassName);

#define DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ClassName) \
DISTRHO_DECLARE_NON_COPY_CLASS(ClassName) \
# define DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ClassName) \
DISTRHO_DECLARE_NON_COPY_CLASS(ClassName) \
DISTRHO_LEAK_DETECTOR(ClassName)
#else
/** Don't use leak detection on release builds. */
# define DISTRHO_LEAK_DETECTOR(ClassName)
# define DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ClassName) \
DISTRHO_DECLARE_NON_COPY_CLASS(ClassName)
#endif

//==============================================================================
/**

source/modules/distrho/extra/d_mutex.hpp → source/modules/distrho/extra/Mutex.hpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2015 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
@@ -38,6 +38,7 @@ public:
* Constructor.
*/
Mutex() noexcept
: fMutex()
{
pthread_mutex_init(&fMutex, nullptr);
}
@@ -92,6 +93,11 @@ public:
* Constructor.
*/
RecursiveMutex() noexcept
#ifdef DISTRHO_OS_WINDOWS
: fSection()
#else
: fMutex()
#endif
{
#ifdef DISTRHO_OS_WINDOWS
InitializeCriticalSection(&fSection);
@@ -168,16 +174,16 @@ private:
// Helper class to lock&unlock a mutex during a function scope.

template <class Mutex>
class ScopedLocker
class ScopeLocker
{
public:
ScopedLocker(const Mutex& mutex) noexcept
ScopeLocker(const Mutex& mutex) noexcept
: fMutex(mutex)
{
fMutex.lock();
}

~ScopedLocker() noexcept
~ScopeLocker() noexcept
{
fMutex.unlock();
}
@@ -186,23 +192,58 @@ private:
const Mutex& fMutex;

DISTRHO_PREVENT_HEAP_ALLOCATION
DISTRHO_DECLARE_NON_COPY_CLASS(ScopedLocker)
DISTRHO_DECLARE_NON_COPY_CLASS(ScopeLocker)
};

// -----------------------------------------------------------------------
// Helper class to try-lock&unlock a mutex during a function scope.

template <class Mutex>
class ScopeTryLocker
{
public:
ScopeTryLocker(const Mutex& mutex) noexcept
: fMutex(mutex),
fLocked(mutex.tryLock()) {}

~ScopeTryLocker() noexcept
{
if (fLocked)
fMutex.unlock();
}

bool wasLocked() const noexcept
{
return fLocked;
}

bool wasNotLocked() const noexcept
{
return !fLocked;
}

private:
const Mutex& fMutex;
const bool fLocked;

DISTRHO_PREVENT_HEAP_ALLOCATION
DISTRHO_DECLARE_NON_COPY_CLASS(ScopeTryLocker)
};

// -----------------------------------------------------------------------
// Helper class to unlock&lock a mutex during a function scope.

template <class Mutex>
class ScopedUnlocker
class ScopeUnlocker
{
public:
ScopedUnlocker(const Mutex& mutex) noexcept
ScopeUnlocker(const Mutex& mutex) noexcept
: fMutex(mutex)
{
fMutex.unlock();
}

~ScopedUnlocker() noexcept
~ScopeUnlocker() noexcept
{
fMutex.lock();
}
@@ -211,17 +252,20 @@ private:
const Mutex& fMutex;

DISTRHO_PREVENT_HEAP_ALLOCATION
DISTRHO_DECLARE_NON_COPY_CLASS(ScopedUnlocker)
DISTRHO_DECLARE_NON_COPY_CLASS(ScopeUnlocker)
};

// -----------------------------------------------------------------------
// Define types

typedef ScopedLocker<Mutex> MutexLocker;
typedef ScopedLocker<RecursiveMutex> RecursiveMutexLocker;
typedef ScopeLocker<Mutex> MutexLocker;
typedef ScopeLocker<RecursiveMutex> RecursiveMutexLocker;

typedef ScopeTryLocker<Mutex> MutexTryLocker;
typedef ScopeTryLocker<RecursiveMutex> RecursiveMutexTryLocker;

typedef ScopedUnlocker<Mutex> MutexUnlocker;
typedef ScopedUnlocker<RecursiveMutex> RecursiveMutexUnlocker;
typedef ScopeUnlocker<Mutex> MutexUnlocker;
typedef ScopeUnlocker<RecursiveMutex> RecursiveMutexUnlocker;

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


source/modules/distrho/extra/d_scopedpointer.hpp → source/modules/distrho/extra/ScopedPointer.hpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2015 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
@@ -27,23 +27,6 @@ START_NAMESPACE_DISTRHO
// The following code was based from juce-core ScopedPointer class
// Copyright (C) 2013 Raw Material Software Ltd.

/**
Used by container classes as an indirect way to delete an object of a
particular type.

The generic implementation of this class simply calls 'delete', but you can
create a specialised version of it for a particular class if you need to
delete that type of object in a more appropriate way.
*/
template<typename ObjectType>
struct ContainerDeletePolicy
{
static void destroy(ObjectType* const object)
{
delete object;
}
};

//==============================================================================
/**
This class holds a pointer which is automatically deleted when this object goes
@@ -107,7 +90,7 @@ public:
*/
~ScopedPointer()
{
ContainerDeletePolicy<ObjectType>::destroy(object);
delete object;
}

/** Changes this ScopedPointer to point to a new object.
@@ -130,7 +113,7 @@ public:
ObjectType* const oldObject = object;
object = objectToTransferFrom.object;
objectToTransferFrom.object = nullptr;
ContainerDeletePolicy<ObjectType>::destroy(oldObject);
delete oldObject;
}

return *this;
@@ -149,7 +132,7 @@ public:
{
ObjectType* const oldObject = object;
object = newObjectToTakePossessionOf;
ContainerDeletePolicy<ObjectType>::destroy(oldObject);
delete oldObject;
}

return *this;

source/modules/distrho/extra/d_sleep.hpp → source/modules/distrho/extra/Sleep.hpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2015 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
@@ -29,6 +29,9 @@
// -----------------------------------------------------------------------
// d_*sleep

/*
* Sleep for 'secs' seconds.
*/
static inline
void d_sleep(const uint secs) noexcept
{
@@ -43,6 +46,9 @@ void d_sleep(const uint secs) noexcept
} DISTRHO_SAFE_EXCEPTION("d_sleep");
}

/*
* Sleep for 'msecs' milliseconds.
*/
static inline
void d_msleep(const uint msecs) noexcept
{

source/modules/distrho/extra/d_string.hpp → source/modules/distrho/extra/String.hpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2015 Filipe Coelho <falktx@falktx.com>
*
* Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this
@@ -17,14 +17,14 @@
#ifndef DISTRHO_STRING_HPP_INCLUDED
#define DISTRHO_STRING_HPP_INCLUDED

#include "d_leakdetector.hpp"
#include "../DistrhoUtils.hpp"

START_NAMESPACE_DISTRHO

// -----------------------------------------------------------------------
// d_string class
// String class

class d_string
class String
{
public:
// -------------------------------------------------------------------
@@ -33,143 +33,153 @@ public:
/*
* Empty string.
*/
explicit d_string() noexcept
{
_init();
}
explicit String() noexcept
: fBuffer(_null()),
fBufferLen(0) {}

/*
* Simple character.
*/
explicit d_string(const char c) noexcept
explicit String(const char c) noexcept
: fBuffer(_null()),
fBufferLen(0)
{
char ch[2];
ch[0] = c;
ch[1] = '\0';

_init();
_dup(ch);
}

/*
* Simple char string.
*/
explicit d_string(char* const strBuf) noexcept
explicit String(char* const strBuf) noexcept
: fBuffer(_null()),
fBufferLen(0)
{
_init();
_dup(strBuf);
}

/*
* Simple const char string.
*/
explicit d_string(const char* const strBuf) noexcept
explicit String(const char* const strBuf) noexcept
: fBuffer(_null()),
fBufferLen(0)
{
_init();
_dup(strBuf);
}

/*
* Integer.
*/
explicit d_string(const int value) noexcept
explicit String(const int value) noexcept
: fBuffer(_null()),
fBufferLen(0)
{
char strBuf[0xff+1];
std::snprintf(strBuf, 0xff, "%d", value);
strBuf[0xff] = '\0';

_init();
_dup(strBuf);
}

/*
* Unsigned integer, possibly in hexadecimal.
*/
explicit d_string(const unsigned int value, const bool hexadecimal = false) noexcept
explicit String(const unsigned int value, const bool hexadecimal = false) noexcept
: fBuffer(_null()),
fBufferLen(0)
{
char strBuf[0xff+1];
std::snprintf(strBuf, 0xff, hexadecimal ? "0x%x" : "%u", value);
strBuf[0xff] = '\0';

_init();
_dup(strBuf);
}

/*
* Long integer.
*/
explicit d_string(const long value) noexcept
explicit String(const long value) noexcept
: fBuffer(_null()),
fBufferLen(0)
{
char strBuf[0xff+1];
std::snprintf(strBuf, 0xff, "%ld", value);
strBuf[0xff] = '\0';

_init();
_dup(strBuf);
}

/*
* Long unsigned integer, possibly hexadecimal.
*/
explicit d_string(const unsigned long value, const bool hexadecimal = false) noexcept
explicit String(const unsigned long value, const bool hexadecimal = false) noexcept
: fBuffer(_null()),
fBufferLen(0)
{
char strBuf[0xff+1];
std::snprintf(strBuf, 0xff, hexadecimal ? "0x%lx" : "%lu", value);
strBuf[0xff] = '\0';

_init();
_dup(strBuf);
}

/*
* Long long integer.
*/
explicit d_string(const long long value) noexcept
explicit String(const long long value) noexcept
: fBuffer(_null()),
fBufferLen(0)
{
char strBuf[0xff+1];
std::snprintf(strBuf, 0xff, "%lld", value);
strBuf[0xff] = '\0';

_init();
_dup(strBuf);
}

/*
* Long long unsigned integer, possibly hexadecimal.
*/
explicit d_string(const unsigned long long value, const bool hexadecimal = false) noexcept
explicit String(const unsigned long long value, const bool hexadecimal = false) noexcept
: fBuffer(_null()),
fBufferLen(0)
{
char strBuf[0xff+1];
std::snprintf(strBuf, 0xff, hexadecimal ? "0x%llx" : "%llu", value);
strBuf[0xff] = '\0';

_init();
_dup(strBuf);
}

/*
* Single-precision floating point number.
*/
explicit d_string(const float value) noexcept
explicit String(const float value) noexcept
: fBuffer(_null()),
fBufferLen(0)
{
char strBuf[0xff+1];
std::snprintf(strBuf, 0xff, "%f", value);
strBuf[0xff] = '\0';

_init();
_dup(strBuf);
}

/*
* Double-precision floating point number.
*/
explicit d_string(const double value) noexcept
explicit String(const double value) noexcept
: fBuffer(_null()),
fBufferLen(0)
{
char strBuf[0xff+1];
std::snprintf(strBuf, 0xff, "%g", value);
strBuf[0xff] = '\0';

_init();
_dup(strBuf);
}

@@ -179,9 +189,10 @@ public:
/*
* Create string from another string.
*/
d_string(const d_string& str) noexcept
String(const String& str) noexcept
: fBuffer(_null()),
fBufferLen(0)
{
_init();
_dup(str.fBuffer);
}

@@ -191,7 +202,7 @@ public:
/*
* Destructor.
*/
~d_string() noexcept
~String() noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(fBuffer != nullptr,);

@@ -210,7 +221,7 @@ public:
/*
* Get length of the string.
*/
size_t length() const noexcept
std::size_t length() const noexcept
{
return fBufferLen;
}
@@ -243,7 +254,7 @@ public:
#ifdef __USE_GNU
return (strcasestr(fBuffer, strBuf) != nullptr);
#else
d_string tmp1(fBuffer), tmp2(strBuf);
String tmp1(fBuffer), tmp2(strBuf);

// memory allocation failed or empty string(s)
if (tmp1.fBuffer == _null() || tmp2.fBuffer == _null())
@@ -261,7 +272,7 @@ public:
/*
* Check if character at 'pos' is a digit.
*/
bool isDigit(const size_t pos) const noexcept
bool isDigit(const std::size_t pos) const noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(pos < fBufferLen, false);

@@ -285,7 +296,7 @@ public:
{
DISTRHO_SAFE_ASSERT_RETURN(prefix != nullptr, false);

const size_t prefixLen(std::strlen(prefix));
const std::size_t prefixLen(std::strlen(prefix));

if (fBufferLen < prefixLen)
return false;
@@ -310,7 +321,7 @@ public:
{
DISTRHO_SAFE_ASSERT_RETURN(suffix != nullptr, false);

const size_t suffixLen(std::strlen(suffix));
const std::size_t suffixLen(std::strlen(suffix));

if (fBufferLen < suffixLen)
return false;
@@ -322,7 +333,7 @@ public:
* Find the first occurrence of character 'c' in the string.
* Returns "length()" if the character is not found.
*/
size_t find(const char c, bool* const found = nullptr) const noexcept
std::size_t find(const char c, bool* const found = nullptr) const noexcept
{
if (fBufferLen == 0 || c == '\0')
{
@@ -331,7 +342,7 @@ public:
return fBufferLen;
}

for (size_t i=0; i < fBufferLen; ++i)
for (std::size_t i=0; i < fBufferLen; ++i)
{
if (fBuffer[i] == c)
{
@@ -350,7 +361,7 @@ public:
* Find the first occurrence of string 'strBuf' in the string.
* Returns "length()" if the string is not found.
*/
size_t find(const char* const strBuf, bool* const found = nullptr) const noexcept
std::size_t find(const char* const strBuf, bool* const found = nullptr) const noexcept
{
if (fBufferLen == 0 || strBuf == nullptr || strBuf[0] == '\0')
{
@@ -375,7 +386,7 @@ public:

if (found != nullptr)
*found = true;
return static_cast<size_t>(ret);
return static_cast<std::size_t>(ret);
}

if (found != nullptr)
@@ -387,7 +398,7 @@ public:
* Find the last occurrence of character 'c' in the string.
* Returns "length()" if the character is not found.
*/
size_t rfind(const char c, bool* const found = nullptr) const noexcept
std::size_t rfind(const char c, bool* const found = nullptr) const noexcept
{
if (fBufferLen == 0 || c == '\0')
{
@@ -396,7 +407,7 @@ public:
return fBufferLen;
}

for (size_t i=fBufferLen; i > 0; --i)
for (std::size_t i=fBufferLen; i > 0; --i)
{
if (fBuffer[i-1] == c)
{
@@ -415,7 +426,7 @@ public:
* Find the last occurrence of string 'strBuf' in the string.
* Returns "length()" if the string is not found.
*/
size_t rfind(const char* const strBuf, bool* const found = nullptr) const noexcept
std::size_t rfind(const char* const strBuf, bool* const found = nullptr) const noexcept
{
if (found != nullptr)
*found = false;
@@ -423,12 +434,12 @@ public:
if (fBufferLen == 0 || strBuf == nullptr || strBuf[0] == '\0')
return fBufferLen;

const size_t strBufLen(std::strlen(strBuf));
const std::size_t strBufLen(std::strlen(strBuf));

size_t ret = fBufferLen;
std::size_t ret = fBufferLen;
const char* tmpBuf = fBuffer;

for (size_t i=0; i < fBufferLen; ++i)
for (std::size_t i=0; i < fBufferLen; ++i)
{
if (std::strstr(tmpBuf+1, strBuf) == nullptr && std::strncmp(tmpBuf, strBuf, strBufLen) == 0)
{
@@ -455,37 +466,41 @@ public:
/*
* Replace all occurrences of character 'before' with character 'after'.
*/
void replace(const char before, const char after) noexcept
String& replace(const char before, const char after) noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(before != '\0' && after != '\0',);
DISTRHO_SAFE_ASSERT_RETURN(before != '\0' && after != '\0', *this);

for (size_t i=0; i < fBufferLen; ++i)
for (std::size_t i=0; i < fBufferLen; ++i)
{
if (fBuffer[i] == before)
fBuffer[i] = after;
}

return *this;
}

/*
* Truncate the string to size 'n'.
*/
void truncate(const size_t n) noexcept
String& truncate(const std::size_t n) noexcept
{
if (n >= fBufferLen)
return;
return *this;

for (size_t i=n; i < fBufferLen; ++i)
for (std::size_t i=n; i < fBufferLen; ++i)
fBuffer[i] = '\0';

fBufferLen = n;

return *this;
}

/*
* Convert all non-basic characters to '_'.
*/
void toBasic() noexcept
String& toBasic() noexcept
{
for (size_t i=0; i < fBufferLen; ++i)
for (std::size_t i=0; i < fBufferLen; ++i)
{
if (fBuffer[i] >= '0' && fBuffer[i] <= '9')
continue;
@@ -498,34 +513,40 @@ public:

fBuffer[i] = '_';
}

return *this;
}

/*
* Convert to all ascii characters to lowercase.
*/
void toLower() noexcept
String& toLower() noexcept
{
static const char kCharDiff('a' - 'A');

for (size_t i=0; i < fBufferLen; ++i)
for (std::size_t i=0; i < fBufferLen; ++i)
{
if (fBuffer[i] >= 'A' && fBuffer[i] <= 'Z')
fBuffer[i] = static_cast<char>(fBuffer[i] + kCharDiff);
}

return *this;
}

/*
* Convert to all ascii characters to uppercase.
*/
void toUpper() noexcept
String& toUpper() noexcept
{
static const char kCharDiff('a' - 'A');

for (size_t i=0; i < fBufferLen; ++i)
for (std::size_t i=0; i < fBufferLen; ++i)
{
if (fBuffer[i] >= 'a' && fBuffer[i] <= 'z')
fBuffer[i] = static_cast<char>(fBuffer[i] - kCharDiff);
}

return *this;
}

/*
@@ -536,6 +557,81 @@ public:
return fBuffer;
}

// -------------------------------------------------------------------
// base64 stuff, based on http://www.adp-gmbh.ch/cpp/common/base64.html
// Copyright (C) 2004-2008 René Nyffenegger

static String asBase64(const void* const data, const std::size_t dataSize)
{
static const char* const kBase64Chars =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";

const std::size_t kTmpBufSize = d_nextPowerOf2(dataSize/3);

const uchar* bytesToEncode((const uchar*)data);

uint i=0, j=0;
uint charArray3[3], charArray4[4];

char strBuf[kTmpBufSize+1];
strBuf[kTmpBufSize] = '\0';
std::size_t strBufIndex = 0;

String ret;

for (std::size_t s=0; s<dataSize; ++s)
{
charArray3[i++] = *(bytesToEncode++);

if (i == 3)
{
charArray4[0] = (charArray3[0] & 0xfc) >> 2;
charArray4[1] = ((charArray3[0] & 0x03) << 4) + ((charArray3[1] & 0xf0) >> 4);
charArray4[2] = ((charArray3[1] & 0x0f) << 2) + ((charArray3[2] & 0xc0) >> 6);
charArray4[3] = charArray3[2] & 0x3f;

for (i=0; i<4; ++i)
strBuf[strBufIndex++] = kBase64Chars[charArray4[i]];

if (strBufIndex >= kTmpBufSize-7)
{
strBuf[strBufIndex] = '\0';
strBufIndex = 0;
ret += strBuf;
}

i = 0;
}
}

if (i != 0)
{
for (j=i; j<3; ++j)
charArray3[j] = '\0';

charArray4[0] = (charArray3[0] & 0xfc) >> 2;
charArray4[1] = ((charArray3[0] & 0x03) << 4) + ((charArray3[1] & 0xf0) >> 4);
charArray4[2] = ((charArray3[1] & 0x0f) << 2) + ((charArray3[2] & 0xc0) >> 6);
charArray4[3] = charArray3[2] & 0x3f;

for (j=0; j<4 && i<3 && j<i+1; ++j)
strBuf[strBufIndex++] = kBase64Chars[charArray4[j]];

for (; i++ < 3;)
strBuf[strBufIndex++] = '=';
}

if (strBufIndex != 0)
{
strBuf[strBufIndex] = '\0';
ret += strBuf;
}

return ret;
}

// -------------------------------------------------------------------
// public operators

@@ -544,7 +640,7 @@ public:
return fBuffer;
}

char operator[](const size_t pos) const noexcept
char operator[](const std::size_t pos) const noexcept
{
if (pos < fBufferLen)
return fBuffer[pos];
@@ -556,7 +652,7 @@ public:
return fallback;
}

char& operator[](const size_t pos) noexcept
char& operator[](const std::size_t pos) noexcept
{
if (pos < fBufferLen)
return fBuffer[pos];
@@ -573,7 +669,7 @@ public:
return (strBuf != nullptr && std::strcmp(fBuffer, strBuf) == 0);
}

bool operator==(const d_string& str) const noexcept
bool operator==(const String& str) const noexcept
{
return operator==(str.fBuffer);
}
@@ -583,32 +679,32 @@ public:
return !operator==(strBuf);
}

bool operator!=(const d_string& str) const noexcept
bool operator!=(const String& str) const noexcept
{
return !operator==(str.fBuffer);
}

d_string& operator=(const char* const strBuf) noexcept
String& operator=(const char* const strBuf) noexcept
{
_dup(strBuf);

return *this;
}

d_string& operator=(const d_string& str) noexcept
String& operator=(const String& str) noexcept
{
_dup(str.fBuffer);

return *this;
}

d_string& operator+=(const char* const strBuf) noexcept
String& operator+=(const char* const strBuf) noexcept
{
if (strBuf == nullptr)
return *this;

const size_t newBufSize = fBufferLen + std::strlen(strBuf) + 1;
char newBuf[newBufSize];
const std::size_t newBufSize = fBufferLen + std::strlen(strBuf) + 1;
char newBuf[newBufSize];

std::strcpy(newBuf, fBuffer);
std::strcat(newBuf, strBuf);
@@ -618,25 +714,25 @@ public:
return *this;
}

d_string& operator+=(const d_string& str) noexcept
String& operator+=(const String& str) noexcept
{
return operator+=(str.fBuffer);
}

d_string operator+(const char* const strBuf) noexcept
String operator+(const char* const strBuf) noexcept
{
const size_t newBufSize = fBufferLen + ((strBuf != nullptr) ? std::strlen(strBuf) : 0) + 1;
char newBuf[newBufSize];
const std::size_t newBufSize = fBufferLen + ((strBuf != nullptr) ? std::strlen(strBuf) : 0) + 1;
char newBuf[newBufSize];

std::strcpy(newBuf, fBuffer);

if (strBuf != nullptr)
std::strcat(newBuf, strBuf);

return d_string(newBuf);
return String(newBuf);
}

d_string operator+(const d_string& str) noexcept
String operator+(const String& str) noexcept
{
return operator+(str.fBuffer);
}
@@ -644,8 +740,8 @@ public:
// -------------------------------------------------------------------

private:
char* fBuffer; // the actual string buffer
size_t fBufferLen; // string length
char* fBuffer; // the actual string buffer
std::size_t fBufferLen; // string length

/*
* Static null string.
@@ -657,16 +753,6 @@ private:
return &sNull;
}

/*
* Shared init function.
* Called on all constructors.
*/
void _init() noexcept
{
fBuffer = _null();
fBufferLen = 0;
}

/*
* Helper function.
* Called whenever the string needs to be allocated.
@@ -675,7 +761,7 @@ private:
* - Allocates string only if 'strBuf' is not null and new string contents are different
* - If 'strBuf' is null, 'size' must be 0
*/
void _dup(const char* const strBuf, const size_t size = 0) noexcept
void _dup(const char* const strBuf, const std::size_t size = 0) noexcept
{
if (strBuf != nullptr)
{
@@ -690,7 +776,11 @@ private:
fBuffer = (char*)std::malloc(fBufferLen+1);

if (fBuffer == nullptr)
return _init();
{
fBuffer = _null();
fBufferLen = 0;
return;
}

std::strcpy(fBuffer, strBuf);

@@ -707,40 +797,40 @@ private:
DISTRHO_SAFE_ASSERT(fBuffer != nullptr);
std::free(fBuffer);

_init();
fBuffer = _null();
fBufferLen = 0;
}
}

DISTRHO_LEAK_DETECTOR(d_string)
DISTRHO_PREVENT_HEAP_ALLOCATION
};

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

static inline
d_string operator+(const d_string& strBefore, const char* const strBufAfter) noexcept
String operator+(const String& strBefore, const char* const strBufAfter) noexcept
{
const char* const strBufBefore = strBefore.buffer();
const size_t newBufSize = strBefore.length() + ((strBufAfter != nullptr) ? std::strlen(strBufAfter) : 0) + 1;
const std::size_t newBufSize = strBefore.length() + ((strBufAfter != nullptr) ? std::strlen(strBufAfter) : 0) + 1;
char newBuf[newBufSize];

std::strcpy(newBuf, strBufBefore);
std::strcat(newBuf, strBufAfter);

return d_string(newBuf);
return String(newBuf);
}

static inline
d_string operator+(const char* const strBufBefore, const d_string& strAfter) noexcept
String operator+(const char* const strBufBefore, const String& strAfter) noexcept
{
const char* const strBufAfter = strAfter.buffer();
const size_t newBufSize = ((strBufBefore != nullptr) ? std::strlen(strBufBefore) : 0) + strAfter.length() + 1;
const std::size_t newBufSize = ((strBufBefore != nullptr) ? std::strlen(strBufBefore) : 0) + strAfter.length() + 1;
char newBuf[newBufSize];

std::strcpy(newBuf, strBufBefore);
std::strcat(newBuf, strBufAfter);

return d_string(newBuf);
return String(newBuf);
}

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

source/modules/distrho/extra/d_thread.hpp → source/modules/distrho/extra/Thread.hpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2015 Filipe Coelho <falktx@falktx.com>
*
* Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this
@@ -17,13 +17,11 @@
#ifndef DISTRHO_THREAD_HPP_INCLUDED
#define DISTRHO_THREAD_HPP_INCLUDED

#include "d_mutex.hpp"
#include "d_sleep.hpp"
#include "d_string.hpp"
#include "Mutex.hpp"
#include "Sleep.hpp"
#include "String.hpp"

#if defined(__GLIBC__) && (__GLIBC__ * 1000 + __GLIBC_MINOR__) >= 2012
// has pthread_setname_np
#elif defined(DISTRHO_OS_LINUX)
#ifdef DISTRHO_OS_LINUX
# include <sys/prctl.h>
#endif

@@ -156,7 +154,7 @@ public:
if (isThreadRunning())
{
// should never happen!
d_stderr2("Carla assertion failure: \"! isThreadRunning()\" in file %s, line %i", __FILE__, __LINE__);
d_stderr2("assertion failure: \"! isThreadRunning()\" in file %s, line %i", __FILE__, __LINE__);

// copy thread id so we can clear our one
pthread_t threadId;
@@ -188,7 +186,7 @@ public:
* Returns the name of the thread.
* This is the name that gets set in the constructor.
*/
const d_string& getThreadName() const noexcept
const String& getThreadName() const noexcept
{
return fName;
}
@@ -200,10 +198,11 @@ public:
{
DISTRHO_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0',);

#ifdef DISTRHO_OS_LINUX
prctl(PR_SET_NAME, name, 0, 0, 0);
#endif
#if defined(__GLIBC__) && (__GLIBC__ * 1000 + __GLIBC_MINOR__) >= 2012
pthread_setname_np(pthread_self(), name);
#elif defined(DISTRHO_OS_LINUX)
prctl(PR_SET_NAME, name, 0, 0, 0);
#endif
}

@@ -211,7 +210,7 @@ public:

private:
Mutex fLock; // Thread lock
const d_string fName; // Thread name
const String fName; // Thread name
volatile pthread_t fHandle; // Handle for this thread
volatile bool fShouldExit; // true if thread should exit


+ 1
- 1
source/modules/distrho/src/DistrhoDefines.h View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2015 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


+ 40
- 14
source/modules/distrho/src/DistrhoPlugin.cpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2015 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
@@ -27,15 +27,20 @@ double d_lastSampleRate = 0.0;
/* ------------------------------------------------------------------------------------------------------------
* Static fallback data, see DistrhoPluginInternal.hpp */

const d_string PluginExporter::sFallbackString;
const String PluginExporter::sFallbackString;
const AudioPort PluginExporter::sFallbackAudioPort;
const ParameterRanges PluginExporter::sFallbackRanges;

/* ------------------------------------------------------------------------------------------------------------
* Plugin */

Plugin::Plugin(const uint32_t parameterCount, const uint32_t programCount, const uint32_t stateCount)
Plugin::Plugin(uint32_t parameterCount, uint32_t programCount, uint32_t stateCount)
: pData(new PrivateData())
{
#if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0
pData->audioPorts = new AudioPort[DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS];
#endif

if (parameterCount > 0)
{
pData->parameterCount = parameterCount;
@@ -46,7 +51,7 @@ Plugin::Plugin(const uint32_t parameterCount, const uint32_t programCount, const
if (programCount > 0)
{
pData->programCount = programCount;
pData->programNames = new d_string[programCount];
pData->programNames = new String[programCount];
}
#else
DISTRHO_SAFE_ASSERT(programCount == 0);
@@ -56,8 +61,8 @@ Plugin::Plugin(const uint32_t parameterCount, const uint32_t programCount, const
if (stateCount > 0)
{
pData->stateCount = stateCount;
pData->stateKeys = new d_string[stateCount];
pData->stateDefValues = new d_string[stateCount];
pData->stateKeys = new String[stateCount];
pData->stateDefValues = new String[stateCount];
}
#else
DISTRHO_SAFE_ASSERT(stateCount == 0);
@@ -72,43 +77,64 @@ Plugin::~Plugin()
/* ------------------------------------------------------------------------------------------------------------
* Host state */

uint32_t Plugin::d_getBufferSize() const noexcept
uint32_t Plugin::getBufferSize() const noexcept
{
return pData->bufferSize;
}

double Plugin::d_getSampleRate() const noexcept
double Plugin::getSampleRate() const noexcept
{
return pData->sampleRate;
}

#if DISTRHO_PLUGIN_WANT_TIMEPOS
const TimePosition& Plugin::d_getTimePosition() const noexcept
const TimePosition& Plugin::getTimePosition() const noexcept
{
return pData->timePosition;
}
#endif

#if DISTRHO_PLUGIN_WANT_LATENCY
void Plugin::d_setLatency(const uint32_t frames) noexcept
void Plugin::setLatency(uint32_t frames) noexcept
{
pData->latency = frames;
}
#endif

#if DISTRHO_PLUGIN_HAS_MIDI_OUTPUT
bool Plugin::d_writeMidiEvent(const MidiEvent& /*midiEvent*/) noexcept
#if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT
bool Plugin::writeMidiEvent(const MidiEvent& /*midiEvent*/) noexcept
{
// TODO
return false;
}
#endif

/* ------------------------------------------------------------------------------------------------------------
* Init */

void Plugin::initAudioPort(bool input, uint32_t index, AudioPort& port)
{
if (port.hints & kAudioPortIsCV)
{
port.name = input ? "CV Input " : "CV Output ";
port.name += String(index+1);
port.symbol = input ? "cv_in_" : "cv_out_";
port.symbol += String(index+1);
}
else
{
port.name = input ? "Audio Input " : "Audio Output ";
port.name += String(index+1);
port.symbol = input ? "audio_in_" : "audio_out_";
port.symbol += String(index+1);
}
}

/* ------------------------------------------------------------------------------------------------------------
* Callbacks (optional) */

void Plugin::d_bufferSizeChanged(uint32_t) {}
void Plugin::d_sampleRateChanged(double) {}
void Plugin::bufferSizeChanged(uint32_t) {}
void Plugin::sampleRateChanged(double) {}

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



+ 3
- 3
source/modules/distrho/src/DistrhoPluginCarla.cpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2015 Filipe Coelho <falktx@falktx.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -76,7 +76,7 @@ public:
#if DISTRHO_PLUGIN_WANT_PROGRAMS
void carla_setMidiProgram(const uint32_t realProgram)
{
fUI.programChanged(realProgram);
fUI.programLoaded(realProgram);
}
#endif

@@ -292,7 +292,7 @@ protected:

CARLA_SAFE_ASSERT_RETURN(realProgram < getMidiProgramCount(),);

fPlugin.setProgram(realProgram);
fPlugin.loadProgram(realProgram);
}
#endif



+ 41
- 37
source/modules/distrho/src/DistrhoPluginChecks.h View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2015 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
@@ -26,14 +26,6 @@
# error DISTRHO_PLUGIN_NAME undefined!
#endif

#ifndef DISTRHO_PLUGIN_HAS_UI
# error DISTRHO_PLUGIN_HAS_UI undefined!
#endif

#ifndef DISTRHO_PLUGIN_IS_SYNTH
# error DISTRHO_PLUGIN_IS_SYNTH undefined!
#endif

#ifndef DISTRHO_PLUGIN_NUM_INPUTS
# error DISTRHO_PLUGIN_NUM_INPUTS undefined!
#endif
@@ -42,51 +34,47 @@
# error DISTRHO_PLUGIN_NUM_OUTPUTS undefined!
#endif

#ifndef DISTRHO_PLUGIN_WANT_LATENCY
# error DISTRHO_PLUGIN_WANT_LATENCY undefined!
#ifndef DISTRHO_PLUGIN_URI
# error DISTRHO_PLUGIN_URI undefined!
#endif

#ifndef DISTRHO_PLUGIN_WANT_PROGRAMS
# error DISTRHO_PLUGIN_WANT_PROGRAMS undefined!
#endif
// -----------------------------------------------------------------------
// Define optional macros if not done yet

#ifndef DISTRHO_PLUGIN_WANT_STATE
# error DISTRHO_PLUGIN_WANT_STATE undefined!
#ifndef DISTRHO_PLUGIN_HAS_UI
# define DISTRHO_PLUGIN_HAS_UI 0
#endif

#ifndef DISTRHO_PLUGIN_WANT_TIMEPOS
# error DISTRHO_PLUGIN_WANT_TIMEPOS undefined!
#ifndef DISTRHO_PLUGIN_IS_RT_SAFE
# define DISTRHO_PLUGIN_IS_RT_SAFE 0
#endif

// -----------------------------------------------------------------------
// Test if synth has audio outputs

#if DISTRHO_PLUGIN_IS_SYNTH && DISTRHO_PLUGIN_NUM_OUTPUTS == 0
# error Synths need audio output to work!
#ifndef DISTRHO_PLUGIN_IS_SYNTH
# define DISTRHO_PLUGIN_IS_SYNTH 0
#endif

// -----------------------------------------------------------------------
// Enable MIDI input if synth, test if midi-input disabled when synth
#ifndef DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
# define DISTRHO_PLUGIN_WANT_DIRECT_ACCESS 0
#endif

#ifndef DISTRHO_PLUGIN_HAS_MIDI_INPUT
# define DISTRHO_PLUGIN_HAS_MIDI_INPUT DISTRHO_PLUGIN_IS_SYNTH
#elif DISTRHO_PLUGIN_IS_SYNTH && ! DISTRHO_PLUGIN_HAS_MIDI_INPUT
# error Synths need MIDI input to work!
#ifndef DISTRHO_PLUGIN_WANT_LATENCY
# define DISTRHO_PLUGIN_WANT_LATENCY 0
#endif

// -----------------------------------------------------------------------
// Define optional macros if not done yet
#ifndef DISTRHO_PLUGIN_WANT_MIDI_OUTPUT
# define DISTRHO_PLUGIN_WANT_MIDI_OUTPUT 0
#endif

#ifndef DISTRHO_PLUGIN_HAS_MIDI_OUTPUT
# define DISTRHO_PLUGIN_HAS_MIDI_OUTPUT 0
#ifndef DISTRHO_PLUGIN_WANT_PROGRAMS
# define DISTRHO_PLUGIN_WANT_PROGRAMS 0
#endif

#ifndef DISTRHO_PLUGIN_IS_RT_SAFE
# define DISTRHO_PLUGIN_IS_RT_SAFE 0
#ifndef DISTRHO_PLUGIN_WANT_STATE
# define DISTRHO_PLUGIN_WANT_STATE 0
#endif

#ifndef DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
# define DISTRHO_PLUGIN_WANT_DIRECT_ACCESS 0
#ifndef DISTRHO_PLUGIN_WANT_TIMEPOS
# define DISTRHO_PLUGIN_WANT_TIMEPOS 0
#endif

#ifndef DISTRHO_UI_USE_NANOVG
@@ -100,6 +88,22 @@
# define DISTRHO_UI_URI DISTRHO_PLUGIN_URI "#UI"
#endif

// -----------------------------------------------------------------------
// Test if synth has audio outputs

#if DISTRHO_PLUGIN_IS_SYNTH && DISTRHO_PLUGIN_NUM_OUTPUTS == 0
# error Synths need audio output to work!
#endif

// -----------------------------------------------------------------------
// Enable MIDI input if synth, test if midi-input disabled when synth

#ifndef DISTRHO_PLUGIN_WANT_MIDI_INPUT
# define DISTRHO_PLUGIN_WANT_MIDI_INPUT DISTRHO_PLUGIN_IS_SYNTH
#elif DISTRHO_PLUGIN_IS_SYNTH && ! DISTRHO_PLUGIN_WANT_MIDI_INPUT
# error Synths need MIDI input to work!
#endif

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

#endif // DISTRHO_PLUGIN_CHECKS_H_INCLUDED

+ 119
- 37
source/modules/distrho/src/DistrhoPluginInternal.hpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2015 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
@@ -38,18 +38,22 @@ extern double d_lastSampleRate;
struct Plugin::PrivateData {
bool isProcessing;

#if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0
AudioPort* audioPorts;
#endif

uint32_t parameterCount;
Parameter* parameters;

#if DISTRHO_PLUGIN_WANT_PROGRAMS
uint32_t programCount;
d_string* programNames;
uint32_t programCount;
String* programNames;
#endif

#if DISTRHO_PLUGIN_WANT_STATE
uint32_t stateCount;
d_string* stateKeys;
d_string* stateDefValues;
uint32_t stateCount;
String* stateKeys;
String* stateDefValues;
#endif

#if DISTRHO_PLUGIN_WANT_LATENCY
@@ -65,6 +69,9 @@ struct Plugin::PrivateData {

PrivateData() noexcept
: isProcessing(false),
#if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0
audioPorts(nullptr),
#endif
parameterCount(0),
parameters(nullptr),
#if DISTRHO_PLUGIN_WANT_PROGRAMS
@@ -88,6 +95,14 @@ struct Plugin::PrivateData {

~PrivateData() noexcept
{
#if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0
if (audioPorts != nullptr)
{
delete[] audioPorts;
audioPorts = nullptr;
}
#endif

if (parameters != nullptr)
{
delete[] parameters;
@@ -132,17 +147,31 @@ public:
DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,);

#if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0
{
uint32_t j=0;
# if DISTRHO_PLUGIN_NUM_INPUTS > 0
for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i, ++j)
fPlugin->initAudioPort(true, i, fData->audioPorts[j]);
# endif
# if DISTRHO_PLUGIN_NUM_OUTPUTS > 0
for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i, ++j)
fPlugin->initAudioPort(false, i, fData->audioPorts[j]);
# endif
}
#endif

for (uint32_t i=0, count=fData->parameterCount; i < count; ++i)
fPlugin->d_initParameter(i, fData->parameters[i]);
fPlugin->initParameter(i, fData->parameters[i]);

#if DISTRHO_PLUGIN_WANT_PROGRAMS
for (uint32_t i=0, count=fData->programCount; i < count; ++i)
fPlugin->d_initProgramName(i, fData->programNames[i]);
fPlugin->initProgramName(i, fData->programNames[i]);
#endif

#if DISTRHO_PLUGIN_WANT_STATE
for (uint32_t i=0, count=fData->stateCount; i < count; ++i)
fPlugin->d_initState(i, fData->stateKeys[i], fData->stateDefValues[i]);
fPlugin->initState(i, fData->stateKeys[i], fData->stateDefValues[i]);
#endif
}

@@ -157,42 +186,42 @@ public:
{
DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, "");

return fPlugin->d_getName();
return fPlugin->getName();
}

const char* getLabel() const noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, "");

return fPlugin->d_getLabel();
return fPlugin->getLabel();
}

const char* getMaker() const noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, "");

return fPlugin->d_getMaker();
return fPlugin->getMaker();
}

const char* getLicense() const noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, "");

return fPlugin->d_getLicense();
return fPlugin->getLicense();
}

uint32_t getVersion() const noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, 0);

return fPlugin->d_getVersion();
return fPlugin->getVersion();
}

long getUniqueId() const noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, 0);

return fPlugin->d_getUniqueId();
return fPlugin->getUniqueId();
}

void* getInstancePointer() const noexcept
@@ -211,6 +240,28 @@ public:
}
#endif

#if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0
const AudioPort& getAudioPort(const bool input, const uint32_t index) const noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, sFallbackAudioPort);

if (input)
{
# if DISTRHO_PLUGIN_NUM_INPUTS > 0
DISTRHO_SAFE_ASSERT_RETURN(index < DISTRHO_PLUGIN_NUM_INPUTS, sFallbackAudioPort);
# endif
}
else
{
# if DISTRHO_PLUGIN_NUM_OUTPUTS > 0
DISTRHO_SAFE_ASSERT_RETURN(index < DISTRHO_PLUGIN_NUM_OUTPUTS, sFallbackAudioPort);
# endif
}

return fData->audioPorts[index + (input ? 0 : DISTRHO_PLUGIN_NUM_INPUTS)];
}
#endif

uint32_t getParameterCount() const noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0);
@@ -230,21 +281,21 @@ public:
return (getParameterHints(index) & kParameterIsOutput);
}

const d_string& getParameterName(const uint32_t index) const noexcept
const String& getParameterName(const uint32_t index) const noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, sFallbackString);

return fData->parameters[index].name;
}

const d_string& getParameterSymbol(const uint32_t index) const noexcept
const String& getParameterSymbol(const uint32_t index) const noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, sFallbackString);

return fData->parameters[index].symbol;
}

const d_string& getParameterUnit(const uint32_t index) const noexcept
const String& getParameterUnit(const uint32_t index) const noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, sFallbackString);

@@ -263,7 +314,7 @@ public:
DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, 0.0f);
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, 0.0f);

return fPlugin->d_getParameterValue(index);
return fPlugin->getParameterValue(index);
}

void setParameterValue(const uint32_t index, const float value)
@@ -271,7 +322,7 @@ public:
DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount,);

fPlugin->d_setParameterValue(index, value);
fPlugin->setParameterValue(index, value);
}

#if DISTRHO_PLUGIN_WANT_PROGRAMS
@@ -282,19 +333,19 @@ public:
return fData->programCount;
}

const d_string& getProgramName(const uint32_t index) const noexcept
const String& getProgramName(const uint32_t index) const noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->programCount, sFallbackString);

return fData->programNames[index];
}

void setProgram(const uint32_t index)
void loadProgram(const uint32_t index)
{
DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->programCount,);

fPlugin->d_setProgram(index);
fPlugin->loadProgram(index);
}
#endif

@@ -306,14 +357,14 @@ public:
return fData->stateCount;
}

const d_string& getStateKey(const uint32_t index) const noexcept
const String& getStateKey(const uint32_t index) const noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->stateCount, sFallbackString);

return fData->stateKeys[index];
}

const d_string& getStateDefaultValue(const uint32_t index) const noexcept
const String& getStateDefaultValue(const uint32_t index) const noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->stateCount, sFallbackString);

@@ -326,7 +377,7 @@ public:
DISTRHO_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',);
DISTRHO_SAFE_ASSERT_RETURN(value != nullptr,);

fPlugin->d_setState(key, value);
fPlugin->setState(key, value);
}

bool wantStateKey(const char* const key) const noexcept
@@ -355,20 +406,38 @@ public:

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

bool isActive() const noexcept
{
return fIsActive;
}

void activate()
{
DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
DISTRHO_SAFE_ASSERT_RETURN(! fIsActive,);

fIsActive = true;
fPlugin->d_activate();
fPlugin->activate();
}

void deactivate()
{
DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
DISTRHO_SAFE_ASSERT_RETURN(fIsActive,);

fIsActive = false;
fPlugin->d_deactivate();
fPlugin->deactivate();
}

void deactivateIfNeeded()
{
DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,);

if (fIsActive)
{
fIsActive = false;
fPlugin->deactivate();
}
}

#if DISTRHO_PLUGIN_IS_SYNTH
@@ -378,8 +447,14 @@ public:
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,);
DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,);

if (! fIsActive)
{
fIsActive = true;
fPlugin->activate();
}

fData->isProcessing = true;
fPlugin->d_run(inputs, outputs, frames, midiEvents, midiEventCount);
fPlugin->run(inputs, outputs, frames, midiEvents, midiEventCount);
fData->isProcessing = false;
}
#else
@@ -388,8 +463,14 @@ public:
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,);
DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,);

if (! fIsActive)
{
fIsActive = true;
fPlugin->activate();
}

fData->isProcessing = true;
fPlugin->d_run(inputs, outputs, frames);
fPlugin->run(inputs, outputs, frames);
fData->isProcessing = false;
}
#endif
@@ -421,9 +502,9 @@ public:

if (doCallback)
{
if (fIsActive) fPlugin->d_deactivate();
fPlugin->d_bufferSizeChanged(bufferSize);
if (fIsActive) fPlugin->d_activate();
if (fIsActive) fPlugin->deactivate();
fPlugin->bufferSizeChanged(bufferSize);
if (fIsActive) fPlugin->activate();
}
}

@@ -440,9 +521,9 @@ public:

if (doCallback)
{
if (fIsActive) fPlugin->d_deactivate();
fPlugin->d_sampleRateChanged(sampleRate);
if (fIsActive) fPlugin->d_activate();
if (fIsActive) fPlugin->deactivate();
fPlugin->sampleRateChanged(sampleRate);
if (fIsActive) fPlugin->activate();
}
}

@@ -457,7 +538,8 @@ private:
// -------------------------------------------------------------------
// Static fallback data, see DistrhoPlugin.cpp

static const d_string sFallbackString;
static const String sFallbackString;
static const AudioPort sFallbackAudioPort;
static const ParameterRanges sFallbackRanges;

DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PluginExporter)


+ 97
- 8
source/modules/distrho/src/DistrhoPluginJack.cpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2015 Filipe Coelho <falktx@falktx.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -16,32 +16,91 @@

#include "DistrhoPluginInternal.hpp"

#if ! DISTRHO_PLUGIN_HAS_UI
# error JACK export requires an UI
#if DISTRHO_PLUGIN_HAS_UI && ! defined(HAVE_DGL)
# undef DISTRHO_PLUGIN_HAS_UI
# define DISTRHO_PLUGIN_HAS_UI 0
#endif

#include "DistrhoUIInternal.hpp"
#if DISTRHO_PLUGIN_HAS_UI
# include "DistrhoUIInternal.hpp"
#else
# include "../extra/Sleep.hpp"
#endif

#include "jack/jack.h"
#include "jack/midiport.h"
#include "jack/transport.h"

#ifndef DISTRHO_OS_WINDOWS
# include <signal.h>
#endif

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

START_NAMESPACE_DISTRHO

#if ! DISTRHO_PLUGIN_WANT_STATE
#if DISTRHO_PLUGIN_HAS_UI && ! DISTRHO_PLUGIN_WANT_STATE
static const setStateFunc setStateCallback = nullptr;
#endif

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

static volatile bool gCloseSignalReceived = false;

#ifdef DISTRHO_OS_WINDOWS
static BOOL WINAPI winSignalHandler(DWORD dwCtrlType) noexcept
{
if (dwCtrlType == CTRL_C_EVENT)
{
gCloseSignalReceived = true;
return TRUE;
}
return FALSE;
}

static void initSignalHandler()
{
SetConsoleCtrlHandler(winSignalHandler, TRUE);
}
#else
static void closeSignalHandler(int) noexcept
{
gCloseSignalReceived = true;
}

static void initSignalHandler()
{
struct sigaction sint;
struct sigaction sterm;

sint.sa_handler = closeSignalHandler;
sint.sa_flags = SA_RESTART;
sint.sa_restorer = nullptr;
sigemptyset(&sint.sa_mask);
sigaction(SIGINT, &sint, nullptr);

sterm.sa_handler = closeSignalHandler;
sterm.sa_flags = SA_RESTART;
sterm.sa_restorer = nullptr;
sigemptyset(&sterm.sa_mask);
sigaction(SIGTERM, &sterm, nullptr);
}
#endif

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

#if DISTRHO_PLUGIN_HAS_UI
class PluginJack : public IdleCallback
#else
class PluginJack
#endif
{
public:
PluginJack(jack_client_t* const client)
: fPlugin(),
#if DISTRHO_PLUGIN_HAS_UI
fUI(this, 0, nullptr, setParameterValueCallback, setStateCallback, nullptr, setSizeCallback, fPlugin.getInstancePointer()),
#endif
fClient(client)
{
char strBuf[0xff+1];
@@ -70,8 +129,10 @@ public:
#if DISTRHO_PLUGIN_WANT_PROGRAMS
if (fPlugin.getProgramCount() > 0)
{
fPlugin.setProgram(0);
fUI.programChanged(0);
fPlugin.loadProgram(0);
# if DISTRHO_PLUGIN_HAS_UI
fUI.programLoaded(0);
# endif
}
#endif

@@ -88,7 +149,9 @@ public:
else
{
fLastOutputValues[i] = 0.0f;
# if DISTRHO_PLUGIN_HAS_UI
fUI.parameterChanged(i, fPlugin.getParameterValue(i));
# endif
}
}
}
@@ -102,14 +165,21 @@ public:
jack_set_process_callback(fClient, jackProcessCallback, this);
jack_on_shutdown(fClient, jackShutdownCallback, this);

fPlugin.activate();

jack_activate(fClient);

#if DISTRHO_PLUGIN_HAS_UI
if (const char* const name = jack_get_client_name(fClient))
fUI.setWindowTitle(name);
else
fUI.setWindowTitle(fPlugin.getName());

fUI.exec(this);
#else
while (! gCloseSignalReceived)
d_sleep(1);
#endif
}

~PluginJack()
@@ -119,6 +189,8 @@ public:

jack_deactivate(fClient);

fPlugin.deactivate();

#if DISTRHO_PLUGIN_IS_SYNTH
jack_port_unregister(fClient, fPortMidiIn);
fPortMidiIn = nullptr;
@@ -146,8 +218,12 @@ public:
// -------------------------------------------------------------------

protected:
#if DISTRHO_PLUGIN_HAS_UI
void idleCallback() override
{
if (gCloseSignalReceived)
return fUI.quit();

float value;

for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i)
@@ -166,6 +242,7 @@ protected:

fUI.exec_idle();
}
#endif

void jackBufferSize(const jack_nframes_t nframes)
{
@@ -273,7 +350,9 @@ protected:
{
d_stderr("jack has shutdown, quitting now...");
fClient = nullptr;
#if DISTRHO_PLUGIN_HAS_UI
fUI.quit();
#endif
}

// -------------------------------------------------------------------
@@ -290,16 +369,20 @@ protected:
}
#endif

#if DISTRHO_PLUGIN_HAS_UI
void setSize(const uint width, const uint height)
{
fUI.setWindowSize(width, height);
}
#endif

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

private:
PluginExporter fPlugin;
#if DISTRHO_PLUGIN_HAS_UI
UIExporter fUI;
#endif

jack_client_t* fClient;

@@ -359,10 +442,12 @@ private:
}
#endif

#if DISTRHO_PLUGIN_HAS_UI
static void setSizeCallback(void* ptr, uint width, uint height)
{
uiPtr->setSize(width, height);
}
#endif

#undef uiPtr
};
@@ -380,7 +465,7 @@ int main()

if (client == nullptr)
{
d_string errorString;
String errorString;

if (status & JackFailure)
errorString += "Overall operation failed;\n";
@@ -422,9 +507,13 @@ int main()

USE_NAMESPACE_DISTRHO;

initSignalHandler();

d_lastBufferSize = jack_get_buffer_size(client);
d_lastSampleRate = jack_get_sample_rate(client);
#if DISTRHO_PLUGIN_HAS_UI
d_lastUiSampleRate = d_lastSampleRate;
#endif

const PluginJack p(client);



+ 12
- 14
source/modules/distrho/src/DistrhoPluginLADSPA+DSSI.cpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2015 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
@@ -16,7 +16,7 @@

#include "DistrhoPluginInternal.hpp"

#if DISTRHO_PLUGIN_HAS_MIDI_OUTPUT
#if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT
# error Cannot use MIDI Output with LADSPA or DSSI
#endif

@@ -24,7 +24,7 @@
# include "dssi/dssi.h"
#else
# include "ladspa/ladspa.h"
# if DISTRHO_PLUGIN_HAS_MIDI_INPUT
# if DISTRHO_PLUGIN_WANT_MIDI_INPUT
# error Cannot use MIDI with LADSPA
# endif
# if DISTRHO_PLUGIN_WANT_STATE
@@ -190,7 +190,7 @@ public:
}
}

#if DISTRHO_PLUGIN_HAS_MIDI_INPUT
#if DISTRHO_PLUGIN_WANT_MIDI_INPUT
// Get MIDI Events
uint32_t midiEventCount = 0;
MidiEvent midiEvents[eventCount];
@@ -271,7 +271,7 @@ public:

updateParameterOutputs();

#if defined(DISTRHO_PLUGIN_TARGET_DSSI) && ! DISTRHO_PLUGIN_HAS_MIDI_INPUT
#if defined(DISTRHO_PLUGIN_TARGET_DSSI) && ! DISTRHO_PLUGIN_WANT_MIDI_INPUT
return; // unused
(void)events; (void)eventCount;
#endif
@@ -314,7 +314,7 @@ public:

DISTRHO_SAFE_ASSERT_RETURN(realProgram < fPlugin.getProgramCount(),);

fPlugin.setProgram(realProgram);
fPlugin.loadProgram(realProgram);

// Update control inputs
for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i)
@@ -435,7 +435,7 @@ static void dssi_select_program(LADSPA_Handle instance, ulong bank, ulong progra
}
# endif

# if DISTRHO_PLUGIN_HAS_MIDI_INPUT
# if DISTRHO_PLUGIN_WANT_MIDI_INPUT
static void dssi_run_synth(LADSPA_Handle instance, ulong sampleCount, snd_seq_event_t* events, ulong eventCount)
{
instancePtr->dssi_run_synth(sampleCount, events, eventCount);
@@ -490,7 +490,7 @@ static DSSI_Descriptor sDssiDescriptor = {
/* select_program */ nullptr,
# endif
/* get_midi_controller_for_port */ nullptr,
# if DISTRHO_PLUGIN_HAS_MIDI_INPUT
# if DISTRHO_PLUGIN_WANT_MIDI_INPUT
dssi_run_synth,
# else
/* run_synth */ nullptr,
@@ -530,10 +530,9 @@ public:
#if DISTRHO_PLUGIN_NUM_INPUTS > 0
for (ulong i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i, ++port)
{
char portName[24] = { '\0' };
std::sprintf(portName, "Audio Input %lu", i+1);
const AudioPort& aport(plugin.getAudioPort(true, i));

portNames[port] = strdup(portName);
portNames[port] = strdup(aport.name);
portDescriptors[port] = LADSPA_PORT_AUDIO | LADSPA_PORT_INPUT;

portRangeHints[port].HintDescriptor = 0x0;
@@ -545,10 +544,9 @@ public:
#if DISTRHO_PLUGIN_NUM_OUTPUTS > 0
for (ulong i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i, ++port)
{
char portName[24] = { '\0' };
std::sprintf(portName, "Audio Output %lu", i+1);
const AudioPort& aport(plugin.getAudioPort(false, i));

portNames[port] = strdup(portName);
portNames[port] = strdup(aport.name);
portDescriptors[port] = LADSPA_PORT_AUDIO | LADSPA_PORT_OUTPUT;

portRangeHints[port].HintDescriptor = 0x0;


+ 185
- 119
source/modules/distrho/src/DistrhoPluginLV2.cpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2015 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
@@ -40,16 +40,12 @@
# error DISTRHO_PLUGIN_URI undefined!
#endif

#if DISTRHO_PLUGIN_WANT_TIMEPOS
# warning LV2 TimePos still TODO
#endif

#define DISTRHO_LV2_USE_EVENTS_IN (DISTRHO_PLUGIN_HAS_MIDI_INPUT || DISTRHO_PLUGIN_WANT_TIMEPOS || (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI))
#define DISTRHO_LV2_USE_EVENTS_OUT (DISTRHO_PLUGIN_HAS_MIDI_OUTPUT || (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI))
#define DISTRHO_LV2_USE_EVENTS_IN (DISTRHO_PLUGIN_WANT_MIDI_INPUT || DISTRHO_PLUGIN_WANT_TIMEPOS || (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI))
#define DISTRHO_LV2_USE_EVENTS_OUT (DISTRHO_PLUGIN_WANT_MIDI_OUTPUT || (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI))

START_NAMESPACE_DISTRHO

typedef std::map<const d_string,d_string> StringMap;
typedef std::map<const String, String> StringMap;

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

@@ -61,9 +57,6 @@ public:
fLastControlValues(nullptr),
fSampleRate(sampleRate),
#if DISTRHO_LV2_USE_EVENTS_IN || DISTRHO_LV2_USE_EVENTS_OUT
# if DISTRHO_PLUGIN_WANT_TIMEPOS
fLastTimeSpeed(0.0),
# endif
fURIDs(uridMap),
#endif
fUridMap(uridMap),
@@ -119,8 +112,8 @@ public:
{
fNeededUiSends[i] = false;

const d_string& d_key(fPlugin.getStateKey(i));
fStateMap[d_key] = fPlugin.getStateDefaultValue(i);
const String& dkey(fPlugin.getStateKey(i));
fStateMap[dkey] = fPlugin.getStateDefaultValue(i);
}
}
else
@@ -133,8 +126,7 @@ public:
#endif

#if DISTRHO_PLUGIN_WANT_TIMEPOS
// hosts may not send all values, resulting on some invalid ones
fTimePosition.bbt.valid = false;
// hosts may not send all values, resulting on some invalid data
fTimePosition.bbt.bar = 1;
fTimePosition.bbt.beat = 1;
fTimePosition.bbt.tick = 0;
@@ -271,7 +263,7 @@ public:
}

#if DISTRHO_LV2_USE_EVENTS_IN
# if DISTRHO_PLUGIN_HAS_MIDI_INPUT
# if DISTRHO_PLUGIN_WANT_MIDI_INPUT
uint32_t midiEventCount = 0;
# endif
LV2_ATOM_SEQUENCE_FOREACH(fPortEventsIn, event)
@@ -279,7 +271,7 @@ public:
if (event == nullptr)
break;

# if DISTRHO_PLUGIN_HAS_MIDI_INPUT
# if DISTRHO_PLUGIN_WANT_MIDI_INPUT
if (event->body.type == fURIDs.midiEvent)
{
if (midiEventCount >= kMaxMidiEvents)
@@ -311,142 +303,178 @@ public:

LV2_Atom* bar = nullptr;
LV2_Atom* barBeat = nullptr;
LV2_Atom* beat = nullptr;
LV2_Atom* beatUnit = nullptr;
LV2_Atom* beatsPerBar = nullptr;
LV2_Atom* beatsPerMinute = nullptr;
LV2_Atom* ticksPerBeat = nullptr;
LV2_Atom* frame = nullptr;
LV2_Atom* speed = nullptr;
LV2_Atom* ticksPerBeat = nullptr;

lv2_atom_object_get(obj,
fURIDs.timeBar, &bar,
fURIDs.timeBarBeat, &barBeat,
fURIDs.timeBeat, &beat,
fURIDs.timeBeatUnit, &beatUnit,
fURIDs.timeBeatsPerBar, &beatsPerBar,
fURIDs.timeBeatsPerMinute, &beatsPerMinute,
fURIDs.timeTicksPerBeat, &ticksPerBeat,
fURIDs.timeFrame, &frame,
fURIDs.timeSpeed, &speed,
fURIDs.timeTicksPerBeat, &ticksPerBeat,
nullptr);

// need to handle this first as other values depend on it
if (ticksPerBeat != nullptr)
{
/**/ if (ticksPerBeat->type == fURIDs.atomDouble)
fLastPositionData.ticksPerBeat = ((LV2_Atom_Double*)ticksPerBeat)->body;
else if (ticksPerBeat->type == fURIDs.atomFloat)
fLastPositionData.ticksPerBeat = ((LV2_Atom_Float*)ticksPerBeat)->body;
else if (ticksPerBeat->type == fURIDs.atomInt)
fLastPositionData.ticksPerBeat = ((LV2_Atom_Int*)ticksPerBeat)->body;
else if (ticksPerBeat->type == fURIDs.atomLong)
fLastPositionData.ticksPerBeat = ((LV2_Atom_Long*)ticksPerBeat)->body;
else
d_stderr("Unknown lv2 ticksPerBeat value type");

if (fLastPositionData.ticksPerBeat > 0)
fTimePosition.bbt.ticksPerBeat = fLastPositionData.ticksPerBeat;
}

// same
if (speed != nullptr)
{
/**/ if (speed->type == fURIDs.atomDouble)
fLastPositionData.speed = ((LV2_Atom_Double*)speed)->body;
else if (speed->type == fURIDs.atomFloat)
fLastPositionData.speed = ((LV2_Atom_Float*)speed)->body;
else if (speed->type == fURIDs.atomInt)
fLastPositionData.speed = ((LV2_Atom_Int*)speed)->body;
else if (speed->type == fURIDs.atomLong)
fLastPositionData.speed = ((LV2_Atom_Long*)speed)->body;
else
d_stderr("Unknown lv2 speed value type");

fTimePosition.playing = d_isNotZero(fLastPositionData.speed);
}

if (bar != nullptr)
{
/**/ if (bar->type == fURIDs.atomDouble)
fTimePosition.bbt.bar = ((LV2_Atom_Double*)bar)->body + 1.0;
fLastPositionData.bar = ((LV2_Atom_Double*)bar)->body;
else if (bar->type == fURIDs.atomFloat)
fTimePosition.bbt.bar = ((LV2_Atom_Float*)bar)->body + 1.0f;
fLastPositionData.bar = ((LV2_Atom_Float*)bar)->body;
else if (bar->type == fURIDs.atomInt)
fTimePosition.bbt.bar = ((LV2_Atom_Int*)bar)->body + 1;
fLastPositionData.bar = ((LV2_Atom_Int*)bar)->body;
else if (bar->type == fURIDs.atomLong)
fTimePosition.bbt.bar = ((LV2_Atom_Long*)bar)->body + 1;
fLastPositionData.bar = ((LV2_Atom_Long*)bar)->body;
else
d_stderr("Unknown lv2 bar value type");
}

if (ticksPerBeat != nullptr)
{
/**/ if (ticksPerBeat->type == fURIDs.atomDouble)
fTimePosition.bbt.ticksPerBeat = ((LV2_Atom_Double*)ticksPerBeat)->body;
else if (ticksPerBeat->type == fURIDs.atomFloat)
fTimePosition.bbt.ticksPerBeat = ((LV2_Atom_Float*)ticksPerBeat)->body;
else if (ticksPerBeat->type == fURIDs.atomInt)
fTimePosition.bbt.ticksPerBeat = ((LV2_Atom_Int*)ticksPerBeat)->body;
else if (ticksPerBeat->type == fURIDs.atomLong)
fTimePosition.bbt.ticksPerBeat = ((LV2_Atom_Long*)ticksPerBeat)->body;
else
d_stderr("Unknown lv2 ticksPerBeat value type");
if (fLastPositionData.bar >= 0)
fTimePosition.bbt.bar = fLastPositionData.bar + 1;
}

if (barBeat != nullptr)
{
double barBeatValue = 0.0;

/**/ if (barBeat->type == fURIDs.atomDouble)
barBeatValue = ((LV2_Atom_Double*)barBeat)->body;
fLastPositionData.barBeat = ((LV2_Atom_Double*)barBeat)->body;
else if (barBeat->type == fURIDs.atomFloat)
barBeatValue = ((LV2_Atom_Float*)barBeat)->body;
fLastPositionData.barBeat = ((LV2_Atom_Float*)barBeat)->body;
else if (barBeat->type == fURIDs.atomInt)
barBeatValue = ((LV2_Atom_Int*)barBeat)->body;
fLastPositionData.barBeat = ((LV2_Atom_Int*)barBeat)->body;
else if (barBeat->type == fURIDs.atomLong)
barBeatValue = ((LV2_Atom_Long*)barBeat)->body;
fLastPositionData.barBeat = ((LV2_Atom_Long*)barBeat)->body;
else
d_stderr("Unknown lv2 barBeat value type");

const double rest = std::fmod(barBeatValue, 1.0);
fTimePosition.bbt.beat = barBeatValue-rest+1.0;
fTimePosition.bbt.tick = rest*fTimePosition.bbt.ticksPerBeat+0.5;
}
// barBeat includes beat
else if (beat != nullptr)
{
/**/ if (beat->type == fURIDs.atomDouble)
fTimePosition.bbt.beat = ((LV2_Atom_Double*)beat)->body + 1.0;
else if (beat->type == fURIDs.atomFloat)
fTimePosition.bbt.beat = ((LV2_Atom_Float*)beat)->body + 1.0f;
else if (beat->type == fURIDs.atomInt)
fTimePosition.bbt.beat = ((LV2_Atom_Int*)beat)->body + 1;
else if (beat->type == fURIDs.atomLong)
fTimePosition.bbt.beat = ((LV2_Atom_Long*)beat)->body + 1;
else
d_stderr("Unknown lv2 beat value type");
if (fLastPositionData.barBeat >= 0.0f)
{
const double rest = std::fmod(fLastPositionData.barBeat, 1.0);
fTimePosition.bbt.beat = fLastPositionData.barBeat-rest+1.0;
fTimePosition.bbt.tick = rest*fTimePosition.bbt.ticksPerBeat+0.5;
}
}

if (beatUnit != nullptr)
{
/**/ if (beatUnit->type == fURIDs.atomDouble)
fTimePosition.bbt.beatType = ((LV2_Atom_Double*)beatUnit)->body;
fLastPositionData.beatUnit = ((LV2_Atom_Double*)beatUnit)->body;
else if (beatUnit->type == fURIDs.atomFloat)
fTimePosition.bbt.beatType = ((LV2_Atom_Float*)beatUnit)->body;
fLastPositionData.beatUnit = ((LV2_Atom_Float*)beatUnit)->body;
else if (beatUnit->type == fURIDs.atomInt)
fTimePosition.bbt.beatType = ((LV2_Atom_Int*)beatUnit)->body;
fLastPositionData.beatUnit = ((LV2_Atom_Int*)beatUnit)->body;
else if (beatUnit->type == fURIDs.atomLong)
fTimePosition.bbt.beatType = ((LV2_Atom_Long*)beatUnit)->body;
fLastPositionData.beatUnit = ((LV2_Atom_Long*)beatUnit)->body;
else
d_stderr("Unknown lv2 beatUnit value type");

if (fLastPositionData.beatUnit > 0)
fTimePosition.bbt.beatType = fLastPositionData.beatUnit;
}

if (beatsPerBar != nullptr)
{
/**/ if (beatsPerBar->type == fURIDs.atomDouble)
fTimePosition.bbt.beatsPerBar = ((LV2_Atom_Double*)beatsPerBar)->body;
fLastPositionData.beatsPerBar = ((LV2_Atom_Double*)beatsPerBar)->body;
else if (beatsPerBar->type == fURIDs.atomFloat)
fTimePosition.bbt.beatsPerBar = ((LV2_Atom_Float*)beatsPerBar)->body;
fLastPositionData.beatsPerBar = ((LV2_Atom_Float*)beatsPerBar)->body;
else if (beatsPerBar->type == fURIDs.atomInt)
fTimePosition.bbt.beatsPerBar = ((LV2_Atom_Int*)beatsPerBar)->body;
fLastPositionData.beatsPerBar = ((LV2_Atom_Int*)beatsPerBar)->body;
else if (beatsPerBar->type == fURIDs.atomLong)
fTimePosition.bbt.beatsPerBar = ((LV2_Atom_Long*)beatsPerBar)->body;
fLastPositionData.beatsPerBar = ((LV2_Atom_Long*)beatsPerBar)->body;
else
d_stderr("Unknown lv2 beatsPerBar value type");

if (fLastPositionData.beatsPerBar > 0.0f)
fTimePosition.bbt.beatsPerBar = fLastPositionData.beatsPerBar;
}

if (beatsPerMinute != nullptr)
{
/**/ if (beatsPerMinute->type == fURIDs.atomDouble)
fTimePosition.bbt.beatsPerMinute = ((LV2_Atom_Double*)beatsPerMinute)->body;
fLastPositionData.beatsPerMinute = ((LV2_Atom_Double*)beatsPerMinute)->body;
else if (beatsPerMinute->type == fURIDs.atomFloat)
fTimePosition.bbt.beatsPerMinute = ((LV2_Atom_Float*)beatsPerMinute)->body;
fLastPositionData.beatsPerMinute = ((LV2_Atom_Float*)beatsPerMinute)->body;
else if (beatsPerMinute->type == fURIDs.atomInt)
fTimePosition.bbt.beatsPerMinute = ((LV2_Atom_Int*)beatsPerMinute)->body;
fLastPositionData.beatsPerMinute = ((LV2_Atom_Int*)beatsPerMinute)->body;
else if (beatsPerMinute->type == fURIDs.atomLong)
fTimePosition.bbt.beatsPerMinute = ((LV2_Atom_Long*)beatsPerMinute)->body;
fLastPositionData.beatsPerMinute = ((LV2_Atom_Long*)beatsPerMinute)->body;
else
d_stderr("Unknown lv2 beatsPerMinute value type");
}

fTimePosition.bbt.barStartTick = fTimePosition.bbt.ticksPerBeat*fTimePosition.bbt.beatsPerBar*(fTimePosition.bbt.bar-1);
if (fLastPositionData.beatsPerMinute > 0.0f)
{
fTimePosition.bbt.beatsPerMinute = fLastPositionData.beatsPerMinute;

if (frame != nullptr && frame->type == fURIDs.atomLong)
fTimePosition.frame = ((LV2_Atom_Long*)frame)->body;
if (d_isNotZero(fLastPositionData.speed))
fTimePosition.bbt.beatsPerMinute *= std::abs(fLastPositionData.speed);
}
}

if (speed != nullptr && speed->type == fURIDs.atomFloat)
if (frame != nullptr)
{
fLastTimeSpeed = ((LV2_Atom_Float*)speed)->body;
fTimePosition.playing = (fLastTimeSpeed == 1.0);
/**/ if (frame->type == fURIDs.atomDouble)
fLastPositionData.frame = ((LV2_Atom_Double*)frame)->body;
else if (frame->type == fURIDs.atomFloat)
fLastPositionData.frame = ((LV2_Atom_Float*)frame)->body;
else if (frame->type == fURIDs.atomInt)
fLastPositionData.frame = ((LV2_Atom_Int*)frame)->body;
else if (frame->type == fURIDs.atomLong)
fLastPositionData.frame = ((LV2_Atom_Long*)frame)->body;
else
d_stderr("Unknown lv2 frame value type");

if (fLastPositionData.frame >= 0)
fTimePosition.frame = fLastPositionData.frame;
}

fTimePosition.bbt.valid = (beatsPerMinute != nullptr && beatsPerBar != nullptr && beatUnit != nullptr);
fTimePosition.bbt.barStartTick = fTimePosition.bbt.ticksPerBeat*
fTimePosition.bbt.beatsPerBar*
(fTimePosition.bbt.bar-1);

fTimePosition.bbt.valid = (fLastPositionData.beatsPerMinute > 0.0 &&
fLastPositionData.beatUnit > 0 &&
fLastPositionData.beatsPerBar > 0.0f);

continue;
}
# endif
@@ -477,7 +505,7 @@ public:
fPlugin.setTimePosition(fTimePosition);
# endif

#if DISTRHO_PLUGIN_HAS_MIDI_INPUT
#if DISTRHO_PLUGIN_WANT_MIDI_INPUT
fPlugin.run(fPortAudioIns, fPortAudioOuts, sampleCount, fMidiEvents, midiEventCount);
#else
fPlugin.run(fPortAudioIns, fPortAudioOuts, sampleCount);
@@ -485,37 +513,56 @@ public:

# if DISTRHO_PLUGIN_WANT_TIMEPOS
// update timePos for next callback
if (fLastTimeSpeed != 0.0)
if (d_isNotZero(fLastPositionData.speed))
{
const double newFrames = fLastTimeSpeed*sampleCount;
if (fLastPositionData.speed > 0.0)
{
// playing forwards
fLastPositionData.frame += sampleCount;
}
else
{
// playing backwards
fLastPositionData.frame -= sampleCount;

fTimePosition.frame += newFrames;
if (fLastPositionData.frame < 0)
fLastPositionData.frame = 0;
}

fTimePosition.frame = fLastPositionData.frame;

if (fTimePosition.bbt.valid)
{
const double samplesPerBeat = 60.0 / fTimePosition.bbt.beatsPerMinute * fSampleRate;
const double ticksPerSample = fTimePosition.bbt.ticksPerBeat / samplesPerBeat;
const double beatsPerMinute = fLastPositionData.beatsPerMinute * fLastPositionData.speed;
const double framesPerBeat = 60.0 * fSampleRate / beatsPerMinute;
const double addedBarBeats = double(sampleCount) / framesPerBeat;

double newTickPos = double(fTimePosition.bbt.tick) + ticksPerSample*newFrames;
double newBeatPos = double(fTimePosition.bbt.beat)-1.0;
double newBarPos = double(fTimePosition.bbt.bar)-1.0;

for (; newTickPos >= fTimePosition.bbt.ticksPerBeat;)
if (fLastPositionData.barBeat >= 0.0f)
{
++newBeatPos;
newTickPos -= fTimePosition.bbt.ticksPerBeat;
}
fLastPositionData.barBeat = std::fmod(fLastPositionData.barBeat+addedBarBeats,
fLastPositionData.beatsPerBar);

for (; newBeatPos >= fTimePosition.bbt.beatsPerBar;)
{
++newBarPos;
newBeatPos -= fTimePosition.bbt.beatsPerBar;
const double rest = std::fmod(fLastPositionData.barBeat, 1.0);
fTimePosition.bbt.beat = fLastPositionData.barBeat-rest+1.0;
fTimePosition.bbt.tick = rest*fTimePosition.bbt.ticksPerBeat+0.5;

if (fLastPositionData.bar >= 0)
{
fLastPositionData.bar += std::floor((fLastPositionData.barBeat+addedBarBeats)/
fLastPositionData.beatsPerBar);

if (fLastPositionData.bar < 0)
fLastPositionData.bar = 0;

fTimePosition.bbt.bar = fLastPositionData.bar + 1;

fTimePosition.bbt.barStartTick = fTimePosition.bbt.ticksPerBeat*
fTimePosition.bbt.beatsPerBar*
(fTimePosition.bbt.bar-1);
}
}

fTimePosition.bbt.bar = newBarPos+1.0;
fTimePosition.bbt.beat = newBeatPos+1.0;
fTimePosition.bbt.tick = newTickPos;
fTimePosition.bbt.barStartTick = fTimePosition.bbt.ticksPerBeat*fTimePosition.bbt.beatsPerBar*(fTimePosition.bbt.bar-1);
fTimePosition.bbt.beatsPerMinute = std::abs(beatsPerMinute);
}
}
# endif
@@ -529,7 +576,7 @@ public:
uint32_t size, offset = 0;
LV2_Atom_Event* aev;

# if DISTRHO_PLUGIN_HAS_MIDI_OUTPUT
# if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT
// TODO
# endif
# if (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI)
@@ -538,16 +585,16 @@ public:
if (! fNeededUiSends[i])
continue;

const d_string& key = fPlugin.getStateKey(i);
const String& key = fPlugin.getStateKey(i);

for (StringMap::const_iterator cit=fStateMap.begin(), cite=fStateMap.end(); cit != cite; ++cit)
{
const d_string& curKey = cit->first;
const String& curKey = cit->first;

if (curKey != key)
continue;

const d_string& value = cit->second;
const String& value = cit->second;

// set msg size (key + value + separator + 2x null terminator)
const size_t msgSize(key.length()+value.length()+3);
@@ -661,7 +708,7 @@ public:
if (realProgram >= fPlugin.getProgramCount())
return;

fPlugin.setProgram(realProgram);
fPlugin.loadProgram(realProgram);

// Update control inputs
for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i)
@@ -684,10 +731,10 @@ public:
{
for (StringMap::const_iterator cit=fStateMap.begin(), cite=fStateMap.end(); cit != cite; ++cit)
{
const d_string& key = cit->first;
const d_string& value = cit->second;
const String& key = cit->first;
const String& value = cit->second;

const d_string urnKey("urn:distrho:" + key);
const String urnKey("urn:distrho:" + key);

// some hosts need +1 for the null terminator, even though the type is string
store(handle, fUridMap->map(fUridMap->handle, urnKey.buffer()), value.buffer(), value.length()+1, fURIDs.atomString, LV2_STATE_IS_POD|LV2_STATE_IS_PORTABLE);
@@ -703,8 +750,8 @@ public:

for (uint32_t i=0, count=fPlugin.getStateCount(); i < count; ++i)
{
const d_string& key(fPlugin.getStateKey(i));
const d_string urnKey("urn:distrho:" + key);
const String& key(fPlugin.getStateKey(i));
const String urnKey("urn:distrho:" + key);

size = 0;
type = 0;
@@ -783,12 +830,33 @@ private:
// Temporary data
float* fLastControlValues;
double fSampleRate;
#if DISTRHO_PLUGIN_HAS_MIDI_INPUT
#if DISTRHO_PLUGIN_WANT_MIDI_INPUT
MidiEvent fMidiEvents[kMaxMidiEvents];
#endif
#if DISTRHO_PLUGIN_WANT_TIMEPOS
TimePosition fTimePosition;
double fLastTimeSpeed;

struct Lv2PositionData {
int64_t bar;
float barBeat;
uint32_t beatUnit;
float beatsPerBar;
float beatsPerMinute;
int64_t frame;
double speed;
int64_t ticksPerBeat;

Lv2PositionData()
: bar(-1),
barBeat(-1.0f),
beatUnit(0),
beatsPerBar(0.0f),
beatsPerMinute(0.0f),
frame(-1),
speed(0.0),
ticksPerBeat(-1) {}

} fLastPositionData;
#endif

// LV2 URIDs
@@ -807,7 +875,6 @@ private:
LV2_URID timePosition;
LV2_URID timeBar;
LV2_URID timeBarBeat;
LV2_URID timeBeat;
LV2_URID timeBeatUnit;
LV2_URID timeBeatsPerBar;
LV2_URID timeBeatsPerMinute;
@@ -829,7 +896,6 @@ private:
timePosition(uridMap->map(uridMap->handle, LV2_TIME__Position)),
timeBar(uridMap->map(uridMap->handle, LV2_TIME__bar)),
timeBarBeat(uridMap->map(uridMap->handle, LV2_TIME__barBeat)),
timeBeat(uridMap->map(uridMap->handle, LV2_TIME__beat)),
timeBeatUnit(uridMap->map(uridMap->handle, LV2_TIME__beatUnit)),
timeBeatsPerBar(uridMap->map(uridMap->handle, LV2_TIME__beatsPerBar)),
timeBeatsPerMinute(uridMap->map(uridMap->handle, LV2_TIME__beatsPerMinute)),
@@ -858,9 +924,9 @@ private:
// check if key already exists
for (StringMap::iterator it=fStateMap.begin(), ite=fStateMap.end(); it != ite; ++it)
{
const d_string& d_key(it->first);
const String& dkey(it->first);

if (d_key == key)
if (dkey == key)
{
it->second = newValue;
return;


+ 241
- 60
source/modules/distrho/src/DistrhoPluginLV2export.cpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2015 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
@@ -23,6 +23,7 @@
#include "lv2/midi.h"
#include "lv2/options.h"
#include "lv2/port-props.h"
#include "lv2/presets.h"
#include "lv2/resize-port.h"
#include "lv2/state.h"
#include "lv2/time.h"
@@ -49,8 +50,20 @@
# define DISTRHO_PLUGIN_HAS_UI 0
#endif

#define DISTRHO_LV2_USE_EVENTS_IN (DISTRHO_PLUGIN_HAS_MIDI_INPUT || DISTRHO_PLUGIN_WANT_TIMEPOS || (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI))
#define DISTRHO_LV2_USE_EVENTS_OUT (DISTRHO_PLUGIN_HAS_MIDI_OUTPUT || (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI))
#if DISTRHO_PLUGIN_HAS_UI
# if DISTRHO_OS_HAIKU
# define DISTRHO_LV2_UI_TYPE "BeUI"
# elif DISTRHO_OS_MAC
# define DISTRHO_LV2_UI_TYPE "CocoaUI"
# elif DISTRHO_OS_WINDOWS
# define DISTRHO_LV2_UI_TYPE "WindowsUI"
# else
# define DISTRHO_LV2_UI_TYPE "X11UI"
# endif
#endif

#define DISTRHO_LV2_USE_EVENTS_IN (DISTRHO_PLUGIN_WANT_MIDI_INPUT || DISTRHO_PLUGIN_WANT_TIMEPOS || (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI))
#define DISTRHO_LV2_USE_EVENTS_OUT (DISTRHO_PLUGIN_WANT_MIDI_OUTPUT || (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI))

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

@@ -66,8 +79,17 @@ void lv2_generate_ttl(const char* const basename)
d_lastBufferSize = 0;
d_lastSampleRate = 0.0;

d_string pluginDLL(basename);
d_string pluginTTL(pluginDLL + ".ttl");
String pluginDLL(basename);
String pluginTTL(pluginDLL + ".ttl");

#if DISTRHO_PLUGIN_HAS_UI
String pluginUI(pluginDLL);
# if ! DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
pluginUI.truncate(pluginDLL.rfind("_dsp"));
pluginUI += "_ui";
const String uiTTL(pluginUI + ".ttl");
# endif
#endif

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

@@ -75,9 +97,12 @@ void lv2_generate_ttl(const char* const basename)
std::cout << "Writing manifest.ttl..."; std::cout.flush();
std::fstream manifestFile("manifest.ttl", std::ios::out);

d_string manifestString;
String manifestString;
manifestString += "@prefix lv2: <" LV2_CORE_PREFIX "> .\n";
manifestString += "@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n";
#if DISTRHO_PLUGIN_WANT_PROGRAMS
manifestString += "@prefix pset: <" LV2_PRESETS_PREFIX "> .\n";
#endif
#if DISTRHO_PLUGIN_HAS_UI
manifestString += "@prefix ui: <" LV2_UI_PREFIX "> .\n";
#endif
@@ -91,42 +116,49 @@ void lv2_generate_ttl(const char* const basename)

#if DISTRHO_PLUGIN_HAS_UI
manifestString += "<" DISTRHO_UI_URI ">\n";
# if DISTRHO_OS_HAIKU
manifestString += " a ui:BeUI ;\n";
# elif DISTRHO_OS_MAC
manifestString += " a ui:CocoaUI ;\n";
# elif DISTRHO_OS_WINDOWS
manifestString += " a ui:WindowsUI ;\n";
# else
manifestString += " a ui:X11UI ;\n";
# endif
# if ! DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
d_string pluginUI(pluginDLL);
pluginUI.truncate(pluginDLL.rfind("_dsp"));
pluginUI += "_ui";

manifestString += " a ui:" DISTRHO_LV2_UI_TYPE " ;\n";
manifestString += " ui:binary <" + pluginUI + "." DISTRHO_DLL_EXTENSION "> ;\n";
# else
manifestString += " ui:binary <" + pluginDLL + "." DISTRHO_DLL_EXTENSION "> ;\n";
#endif
# if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
manifestString += "\n";
manifestString += " lv2:extensionData ui:idleInterface ,\n";
# if DISTRHO_PLUGIN_WANT_PROGRAMS
# if DISTRHO_PLUGIN_WANT_PROGRAMS
manifestString += " ui:showInterface ,\n";
manifestString += " <" LV2_PROGRAMS__Interface "> ;\n";
# else
# else
manifestString += " ui:showInterface ;\n";
# endif
# endif
manifestString += "\n";
manifestString += " lv2:optionalFeature ui:noUserResize ,\n";
manifestString += " ui:resize ,\n";
manifestString += " ui:touch ;\n";
# if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
manifestString += "\n";
manifestString += " lv2:requiredFeature <" LV2_DATA_ACCESS_URI "> ,\n";
manifestString += " <" LV2_INSTANCE_ACCESS_URI "> ,\n";
manifestString += " <" LV2_OPTIONS__options "> ,\n";
manifestString += " <" LV2_URID__map "> .\n";
# else
manifestString += " lv2:requiredFeature <" LV2_OPTIONS__options "> ,\n";
manifestString += " rdfs:seeAlso <" + uiTTL + "> .\n";
# endif
manifestString += " <" LV2_URID__map "> .\n";
manifestString += "\n";
#endif

#if DISTRHO_PLUGIN_WANT_PROGRAMS
const String presetSeparator(std::strstr(DISTRHO_PLUGIN_URI, "#") != nullptr ? ":" : "#");

char strBuf[0xff+1];
strBuf[0xff] = '\0';

// Presets
for (uint32_t i = 0; i < plugin.getProgramCount(); ++i)
{
std::snprintf(strBuf, 0xff, "%03i", i+1);

manifestString += "<" DISTRHO_PLUGIN_URI + presetSeparator + "preset" + strBuf + ">\n";
manifestString += " a pset:Preset ;\n";
manifestString += " lv2:appliesTo <" DISTRHO_PLUGIN_URI "> ;\n";
manifestString += " rdfs:seeAlso <presets.ttl> .\n";
manifestString += "\n";
}
#endif

manifestFile << manifestString << std::endl;
@@ -140,7 +172,7 @@ void lv2_generate_ttl(const char* const basename)
std::cout << "Writing " << pluginTTL << "..."; std::cout.flush();
std::fstream pluginFile(pluginTTL, std::ios::out);

d_string pluginString;
String pluginString;

// header
#if DISTRHO_LV2_USE_EVENTS_IN
@@ -158,7 +190,9 @@ void lv2_generate_ttl(const char* const basename)

// plugin
pluginString += "<" DISTRHO_PLUGIN_URI ">\n";
#if DISTRHO_PLUGIN_IS_SYNTH
#ifdef DISTRHO_PLUGIN_LV2_CATEGORY
pluginString += " a " DISTRHO_PLUGIN_LV2_CATEGORY ", lv2:Plugin ;\n";
#elif DISTRHO_PLUGIN_IS_SYNTH
pluginString += " a lv2:InstrumentPlugin, lv2:Plugin ;\n";
#else
pluginString += " a lv2:Plugin ;\n";
@@ -205,18 +239,27 @@ void lv2_generate_ttl(const char* const basename)
#if DISTRHO_PLUGIN_NUM_INPUTS > 0
for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i, ++portIndex)
{
const AudioPort& port(plugin.getAudioPort(true, i));

if (i == 0)
pluginString += " lv2:port [\n";
else
pluginString += " [\n";

pluginString += " a lv2:InputPort, lv2:AudioPort ;\n";
pluginString += " lv2:index " + d_string(portIndex) + " ;\n";
pluginString += " lv2:symbol \"lv2_audio_in_" + d_string(i+1) + "\" ;\n";
pluginString += " lv2:name \"Audio Input " + d_string(i+1) + "\" ;\n";
if (port.hints & kAudioPortIsCV)
pluginString += " a lv2:InputPort, lv2:CVPort ;\n";
else
pluginString += " a lv2:InputPort, lv2:AudioPort ;\n";

pluginString += " lv2:index " + String(portIndex) + " ;\n";
pluginString += " lv2:symbol \"" + port.symbol + "\" ;\n";
pluginString += " lv2:name \"" + port.name + "\" ;\n";

if (port.hints & kAudioPortIsSidechain)
pluginString += " lv2:portProperty lv2:isSideChain;\n";

if (i+1 == DISTRHO_PLUGIN_NUM_INPUTS)
pluginString += " ] ;\n\n";
pluginString += " ] ;\n";
else
pluginString += " ] ,\n";
}
@@ -226,18 +269,27 @@ void lv2_generate_ttl(const char* const basename)
#if DISTRHO_PLUGIN_NUM_OUTPUTS > 0
for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i, ++portIndex)
{
const AudioPort& port(plugin.getAudioPort(false, i));

if (i == 0)
pluginString += " lv2:port [\n";
else
pluginString += " [\n";

pluginString += " a lv2:OutputPort, lv2:AudioPort ;\n";
pluginString += " lv2:index " + d_string(portIndex) + " ;\n";
pluginString += " lv2:symbol \"lv2_audio_out_" + d_string(i+1) + "\" ;\n";
pluginString += " lv2:name \"Audio Output " + d_string(i+1) + "\" ;\n";
if (port.hints & kAudioPortIsCV)
pluginString += " a lv2:OutputPort, lv2:CVPort ;\n";
else
pluginString += " a lv2:OutputPort, lv2:AudioPort ;\n";

pluginString += " lv2:index " + String(portIndex) + " ;\n";
pluginString += " lv2:symbol \"" + port.symbol + "\" ;\n";
pluginString += " lv2:name \"" + port.name + "\" ;\n";

if (port.hints & kAudioPortIsSidechain)
pluginString += " lv2:portProperty lv2:isSideChain;\n";

if (i+1 == DISTRHO_PLUGIN_NUM_OUTPUTS)
pluginString += " ] ;\n\n";
pluginString += " ] ;\n";
else
pluginString += " ] ,\n";
}
@@ -247,15 +299,15 @@ void lv2_generate_ttl(const char* const basename)
#if DISTRHO_LV2_USE_EVENTS_IN
pluginString += " lv2:port [\n";
pluginString += " a lv2:InputPort, atom:AtomPort ;\n";
pluginString += " lv2:index " + d_string(portIndex) + " ;\n";
pluginString += " lv2:index " + String(portIndex) + " ;\n";
pluginString += " lv2:name \"Events Input\" ;\n";
pluginString += " lv2:symbol \"lv2_events_in\" ;\n";
pluginString += " rsz:minimumSize " + d_string(DISTRHO_PLUGIN_MINIMUM_BUFFER_SIZE) + " ;\n";
pluginString += " rsz:minimumSize " + String(DISTRHO_PLUGIN_MINIMUM_BUFFER_SIZE) + " ;\n";
pluginString += " atom:bufferType atom:Sequence ;\n";
# if (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI)
pluginString += " atom:supports <" LV2_ATOM__String "> ;\n";
# endif
# if DISTRHO_PLUGIN_HAS_MIDI_INPUT
# if DISTRHO_PLUGIN_WANT_MIDI_INPUT
pluginString += " atom:supports <" LV2_MIDI__MidiEvent "> ;\n";
# endif
# if DISTRHO_PLUGIN_WANT_TIMEPOS
@@ -268,15 +320,15 @@ void lv2_generate_ttl(const char* const basename)
#if DISTRHO_LV2_USE_EVENTS_OUT
pluginString += " lv2:port [\n";
pluginString += " a lv2:OutputPort, atom:AtomPort ;\n";
pluginString += " lv2:index " + d_string(portIndex) + " ;\n";
pluginString += " lv2:index " + String(portIndex) + " ;\n";
pluginString += " lv2:name \"Events Output\" ;\n";
pluginString += " lv2:symbol \"lv2_events_out\" ;\n";
pluginString += " rsz:minimumSize " + d_string(DISTRHO_PLUGIN_MINIMUM_BUFFER_SIZE) + " ;\n";
pluginString += " rsz:minimumSize " + String(DISTRHO_PLUGIN_MINIMUM_BUFFER_SIZE) + " ;\n";
pluginString += " atom:bufferType atom:Sequence ;\n";
# if (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI)
pluginString += " atom:supports <" LV2_ATOM__String "> ;\n";
# endif
# if DISTRHO_PLUGIN_HAS_MIDI_OUTPUT
# if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT
pluginString += " atom:supports <" LV2_MIDI__MidiEvent "> ;\n";
# endif
pluginString += " ] ;\n\n";
@@ -286,7 +338,7 @@ void lv2_generate_ttl(const char* const basename)
#if DISTRHO_PLUGIN_WANT_LATENCY
pluginString += " lv2:port [\n";
pluginString += " a lv2:OutputPort, lv2:ControlPort ;\n";
pluginString += " lv2:index " + d_string(portIndex) + " ;\n";
pluginString += " lv2:index " + String(portIndex) + " ;\n";
pluginString += " lv2:name \"Latency\" ;\n";
pluginString += " lv2:symbol \"lv2_latency\" ;\n";
pluginString += " lv2:designation lv2:latency ;\n";
@@ -307,15 +359,15 @@ void lv2_generate_ttl(const char* const basename)
else
pluginString += " a lv2:InputPort, lv2:ControlPort ;\n";

pluginString += " lv2:index " + d_string(portIndex) + " ;\n";
pluginString += " lv2:index " + String(portIndex) + " ;\n";
pluginString += " lv2:name \"" + plugin.getParameterName(i) + "\" ;\n";

// symbol
{
d_string symbol(plugin.getParameterSymbol(i));
String symbol(plugin.getParameterSymbol(i));

if (symbol.isEmpty())
symbol = "lv2_port_" + d_string(portIndex-1);
symbol = "lv2_port_" + String(portIndex-1);

pluginString += " lv2:symbol \"" + symbol + "\" ;\n";
}
@@ -326,21 +378,21 @@ void lv2_generate_ttl(const char* const basename)

if (plugin.getParameterHints(i) & kParameterIsInteger)
{
pluginString += " lv2:default " + d_string(int(plugin.getParameterValue(i))) + " ;\n";
pluginString += " lv2:minimum " + d_string(int(ranges.min)) + " ;\n";
pluginString += " lv2:maximum " + d_string(int(ranges.max)) + " ;\n";
pluginString += " lv2:default " + String(int(plugin.getParameterValue(i))) + " ;\n";
pluginString += " lv2:minimum " + String(int(ranges.min)) + " ;\n";
pluginString += " lv2:maximum " + String(int(ranges.max)) + " ;\n";
}
else
{
pluginString += " lv2:default " + d_string(plugin.getParameterValue(i)) + " ;\n";
pluginString += " lv2:minimum " + d_string(ranges.min) + " ;\n";
pluginString += " lv2:maximum " + d_string(ranges.max) + " ;\n";
pluginString += " lv2:default " + String(plugin.getParameterValue(i)) + " ;\n";
pluginString += " lv2:minimum " + String(ranges.min) + " ;\n";
pluginString += " lv2:maximum " + String(ranges.max) + " ;\n";
}
}

// unit
{
const d_string& unit(plugin.getParameterUnit(i));
const String& unit(plugin.getParameterUnit(i));

if (! unit.isEmpty())
{
@@ -400,11 +452,140 @@ void lv2_generate_ttl(const char* const basename)
}
}

pluginString += " doap:name \"" + d_string(plugin.getName()) + "\" ;\n";
pluginString += " doap:maintainer [ foaf:name \"" + d_string(plugin.getMaker()) + "\" ] .\n";
pluginString += " doap:name \"" + String(plugin.getName()) + "\" ;\n";
pluginString += " doap:maintainer [ foaf:name \"" + String(plugin.getMaker()) + "\" ] .\n";

pluginFile << pluginString << std::endl;
pluginFile.close();
std::cout << " done!" << std::endl;
}

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

#if DISTRHO_PLUGIN_HAS_UI && ! DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
{
std::cout << "Writing " << uiTTL << "..."; std::cout.flush();
std::fstream uiFile(uiTTL, std::ios::out);

String uiString;
uiString += "@prefix lv2: <" LV2_CORE_PREFIX "> .\n";
uiString += "@prefix ui: <" LV2_UI_PREFIX "> .\n";
uiString += "\n";

uiString += "<" DISTRHO_UI_URI ">\n";
uiString += " lv2:extensionData ui:idleInterface ,\n";
# if DISTRHO_PLUGIN_WANT_PROGRAMS
uiString += " ui:showInterface ,\n";
uiString += " <" LV2_PROGRAMS__Interface "> ;\n";
# else
uiString += " ui:showInterface ;\n";
# endif
uiString += "\n";
uiString += " lv2:optionalFeature ui:noUserResize ,\n";
uiString += " ui:resize ,\n";
uiString += " ui:touch ;\n";
uiString += "\n";
uiString += " lv2:requiredFeature <" LV2_OPTIONS__options "> ,\n";
uiString += " <" LV2_URID__map "> .\n";

uiFile << uiString << std::endl;
uiFile.close();
std::cout << " done!" << std::endl;
}
#endif

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

#if DISTRHO_PLUGIN_WANT_PROGRAMS
{
std::cout << "Writing presets.ttl..."; std::cout.flush();
std::fstream presetsFile("presets.ttl", std::ios::out);

String presetsString;
presetsString += "@prefix lv2: <" LV2_CORE_PREFIX "> .\n";
presetsString += "@prefix pset: <" LV2_PRESETS_PREFIX "> .\n";
presetsString += "@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n";
# if DISTRHO_PLUGIN_WANT_STATE
presetsString += "@prefix state: <" LV2_STATE_PREFIX "> .\n";
# endif
presetsString += "\n";

const uint32_t numParameters = plugin.getParameterCount();
const uint32_t numPrograms = plugin.getProgramCount();
# if DISTRHO_PLUGIN_WANT_STATE
const uint32_t numStates = plugin.getStateCount();
# endif

const String presetSeparator(std::strstr(DISTRHO_PLUGIN_URI, "#") != nullptr ? ":" : "#");

char strBuf[0xff+1];
strBuf[0xff] = '\0';

String presetString;

for (uint32_t i=0; i<numPrograms; ++i)
{
std::snprintf(strBuf, 0xff, "%03i", i+1);

plugin.loadProgram(i);

presetString = "<" DISTRHO_PLUGIN_URI + presetSeparator + "preset" + strBuf + ">\n";
presetString += " rdfs:label \"" + plugin.getProgramName(i) + "\" ;\n\n";

// TODO
# if 0 // DISTRHO_PLUGIN_WANT_STATE
for (uint32_t j=0; j<numStates; ++j)
{
if (j == 0)
presetString += " state:state [\n";
else
presetString += " [\n";

presetString += " <urn:distrho:" + plugin.getStateKey(j) + ">\n";
presetString += "\"\"\"\n";
presetString += plugin.getState(j);
presetString += "\"\"\"\n";

if (j+1 == numStates)
{
if (numParameters > 0)
presetString += " ] ;\n\n";
else
presetString += " ] .\n\n";
}
else
{
presetString += " ] ,\n";
}
}
# endif

for (uint32_t j=0; j <numParameters; ++j)
{
if (j == 0)
presetString += " lv2:port [\n";
else
presetString += " [\n";

presetString += " lv2:symbol \"" + plugin.getParameterSymbol(j) + "\" ;\n";

if (plugin.getParameterHints(j) & kParameterIsInteger)
presetString += " pset:value " + String(int(plugin.getParameterValue(j))) + " ;\n";
else
presetString += " pset:value " + String(plugin.getParameterValue(j)) + " ;\n";

if (j+1 == numParameters)
presetString += " ] .\n\n";
else
presetString += " ] ,\n";
}

presetsString += presetString;
}

presetsFile << presetsString << std::endl;
presetsFile.close();
std::cout << " done!" << std::endl;
}
#endif
}

+ 89
- 35
source/modules/distrho/src/DistrhoPluginVST.cpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2015 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
@@ -64,7 +64,7 @@ struct ERect {

START_NAMESPACE_DISTRHO

typedef std::map<const d_string,d_string> StringMap;
typedef std::map<const String, String> StringMap;

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

@@ -107,9 +107,9 @@ public:
bool* parameterChecks;
float* parameterValues;

#if DISTRHO_PLUGIN_WANT_STATE
# if DISTRHO_PLUGIN_WANT_STATE
virtual void setStateFromUI(const char* const newKey, const char* const newValue) = 0;
#endif
# endif
};

// -----------------------------------------------------------------------
@@ -160,24 +160,28 @@ public:
// -------------------------------------------------------------------
// functions called from the plugin side, may block

#if DISTRHO_PLUGIN_WANT_STATE
# if DISTRHO_PLUGIN_WANT_STATE
void setStateFromPlugin(const char* const key, const char* const value)
{
fUI.stateChanged(key, value);
}
#endif
# endif

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

protected:
intptr_t hostCallback(const int32_t opcode, const int32_t index, const intptr_t value, void* const ptr, const float opt)
intptr_t hostCallback(const int32_t opcode,
const int32_t index = 0,
const intptr_t value = 0,
void* const ptr = nullptr,
const float opt = 0.0f)
{
return fAudioMaster(fEffect, opcode, index, value, ptr, opt);
}

void editParameter(const uint32_t index, const bool started)
{
hostCallback(started ? audioMasterBeginEdit : audioMasterEndEdit, index, 0, nullptr, 0.0f);
hostCallback(started ? audioMasterBeginEdit : audioMasterEndEdit, index);
}

void setParameterValue(const uint32_t index, const float realValue)
@@ -191,31 +195,31 @@ protected:

void setState(const char* const key, const char* const value)
{
#if DISTRHO_PLUGIN_WANT_STATE
# if DISTRHO_PLUGIN_WANT_STATE
fUiHelper->setStateFromUI(key, value);
#else
# else
return; // unused
(void)key;
(void)value;
#endif
# endif
}

void sendNote(const uint8_t channel, const uint8_t note, const uint8_t velocity)
{
#if 0 //DISTRHO_PLUGIN_HAS_MIDI_INPUT
# if 0 //DISTRHO_PLUGIN_WANT_MIDI_INPUT
// TODO
#else
# else
return; // unused
(void)channel;
(void)note;
(void)velocity;
#endif
# endif
}

void setSize(const uint width, const uint height)
{
fUI.setWindowSize(width, height);
hostCallback(audioMasterSizeWindow, width, height, nullptr, 0.0f);
hostCallback(audioMasterSizeWindow, width, height);
}

private:
@@ -278,7 +282,7 @@ public:
std::memset(fProgramName, 0, sizeof(char)*(32+1));
std::strcpy(fProgramName, "Default");

#if DISTRHO_PLUGIN_HAS_MIDI_INPUT
#if DISTRHO_PLUGIN_WANT_MIDI_INPUT
fMidiEventCount = 0;
#endif

@@ -315,8 +319,8 @@ public:

for (uint32_t i=0, count=fPlugin.getStateCount(); i<count; ++i)
{
const d_string& d_key(fPlugin.getStateKey(i));
fStateMap[d_key] = fPlugin.getStateDefaultValue(i);
const String& dkey(fPlugin.getStateKey(i));
fStateMap[dkey] = fPlugin.getStateDefaultValue(i);
}
#endif
}
@@ -389,10 +393,27 @@ public:
case effMainsChanged:
if (value != 0)
{
fPlugin.activate();
#if DISTRHO_PLUGIN_HAS_MIDI_INPUT
#if DISTRHO_PLUGIN_WANT_MIDI_INPUT
fMidiEventCount = 0;

// tell host we want MIDI events
hostCallback(audioMasterWantMidi);
#endif

// deactivate for possible changes
fPlugin.deactivateIfNeeded();

// check if something changed
const uint32_t bufferSize = static_cast<uint32_t>(hostCallback(audioMasterGetBlockSize));
const double sampleRate = static_cast<double>(hostCallback(audioMasterGetSampleRate));

if (bufferSize != 0)
fPlugin.setBufferSize(bufferSize, true);

if (sampleRate != 0.0)
fPlugin.setSampleRate(sampleRate, true);

fPlugin.activate();
}
else
{
@@ -436,8 +457,8 @@ public:
# if DISTRHO_PLUGIN_WANT_STATE
for (StringMap::const_iterator cit=fStateMap.begin(), cite=fStateMap.end(); cit != cite; ++cit)
{
const d_string& key = cit->first;
const d_string& value = cit->second;
const String& key = cit->first;
const String& value = cit->second;

fVstUI->setStateFromPlugin(key, value);
}
@@ -485,15 +506,15 @@ public:
}
else
{
d_string chunkStr;
String chunkStr;

for (StringMap::const_iterator cit=fStateMap.begin(), cite=fStateMap.end(); cit != cite; ++cit)
{
const d_string& key = cit->first;
const d_string& value = cit->second;
const String& key = cit->first;
const String& value = cit->second;

// join key and value
d_string tmpStr;
String tmpStr;
tmpStr = key;
tmpStr += "\xff";
tmpStr += value;
@@ -537,8 +558,10 @@ public:

setStateFromUI(key, value);

# if DISTRHO_PLUGIN_HAS_UI
if (fVstUI != nullptr)
fVstUI->setStateFromPlugin(key, value);
# endif

// get next key
key = value+(std::strlen(value)+1);
@@ -548,8 +571,14 @@ public:
}
#endif // DISTRHO_PLUGIN_WANT_STATE

#if DISTRHO_PLUGIN_HAS_MIDI_INPUT
#if DISTRHO_PLUGIN_WANT_MIDI_INPUT
case effProcessEvents:
if (! fPlugin.isActive())
{
// host has not activated the plugin yet, nasty!
vst_dispatcher(effMainsChanged, 0, 1, nullptr, 0.0f);
}

if (const VstEvents* const events = (const VstEvents*)ptr)
{
if (events->numEvents == 0)
@@ -586,7 +615,7 @@ public:
}
break;

#if DISTRHO_PLUGIN_HAS_MIDI_INPUT || DISTRHO_PLUGIN_HAS_MIDI_OUTPUT || DISTRHO_PLUGIN_WANT_TIMEPOS || DISTRHO_OS_MAC
#if DISTRHO_PLUGIN_WANT_MIDI_INPUT || DISTRHO_PLUGIN_WANT_MIDI_OUTPUT || DISTRHO_PLUGIN_WANT_TIMEPOS || DISTRHO_OS_MAC
case effCanDo:
if (const char* const canDo = (const char*)ptr)
{
@@ -597,13 +626,13 @@ public:
return 0xbeef0000;
}
# endif
# if DISTRHO_PLUGIN_HAS_MIDI_INPUT
# if DISTRHO_PLUGIN_WANT_MIDI_INPUT
if (std::strcmp(canDo, "receiveVstEvents") == 0)
return 1;
if (std::strcmp(canDo, "receiveVstMidiEvent") == 0)
return 1;
# endif
# if DISTRHO_PLUGIN_HAS_MIDI_OUTPUT
# if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT
if (std::strcmp(canDo, "sendVstEvents") == 0)
return 1;
if (std::strcmp(canDo, "sendVstMidiEvent") == 0)
@@ -646,10 +675,19 @@ public:

void vst_processReplacing(const float** const inputs, float** const outputs, const int32_t sampleFrames)
{
if (sampleFrames <= 0)
return;

if (! fPlugin.isActive())
{
// host has not activated the plugin yet, nasty!
vst_dispatcher(effMainsChanged, 0, 1, nullptr, 0.0f);
}

#if DISTRHO_PLUGIN_WANT_TIMEPOS
static const int kWantVstTimeFlags(kVstTransportPlaying|kVstPpqPosValid|kVstTempoValid|kVstTimeSigValid);

if (const VstTimeInfo* const vstTimeInfo = (const VstTimeInfo*)fAudioMaster(fEffect, audioMasterGetTime, 0, kWantVstTimeFlags, nullptr, 0.0f))
if (const VstTimeInfo* const vstTimeInfo = (const VstTimeInfo*)hostCallback(audioMasterGetTime, 0, kWantVstTimeFlags))
{
fTimePosition.frame = vstTimeInfo->samplePos;
fTimePosition.playing = (vstTimeInfo->flags & kVstTransportPlaying);
@@ -690,7 +728,7 @@ public:
}
#endif

#if DISTRHO_PLUGIN_HAS_MIDI_INPUT
#if DISTRHO_PLUGIN_WANT_MIDI_INPUT
fPlugin.run(inputs, outputs, sampleFrames, fMidiEvents, fMidiEventCount);
fMidiEventCount = 0;
#else
@@ -724,7 +762,7 @@ private:
// Temporary data
char fProgramName[32+1];

#if DISTRHO_PLUGIN_HAS_MIDI_INPUT
#if DISTRHO_PLUGIN_WANT_MIDI_INPUT
uint32_t fMidiEventCount;
MidiEvent fMidiEvents[kMaxMidiEvents];
#endif
@@ -747,6 +785,18 @@ private:
StringMap fStateMap;
#endif

// -------------------------------------------------------------------
// host callback

intptr_t hostCallback(const int32_t opcode,
const int32_t index = 0,
const intptr_t value = 0,
void* const ptr = nullptr,
const float opt = 0.0f)
{
return fAudioMaster(fEffect, opcode, index, value, ptr, opt);
}

// -------------------------------------------------------------------
// functions called from the plugin side, RT no block

@@ -762,7 +812,11 @@ private:
// -------------------------------------------------------------------
// functions called from the UI side, may block

# if DISTRHO_PLUGIN_HAS_UI
void setStateFromUI(const char* const key, const char* const newValue) override
# else
void setStateFromUI(const char* const key, const char* const newValue)
# endif
{
fPlugin.setState(key, newValue);

@@ -773,9 +827,9 @@ private:
// check if key already exists
for (StringMap::iterator it=fStateMap.begin(), ite=fStateMap.end(); it != ite; ++it)
{
const d_string& d_key(it->first);
const String& dkey(it->first);

if (d_key == key)
if (dkey == key)
{
it->second = newValue;
return;


+ 16
- 12
source/modules/distrho/src/DistrhoUI.cpp View File

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

#include "DistrhoUIInternal.hpp"
#include "src/WidgetPrivateData.hpp"

START_NAMESPACE_DISTRHO

@@ -28,11 +29,14 @@ Window* d_lastUiWindow = nullptr;
/* ------------------------------------------------------------------------------------------------------------
* UI */

UI::UI()
UI::UI(uint width, uint height)
: UIWidget(*d_lastUiWindow),
pData(new PrivateData())
{
UIWidget::setNeedsFullViewport(true);
((UIWidget*)this)->pData->needsFullViewport = false;

if (width > 0 && height > 0)
setSize(width, height);
}

UI::~UI()
@@ -43,30 +47,30 @@ UI::~UI()
/* ------------------------------------------------------------------------------------------------------------
* Host state */

double UI::d_getSampleRate() const noexcept
double UI::getSampleRate() const noexcept
{
return pData->sampleRate;
}

void UI::d_editParameter(const uint32_t index, const bool started)
void UI::editParameter(uint32_t index, bool started)
{
pData->editParamCallback(index + pData->parameterOffset, started);
}

void UI::d_setParameterValue(const uint32_t index, const float value)
void UI::setParameterValue(uint32_t index, float value)
{
pData->setParamCallback(index + pData->parameterOffset, value);
}

#if DISTRHO_PLUGIN_WANT_STATE
void UI::d_setState(const char* const key, const char* const value)
void UI::setState(const char* key, const char* value)
{
pData->setStateCallback(key, value);
}
#endif

#if DISTRHO_PLUGIN_IS_SYNTH
void UI::d_sendNote(const uint8_t channel, const uint8_t note, const uint8_t velocity)
void UI::sendNote(uint8_t channel, uint8_t note, uint8_t velocity)
{
pData->sendNoteCallback(channel, note, velocity);
}
@@ -76,7 +80,7 @@ void UI::d_sendNote(const uint8_t channel, const uint8_t note, const uint8_t vel
/* ------------------------------------------------------------------------------------------------------------
* Direct DSP access */

void* UI::d_getPluginInstancePointer() const noexcept
void* UI::getPluginInstancePointer() const noexcept
{
return pData->dspPtr;
}
@@ -85,16 +89,16 @@ void* UI::d_getPluginInstancePointer() const noexcept
/* ------------------------------------------------------------------------------------------------------------
* DSP/Plugin Callbacks (optional) */

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

/* ------------------------------------------------------------------------------------------------------------
* UI Callbacks (optional) */

void UI::d_uiFileBrowserSelected(const char*)
void UI::uiFileBrowserSelected(const char*)
{
}

void UI::d_uiReshape(uint width, uint height)
void UI::uiReshape(uint width, uint height)
{
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);


+ 3
- 3
source/modules/distrho/src/DistrhoUIDSSI.cpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2015 Filipe Coelho <falktx@falktx.com>
*
* Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this
@@ -20,7 +20,7 @@
# error DSSI UIs do not support direct access!
#endif

#include "../extra/d_sleep.hpp"
#include "../extra/Sleep.hpp"

#include <lo/lo.h>

@@ -136,7 +136,7 @@ public:
#if DISTRHO_PLUGIN_WANT_PROGRAMS
void dssiui_program(ulong bank, ulong program)
{
fUI.programChanged(bank * 128 + program);
fUI.programLoaded(bank * 128 + program);
}
#endif



+ 14
- 14
source/modules/distrho/src/DistrhoUIInternal.hpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2015 Filipe Coelho <falktx@falktx.com>
*
* Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this
@@ -18,10 +18,10 @@
#define DISTRHO_UI_INTERNAL_HPP_INCLUDED

#include "../DistrhoUI.hpp"
#include "../../dgl/App.hpp"
#include "../../dgl/Application.hpp"
#include "../../dgl/Window.hpp"

using DGL::App;
using DGL::Application;
using DGL::IdleCallback;
using DGL::Window;

@@ -142,7 +142,7 @@ UI* createUiWrapper(void* const dspPtr, Window* const window)
class UIExporterWindow : public Window
{
public:
UIExporterWindow(App& app, const intptr_t winId, void* const dspPtr)
UIExporterWindow(Application& app, const intptr_t winId, void* const dspPtr)
: Window(app, winId),
fUI(createUiWrapper(dspPtr, this)),
fIsReady(false)
@@ -175,7 +175,7 @@ protected:
{
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,);

fUI->d_uiReshape(width, height);
fUI->uiReshape(width, height);
fIsReady = true;
}

@@ -184,7 +184,7 @@ protected:
{
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,);

fUI->d_uiFileBrowserSelected(filename);
fUI->uiFileBrowserSelected(filename);
}

private:
@@ -257,15 +257,15 @@ public:
{
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,);

fUI->d_parameterChanged(index, value);
fUI->parameterChanged(index, value);
}

#if DISTRHO_PLUGIN_WANT_PROGRAMS
void programChanged(const uint32_t index)
void programLoaded(const uint32_t index)
{
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,);

fUI->d_programChanged(index);
fUI->programLoaded(index);
}
#endif

@@ -276,7 +276,7 @@ public:
DISTRHO_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',);
DISTRHO_SAFE_ASSERT_RETURN(value != nullptr,);

fUI->d_stateChanged(key, value);
fUI->stateChanged(key, value);
}
#endif

@@ -295,7 +295,7 @@ public:
void exec_idle()
{
if (glWindow.isReady())
fUI->d_uiIdle();
fUI->uiIdle();
}

bool idle()
@@ -305,7 +305,7 @@ public:
glApp.idle();

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

return ! glApp.isQuiting();
}
@@ -364,14 +364,14 @@ public:
fData->sampleRate = sampleRate;

if (doCallback)
fUI->d_sampleRateChanged(sampleRate);
fUI->sampleRateChanged(sampleRate);
}

private:
// -------------------------------------------------------------------
// DGL Application and Window for this widget

App glApp;
Application glApp;
UIExporterWindow glWindow;

// prevent recursion


+ 4
- 4
source/modules/distrho/src/DistrhoUILV2.cpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2015 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
@@ -16,7 +16,7 @@

#include "DistrhoUIInternal.hpp"

#include "../extra/d_string.hpp"
#include "../extra/String.hpp"

#include "lv2/atom.h"
#include "lv2/atom-util.h"
@@ -195,7 +195,7 @@ public:
{
const uint32_t realProgram(bank * 128 + program);

fUI.programChanged(realProgram);
fUI.programLoaded(realProgram);
}
#endif

@@ -222,7 +222,7 @@ protected:
const uint32_t eventInPortIndex(DISTRHO_PLUGIN_NUM_INPUTS + DISTRHO_PLUGIN_NUM_OUTPUTS);

// join key and value
d_string tmpStr;
String tmpStr;
tmpStr += key;
tmpStr += "\xff";
tmpStr += value;


+ 1
- 0
source/modules/distrho/src/dssi View File

@@ -0,0 +1 @@
../../../includes/dssi/

+ 1
- 0
source/modules/distrho/src/ladspa View File

@@ -0,0 +1 @@
../../../includes/ladspa/

+ 1
- 0
source/modules/distrho/src/lv2 View File

@@ -0,0 +1 @@
../../../includes/lv2/

+ 1
- 0
source/modules/distrho/src/vestige View File

@@ -0,0 +1 @@
../../../includes/vestige/

Loading…
Cancel
Save