Browse Source

Remove everything from gh-pages branch

gh-pages
falkTX 10 years ago
parent
commit
a439d215dd
100 changed files with 0 additions and 41801 deletions
  1. +0
    -13
      LICENSE
  2. +0
    -28
      README.md
  3. +0
    -91
      dgl/App.hpp
  4. +0
    -187
      dgl/Base.hpp
  5. +0
    -112
      dgl/Color.hpp
  6. +0
    -750
      dgl/Geometry.hpp
  7. +0
    -147
      dgl/Image.hpp
  8. +0
    -54
      dgl/ImageAboutWindow.hpp
  9. +0
    -67
      dgl/ImageButton.hpp
  10. +0
    -103
      dgl/ImageKnob.hpp
  11. +0
    -98
      dgl/ImageSlider.hpp
  12. +0
    -65
      dgl/ImageSwitch.hpp
  13. +0
    -84
      dgl/Makefile
  14. +0
    -132
      dgl/Makefile.mk
  15. +0
    -799
      dgl/NanoVG.hpp
  16. +0
    -81
      dgl/StandaloneWindow.hpp
  17. +0
    -387
      dgl/Widget.hpp
  18. +0
    -134
      dgl/Window.hpp
  19. +0
    -75
      dgl/src/App.cpp
  20. +0
    -71
      dgl/src/AppPrivateData.hpp
  21. +0
    -245
      dgl/src/Color.cpp
  22. +0
    -1072
      dgl/src/Geometry.cpp
  23. +0
    -192
      dgl/src/Image.cpp
  24. +0
    -89
      dgl/src/ImageAboutWindow.cpp
  25. +0
    -190
      dgl/src/ImageButton.cpp
  26. +0
    -459
      dgl/src/ImageKnob.cpp
  27. +0
    -399
      dgl/src/ImageSlider.cpp
  28. +0
    -122
      dgl/src/ImageSwitch.cpp
  29. +0
    -780
      dgl/src/NanoVG.cpp
  30. +0
    -255
      dgl/src/Widget.cpp
  31. +0
    -1232
      dgl/src/Window.cpp
  32. +0
    -18
      dgl/src/nanovg/LICENSE.txt
  33. +0
    -1673
      dgl/src/nanovg/fontstash.h
  34. +0
    -2475
      dgl/src/nanovg/nanovg.c
  35. +0
    -590
      dgl/src/nanovg/nanovg.h
  36. +0
    -1293
      dgl/src/nanovg/nanovg_gl.h
  37. +0
    -4676
      dgl/src/nanovg/stb_image.c
  38. +0
    -2064
      dgl/src/nanovg/stb_truetype.h
  39. +0
    -121
      dgl/src/pugl/common.h
  40. +0
    -41
      dgl/src/pugl/event.h
  41. +0
    -32
      dgl/src/pugl/gl.h
  42. +0
    -32
      dgl/src/pugl/glu.h
  43. +0
    -383
      dgl/src/pugl/pugl.h
  44. +0
    -350
      dgl/src/pugl/pugl_internal.h
  45. +0
    -573
      dgl/src/pugl/pugl_osx.m
  46. +0
    -481
      dgl/src/pugl/pugl_win.cpp
  47. +0
    -606
      dgl/src/pugl/pugl_x11.c
  48. +0
    -2431
      dgl/src/sofd/libsofd.c
  49. +0
    -175
      dgl/src/sofd/libsofd.h
  50. +0
    -800
      distrho/DistrhoPlugin.hpp
  51. +0
    -30
      distrho/DistrhoPluginMain.cpp
  52. +0
    -196
      distrho/DistrhoUI.hpp
  53. +0
    -29
      distrho/DistrhoUIMain.cpp
  54. +0
    -202
      distrho/DistrhoUtils.hpp
  55. +0
    -141
      distrho/extra/d_leakdetector.hpp
  56. +0
    -230
      distrho/extra/d_mutex.hpp
  57. +0
    -247
      distrho/extra/d_scopedpointer.hpp
  58. +0
    -62
      distrho/extra/d_sleep.hpp
  59. +0
    -750
      distrho/extra/d_string.hpp
  60. +0
    -291
      distrho/extra/d_thread.hpp
  61. +0
    -134
      distrho/src/DistrhoDefines.h
  62. +0
    -115
      distrho/src/DistrhoPlugin.cpp
  63. +0
    -480
      distrho/src/DistrhoPluginCarla.cpp
  64. +0
    -109
      distrho/src/DistrhoPluginChecks.h
  65. +0
    -471
      distrho/src/DistrhoPluginInternal.hpp
  66. +0
    -434
      distrho/src/DistrhoPluginJack.cpp
  67. +0
    -713
      distrho/src/DistrhoPluginLADSPA+DSSI.cpp
  68. +0
    -1107
      distrho/src/DistrhoPluginLV2.cpp
  69. +0
    -410
      distrho/src/DistrhoPluginLV2export.cpp
  70. +0
    -1071
      distrho/src/DistrhoPluginVST.cpp
  71. +0
    -122
      distrho/src/DistrhoUI.cpp
  72. +0
    -511
      distrho/src/DistrhoUIDSSI.cpp
  73. +0
    -393
      distrho/src/DistrhoUIInternal.hpp
  74. +0
    -536
      distrho/src/DistrhoUILV2.cpp
  75. +0
    -441
      distrho/src/dssi/dssi.h
  76. +0
    -272
      distrho/src/dssi/seq_event-compat.h
  77. +0
    -603
      distrho/src/ladspa/ladspa.h
  78. +0
    -747
      distrho/src/lv2/atom-forge.h
  79. +0
    -249
      distrho/src/lv2/atom-helpers.h
  80. +0
    -446
      distrho/src/lv2/atom-util.h
  81. +0
    -246
      distrho/src/lv2/atom.h
  82. +0
    -30
      distrho/src/lv2/buf-size.h
  83. +0
    -63
      distrho/src/lv2/data-access.h
  84. +0
    -144
      distrho/src/lv2/dynmanifest.h
  85. +0
    -266
      distrho/src/lv2/event-helpers.h
  86. +0
    -294
      distrho/src/lv2/event.h
  87. +0
    -37
      distrho/src/lv2/instance-access.h
  88. +0
    -99
      distrho/src/lv2/log.h
  89. +0
    -146
      distrho/src/lv2/logger.h
  90. +0
    -98
      distrho/src/lv2/lv2-midifunctions.h
  91. +0
    -175
      distrho/src/lv2/lv2-miditype.h
  92. +0
    -458
      distrho/src/lv2/lv2.h
  93. +0
    -109
      distrho/src/lv2/lv2_external_ui.h
  94. +0
    -33
      distrho/src/lv2/lv2_kxstudio_properties.h
  95. +0
    -174
      distrho/src/lv2/lv2_programs.h
  96. +0
    -119
      distrho/src/lv2/lv2_rtmempool.h
  97. +0
    -226
      distrho/src/lv2/midi.h
  98. +0
    -34
      distrho/src/lv2/morph.h
  99. +0
    -132
      distrho/src/lv2/options.h
  100. +0
    -49
      distrho/src/lv2/parameters.h

+ 0
- 13
LICENSE View File

@@ -1,13 +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.

+ 0
- 28
README.md View File

@@ -1,28 +0,0 @@
# DPF - DISTRHO Plugin Framework

DPF is designed to make development of new plugins an easy and enjoyable task.<br/>
It allows developers to create plugins with custom UIs using a simple C++ API.<br/>
The framework facilitates exporting various different plugin formats from the same code-base.<br/>

DPF can build for LADSPA, DSSI, LV2 and VST formats.<br/>
LADSPA, DSSI and VST implementations are complete, LV2 at ~95% completion.<br/>
A JACK/Standalone mode is also available, allowing you to quickly test plugins.<br/>

Plugin DSP and UI communication is done via key-value string pairs.<br/>
You send messages from the UI to the DSP side, which is automatically saved in the host when required.<br/>

Getting time information from the host is possible.<br/>
It uses the same format as the JACK Transport API, making porting some code easier.<br/>


List of plugins made with DPF:<br/>
- [DISTRHO Mini-Series](https://github.com/DISTRHO/mini-series)
- [DISTRHO MVerb](https://github.com/DISTRHO/MVerb)
- [DISTRHO Nekobi](https://github.com/DISTRHO/nekobi)
- [DISTRHO ProM](https://github.com/DISTRHO/prom)
- [Juice Plugins](https://github.com/DISTRHO/JuicePlugins) (work in progress)
- [ZamAudio Suite](https://github.com/zamaudio/zam-plugins)


Plugin examples are available [here](https://github.com/DISTRHO/plugin-examples).<br/>
OpenGL UI examples are available [here](https://github.com/DISTRHO/gl-examples).

+ 0
- 91
dgl/App.hpp View File

@@ -1,91 +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.
*/

#ifndef DGL_APP_HPP_INCLUDED
#define DGL_APP_HPP_INCLUDED

#include "Base.hpp"

START_NAMESPACE_DGL

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

class Window;

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

/**
Base DGL Application class.

One application instance is required for creating a window.
There's no single/global application instance in DGL, and multiple
windows can share the same app instance.

In standalone mode an application will automatically quit its
event-loop when all its windows are closed.
*/
class App
{
public:
/**
Constructor.
*/
App();

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

/**
Idle function.
This runs the application event-loop once.
*/
void idle();

/**
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.
*/
void exec();

/**
Quit the application.
This stops the event-loop and closes all Windows.
*/
void quit();

/**
Check if the application is about to quit.
Returning true means there's no event-loop running at the moment (or it's just about to stop).
*/
bool isQuiting() const noexcept;

private:
struct PrivateData;
PrivateData* const pData;
friend class Window;

DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(App)
};

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

END_NAMESPACE_DGL

#endif // DGL_APP_HPP_INCLUDED

+ 0
- 187
dgl/Base.hpp View File

@@ -1,187 +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.
*/

#ifndef DGL_BASE_HPP_INCLUDED
#define DGL_BASE_HPP_INCLUDED

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

// -----------------------------------------------------------------------
// Define namespace

#ifndef DGL_NAMESPACE
# define DGL_NAMESPACE DGL
#endif

#define START_NAMESPACE_DGL namespace DGL_NAMESPACE {
#define END_NAMESPACE_DGL }
#define USE_NAMESPACE_DGL using namespace DGL_NAMESPACE;

#ifdef DISTRHO_OS_WINDOWS
// -----------------------------------------------------------------------
// Fix OpenGL includes for Windows, based on glfw code

#ifndef APIENTRY
# define APIENTRY __stdcall
#endif // APIENTRY

/* We need WINGDIAPI defined */
#ifndef WINGDIAPI
# if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__POCC__)
# define WINGDIAPI __declspec(dllimport)
# elif defined(__LCC__)
# define WINGDIAPI __stdcall
# else
# define WINGDIAPI extern
# endif
# define DGL_WINGDIAPI_DEFINED
#endif // WINGDIAPI

/* Some <GL/glu.h> files also need CALLBACK defined */
#ifndef CALLBACK
# if defined(_MSC_VER)
# if (defined(_M_MRX000) || defined(_M_IX86) || defined(_M_ALPHA) || defined(_M_PPC)) && !defined(MIDL_PASS)
# define CALLBACK __stdcall
# else
# define CALLBACK
# endif
# else
# define CALLBACK __stdcall
# endif
# define DGL_CALLBACK_DEFINED
#endif // CALLBACK

/* Most GL/glu.h variants on Windows need wchar_t */
#include <cstddef>

#endif // DISTRHO_OS_WINDOWS

// -----------------------------------------------------------------------
// OpenGL includes

#ifdef DISTRHO_OS_MAC
# include "OpenGL/gl.h"
#else
# define GL_GLEXT_PROTOTYPES
# include "GL/gl.h"
# include "GL/glext.h"
#endif

// -----------------------------------------------------------------------
// Missing OpenGL defines

#if defined(GL_BGR_EXT) && ! defined(GL_BGR)
# define GL_BGR GL_BGR_EXT
#endif

#if defined(GL_BGRA_EXT) && ! defined(GL_BGRA)
# define GL_BGRA GL_BGRA_EXT
#endif

#ifndef GL_CLAMP_TO_BORDER
# define GL_CLAMP_TO_BORDER 0x812D
#endif

#ifdef DISTRHO_OS_WINDOWS
// -----------------------------------------------------------------------
// Fix OpenGL includes for Windows, based on glfw code

#ifdef DGL_WINGDIAPI_DEFINED
# undef WINGDIAPI
# undef DGL_WINGDIAPI_DEFINED
#endif

#ifdef DGL_CALLBACK_DEFINED
# undef CALLBACK
# undef DGL_CALLBACK_DEFINED
#endif

#endif // DISTRHO_OS_WINDOWS

START_NAMESPACE_DGL

// -----------------------------------------------------------------------
// Base DGL enums

/**
Convenience symbols for ASCII control characters.
*/
enum Char {
CHAR_BACKSPACE = 0x08,
CHAR_ESCAPE = 0x1B,
CHAR_DELETE = 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 */
};

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

// -----------------------------------------------------------------------
// Base DGL classes

/**
Idle callback.
*/
class IdleCallback
{
public:
virtual ~IdleCallback() {}
virtual void idleCallback() = 0;
};

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

END_NAMESPACE_DGL

#endif // DGL_BASE_HPP_INCLUDED

+ 0
- 112
dgl/Color.hpp View File

@@ -1,112 +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.
*/

#ifndef DGL_COLOR_HPP_INCLUDED
#define DGL_COLOR_HPP_INCLUDED

#include "Base.hpp"

struct NVGcolor;

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.
*/
struct Color {
/**
Direct access to the color values.
*/
union {
float rgba[4];
struct { float red, green, blue, alpha; };
};

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

/**
Create a color from red, green, blue and alpha numeric values.
Values must be in [0..255] range.
*/
Color(int red, int green, int blue, int alpha = 255) noexcept;

/**
Create a color from red, green, blue and alpha floating-point values.
Values must in [0..1] range.
*/
Color(float red, float green, float blue, float alpha = 1.0f) noexcept;

/**
Create a color by copying another color.
*/
Color(const Color& color) noexcept;
Color& operator=(const Color& color) noexcept;

/**
Create a color by linearly interpolating two other colors.
*/
Color(const Color& color1, const Color& color2, float u) noexcept;

/**
Create a color specified by hue, saturation and lightness.
Values must in [0..1] range.
*/
static Color fromHSL(float hue, float saturation, float lightness, float alpha = 1.0f);

/**
Create a color from a HTML string like "#333" or "#112233".
*/
static Color fromHTML(const char* rgb, float alpha = 1.0f);

/**
Linearly interpolate this color against another.
*/
void interpolate(const Color& other, float u) noexcept;

/**
Check if this color matches another.
@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;
bool operator==(const Color& color) noexcept;
bool operator!=(const Color& color) noexcept;

/**
Fix color bounds if needed.
*/
void fixBounds() noexcept;

/**
@internal
Needed for NanoVG compatibility.
*/
Color(const NVGcolor&) noexcept;
operator NVGcolor() const noexcept;
};

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

END_NAMESPACE_DGL

#endif // DGL_COLOR_HPP_INCLUDED

+ 0
- 750
dgl/Geometry.hpp View File

@@ -1,750 +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.
*/

#ifndef DGL_GEOMETRY_HPP_INCLUDED
#define DGL_GEOMETRY_HPP_INCLUDED

#include "Base.hpp"

START_NAMESPACE_DGL

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

template<typename> class Line;
template<typename> class Circle;
template<typename> class Triangle;
template<typename> class Rectangle;

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

/**
DGL Point class.

This class describes a single point in space, defined by an X and Y value.
*/
template<typename T>
class Point
{
public:
/**
Constructor for (0, 0) point.
*/
Point() noexcept;

/**
Constructor using custom X and Y values.
*/
Point(const T& x, const T& y) noexcept;

/**
Constructor using another Point class values.
*/
Point(const Point<T>& pos) noexcept;

/**
Get X value.
*/
const T& getX() const noexcept;

/**
Get Y value.
*/
const T& getY() const noexcept;

/**
Set X value to @a x.
*/
void setX(const T& x) noexcept;

/**
Set Y value to @a y.
*/
void setY(const T& y) noexcept;

/**
Set X and Y values to @a x and @a y respectively.
*/
void setPos(const T& x, const T& y) noexcept;

/**
Set X and Y values according to @a pos.
*/
void setPos(const Point<T>& pos) noexcept;

/**
Move this point by @a x and @a y values.
*/
void moveBy(const T& x, const T& y) noexcept;

/**
Move this point by @a pos.
*/
void moveBy(const Point<T>& pos) noexcept;

/**
Return true if point is (0, 0).
*/
bool isZero() const noexcept;

/**
Return true if point is not (0, 0).
*/
bool isNotZero() const noexcept;

Point<T> operator+(const Point<T>& pos) noexcept;
Point<T> operator-(const Point<T>& pos) noexcept;
Point<T>& operator=(const Point<T>& pos) noexcept;
Point<T>& operator+=(const Point<T>& pos) noexcept;
Point<T>& operator-=(const Point<T>& pos) noexcept;
bool operator==(const Point<T>& pos) const noexcept;
bool operator!=(const Point<T>& pos) const noexcept;

private:
T fX, fY;
template<typename> friend class Line;
template<typename> friend class Circle;
template<typename> friend class Triangle;
template<typename> friend class Rectangle;
};

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

/**
DGL Size class.

This class describes a size, defined by a width and height value.
*/
template<typename T>
class Size
{
public:
/**
Constructor for null size (0x0).
*/
Size() noexcept;

/**
Constructor using custom width and height values.
*/
Size(const T& width, const T& height) noexcept;

/**
Constructor using another Size class values.
*/
Size(const Size<T>& size) noexcept;

/**
Get width.
*/
const T& getWidth() const noexcept;

/**
Get height.
*/
const T& getHeight() const noexcept;

/**
Set width.
*/
void setWidth(const T& width) noexcept;

/**
Set height.
*/
void setHeight(const T& height) noexcept;

/**
Set size to @a width and @a height.
*/
void setSize(const T& width, const T& height) noexcept;

/**
Set size.
*/
void setSize(const Size<T>& size) noexcept;

/**
Grow size by @a multiplier.
*/
void growBy(double multiplier) noexcept;

/**
Shrink size by @a divider.
*/
void shrinkBy(double divider) noexcept;

/**
Return true if size is null (0x0).
An null size is also invalid.
*/
bool isNull() const noexcept;

/**
Return true if size is not null (0x0).
A non-null size is still invalid if its width or height is negative.
*/
bool isNotNull() const noexcept;

/**
Return true if size is valid (width and height are higher than zero).
*/
bool isValid() const noexcept;

/**
Return true if size is invalid (width or height are lower or equal to zero).
An invalid size might not be null under some circumstances.
*/
bool isInvalid() const noexcept;

Size<T> operator+(const Size<T>& size) noexcept;
Size<T> operator-(const Size<T>& size) noexcept;
Size<T>& operator=(const Size<T>& size) noexcept;
Size<T>& operator+=(const Size<T>& size) noexcept;
Size<T>& operator-=(const Size<T>& size) noexcept;
Size<T>& operator*=(double m) noexcept;
Size<T>& operator/=(double d) noexcept;
bool operator==(const Size<T>& size) const noexcept;
bool operator!=(const Size<T>& size) const noexcept;

private:
T fWidth, fHeight;
template<typename> friend class Rectangle;
};

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

/**
DGL Line class.

This class describes a line, defined by two points.
*/
template<typename T>
class Line
{
public:
/**
Constructor for a null line ([0,0] to [0,0]).
*/
Line() noexcept;

/**
Constructor using custom start X, start Y, end X and end Y values.
*/
Line(const T& startX, const T& startY, const T& endX, const T& endY) noexcept;

/**
Constructor using custom start X, start Y and end pos values.
*/
Line(const T& startX, const T& startY, const Point<T>& endPos) noexcept;

/**
Constructor using custom start pos, end X and end Y values.
*/
Line(const Point<T>& startPos, const T& endX, const T& endY) noexcept;

/**
Constructor using custom start and end pos values.
*/
Line(const Point<T>& startPos, const Point<T>& endPos) noexcept;

/**
Constructor using another Line class values.
*/
Line(const Line<T>& line) noexcept;

/**
Get start X value.
*/
const T& getStartX() const noexcept;

/**
Get start Y value.
*/
const T& getStartY() const noexcept;

/**
Get end X value.
*/
const T& getEndX() const noexcept;

/**
Get end Y value.
*/
const T& getEndY() const noexcept;

/**
Get start position.
*/
const Point<T>& getStartPos() const noexcept;

/**
Get end position.
*/
const Point<T>& getEndPos() const noexcept;

/**
Set start X value to @a x.
*/
void setStartX(const T& x) noexcept;

/**
Set start Y value to @a y.
*/
void setStartY(const T& y) noexcept;

/**
Set start X and Y values to @a x and @a y respectively.
*/
void setStartPos(const T& x, const T& y) noexcept;

/**
Set start X and Y values according to @a pos.
*/
void setStartPos(const Point<T>& pos) noexcept;

/**
Set end X value to @a x.
*/
void setEndX(const T& x) noexcept;

/**
Set end Y value to @a y.
*/
void setEndY(const T& y) noexcept;

/**
Set end X and Y values to @a x and @a y respectively.
*/
void setEndPos(const T& x, const T& y) noexcept;

/**
Set end X and Y values according to @a pos.
*/
void setEndPos(const Point<T>& pos) noexcept;

/**
Move this line by @a x and @a y values.
*/
void moveBy(const T& x, const T& y) noexcept;

/**
Move this line by @a pos.
*/
void moveBy(const Point<T>& pos) noexcept;

/**
Draw this line using the current OpenGL state.
*/
void draw();

/**
Return true if line is null (start and end pos are equal).
*/
bool isNull() const noexcept;

/**
Return true if line is not null (start and end pos are different).
*/
bool isNotNull() const noexcept;

Line<T>& operator=(const Line<T>& line) noexcept;
bool operator==(const Line<T>& line) const noexcept;
bool operator!=(const Line<T>& line) const noexcept;

private:
Point<T> fPosStart, fPosEnd;
};

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

/**
DGL Circle class.

This class describes a circle, defined by position, size and a minimum of 3 segments.

TODO: report if circle starts at top-left, bottom-right or center.
and size grows from which point?
*/
template<typename T>
class Circle
{
public:
/**
Constructor for a null circle.
*/
Circle() noexcept;

/**
Constructor using custom X, Y and size values.
*/
Circle(const T& x, const T& y, const float size, const uint numSegments = 300);

/**
Constructor using custom position and size values.
*/
Circle(const Point<T>& pos, const float size, const uint numSegments = 300);

/**
Constructor using another Circle class values.
*/
Circle(const Circle<T>& cir) noexcept;

/**
Get X value.
*/
const T& getX() const noexcept;

/**
Get Y value.
*/
const T& getY() const noexcept;

/**
Get position.
*/
const Point<T>& getPos() const noexcept;

/**
Set X value to @a x.
*/
void setX(const T& x) noexcept;

/**
Set Y value to @a y.
*/
void setY(const T& y) noexcept;

/**
Set X and Y values to @a x and @a y respectively.
*/
void setPos(const T& x, const T& y) noexcept;

/**
Set X and Y values according to @a pos.
*/
void setPos(const Point<T>& pos) noexcept;

/**
Get size.
*/
float getSize() const noexcept;

/**
Set size.
@note Must always be > 0
*/
void setSize(const float size) noexcept;

/**
Get the current number of line segments that make this circle.
*/
uint getNumSegments() const noexcept;

/**
Set the number of line segments that will make this circle.
@note Must always be >= 3
*/
void setNumSegments(const uint num);

/**
Draw this circle using the current OpenGL state.
*/
void draw();

/**
Draw lines (outline of this circle) using the current OpenGL state.
*/
void drawOutline();

Circle<T>& operator=(const Circle<T>& cir) noexcept;
bool operator==(const Circle<T>& cir) const noexcept;
bool operator!=(const Circle<T>& cir) const noexcept;

private:
Point<T> fPos;
float fSize;
uint fNumSegments;

// cached values
float fTheta, fCos, fSin;

void _draw(const bool outline);
};

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

/**
DGL Triangle class.

This class describes a triangle, defined by 3 points.
*/
template<typename T>
class Triangle
{
public:
/**
Constructor for a null triangle.
*/
Triangle() noexcept;

/**
Constructor using custom X and Y values.
*/
Triangle(const T& x1, const T& y1, const T& x2, const T& y2, const T& x3, const T& y3) noexcept;

/**
Constructor using custom position values.
*/
Triangle(const Point<T>& pos1, const Point<T>& pos2, const Point<T>& pos3) noexcept;

/**
Constructor using another Triangle class values.
*/
Triangle(const Triangle<T>& tri) noexcept;

/**
Draw this triangle using the current OpenGL state.
*/
void draw();

/**
Draw lines (outline of this triangle) using the current OpenGL state.
*/
void drawOutline();

/**
Return true if triangle is null (all its points are equal).
An null triangle is also invalid.
*/
bool isNull() const noexcept;

/**
Return true if triangle is not null (one its points is different from the others).
A non-null triangle is still invalid if two of its points are equal.
*/
bool isNotNull() const noexcept;

/**
Return true if triangle is valid (all its points are different).
*/
bool isValid() const noexcept;

/**
Return true if triangle is invalid (one or two of its points are equal).
An invalid triangle might not be null under some circumstances.
*/
bool isInvalid() const noexcept;

Triangle<T>& operator=(const Triangle<T>& tri) noexcept;
bool operator==(const Triangle<T>& tri) const noexcept;
bool operator!=(const Triangle<T>& tri) const noexcept;

private:
Point<T> fPos1, fPos2, fPos3;

void _draw(const bool outline);
};

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

/**
DGL Rectangle class.

This class describes a rectangle, defined by a starting point and a size.
*/
template<typename T>
class Rectangle
{
public:
/**
Constructor for a null rectangle.
*/
Rectangle() noexcept;

/**
Constructor using custom X, Y, width and height values.
*/
Rectangle(const T& x, const T& y, const T& width, const T& height) noexcept;

/**
Constructor using custom X, Y and size values.
*/
Rectangle(const T& x, const T& y, const Size<T>& size) noexcept;

/**
Constructor using custom pos, width and height values.
*/
Rectangle(const Point<T>& pos, const T& width, const T& height) noexcept;

/**
Constructor using custom position and size.
*/
Rectangle(const Point<T>& pos, const Size<T>& size) noexcept;

/**
Constructor using another Rectangle class values.
*/
Rectangle(const Rectangle<T>& rect) noexcept;

/**
Get X value.
*/
const T& getX() const noexcept;

/**
Get Y value.
*/
const T& getY() const noexcept;

/**
Get width.
*/
const T& getWidth() const noexcept;

/**
Get height.
*/
const T& getHeight() const noexcept;

/**
Get position.
*/
const Point<T>& getPos() const noexcept;

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

/**
Set X value as @a x.
*/
void setX(const T& x) noexcept;

/**
Set Y value as @a y.
*/
void setY(const T& y) noexcept;

/**
Set X and Y values as @a x and @a y respectively.
*/
void setPos(const T& x, const T& y) noexcept;

/**
Set X and Y values according to @a pos.
*/
void setPos(const Point<T>& pos) noexcept;

/**
Move this rectangle by @a x and @a y values.
*/
void moveBy(const T& x, const T& y) noexcept;

/**
Move this rectangle by @a pos.
*/
void moveBy(const Point<T>& pos) noexcept;

/**
Set width.
*/
void setWidth(const T& width) noexcept;

/**
Set height.
*/
void setHeight(const T& height) noexcept;

/**
Set size using @a width and @a height.
*/
void setSize(const T& width, const T& height) noexcept;

/**
Set size.
*/
void setSize(const Size<T>& size) noexcept;

/**
Grow size by @a multiplier.
*/
void growBy(double multiplier) noexcept;

/**
Shrink size by @a divider.
*/
void shrinkBy(double divider) noexcept;

/**
Set rectangle using @a pos and @a size.
*/
void setRectangle(const Point<T>& pos, const Size<T>& size) noexcept;

/**
Set rectangle.
*/
void setRectangle(const Rectangle<T>& rect) noexcept;

/**
Check if this rectangle contains the point defined by @a X and @a Y.
*/
bool contains(const T& x, const T& y) const noexcept;

/**
Check if this rectangle contains the point @a pos.
*/
bool contains(const Point<T>& pos) const noexcept;

/**
Check if this rectangle contains X.
*/
bool containsX(const T& x) const noexcept;

/**
Check if this rectangle contains Y.
*/
bool containsY(const T& y) const noexcept;

/**
Draw this rectangle using the current OpenGL state.
*/
void draw();

/**
Draw lines (outline of this rectangle) using the current OpenGL state.
*/
void drawOutline();

Rectangle<T>& operator=(const Rectangle<T>& rect) noexcept;
Rectangle<T>& operator*=(double m) noexcept;
Rectangle<T>& operator/=(double d) noexcept;
bool operator==(const Rectangle<T>& size) const noexcept;
bool operator!=(const Rectangle<T>& size) const noexcept;

private:
Point<T> fPos;
Size<T> fSize;

void _draw(const bool outline);
};

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

END_NAMESPACE_DGL

#endif // DGL_GEOMETRY_HPP_INCLUDED

+ 0
- 147
dgl/Image.hpp View File

@@ -1,147 +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.
*/

#ifndef DGL_IMAGE_HPP_INCLUDED
#define DGL_IMAGE_HPP_INCLUDED

#include "Geometry.hpp"

START_NAMESPACE_DGL

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

/**
Base DGL Image class.

This is an Image class that handles raw image data in pixels.
You can init the image data on the contructor or later on by calling loadFromMemory().

To generate raw data useful for this class see the utils/png2rgba.py script.
Be careful when using a PNG without alpha channel, for those the format is 'GL_BGR'
instead of the default 'GL_BGRA'.

Images are drawn on screen via 2D textures.
*/
class Image
{
public:
/**
Constructor for a null Image.
*/
Image();

/**
Constructor using raw image data.
@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.
*/
Image(const char* const rawData, const Size<uint>& size, const GLenum format = GL_BGRA, const GLenum type = GL_UNSIGNED_BYTE);

/**
Constructor using another image data.
*/
Image(const Image& image);

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

/**
Load image data from memory.
@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.
*/
void loadFromMemory(const char* const rawData, const Size<uint>& size, const GLenum format = GL_BGRA, const GLenum type = GL_UNSIGNED_BYTE) noexcept;

/**
Check if this image is valid.
*/
bool isValid() const noexcept;

/**
Get width.
*/
uint getWidth() const noexcept;

/**
Get height.
*/
uint getHeight() const noexcept;

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

/**
Get the raw image data.
*/
const char* getRawData() const noexcept;

/**
Get the image format.
*/
GLenum getFormat() const noexcept;

/**
Get the image type.
*/
GLenum getType() const noexcept;

/**
Draw this image at (0, 0) point.
*/
void draw();

/**
Draw this image at (x, y) point.
*/
void drawAt(const int x, const int y);

/**
Draw this image at position @a pos.
*/
void drawAt(const Point<int>& pos);

Image& operator=(const Image& image) noexcept;
bool operator==(const Image& image) const noexcept;
bool operator!=(const Image& image) const noexcept;

private:
const char* fRawData;
Size<uint> fSize;
GLenum fFormat;
GLenum fType;
GLuint fTextureId;
bool fIsReady;
};

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

END_NAMESPACE_DGL

#endif // DGL_IMAGE_HPP_INCLUDED

+ 0
- 54
dgl/ImageAboutWindow.hpp View File

@@ -1,54 +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.
*/

#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

#endif // DGL_IMAGE_ABOUT_WINDOW_HPP_INCLUDED

+ 0
- 67
dgl/ImageButton.hpp View File

@@ -1,67 +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.
*/

#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

#endif // DGL_IMAGE_BUTTON_HPP_INCLUDED

+ 0
- 103
dgl/ImageKnob.hpp View File

@@ -1,103 +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.
*/

#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

#endif // DGL_IMAGE_KNOB_HPP_INCLUDED

+ 0
- 98
dgl/ImageSlider.hpp View File

@@ -1,98 +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.
*/

#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

#endif // DGL_IMAGE_SLIDER_HPP_INCLUDED

+ 0
- 65
dgl/ImageSwitch.hpp View File

@@ -1,65 +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.
*/

#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

#endif // DGL_IMAGE_SWITCH_HPP_INCLUDED

+ 0
- 84
dgl/Makefile View File

@@ -1,84 +0,0 @@
#!/usr/bin/make -f
# Makefile for dgl #
# ---------------- #
# Created by falkTX
#

include Makefile.mk

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

BUILD_C_FLAGS += $(DGL_FLAGS) -I. -Isrc
BUILD_CXX_FLAGS += $(DGL_FLAGS) -I. -Isrc
LINK_FLAGS += $(DGL_LIBS)

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

OBJS = \
src/App.cpp.o \
src/Color.cpp.o \
src/Geometry.cpp.o \
src/Image.cpp.o \
src/ImageAboutWindow.cpp.o \
src/ImageButton.cpp.o \
src/ImageKnob.cpp.o \
src/ImageSlider.cpp.o \
src/ImageSwitch.cpp.o \
src/NanoVG.cpp.o \
src/Widget.cpp.o

ifeq ($(MACOS),true)
OBJS += src/Window.mm.o
else
OBJS += src/Window.cpp.o
endif

TARGET = ../libdgl.a

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

all: $(TARGET)

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

../libdgl.a: $(OBJS)
rm -f $@
$(AR) crs $@ $^

../libdgl.dll: $(OBJS)
# -Wl,--output-def,$@.def,--out-implib,$@.a
$(CXX) $^ -shared $(LINK_FLAGS) -o $@

../libdgl.dylib: $(OBJS)
$(CXX) $^ -dynamiclib $(LINK_FLAGS) -o $@

../libdgl.so: $(OBJS)
$(CXX) $^ -shared $(LINK_FLAGS) -o $@

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

%.c.o: %.c
$(CC) $< $(BUILD_C_FLAGS) -c -o $@

%.cpp.o: %.cpp
$(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@

src/Window.cpp.o: src/Window.cpp src/pugl/*
$(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@

src/Window.mm.o: src/Window.cpp src/pugl/*
$(CXX) $< $(BUILD_CXX_FLAGS) -ObjC++ -c -o $@

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

clean:
rm -f src/*.d src/*.o ../libdgl.*

debug:
$(MAKE) DEBUG=true

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

-include $(OBJS:%.o=%.d)

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

+ 0
- 132
dgl/Makefile.mk View File

@@ -1,132 +0,0 @@
#!/usr/bin/make -f
# Makefile for dgl #
# ---------------- #
# Created by falkTX
#

AR ?= ar
CC ?= gcc
CXX ?= g++

# --------------------------------------------------------------
# Fallback to Linux if no other OS defined

ifneq ($(HAIKU),true)
ifneq ($(MACOS),true)
ifneq ($(WIN32),true)
LINUX=true
endif
endif
endif

# --------------------------------------------------------------
# Set build and link flags

BASE_FLAGS = -Wall -Wextra -pipe -MD -MP
BASE_OPTS = -O2 -ffast-math -mtune=generic -msse -msse2 -fdata-sections -ffunction-sections

ifneq ($(MACOS),true)
# MacOS doesn't support this
BASE_OPTS += -mfpmath=sse
endif

ifeq ($(MACOS),true)
# MacOS linker flags
LINK_OPTS = -fdata-sections -ffunction-sections -Wl,-dead_strip -Wl,-dead_strip_dylibs
else
# Common linker flags
LINK_OPTS = -fdata-sections -ffunction-sections -Wl,--gc-sections -Wl,-O1 -Wl,--as-needed -Wl,--strip-all
endif

ifeq ($(RASPPI),true)
# Raspberry-Pi optimization flags
BASE_OPTS = -O2 -ffast-math -march=armv6 -mfpu=vfp -mfloat-abi=hard
LINK_OPTS = -Wl,-O1 -Wl,--as-needed -Wl,--strip-all
endif

ifeq ($(PANDORA),true)
# OpenPandora optimization flags
BASE_OPTS = -O2 -ffast-math -march=armv7-a -mcpu=cortex-a8 -mtune=cortex-a8 -mfpu=neon -mfloat-abi=softfp
LINK_OPTS = -Wl,-O1 -Wl,--as-needed -Wl,--strip-all
endif

ifneq ($(NOOPT),true)
# No optimization flags
BASE_OPTS = -O2 -ffast-math -fdata-sections -ffunction-sections
endif

ifneq ($(WIN32),true)
# not needed for Windows
BASE_FLAGS += -fPIC -DPIC
endif

ifeq ($(DEBUG),true)
BASE_FLAGS += -DDEBUG -O0 -g
LINK_OPTS =
else
BASE_FLAGS += -DNDEBUG $(BASE_OPTS) -fvisibility=hidden
CXXFLAGS += -fvisibility-inlines-hidden
endif

BUILD_C_FLAGS = $(BASE_FLAGS) -std=c99 -std=gnu99 $(CFLAGS)
BUILD_CXX_FLAGS = $(BASE_FLAGS) -std=c++0x -std=gnu++0x $(CXXFLAGS) $(CPPFLAGS)
LINK_FLAGS = $(LINK_OPTS) -Wl,--no-undefined $(LDFLAGS)

ifeq ($(MACOS),true)
# No C++11 support
BUILD_CXX_FLAGS = $(BASE_FLAGS) $(CXXFLAGS) $(CPPFLAGS)
LINK_FLAGS = $(LINK_OPTS) $(LDFLAGS)
endif

# --------------------------------------------------------------
# Strict test build

ifeq ($(TESTBUILD),true)
BASE_FLAGS += -Werror -Wcast-qual -Wconversion -Wformat -Wformat-security -Wredundant-decls -Wshadow -Wstrict-overflow -fstrict-overflow -Wundef -Wwrite-strings
BASE_FLAGS += -Wpointer-arith -Wabi -Winit-self -Wuninitialized -Wstrict-overflow=5
# BASE_FLAGS += -Wfloat-equal
ifeq ($(CC),clang)
BASE_FLAGS += -Wdocumentation -Wdocumentation-unknown-command
BASE_FLAGS += -Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-padded -Wno-exit-time-destructors -Wno-float-equal
else
BASE_FLAGS += -Wcast-align -Wunsafe-loop-optimizations
endif
ifneq ($(MACOS),true)
BASE_FLAGS += -Wmissing-declarations -Wsign-conversion
ifneq ($(CC),clang)
BASE_FLAGS += -Wlogical-op
endif
endif
CFLAGS += -Wold-style-definition -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes
CXXFLAGS += -Weffc++ -Wnon-virtual-dtor -Woverloaded-virtual
endif

# --------------------------------------------------------------
# Check for required libs

ifeq ($(LINUX),true)
ifneq ($(shell pkg-config --exists gl && echo true),true)
$(error OpenGL missing, cannot continue)
endif
ifneq ($(shell pkg-config --exists x11 && echo true),true)
$(error X11 missing, cannot continue)
endif
endif

# --------------------------------------------------------------
# Set libs stuff

ifeq ($(LINUX),true)
DGL_FLAGS = $(shell pkg-config --cflags gl x11)
DGL_LIBS = $(shell pkg-config --libs gl x11)
endif

ifeq ($(MACOS),true)
DGL_LIBS = -framework OpenGL -framework Cocoa
endif

ifeq ($(WIN32),true)
DGL_LIBS = -lopengl32 -lgdi32
endif

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

+ 0
- 799
dgl/NanoVG.hpp View File

@@ -1,799 +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.
*/

#ifndef DGL_NANO_WIDGET_HPP_INCLUDED
#define DGL_NANO_WIDGET_HPP_INCLUDED

#include "Color.hpp"
#include "Widget.hpp"

struct NVGcontext;
struct NVGpaint;

START_NAMESPACE_DGL

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

/**
NanoVG Image class.

This implements NanoVG images as a C++ class where deletion is handled automatically.
Images need to be created within a NanoVG or NanoWidget class.
*/
class NanoImage
{
public:
/**
Destructor.
*/
~NanoImage();

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

/**
Update image data.
*/
void updateImage(const uchar* const data);

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

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

void _updateSize();

DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(NanoImage)
};

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

/**
NanoVG class.

This class exposes the NanoVG drawing API.
All calls should be wrapped in beginFrame() and endFrame().

@section State Handling
NanoVG contains state which represents how paths will be rendered.
The state contains transform, fill and stroke styles, text and font styles, and scissor clipping.

@section Render styles
Fill and stroke render style can be either a solid color or a paint which is a gradient or a pattern.
Solid color is simply defined as a color value, different kinds of paints can be created
using linearGradient(), boxGradient(), radialGradient() and imagePattern().

Current render style can be saved and restored using save() and restore().

@section Transforms
The paths, gradients, patterns and scissor region are transformed by an transformation
matrix at the time when they are passed to the API.
The current transformation matrix is a affine matrix:
[sx kx tx]
[ky sy ty]
[ 0 0 1]
Where: sx,sy define scaling, kx,ky skewing, and tx,ty translation.
The last row is assumed to be 0,0,1 and is not stored.

Apart from resetTransform(), 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 save() and restore().

@section Images
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.

@section Paints
NanoVG supports four types of paints: linear gradient, box gradient, radial gradient and image pattern.
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
user interface cases like rendering a text edit or a timeline.

@section Paths
Drawing a new shape starts with beginPath(), it clears all the currently defined paths.
Then you define one or more paths and sub-paths which describe the shape. The are functions
to draw common shapes like rectangles and circles, and lower level step-by-step functions,
which allow to define a path curve by curve.

NanoVG uses even-odd fill rule to draw the shapes. Solid shapes should have counter clockwise
winding and holes should have counter clockwise order. To specify winding of a path you can
call pathWinding(). This is useful especially for the common shapes, which are drawn CCW.

Finally you can fill the path using current fill style by calling fill(), and stroke it
with current stroke style by calling stroke().

The curve segments and sub-paths are transformed by the current transform.

@section Text
NanoVG allows you to load .ttf files and use the font to render text.

The appearance of the text can be defined by setting the current text style
and by specifying the fill color. Common text and font settings such as
font size, letter spacing and text align are supported. Font blur allows you
to create simple text effects such as drop shadows.

At render time the font face can be set based on the font handles or name.

Font measure functions return values in local space, the calculations are
carried in the same resolution as the final rendering. This is done because
the text glyph positions are snapped to the nearest pixels sharp rendering.

The local space means that values are not rotated or scale as per the current
transformation. For example if you set font size to 12, which would mean that
line height is 16, then regardless of the current scaling and rotation, the
returned line height is always 16. Some measures may vary because of the scaling
since aforementioned pixel snapping.

While this may sound a little odd, the setup allows you to always render the
same way regardless of scaling. i.e. following works regardless of scaling:

@code
const char* txt = "Text me up.";
textBounds(vg, x,y, txt, NULL, bounds);
beginPath(vg);
roundedRect(vg, bounds[0], bounds[1], bounds[2]-bounds[0], bounds[3]-bounds[1]);
fill(vg);
@endcode

Note: currently only solid color fill is supported for text.
*/
class NanoVG
{
public:
enum Align {
// Horizontal align
ALIGN_LEFT = 1 << 0, // Align horizontally to left (default).
ALIGN_CENTER = 1 << 1, // Align horizontally to center.
ALIGN_RIGHT = 1 << 2, // Align horizontally to right.
// Vertical align
ALIGN_TOP = 1 << 3, // Align vertically to top.
ALIGN_MIDDLE = 1 << 4, // Align vertically to middle.
ALIGN_BOTTOM = 1 << 5, // Align vertically to bottom.
ALIGN_BASELINE = 1 << 6 // Align vertically to baseline (default).
};

enum Alpha {
STRAIGHT_ALPHA,
PREMULTIPLIED_ALPHA
};

enum LineCap {
BUTT,
ROUND,
SQUARE,
BEVEL,
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
};

enum Winding {
CCW = 1, // Winding for solid shapes
CW = 2 // Winding for holes
};

struct Paint {
float xform[6];
float extent[2];
float radius;
float feather;
Color innerColor;
Color outerColor;
int imageId;
PatternRepeat repeat;

Paint() noexcept;

/**
@internal
*/
Paint(const NVGpaint&) noexcept;
operator NVGpaint() const noexcept;
};

struct GlyphPosition {
const char* str; // Position of the glyph in the input string.
float x; // The x-coordinate of the logical glyph position.
float minx, maxx; // The bounds of the glyph shape.
};

struct TextRow {
const char* start; // Pointer to the input text where the row starts.
const char* end; // Pointer to the input text where the row ends (one past the last character).
const char* next; // Pointer to the beginning of the next row.
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 int FontId;

/**
Constructor.
Uses 512x512 as default atlas size.
*/
NanoVG();

/**
Constructor using custom text atlas size.
*/
NanoVG(const int textAtlasWidth, const int textAtlasHeight);

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

/**
Get the NanoVG context.
You should not need this under normal circumstances.
*/
NVGcontext* getContext() const noexcept
{
return fContext;
}

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

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

/**
Ends drawing flushing remaining render state.
*/
void endFrame();

/* --------------------------------------------------------------------
* State Handling */

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

/**
Pops and restores current render state.
*/
void restore();

/**
Resets current render state to default values. Does not affect the render state stack.
*/
void reset();

/* --------------------------------------------------------------------
* Render styles */

/**
Sets current stroke style to a solid color.
*/
void strokeColor(const Color& color);

/**
Sets current stroke style to a solid color, made from red, green, blue and alpha numeric values.
Values must be in [0..255] range.
*/
void strokeColor(const int red, const int green, const int blue, const int alpha = 255);

/**
Sets current stroke style to a solid color, made from red, green, blue and alpha numeric values.
Values must in [0..1] range.
*/
void strokeColor(const float red, const float green, const float blue, const float alpha = 1.0f);

/**
Sets current stroke style to a paint, which can be a one of the gradients or a pattern.
*/
void strokePaint(const Paint& paint);

/**
Sets current fill style to a solid color.
*/
void fillColor(const Color& color);

/**
Sets current fill style to a solid color, made from red, green, blue and alpha numeric values.
Values must be in [0..255] range.
*/
void fillColor(const int red, const int green, const int blue, const int alpha = 255);

/**
Sets current fill style to a solid color, made from red, green, blue and alpha numeric values.
Values must in [0..1] range.
*/
void fillColor(const float red, const float green, const float blue, const float alpha = 1.0f);

/**
Sets current fill style to a paint, which can be a one of the gradients or a pattern.
*/
void fillPaint(const Paint& paint);

/**
Sets the miter limit of the stroke style.
Miter limit controls when a sharp corner is beveled.
*/
void miterLimit(float limit);

/**
Sets the stroke width of the stroke style.
*/
void strokeWidth(float size);

/**
Sets how the end of the line (cap) is drawn,
Can be one of: BUTT, ROUND, SQUARE.
*/
void lineCap(LineCap cap = BUTT);

/**
Sets how sharp path corners are drawn.
Can be one of MITER, ROUND, BEVEL.
*/
void lineJoin(LineCap join = MITER);

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

/**
Resets current transform to a identity matrix.
*/
void resetTransform();

/**
Pre-multiplies current coordinate system by specified matrix.
The parameters are interpreted as matrix as follows:
[a c e]
[b d f]
[0 0 1]
*/
void transform(float a, float b, float c, float d, float e, float f);

/**
Translates current coordinate system.
*/
void translate(float x, float y);

/**
Rotates current coordinate system. Angle is specified in radians.
*/
void rotate(float angle);

/**
Skews the current coordinate system along X axis. Angle is specified in radians.
*/
void skewX(float angle);

/**
Skews the current coordinate system along Y axis. Angle is specified in radians.
*/
void skewY(float angle);

/**
Scales the current coordinate system.
*/
void scale(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]
*/
void currentTransform(float xform[6]);

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

/**
Sets the transform to identity matrix.
*/
static void transformIdentity(float dst[6]);

/**
Sets the transform to translation matrix
*/
static void transformTranslate(float dst[6], float tx, float ty);

/**
Sets the transform to scale matrix.
*/
static void transformScale(float dst[6], float sx, float sy);

/**
Sets the transform to rotate matrix. Angle is specified in radians.
*/
static void transformRotate(float dst[6], float a);

/**
Sets the transform to skew-x matrix. Angle is specified in radians.
*/
static void transformSkewX(float dst[6], float a);

/**
Sets the transform to skew-y matrix. Angle is specified in radians.
*/
static void transformSkewY(float dst[6], float a);

/**
Sets the transform to the result of multiplication of two transforms, of A = A*B.
*/
static void transformMultiply(float dst[6], const float src[6]);

/**
Sets the transform to the result of multiplication of two transforms, of A = B*A.
*/
static void transformPremultiply(float dst[6], const float src[6]);

/**
Sets the destination to inverse of specified transform.
Returns 1 if the inverse could be calculated, else 0.
*/
static int transformInverse(float dst[6], const float src[6]);

/**
Transform a point by given transform.
*/
static void transformPoint(float& dstx, float& dsty, const float xform[6], float srcx, float srcy);

/**
Convert degrees to radians.
*/
static float degToRad(float deg);

/**
Convert radians to degrees.
*/
static float radToDeg(float rad);

/* --------------------------------------------------------------------
* Images */

/**
Creates image by loading it from the disk from specified file name.
*/
NanoImage* createImage(const char* filename);

/**
Creates image by loading it from the specified chunk of memory.
*/
NanoImage* createImageMem(uchar* data, int ndata);

/**
Creates image from specified image data.
*/
NanoImage* createImageRGBA(uint w, uint h, const uchar* data);

/* --------------------------------------------------------------------
* Paints */

/**
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 fillPaint() or strokePaint().
*/
Paint linearGradient(float sx, float sy, float ex, float ey, const Color& icol, const Color& ocol);

/**
Creates and returns a box gradient. Box gradient is a feathered rounded rectangle, it is useful for rendering
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 fillPaint() or strokePaint().
*/
Paint boxGradient(float x, float y, float w, float h, float r, float f, const Color& icol, const Color& 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 fillPaint() or strokePaint().
*/
Paint radialGradient(float cx, float cy, float inr, float outr, const Color& icol, const Color& ocol);

/**
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.
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);

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

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

/**
Reset and disables scissoring.
*/
void resetScissor();

/* --------------------------------------------------------------------
* Paths */

/**
Clears the current path and sub-paths.
*/
void beginPath();

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

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

/**
Adds 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 an arc segment at the corner defined by the last path point, and two specified points.
*/
void arcTo(float x1, float y1, float x2, float y2, float radius);

/**
Closes current sub-path with a line segment.
*/
void closePath();

/**
Sets the current sub-path winding.
*/
void pathWinding(Winding dir);

/**
Creates new arc shaped sub-path.
*/
void arc(float cx, float cy, float r, float a0, float a1, Winding dir);

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

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

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

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

/**
Fills the current path with current fill style.
*/
void fill();

/**
Fills the current path with current stroke style.
*/
void stroke();

/* --------------------------------------------------------------------
* Text */

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

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

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

/**
Sets the font size of current text style.
*/
void fontSize(float size);

/**
Sets the blur of current text style.
*/
void fontBlur(float blur);

/**
Sets the letter spacing of current text style.
*/
void textLetterSpacing(float spacing);

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

/**
Sets the text align of current text style.
*/
void textAlign(Align align);

/**
Sets the text align of current text style.
Overloaded function for convenience.
@see Align
*/
void textAlign(int align);

/**
Sets the font face based on specified id of current text style.
*/
void fontFaceId(FontId font);

/**
Sets the font face based on specified name of current text style.
*/
void fontFace(const char* font);

/**
Draws text string at specified location. If end is specified only the sub-string up to the end is drawn.
*/
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.
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);

/**
Measures the specified text string. 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 textBounds(float x, float y, const char* string, const char* end, Rectangle<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 textBoxBounds(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 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.
Measured values are returned in local coordinate space.
*/
void textMetrics(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 textBreakLines(const char* string, const char* end, float breakRowWidth, TextRow* rows, int maxRows);

private:
NVGcontext* const fContext;
bool fInFrame;

DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(NanoVG)
};

// -----------------------------------------------------------------------
// NanoWidget

/**
NanoVG Widget class.

This class implements the NanoVG drawing API inside a DGL Widget.
The drawing function onDisplay() is implemented internally but a
new onNanoDisplay() needs to be overridden instead.
*/
class NanoWidget : public Widget,
public NanoVG
{
public:
/**
Constructor.
*/
NanoWidget(Window& parent)
: Widget(parent),
NanoVG(),
leakDetector_NanoWidget()
{
setNeedsScaling(true);
}

protected:
/**
New virtual onDisplay function.
@see onDisplay
*/
virtual void onNanoDisplay() = 0;

private:
/**
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);
}

DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(NanoWidget)
};

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

END_NAMESPACE_DGL

#endif // DGL_NANO_WIDGET_HPP_INCLUDED

+ 0
- 81
dgl/StandaloneWindow.hpp View File

@@ -1,81 +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.
*/

#ifndef DGL_STANDALONE_WINDOW_HPP_INCLUDED
#define DGL_STANDALONE_WINDOW_HPP_INCLUDED

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

START_NAMESPACE_DGL

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

class StandaloneWindow : public App,
public Window
{
public:
StandaloneWindow()
: App(),
Window((App&)*this),
fWidget(nullptr) {}

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

private:
Widget* fWidget;

void _addWidget(Widget* widget) override
{
if (fWidget == nullptr)
{
fWidget = widget;
fWidget->setNeedsFullViewport(true);
}
Window::_addWidget(widget);
}

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

DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(StandaloneWindow)
};

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

END_NAMESPACE_DGL

#endif // DGL_STANDALONE_WINDOW_HPP_INCLUDED

+ 0
- 387
dgl/Widget.hpp View File

@@ -1,387 +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.
*/

#ifndef DGL_WIDGET_HPP_INCLUDED
#define DGL_WIDGET_HPP_INCLUDED

#include "Geometry.hpp"

START_NAMESPACE_DGL

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

class App;
class Window;
class StandaloneWindow;

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

/**
Base DGL Widget class.

This is the base Widget class, from which all widgets are built.

All widgets have a parent Window where they'll be drawn.
This parent is never changed during the widget lifetime.

Widgets receive events in relative coordinates.
(0, 0) means its top-left position.

Windows paint widgets in the order they are constructed.
Early widgets are drawn first, at the bottom, then newer ones on top.
Events are sent in the inverse order so that the top-most widget gets
a chance to catch the event and stop its propagation.

All widget event callbacks do nothing by default.
*/
class Widget
{
public:
/**
Base event data.
@a mod The currently active keyboard modifiers, @see Modifier.
@a time The timestamp (if any).
*/
struct BaseEvent {
uint mod;
uint32_t time;

/** Constuctor */
BaseEvent() noexcept : mod(0x0), time(0) {}
/** Destuctor */
virtual ~BaseEvent() noexcept {}
};

/**
Keyboard event.
@a press True if the key was pressed, false if released.
@a key Unicode point of the key pressed.
@see onKeyboard
*/
struct KeyboardEvent : BaseEvent {
bool press;
uint key;

/** Constuctor */
KeyboardEvent() noexcept
: BaseEvent(),
press(false),
key(0) {}
};

/**
Special keyboard event.
@a press True if the key was pressed, false if released.
@a key The key pressed.
@see onSpecial
*/
struct SpecialEvent : BaseEvent {
bool press;
Key key;

/** Constuctor */
SpecialEvent() noexcept
: BaseEvent(),
press(false),
key(Key(0)) {}
};

/**
Mouse event.
@a button The button number (1 = left, 2 = middle, 3 = right).
@a press True if the key was pressed, false if released.
@a pos The widget-relative coordinates of the pointer.
@see onMouse
*/
struct MouseEvent : BaseEvent {
int button;
bool press;
Point<int> pos;

/** Constuctor */
MouseEvent() noexcept
: BaseEvent(),
button(0),
press(false),
pos(0, 0) {}
};

/**
Mouse motion event.
@a pos The widget-relative coordinates of the pointer.
@see onMotion
*/
struct MotionEvent : BaseEvent {
Point<int> pos;

/** Constuctor */
MotionEvent() noexcept
: BaseEvent(),
pos(0, 0) {}
};

/**
Mouse scroll event.
@a pos The widget-relative coordinates of the pointer.
@a delta The scroll distance.
@see onScroll
*/
struct ScrollEvent : BaseEvent {
Point<int> pos;
Point<float> delta;

/** Constuctor */
ScrollEvent() noexcept
: BaseEvent(),
pos(0, 0),
delta(0.0f, 0.0f) {}
};

/**
Resize event.
@a size The new widget size.
@a oldSize The previous size, may be null.
@see onResize
*/
struct ResizeEvent {
Size<uint> size;
Size<uint> oldSize;

/** Constuctor */
ResizeEvent() noexcept
: size(0, 0),
oldSize(0, 0) {}
};

/**
Constructor.
*/
explicit Widget(Window& parent);

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

/**
Check if this widget is visible within its parent window.
Invisible widgets do not receive events except resize.
*/
bool isVisible() const noexcept;

/**
Set widget visible (or not) according to @a yesNo.
*/
void setVisible(bool yesNo);

/**
Show widget.
This is the same as calling setVisible(true).
*/
void show();

/**
Hide widget.
This is the same as calling setVisible(false).
*/
void hide();

/**
Get width.
*/
uint getWidth() const noexcept;

/**
Get height.
*/
uint getHeight() const noexcept;

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

/**
Set width.
*/
void setWidth(uint width) noexcept;

/**
Set height.
*/
void setHeight(uint height) noexcept;

/**
Set size using @a width and @a height values.
*/
void setSize(uint width, uint height) noexcept;

/**
Set size.
*/
void setSize(const Size<uint>& size) noexcept;

/**
Get absolute X.
*/
int getAbsoluteX() const noexcept;

/**
Get absolute Y.
*/
int getAbsoluteY() const noexcept;

/**
Get absolute position.
*/
const Point<int>& getAbsolutePos() const noexcept;

/**
Set absolute X.
*/
void setAbsoluteX(int x) noexcept;

/**
Set absolute Y.
*/
void setAbsoluteY(int y) noexcept;

/**
Set absolute position using @a x and @a y values.
*/
void setAbsolutePos(int x, int y) noexcept;

/**
Set absolute position.
*/
void setAbsolutePos(const Point<int>& pos) noexcept;

/**
Get this widget's window application.
Same as calling getParentWindow().getApp().
*/
App& getParentApp() const noexcept;

/**
Get parent window, as passed in the constructor.
*/
Window& getParentWindow() const noexcept;

/**
Check if this widget contains the point defined by @a x and @a y.
*/
bool contains(int x, int y) const noexcept;

/**
Check if this widget contains the point @a pos.
*/
bool contains(const Point<int>& pos) const noexcept;

/**
Tell this widget's window to repaint itself.
*/
void repaint() noexcept;

/**
Get the Id associated with this widget.
@see setId
*/
uint getId() const noexcept;

/**
Set an Id to be associated with this widget.
@see getId
*/
void setId(uint id) noexcept;

protected:
/**
A function called to draw the view contents with OpenGL.
*/
virtual void onDisplay() = 0;

/**
A function called when a key is pressed or released.
@return True to stop event propagation, false otherwise.
*/
virtual bool onKeyboard(const KeyboardEvent&);

/**
A function called when a special key is pressed or released.
@return True to stop event propagation, false otherwise.
*/
virtual bool onSpecial(const SpecialEvent&);

/**
A function called when a mouse button is pressed or released.
@return True to stop event propagation, false otherwise.
*/
virtual bool onMouse(const MouseEvent&);

/**
A function called when the pointer moves.
@return True to stop event propagation, false otherwise.
*/
virtual bool onMotion(const MotionEvent&);

/**
A function called on scrolling (e.g. mouse wheel or track pad).
@return True to stop event propagation, false otherwise.
*/
virtual bool onScroll(const ScrollEvent&);

/**
A function called when the widget is resized.
*/
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;

friend class Window;
friend class StandaloneWindow;

DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(Widget)
};

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

END_NAMESPACE_DGL

#endif // DGL_WIDGET_HPP_INCLUDED

+ 0
- 134
dgl/Window.hpp View File

@@ -1,134 +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.
*/

#ifndef DGL_WINDOW_HPP_INCLUDED
#define DGL_WINDOW_HPP_INCLUDED

#include "Geometry.hpp"

START_NAMESPACE_DGL

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

class App;
class Widget;
class StandaloneWindow;

class Window
{
public:
/**
File browser options.
*/
struct FileBrowserOptions {
const char* startDir;
const char* title;
uint width;
uint height;

/**
File browser buttons.

0 means hidden.
1 means visible and unchecked.
2 means visible and checked.
*/
struct Buttons {
uint listAllFiles;
uint showHidden;
uint showPlaces;

/** Constuctor for default values */
Buttons()
: listAllFiles(2),
showHidden(1),
showPlaces(1) {}
} buttons;

/** Constuctor for default values */
FileBrowserOptions()
: startDir(nullptr),
title(nullptr),
width(0),
height(0),
buttons() {}
};

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

void show();
void hide();
void close();
void exec(bool lockWait = false);

void focus();
void repaint() noexcept;

bool openFileBrowser(const FileBrowserOptions& options);

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

bool isResizable() const noexcept;
void setResizable(bool yesNo);

uint getWidth() const noexcept;
uint getHeight() const noexcept;
Size<uint> getSize() const noexcept;
void setSize(uint width, uint height);
void setSize(Size<uint> size);

const char* getTitle() const noexcept;
void setTitle(const char* title);

void setTransientWinId(uintptr_t winId);

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

void addIdleCallback(IdleCallback* const callback);
void removeIdleCallback(IdleCallback* const callback);

protected:
virtual void onDisplayBefore();
virtual void onDisplayAfter();
virtual void onReshape(uint width, uint height);
virtual void onClose();

virtual void fileBrowserSelected(const char* filename);

private:
struct PrivateData;
PrivateData* const pData;
friend class App;
friend class Widget;
friend class StandaloneWindow;

virtual void _addWidget(Widget* const widget);
virtual void _removeWidget(Widget* const widget);
void _idle();

DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(Window)
};

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

END_NAMESPACE_DGL

#endif // DGL_WINDOW_HPP_INCLUDED

+ 0
- 75
dgl/src/App.cpp View File

@@ -1,75 +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 "AppPrivateData.hpp"
#include "../Window.hpp"

START_NAMESPACE_DGL

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

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

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

void App::idle()
{
for (std::list<Window*>::iterator it = pData->windows.begin(), ite = pData->windows.end(); it != ite; ++it)
{
Window* const window(*it);
window->_idle();
}

for (std::list<IdleCallback*>::iterator it = pData->idleCallbacks.begin(), ite = pData->idleCallbacks.end(); it != ite; ++it)
{
IdleCallback* const idleCallback(*it);
idleCallback->idleCallback();
}
}

void App::exec()
{
for (; pData->doLoop;)
{
idle();
d_msleep(10);
}
}

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

for (std::list<Window*>::reverse_iterator rit = pData->windows.rbegin(), rite = pData->windows.rend(); rit != rite; ++rit)
{
Window* const window(*rit);
window->close();
}
}

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

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

END_NAMESPACE_DGL

+ 0
- 71
dgl/src/AppPrivateData.hpp View File

@@ -1,71 +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.
*/

#ifndef DGL_APP_PRIVATE_DATA_HPP_INCLUDED
#define DGL_APP_PRIVATE_DATA_HPP_INCLUDED

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

#include <list>

START_NAMESPACE_DGL

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

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

PrivateData()
: doLoop(true),
visibleWindows(0),
windows(),
idleCallbacks() {}

~PrivateData()
{
DISTRHO_SAFE_ASSERT(! doLoop);
DISTRHO_SAFE_ASSERT(visibleWindows == 0);

windows.clear();
idleCallbacks.clear();
}

void oneShown() noexcept
{
if (++visibleWindows == 1)
doLoop = true;
}

void oneHidden() noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(visibleWindows > 0,);

if (--visibleWindows == 0)
doLoop = false;
}

DISTRHO_DECLARE_NON_COPY_STRUCT(PrivateData)
};

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

END_NAMESPACE_DGL

#endif // DGL_APP_PRIVATE_DATA_HPP_INCLUDED

+ 0
- 245
dgl/src/Color.cpp View File

@@ -1,245 +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 "../Color.hpp"

#include "nanovg/nanovg.h"

START_NAMESPACE_DGL

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

static void fixRange(float& value)
{
/**/ if (value < 0.0f)
value = 0.0f;
else if (value > 1.0f)
value = 1.0f;
}

static float getFixedRange(const float& value)
{
if (value <= 0.0f)
return 0.0f;
if (value >= 1.0f)
return 1.0f;
return value;
}

static uchar getFixedRange2(const float& value)
{
const float value2(getFixedRange(value)*255.0f);
if (value2 <= 0.0f)
return 0;
if (value2 >= 255.0f)
return 255;
return static_cast<uchar>(value2);
}

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

Color::Color() noexcept
: red(1.0f),
green(1.0f),
blue(1.0f),
alpha(1.0f) {}

Color::Color(int r, int g, int b, int a) noexcept
: red(static_cast<float>(r)/255.0f),
green(static_cast<float>(g)/255.0f),
blue(static_cast<float>(b)/255.0f),
alpha(static_cast<float>(a)/255.0f)
{
fixBounds();
}

Color::Color(float r, float g, float b, float a) noexcept
: red(r),
green(g),
blue(b),
alpha(a)
{
fixBounds();
}

Color::Color(const Color& color) noexcept
: red(color.red),
green(color.green),
blue(color.blue),
alpha(color.alpha)
{
fixBounds();
}

Color& Color::operator=(const Color& color) noexcept
{
red = color.red;
green = color.green;
blue = color.blue;
alpha = color.alpha;
fixBounds();
return *this;
}

Color::Color(const Color& color1, const Color& color2, float u) noexcept
: red(color1.red),
green(color1.green),
blue(color1.blue),
alpha(color1.alpha)
{
interpolate(color2, u);
}

Color Color::fromHSL(float hue, float saturation, float lightness, float alpha)
{
return nvgHSLA(hue, saturation, lightness, static_cast<uchar>(getFixedRange(alpha)*255.0f));
}

Color Color::fromHTML(const char* rgb, float alpha)
{
Color fallback;
DISTRHO_SAFE_ASSERT_RETURN(rgb != nullptr && rgb[0] != '\0', fallback);

if (rgb[0] == '#') ++rgb;
DISTRHO_SAFE_ASSERT_RETURN(rgb[0] != '\0', fallback);

std::size_t rgblen(std::strlen(rgb));
DISTRHO_SAFE_ASSERT_RETURN(rgblen == 3 || rgblen == 6, fallback);

char rgbtmp[3] = { '\0', '\0', '\0' };
int r, g, b;

if (rgblen == 3)
{
rgbtmp[0] = rgb[0];
r = static_cast<int>(std::strtol(rgbtmp, nullptr, 16));

rgbtmp[0] = rgb[1];
g = static_cast<int>(std::strtol(rgbtmp, nullptr, 16));

rgbtmp[0] = rgb[2];
b = static_cast<int>(std::strtol(rgbtmp, nullptr, 16));
}
else
{
rgbtmp[0] = rgb[0];
rgbtmp[1] = rgb[1];
r = static_cast<int>(std::strtol(rgbtmp, nullptr, 16));

rgbtmp[0] = rgb[2];
rgbtmp[1] = rgb[3];
g = static_cast<int>(std::strtol(rgbtmp, nullptr, 16));

rgbtmp[0] = rgb[4];
rgbtmp[1] = rgb[5];
b = static_cast<int>(std::strtol(rgbtmp, nullptr, 16));
}

return Color(r, g, b, static_cast<int>(getFixedRange(alpha)*255.0f));
}

void Color::interpolate(const Color& other, float u) noexcept
{
fixRange(u);
const float oneMinusU(1.0f - u);

red = red * oneMinusU + other.red * u;
green = green * oneMinusU + other.green * u;
blue = blue * oneMinusU + other.blue * u;
alpha = alpha * oneMinusU + other.alpha * u;

fixBounds();
}

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

bool Color::isEqual(const Color& color, bool withAlpha) noexcept
{
const uchar r1 = getFixedRange2(rgba[0]);
const uchar g1 = getFixedRange2(rgba[1]);
const uchar b1 = getFixedRange2(rgba[2]);
const uchar a1 = getFixedRange2(rgba[3]);

const uchar r2 = getFixedRange2(color.rgba[0]);
const uchar g2 = getFixedRange2(color.rgba[1]);
const uchar b2 = getFixedRange2(color.rgba[2]);
const uchar a2 = getFixedRange2(color.rgba[3]);

if (withAlpha)
return (r1 == r2 && g1 == g2 && b1 == b2 && a1 == a2);
else
return (r1 == r2 && g1 == g2 && b1 == b2);
}

bool Color::isNotEqual(const Color& color, bool withAlpha) noexcept
{
const uchar r1 = getFixedRange2(rgba[0]);
const uchar g1 = getFixedRange2(rgba[1]);
const uchar b1 = getFixedRange2(rgba[2]);
const uchar a1 = getFixedRange2(rgba[3]);

const uchar r2 = getFixedRange2(color.rgba[0]);
const uchar g2 = getFixedRange2(color.rgba[1]);
const uchar b2 = getFixedRange2(color.rgba[2]);
const uchar a2 = getFixedRange2(color.rgba[3]);

if (withAlpha)
return (r1 != r2 || g1 != g2 || b1 != b2 || a1 != a2);
else
return (r1 != r2 || g1 != g2 || b1 != b2);
}

bool Color::operator==(const Color& color) noexcept
{
return isEqual(color, true);
}

bool Color::operator!=(const Color& color) noexcept
{
return isNotEqual(color, true);
}

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

void Color::fixBounds() noexcept
{
fixRange(red);
fixRange(green);
fixRange(blue);
fixRange(alpha);
}

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

Color::Color(const NVGcolor& c) noexcept
: red(c.r), green(c.g), blue(c.b), alpha(c.a)
{
fixBounds();
}

Color::operator NVGcolor() const noexcept
{
NVGcolor nc;
nc.r = red;
nc.g = green;
nc.b = blue;
nc.a = alpha;
return nc;
}

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

END_NAMESPACE_DGL

+ 0
- 1072
dgl/src/Geometry.cpp
File diff suppressed because it is too large
View File


+ 0
- 192
dgl/src/Image.cpp View File

@@ -1,192 +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 "../Image.hpp"

START_NAMESPACE_DGL

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

Image::Image()
: fRawData(nullptr),
fSize(0, 0),
fFormat(0),
fType(0),
fTextureId(0),
fIsReady(false)
{
glGenTextures(1, &fTextureId);
}

Image::Image(const char* const rawData, const uint width, const uint height, const GLenum format, const GLenum type)
: fRawData(rawData),
fSize(width, height),
fFormat(format),
fType(type),
fTextureId(0),
fIsReady(false)
{
glGenTextures(1, &fTextureId);
}

Image::Image(const char* const rawData, const Size<uint>& size, const GLenum format, const GLenum type)
: fRawData(rawData),
fSize(size),
fFormat(format),
fType(type),
fTextureId(0),
fIsReady(false)
{
glGenTextures(1, &fTextureId);
}

Image::Image(const Image& image)
: fRawData(image.fRawData),
fSize(image.fSize),
fFormat(image.fFormat),
fType(image.fType),
fTextureId(0),
fIsReady(false)
{
glGenTextures(1, &fTextureId);
}

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

void Image::loadFromMemory(const char* const rawData, const uint width, const uint height, const GLenum format, const GLenum type) noexcept
{
loadFromMemory(rawData, Size<uint>(width, height), format, type);
}

void Image::loadFromMemory(const char* const rawData, const Size<uint>& size, const GLenum format, const GLenum type) noexcept
{
fRawData = rawData;
fSize = size;
fFormat = format;
fType = type;
fIsReady = false;
}

bool Image::isValid() const noexcept
{
return (fRawData != nullptr && fSize.getWidth() > 0 && fSize.getHeight() > 0);
}

uint Image::getWidth() const noexcept
{
return fSize.getWidth();
}

uint Image::getHeight() const noexcept
{
return fSize.getHeight();
}

const Size<uint>& Image::getSize() const noexcept
{
return fSize;
}

const char* Image::getRawData() const noexcept
{
return fRawData;
}

GLenum Image::getFormat() const noexcept
{
return fFormat;
}

GLenum Image::getType() const noexcept
{
return fType;
}

void Image::draw()
{
drawAt(0, 0);
}

void Image::drawAt(const int x, const int y)
{
drawAt(Point<int>(x, y));
}

void Image::drawAt(const Point<int>& pos)
{
if (fTextureId == 0 || ! isValid())
return;

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);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
static_cast<GLsizei>(fSize.getWidth()), static_cast<GLsizei>(fSize.getHeight()), 0,
fFormat, fType, fRawData);

fIsReady = true;
}

Rectangle<int>(pos, static_cast<int>(fSize.getWidth()), static_cast<int>(fSize.getHeight())).draw();

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

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

Image& Image::operator=(const Image& image) noexcept
{
fRawData = image.fRawData;
fSize = image.fSize;
fFormat = image.fFormat;
fType = image.fType;
fIsReady = false;
return *this;
}

bool Image::operator==(const Image& image) const noexcept
{
return (fRawData == image.fRawData && fSize == image.fSize);
}

bool Image::operator!=(const Image& image) const noexcept
{
return !operator==(image);
}

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

END_NAMESPACE_DGL

+ 0
- 89
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
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
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
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
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

+ 0
- 780
dgl/src/NanoVG.cpp View File

@@ -1,780 +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 "../NanoVG.hpp"
#include "../Window.hpp"

// -----------------------------------------------------------------------
// Ignore some warnings if debugging

#if 0 //def DEBUG
# define NANOVG_GL3 0
# define NANOVG_GLES2 0
# define NANOVG_GLES3 0
# define NANOVG_GL_USE_UNIFORMBUFFER 0
# if defined(__clang__)
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Weverything"
# elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wall"
# pragma GCC diagnostic ignored "-Wextra"
# pragma GCC diagnostic ignored "-Wconversion"
# pragma GCC diagnostic ignored "-Weffc++"
# pragma GCC diagnostic ignored "-Wsign-conversion"
# pragma GCC diagnostic ignored "-Wundef"
# pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
# endif
#endif

// -----------------------------------------------------------------------
// Include NanoVG OpenGL implementation

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

#if defined(NANOVG_GL2)
# define nvgCreateGL nvgCreateGL2
# define nvgDeleteGL nvgDeleteGL2
#elif defined(NANOVG_GL3)
# define nvgCreateGL nvgCreateGL3
# define nvgDeleteGL nvgDeleteGL3
#elif defined(NANOVG_GLES2)
# define nvgCreateGL nvgCreateGLES2
# define nvgDeleteGL nvgDeleteGLES2
#elif defined(NANOVG_GLES3)
# define nvgCreateGL nvgCreateGLES3
# define nvgDeleteGL nvgDeleteGLES3
#endif

// -----------------------------------------------------------------------
// Restore normal state if debugging

#if 0//def DEBUG
# if defined(__clang__)
# pragma clang diagnostic pop
# elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
# pragma GCC diagnostic pop
# endif
#endif

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

START_NAMESPACE_DGL

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

NanoVG::Paint::Paint() noexcept
: radius(0.0f), feather(0.0f), innerColor(), outerColor(), imageId(0), repeat(REPEAT_NONE)
{
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), repeat(static_cast<PatternRepeat>(p.repeat))
{
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;
p.repeat = repeat;
std::memcpy(p.xform, xform, sizeof(float)*6);
std::memcpy(p.extent, extent, sizeof(float)*2);
return p;
}

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

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

NanoImage::~NanoImage()
{
if (fContext != nullptr && fImageId != 0)
nvgDeleteImage(fContext, fImageId);
}

Size<uint> NanoImage::getSize() const noexcept
{
return fSize;
}

void NanoImage::updateImage(const uchar* const data)
{
DISTRHO_SAFE_ASSERT_RETURN(data != nullptr,);

if (fContext != nullptr && fImageId != 0)
{
nvgUpdateImage(fContext, fImageId, data);
_updateSize();
}
}

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

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

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

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

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

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

NanoVG::NanoVG(const int textAtlasWidth, const int textAtlasHeight)
: fContext(nvgCreateGL(textAtlasWidth, textAtlasHeight, NVG_ANTIALIAS)),
fInFrame(false),
leakDetector_NanoVG()
{
DISTRHO_SAFE_ASSERT_RETURN(fContext != nullptr,);
}

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

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

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

void NanoVG::beginFrame(const uint width, const uint height, const float scaleFactor, const Alpha alpha)
{
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));
}

void NanoVG::beginFrame(Widget* const widget)
{
if (fContext == nullptr) return;
DISTRHO_SAFE_ASSERT_RETURN(widget != nullptr,);
DISTRHO_SAFE_ASSERT_RETURN(! fInFrame,);

Window& window(widget->getParentWindow());

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

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

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

fInFrame = false;
}

// -----------------------------------------------------------------------
// State Handling

void NanoVG::save()
{
if (fContext != nullptr)
nvgSave(fContext);
}

void NanoVG::restore()
{
if (fContext != nullptr)
nvgRestore(fContext);
}

void NanoVG::reset()
{
if (fContext != nullptr)
nvgReset(fContext);
}

// -----------------------------------------------------------------------
// Render styles

void NanoVG::strokeColor(const Color& color)
{
if (fContext != nullptr)
nvgStrokeColor(fContext, color);
}

void NanoVG::strokeColor(const int red, const int green, const int blue, const int alpha)
{
if (fContext != nullptr)
{
DISTRHO_SAFE_ASSERT_RETURN(red >= 0 && red <= 255,);
DISTRHO_SAFE_ASSERT_RETURN(green >= 0 && green <= 255,);
DISTRHO_SAFE_ASSERT_RETURN(blue >= 0 && blue <= 255,);
DISTRHO_SAFE_ASSERT_RETURN(alpha >= 0 && alpha <= 255,);

nvgStrokeColor(fContext, nvgRGBA(static_cast<uchar>(red),
static_cast<uchar>(green),
static_cast<uchar>(blue),
static_cast<uchar>(alpha)));
}
}

void NanoVG::strokeColor(const float red, const float green, const float blue, const float alpha)
{
if (fContext != nullptr)
nvgStrokeColor(fContext, nvgRGBAf(red, green, blue, alpha));
}

void NanoVG::strokePaint(const Paint& paint)
{
if (fContext != nullptr)
nvgStrokePaint(fContext, paint);
}

void NanoVG::fillColor(const Color& color)
{
if (fContext != nullptr)
nvgFillColor(fContext, color);
}

void NanoVG::fillColor(const int red, const int green, const int blue, const int alpha)
{
if (fContext != nullptr)
{
DISTRHO_SAFE_ASSERT_RETURN(red >= 0 && red <= 255,);
DISTRHO_SAFE_ASSERT_RETURN(green >= 0 && green <= 255,);
DISTRHO_SAFE_ASSERT_RETURN(blue >= 0 && blue <= 255,);
DISTRHO_SAFE_ASSERT_RETURN(alpha >= 0 && alpha <= 255,);

nvgFillColor(fContext, nvgRGBA(static_cast<uchar>(red),
static_cast<uchar>(green),
static_cast<uchar>(blue),
static_cast<uchar>(alpha)));
}
}

void NanoVG::fillColor(const float red, const float green, const float blue, const float alpha)
{
if (fContext != nullptr)
nvgFillColor(fContext, nvgRGBAf(red, green, blue, alpha));
}

void NanoVG::fillPaint(const Paint& paint)
{
if (fContext != nullptr)
nvgFillPaint(fContext, paint);
}

void NanoVG::miterLimit(float limit)
{
if (fContext == nullptr) return;
DISTRHO_SAFE_ASSERT_RETURN(limit > 0.0f,);

nvgMiterLimit(fContext, limit);
}

void NanoVG::strokeWidth(float size)
{
if (fContext == nullptr) return;
DISTRHO_SAFE_ASSERT_RETURN(size > 0.0f,);

nvgStrokeWidth(fContext, size);
}

void NanoVG::lineCap(NanoVG::LineCap cap)
{
if (fContext != nullptr)
nvgLineCap(fContext, cap);
}

void NanoVG::lineJoin(NanoVG::LineCap join)
{
if (fContext != nullptr)
nvgLineJoin(fContext, join);
}

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

void NanoVG::resetTransform()
{
if (fContext != nullptr)
nvgResetTransform(fContext);
}

void NanoVG::transform(float a, float b, float c, float d, float e, float f)
{
if (fContext != nullptr)
nvgTransform(fContext, a, b, c, d, e, f);
}

void NanoVG::translate(float x, float y)
{
if (fContext != nullptr)
nvgTranslate(fContext, x, y);
}

void NanoVG::rotate(float angle)
{
if (fContext == nullptr) return;
DISTRHO_SAFE_ASSERT_RETURN(angle > 0.0f,);

nvgRotate(fContext, angle);
}

void NanoVG::skewX(float angle)
{
if (fContext == nullptr) return;
DISTRHO_SAFE_ASSERT_RETURN(angle > 0.0f,);

nvgSkewX(fContext, angle);
}

void NanoVG::skewY(float angle)
{
if (fContext == nullptr) return;
DISTRHO_SAFE_ASSERT_RETURN(angle > 0.0f,);

nvgSkewY(fContext, angle);
}

void NanoVG::scale(float x, float y)
{
if (fContext == nullptr) return;
DISTRHO_SAFE_ASSERT_RETURN(x > 0.0f,);
DISTRHO_SAFE_ASSERT_RETURN(y > 0.0f,);

nvgScale(fContext, x, y);
}

void NanoVG::currentTransform(float xform[6])
{
if (fContext != nullptr)
nvgCurrentTransform(fContext, xform);
}

void NanoVG::transformIdentity(float dst[6])
{
nvgTransformIdentity(dst);
}

void NanoVG::transformTranslate(float dst[6], float tx, float ty)
{
nvgTransformTranslate(dst, tx, ty);
}

void NanoVG::transformScale(float dst[6], float sx, float sy)
{
nvgTransformScale(dst, sx, sy);
}

void NanoVG::transformRotate(float dst[6], float a)
{
nvgTransformRotate(dst, a);
}

void NanoVG::transformSkewX(float dst[6], float a)
{
nvgTransformSkewX(dst, a);
}

void NanoVG::transformSkewY(float dst[6], float a)
{
nvgTransformSkewY(dst, a);
}

void NanoVG::transformMultiply(float dst[6], const float src[6])
{
nvgTransformMultiply(dst, src);
}

void NanoVG::transformPremultiply(float dst[6], const float src[6])
{
nvgTransformPremultiply(dst, src);
}

int NanoVG::transformInverse(float dst[6], const float src[6])
{
return nvgTransformInverse(dst, src);
}

void NanoVG::transformPoint(float& dstx, float& dsty, const float xform[6], float srcx, float srcy)
{
nvgTransformPoint(&dstx, &dsty, xform, srcx, srcy);
}

float NanoVG::degToRad(float deg)
{
return nvgDegToRad(deg);
}

float NanoVG::radToDeg(float rad)
{
return nvgRadToDeg(rad);
}

// -----------------------------------------------------------------------
// Images

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

if (const int imageId = nvgCreateImage(fContext, filename))
return new NanoImage(fContext, imageId);

return nullptr;
}

NanoImage* NanoVG::createImageMem(uchar* data, int ndata)
{
if (fContext == nullptr) return nullptr;
DISTRHO_SAFE_ASSERT_RETURN(data != nullptr, nullptr);
DISTRHO_SAFE_ASSERT_RETURN(ndata > 0, nullptr);

if (const int imageId = nvgCreateImageMem(fContext, data, ndata))
return new NanoImage(fContext, imageId);

return nullptr;
}

NanoImage* NanoVG::createImageRGBA(uint w, uint h, const uchar* data)
{
if (fContext == nullptr) return nullptr;
DISTRHO_SAFE_ASSERT_RETURN(data != nullptr, nullptr);

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

return nullptr;
}

// -----------------------------------------------------------------------
// Paints

NanoVG::Paint NanoVG::linearGradient(float sx, float sy, float ex, float ey, const Color& icol, const Color& ocol)
{
if (fContext == nullptr) return Paint();
return nvgLinearGradient(fContext, sx, sy, ex, ey, icol, ocol);
}

NanoVG::Paint NanoVG::boxGradient(float x, float y, float w, float h, float r, float f, const Color& icol, const Color& ocol)
{
if (fContext == nullptr) return Paint();
return nvgBoxGradient(fContext, x, y, w, h, r, f, icol, ocol);
}

NanoVG::Paint NanoVG::radialGradient(float cx, float cy, float inr, float outr, const Color& icol, const Color& ocol)
{
if (fContext == nullptr) return Paint();
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)
{
if (fContext == nullptr) return Paint();
DISTRHO_SAFE_ASSERT_RETURN(image != nullptr, Paint());

return nvgImagePattern(fContext, ox, oy, ex, ey, angle, image->fImageId, repeat);
}

// -----------------------------------------------------------------------
// Scissoring

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

void NanoVG::resetScissor()
{
if (fContext != nullptr)
nvgResetScissor(fContext);
}

// -----------------------------------------------------------------------
// Paths

void NanoVG::beginPath()
{
if (fContext != nullptr)
nvgBeginPath(fContext);
}

void NanoVG::moveTo(float x, float y)
{
if (fContext != nullptr)
nvgMoveTo(fContext, x, y);
}

void NanoVG::lineTo(float x, float y)
{
if (fContext != nullptr)
nvgLineTo(fContext, x, y);
}

void NanoVG::bezierTo(float c1x, float c1y, float c2x, float c2y, float x, float y)
{
if (fContext != nullptr)
nvgBezierTo(fContext, c1x, c1y, c2x, c2y, x, y);
}

void NanoVG::arcTo(float x1, float y1, float x2, float y2, float radius)
{
if (fContext != nullptr)
nvgArcTo(fContext, x1, y1, x2, y2, radius);
}

void NanoVG::closePath()
{
if (fContext != nullptr)
nvgClosePath(fContext);
}

void NanoVG::pathWinding(NanoVG::Winding dir)
{
if (fContext != nullptr)
nvgPathWinding(fContext, dir);
}

void NanoVG::arc(float cx, float cy, float r, float a0, float a1, NanoVG::Winding dir)
{
if (fContext != nullptr)
nvgArc(fContext, cx, cy, r, a0, a1, dir);
}

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

void NanoVG::roundedRect(float x, float y, float w, float h, float r)
{
if (fContext != nullptr)
nvgRoundedRect(fContext, x, y, w, h, r);
}

void NanoVG::ellipse(float cx, float cy, float rx, float ry)
{
if (fContext != nullptr)
nvgEllipse(fContext, cx, cy, rx, ry);
}

void NanoVG::circle(float cx, float cy, float r)
{
if (fContext != nullptr)
nvgCircle(fContext, cx, cy, r);
}

void NanoVG::fill()
{
if (fContext != nullptr)
nvgFill(fContext);
}

void NanoVG::stroke()
{
if (fContext != nullptr)
nvgStroke(fContext);
}

// -----------------------------------------------------------------------
// Text

NanoVG::FontId NanoVG::createFont(const char* name, const char* filename)
{
if (fContext == nullptr) return -1;
DISTRHO_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0', -1);
DISTRHO_SAFE_ASSERT_RETURN(filename != nullptr && filename[0] != '\0', -1);

return nvgCreateFont(fContext, name, filename);
}

NanoVG::FontId NanoVG::createFontMem(const char* name, const uchar* data, int ndata, 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);
}

NanoVG::FontId NanoVG::findFont(const char* name)
{
if (fContext == nullptr) return -1;
DISTRHO_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0', -1);

return nvgFindFont(fContext, name);
}

void NanoVG::fontSize(float size)
{
if (fContext == nullptr) return;
DISTRHO_SAFE_ASSERT_RETURN(size > 0.0f,);

nvgFontSize(fContext, size);
}

void NanoVG::fontBlur(float blur)
{
if (fContext == nullptr) return;
DISTRHO_SAFE_ASSERT_RETURN(blur >= 0.0f,);

nvgFontBlur(fContext, blur);
}

void NanoVG::textLetterSpacing(float spacing)
{
if (fContext == nullptr) return;
DISTRHO_SAFE_ASSERT_RETURN(spacing >= 0.0f,);

nvgTextLetterSpacing(fContext, spacing);
}

void NanoVG::textLineHeight(float lineHeight)
{
if (fContext == nullptr) return;
DISTRHO_SAFE_ASSERT_RETURN(lineHeight > 0.0f,);

nvgTextLineHeight(fContext, lineHeight);
}

void NanoVG::textAlign(NanoVG::Align align)
{
if (fContext != nullptr)
nvgTextAlign(fContext, align);
}

void NanoVG::textAlign(int align)
{
if (fContext != nullptr)
nvgTextAlign(fContext, align);
}

void NanoVG::fontFaceId(FontId font)
{
if (fContext == nullptr) return;
DISTRHO_SAFE_ASSERT_RETURN(font >= 0,);

nvgFontFaceId(fContext, font);
}

void NanoVG::fontFace(const char* font)
{
if (fContext == nullptr) return;
DISTRHO_SAFE_ASSERT_RETURN(font != nullptr && font[0] != '\0',);

nvgFontFace(fContext, font);
}

float NanoVG::text(float x, float y, const char* string, const char* end)
{
if (fContext == nullptr) return 0.0f;
DISTRHO_SAFE_ASSERT_RETURN(string != nullptr && string[0] != '\0', 0.0f);

return nvgText(fContext, x, y, string, end);
}

void NanoVG::textBox(float x, float y, float breakRowWidth, const char* string, const char* end)
{
if (fContext == nullptr) return;
DISTRHO_SAFE_ASSERT_RETURN(string != nullptr && string[0] != '\0',);

nvgTextBox(fContext, x, y, breakRowWidth, string, end);
}

float NanoVG::textBounds(float x, float y, const char* string, const char* end, Rectangle<float>& bounds)
{
if (fContext == nullptr) return 0.0f;
DISTRHO_SAFE_ASSERT_RETURN(string != nullptr && string[0] != '\0', 0.0f);

float b[4];
const float ret = nvgTextBounds(fContext, x, y, string, end, b);
bounds = Rectangle<float>(b[0], b[1], b[2], b[3]);
return ret;
}

void NanoVG::textBoxBounds(float x, float y, float breakRowWidth, const char* string, const char* end, float* bounds)
{
if (fContext == nullptr) return;
DISTRHO_SAFE_ASSERT_RETURN(string != nullptr && string[0] != '\0',);

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

void NanoVG::textMetrics(float* ascender, float* descender, float* lineh)
{
if (fContext != nullptr)
nvgTextMetrics(fContext, ascender, descender, lineh);
}

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

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

END_NAMESPACE_DGL

extern "C" {
#include "nanovg/nanovg.c"
}

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

+ 0
- 255
dgl/src/Widget.cpp View File

@@ -1,255 +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 "../Widget.hpp"
#include "../Window.hpp"

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()
{
fParent._addWidget(this);
}

Widget::~Widget()
{
fParent._removeWidget(this);
}

bool Widget::isVisible() const noexcept
{
return fVisible;
}

void Widget::setVisible(bool yesNo)
{
if (fVisible == yesNo)
return;

fVisible = yesNo;
fParent.repaint();
}

void Widget::show()
{
setVisible(true);
}

void Widget::hide()
{
setVisible(false);
}

uint Widget::getWidth() const noexcept
{
return fSize.getWidth();
}

uint Widget::getHeight() const noexcept
{
return fSize.getHeight();
}

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

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

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

fSize.setWidth(width);
onResize(ev);

fParent.repaint();
}

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

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

fSize.setHeight(height);
onResize(ev);

fParent.repaint();
}

void Widget::setSize(uint width, uint height) noexcept
{
setSize(Size<uint>(width, height));
}

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

ResizeEvent ev;
ev.oldSize = fSize;
ev.size = size;

fSize = size;
onResize(ev);

fParent.repaint();
}

int Widget::getAbsoluteX() const noexcept
{
return fAbsolutePos.getX();
}

int Widget::getAbsoluteY() const noexcept
{
return fAbsolutePos.getY();
}

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

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

fAbsolutePos.setX(x);
fParent.repaint();
}

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

fAbsolutePos.setY(y);
fParent.repaint();
}

void Widget::setAbsolutePos(int x, int y) noexcept
{
setAbsolutePos(Point<int>(x, y));
}

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

fAbsolutePos = pos;
fParent.repaint();
}

App& Widget::getParentApp() const noexcept
{
return fParent.getApp();
}

Window& Widget::getParentWindow() const noexcept
{
return fParent;
}

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

bool Widget::contains(const Point<int>& pos) const noexcept
{
return contains(pos.getX(), pos.getY());
}

void Widget::repaint() noexcept
{
fParent.repaint();
}

uint Widget::getId() const noexcept
{
return fId;
}

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

bool Widget::onKeyboard(const KeyboardEvent&)
{
return false;
}

bool Widget::onSpecial(const SpecialEvent&)
{
return false;
}

bool Widget::onMouse(const MouseEvent&)
{
return false;
}

bool Widget::onMotion(const MotionEvent&)
{
return false;
}

bool Widget::onScroll(const ScrollEvent&)
{
return false;
}

void Widget::onResize(const ResizeEvent&)
{
}

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

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

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

END_NAMESPACE_DGL

+ 0
- 1232
dgl/src/Window.cpp
File diff suppressed because it is too large
View File


+ 0
- 18
dgl/src/nanovg/LICENSE.txt View File

@@ -1,18 +0,0 @@
Copyright (c) 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.

+ 0
- 1673
dgl/src/nanovg/fontstash.h
File diff suppressed because it is too large
View File


+ 0
- 2475
dgl/src/nanovg/nanovg.c
File diff suppressed because it is too large
View File


+ 0
- 590
dgl/src/nanovg/nanovg.h View File

@@ -1,590 +0,0 @@
//
// Copyright (c) 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_H
#define NANOVG_H

#ifdef __cplusplus
extern "C" {
#endif

#define NVG_PI 3.14159265358979323846264338327f

struct NVGcontext;

struct NVGcolor {
union {
float rgba[4];
struct {
float r,g,b,a;
};
};
};

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

enum NVGwinding {
NVG_CCW = 1, // Winding for solid shapes
NVG_CW = 2, // Winding for holes
};

enum NVGsolidity {
NVG_SOLID = 1, // CCW
NVG_HOLE = 2, // CW
};

enum NVGlineCap {
NVG_BUTT,
NVG_ROUND,
NVG_SQUARE,
NVG_BEVEL,
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.
NVG_ALIGN_CENTER = 1<<1, // Align text horizontally to center.
NVG_ALIGN_RIGHT = 1<<2, // Align text horizontally to right.
// 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,
};

struct NVGglyphPosition {
const char* str; // Position of the glyph in the input string.
float x; // The x-coordinate of the logical glyph position.
float minx, maxx; // The bounds of the glyph shape.
};

struct NVGtextRow {
const char* start; // Pointer to the input text where the row starts.
const char* end; // Pointer to the input text where the row ends (one past the last character).
const char* next; // Pointer to the beginning of the next row.
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.
};


// Begin drawing a new frame
// Calls to nanovg drawing API should be wrapped in nvgBeginFrame() & nvgEndFrame()
// nvgBeginFrame() defines the size of the window to render to in relation currently
// set viewport (i.e. glViewport on GL backends). Device pixel ration allows to
// control the rendering on Hi-DPI devices.
// 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);

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

//
// Color utils
//
// 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);

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


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

// Returns a color value from red, green, blue and alpha values.
struct 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);

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

// Sets transparency of a color value.
struct NVGcolor nvgTransRGBAf(struct 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);

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

//
// State Handling
//
// NanoVG contains state which represents how paths will be rendered.
// The state contains transform, fill and stroke styles, text and font styles,
// and scissor clipping.

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

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

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

//
// Render styles
//
// Fill and stroke render style can be either a solid color or a paint which is a gradient or a pattern.
// 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().

// Sets current stroke style to a solid color.
void nvgStrokeColor(struct NVGcontext* ctx, struct 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);

// Sets current fill cstyle to a solid color.
void nvgFillColor(struct NVGcontext* ctx, struct 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);

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

// Sets the stroke witdth of the stroke style.
void nvgStrokeWidth(struct 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);

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

//
// Transforms
//
// The paths, gradients, patterns and scissor region are transformed by an transformation
// matrix at the time when they are passed to the API.
// The current transformation matrix is a affine matrix:
// [sx kx tx]
// [ky sy ty]
// [ 0 0 1]
// Where: sx,sy define scaling, kx,ky skewing, and tx,ty translation.
// The last row is assumed to be 0,0,1 and is not stored.
//
// 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().

// Resets current transform to a identity matrix.
void nvgResetTransform(struct 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);

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

// Rotates current coordinate system. Angle is specifid in radians.
void nvgRotate(struct 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 Y axis. Angle is specifid in radians.
void nvgSkewY(struct NVGcontext* ctx, float angle);

// Scales the current coordinat system.
void nvgScale(struct 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);


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

// Sets the transform to identity matrix.
void nvgTransformIdentity(float* dst);

// Sets the transform to translation matrix matrix.
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.
void nvgTransformRotate(float* dst, float a);

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

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

// Sets the transform to the result of multiplication of two transforms, of A = A*B.
void nvgTransformMultiply(float* dst, const float* src);

// Sets the transform to the result of multiplication of two transforms, of A = B*A.
void nvgTransformPremultiply(float* dst, const float* src);

// Sets the destination to inverse of specified transform.
// Returns 1 if the inverse could be calculated, else 0.
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.
float nvgDegToRad(float deg);
float nvgRadToDeg(float rad);

//
// Images
//
// 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.

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

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

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

// Updates image data specified by image handle.
void nvgUpdateImage(struct 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);

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

//
// Paints
//
// NanoVG supports four types of paints: linear gradient, box gradient, radial gradient and image pattern.
// These can be used as paints for strokes and fills.

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

// 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,
// (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);

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

// 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.
// 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);

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

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

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

//
// Paths
//
// Drawing a new shape starts with nvgBeginPath(), it clears all the currently defined paths.
// Then you define one or more paths and sub-paths which describe the shape. The are functions
// to draw common shapes like rectangles and circles, and lower level step-by-step functions,
// which allow to define a path curve by curve.
//
// NanoVG uses even-odd fill rule to draw the shapes. Solid shapes should have counter clockwise
// winding and holes should have counter clockwise order. To specify winding of a path you can
// call nvgPathWinding(). This is useful especially for the common shapes, which are drawn CCW.
//
// Finally you can fill the path using current fill style by calling nvgFill(), and stroke it
// with current stroke style by calling nvgStroke().
//
// The curve segments and sub-paths are transformed by the current transform.

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

// Starts new sub-path with specified point as first point.
void nvgMoveTo(struct 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);

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

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

// Sets the current sub-path winding, see NVGwinding and NVGsolidity.
void nvgPathWinding(struct 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 rectangle shaped sub-path.
void nvgRect(struct 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);

// Creates new ellipse shaped sub-path.
void nvgEllipse(struct 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);

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

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


//
// Text
//
// NanoVG allows you to load .ttf files and use the font to render text.
//
// The appearance of the text can be defined by setting the current text style
// and by specifying the fill color. Common text and font settings such as
// font size, letter spacing and text align are supported. Font blur allows you
// to create simple text effects such as drop shadows.
//
// At render time the font face can be set based on the font handles or name.
//
// Font measure functions return values in local space, the calculations are
// carried in the same resolution as the final rendering. This is done because
// the text glyph positions are snapped to the nearest pixels sharp rendering.
//
// The local space means that values are not rotated or scale as per the current
// transformation. For example if you set font size to 12, which would mean that
// line height is 16, then regardless of the current scaling and rotation, the
// returned line height is always 16. Some measures may vary because of the scaling
// since aforementioned pixel snapping.
//
// While this may sound a little odd, the setup allows you to always render the
// same way regardless of scaling. I.e. following works regardless of scaling:
//
// const char* txt = "Text me up.";
// nvgTextBounds(vg, x,y, txt, NULL, bounds);
// nvgBeginPath(vg);
// nvgRoundedRect(vg, bounds[0],bounds[1], bounds[2]-bounds[0], bounds[3]-bounds[1]);
// nvgFill(vg);
//
// Note: currently only solid color fill is supported for text.

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

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

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

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

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

// Sets the letter spacing of current text style.
void nvgTextLetterSpacing(struct 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 text align of current text style, see NVGaling for options.
void nvgTextAlign(struct NVGcontext* ctx, int align);

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

// Sets the font face based on specified name of current text style.
void nvgFontFace(struct 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);

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

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

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

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

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

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

//
// Internal Render API
//
enum NVGtexture {
NVG_TEXTURE_ALPHA = 0x01,
NVG_TEXTURE_RGBA = 0x02,
};

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

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

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

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 (*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 (*renderDelete)(void* uptr);
};

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

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

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

#ifdef __cplusplus
}
#endif

#endif // NANOVG_H

+ 0
- 1293
dgl/src/nanovg/nanovg_gl.h
File diff suppressed because it is too large
View File


+ 0
- 4676
dgl/src/nanovg/stb_image.c
File diff suppressed because it is too large
View File


+ 0
- 2064
dgl/src/nanovg/stb_truetype.h
File diff suppressed because it is too large
View File


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

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

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

THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

#ifndef PUGL_COMMON_H_INCLUDED
#define PUGL_COMMON_H_INCLUDED

#ifdef __cplusplus
extern "C" {
#endif

/**
@addtogroup pugl
@{
*/

/**
A Pugl view.
*/
typedef struct PuglViewImpl PuglView;

/**
A native window handle.

On X11, this is a Window.
On OSX, this is an NSView*.
On Windows, this is a HWND.
*/
typedef intptr_t PuglNativeWindow;

/**
Handle for opaque user data.
*/
typedef void* PuglHandle;

/**
Return status code.
*/
typedef enum {
PUGL_SUCCESS = 0
} PuglStatus;

/**
Drawing context type.
*/
typedef enum {
PUGL_GL,
PUGL_CAIRO
} PuglContextType;

/**
Convenience symbols for ASCII control characters.
*/
typedef enum {
PUGL_CHAR_BACKSPACE = 0x08,
PUGL_CHAR_ESCAPE = 0x1B,
PUGL_CHAR_DELETE = 0x7F
} PuglChar;

/**
Keyboard modifier flags.
*/
typedef enum {
PUGL_MOD_SHIFT = 1 << 0, /**< Shift key */
PUGL_MOD_CTRL = 1 << 1, /**< Control key */
PUGL_MOD_ALT = 1 << 2, /**< Alt/Option key */
PUGL_MOD_SUPER = 1 << 3 /**< Mod4/Command/Windows key */
} PuglMod;

/**
Special (non-Unicode) keyboard keys.
*/
typedef enum {
PUGL_KEY_F1 = 1,
PUGL_KEY_F2,
PUGL_KEY_F3,
PUGL_KEY_F4,
PUGL_KEY_F5,
PUGL_KEY_F6,
PUGL_KEY_F7,
PUGL_KEY_F8,
PUGL_KEY_F9,
PUGL_KEY_F10,
PUGL_KEY_F11,
PUGL_KEY_F12,
PUGL_KEY_LEFT,
PUGL_KEY_UP,
PUGL_KEY_RIGHT,
PUGL_KEY_DOWN,
PUGL_KEY_PAGE_UP,
PUGL_KEY_PAGE_DOWN,
PUGL_KEY_HOME,
PUGL_KEY_END,
PUGL_KEY_INSERT,
PUGL_KEY_SHIFT,
PUGL_KEY_CTRL,
PUGL_KEY_ALT,
PUGL_KEY_SUPER
} PuglKey;

/**
@}
*/

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

#endif /* PUGL_COMMON_H_INCLUDED */

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

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

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

THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

#ifndef PUGL_EVENT_H_INCLUDED
#define PUGL_EVENT_H_INCLUDED

#ifdef __cplusplus
extern "C" {
#else
# include <stdbool.h>
#endif

#include "pugl/common.h"

/**
@addtogroup pugl
@{
*/

/**
@}
*/

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

#endif /* PUGL_EVENT_H_INCLUDED */

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

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

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

THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

/**
@file gl.h Portable header wrapper for gl.h.

Unfortunately, GL includes vary across platforms so this header allows for
pure portable programs.
*/

#ifdef __APPLE__
# include "OpenGL/gl.h"
#else
# ifdef _WIN32
# include <windows.h> /* Broken Windows GL headers require this */
# endif
# include "GL/gl.h"
#endif


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

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

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

THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

/**
@file glu.h Portable header wrapper for glu.h.

Unfortunately, GL includes vary across platforms so this header allows for
pure portable programs.
*/

#ifdef __APPLE__
# include "OpenGL/glu.h"
#else
# ifdef _WIN32
# include <windows.h> /* Broken Windows GL headers require this */
# endif
# include "GL/glu.h"
#endif


+ 0
- 383
dgl/src/pugl/pugl.h View File

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

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

THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

/**
@file pugl.h API for Pugl, a minimal portable API for OpenGL.
*/

#ifndef PUGL_H_INCLUDED
#define PUGL_H_INCLUDED

#include <stdint.h>

#include "pugl/common.h"
#include "pugl/event.h"

#ifdef PUGL_SHARED
# ifdef _WIN32
# define PUGL_LIB_IMPORT __declspec(dllimport)
# define PUGL_LIB_EXPORT __declspec(dllexport)
# else
# define PUGL_LIB_IMPORT __attribute__((visibility("default")))
# define PUGL_LIB_EXPORT __attribute__((visibility("default")))
# endif
# ifdef PUGL_INTERNAL
# define PUGL_API PUGL_LIB_EXPORT
# else
# define PUGL_API PUGL_LIB_IMPORT
# endif
#else
# ifdef _WIN32
# define PUGL_API
# else
# define PUGL_API __attribute__((visibility("hidden")))
# endif
#endif

#ifdef __cplusplus
extern "C" {
#else
# include <stdbool.h>
#endif

/**
@defgroup pugl Pugl
A minimal portable API for OpenGL.
@{
*/

/**
A function called when the window is closed.
*/
typedef void (*PuglCloseFunc)(PuglView* view);

/**
A function called to draw the view contents with OpenGL.
*/
typedef void (*PuglDisplayFunc)(PuglView* view);

/**
A function called when a key is pressed or released.
@param view The view the event occured in.
@param press True if the key was pressed, false if released.
@param key Unicode point of the key pressed.
*/
typedef void (*PuglKeyboardFunc)(PuglView* view, bool press, uint32_t key);

/**
A function called when the pointer moves.
@param view The view the event occured in.
@param x The window-relative x coordinate of the pointer.
@param y The window-relative y coordinate of the pointer.
*/
typedef void (*PuglMotionFunc)(PuglView* view, int x, int y);

/**
A function called when a mouse button is pressed or released.
@param view The view the event occured in.
@param button The button number (1 = left, 2 = middle, 3 = right).
@param press True if the key was pressed, false if released.
@param x The window-relative x coordinate of the pointer.
@param y The window-relative y coordinate of the pointer.
*/
typedef void (*PuglMouseFunc)(
PuglView* view, int button, bool press, int x, int y);

/**
A function called when the view is resized.
@param view The view being resized.
@param width The new view width.
@param height The new view height.
*/
typedef void (*PuglReshapeFunc)(PuglView* view, int width, int height);

/**
A function called on scrolling (e.g. mouse wheel or track pad).

The distances used here are in "lines", a single tick of a clicking mouse
wheel. For example, @p dy = 1.0 scrolls 1 line up. Some systems and
devices support finer resolution and/or higher values for fast scrolls,
so programs should handle any value gracefully.

@param view The view being scrolled.
@param x The window-relative x coordinate of the pointer.
@param y The window-relative y coordinate of the pointer.
@param dx The scroll x distance.
@param dx The scroll y distance.
*/
typedef void (*PuglScrollFunc)(PuglView* view, int x, int y, float dx, float dy);

/**
A function called when a special key is pressed or released.

This callback allows the use of keys that do not have unicode points.
Note that some are non-printable keys.

@param view The view the event occured in.
@param press True if the key was pressed, false if released.
@param key The key pressed.
*/
typedef void (*PuglSpecialFunc)(PuglView* view, bool press, PuglKey key);

/**
A function called when a filename is selected via file-browser.

@param view The view the event occured in.
@param filename The selected file name or NULL if the dialog was canceled.
*/
typedef void (*PuglFileSelectedFunc)(PuglView* view, const char* filename);

/**
@name Initialization
Configuration functions which must be called before creating a window.
@{
*/

/**
Create a Pugl context.

To create a window, call the various puglInit* functions as necessary, then
call puglCreateWindow().
*/
PUGL_API PuglView*
puglInit(void);

/**
Set the parent window before creating a window (for embedding).
*/
PUGL_API void
puglInitWindowParent(PuglView* view, PuglNativeWindow parent);

/**
Set the window size before creating a window.
*/
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.

@return 1 (pugl does not currently support multiple windows).
*/
PUGL_API int
puglCreateWindow(PuglView* view, const char* title);

/**
Show the current window.
*/
PUGL_API void
puglShowWindow(PuglView* view);

/**
Hide the current window.
*/
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.

This is generally a pointer to a struct which contains all necessary state.
Everything needed in callbacks should be here, not in static variables.

Note the lack of this facility makes GLUT unsuitable for plugins or
non-trivial programs; this mistake is largely why Pugl exists.
*/
PUGL_API void
puglSetHandle(PuglView* view, PuglHandle handle);

/**
Get the handle to be passed to all callbacks.
*/
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.
*/
PUGL_API uint32_t
puglGetEventTimestamp(PuglView* view);

/**
Get the currently active modifiers (PuglMod flags).

This should only be called from an event handler.
*/
PUGL_API int
puglGetModifiers(PuglView* view);

/**
Ignore synthetic repeated key events.
*/
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.
*/
PUGL_API void
puglSetCloseFunc(PuglView* view, PuglCloseFunc closeFunc);

/**
Set the display function which should draw the UI using GL.
*/
PUGL_API void
puglSetDisplayFunc(PuglView* view, PuglDisplayFunc displayFunc);

/**
Set the function to call on keyboard events.
*/
PUGL_API void
puglSetKeyboardFunc(PuglView* view, PuglKeyboardFunc keyboardFunc);

/**
Set the function to call on mouse motion.
*/
PUGL_API void
puglSetMotionFunc(PuglView* view, PuglMotionFunc motionFunc);

/**
Set the function to call on mouse button events.
*/
PUGL_API void
puglSetMouseFunc(PuglView* view, PuglMouseFunc mouseFunc);

/**
Set the function to call on scroll events.
*/
PUGL_API void
puglSetScrollFunc(PuglView* view, PuglScrollFunc scrollFunc);

/**
Set the function to call on special events.
*/
PUGL_API void
puglSetSpecialFunc(PuglView* view, PuglSpecialFunc specialFunc);

/**
Set the function to call when the window size changes.
*/
PUGL_API void
puglSetReshapeFunc(PuglView* view, PuglReshapeFunc reshapeFunc);

/**
Set the function to call on file-browser selections.
*/
PUGL_API void
puglSetFileSelectedFunc(PuglView* view, PuglFileSelectedFunc fileSelectedFunc);

/**
@}
*/

/**
Grab the input focus.
*/
PUGL_API void
puglGrabFocus(PuglView* view);

/**
Process all pending window events.

This handles input events as well as rendering, so it should be called
regularly and rapidly enough to keep the UI responsive.
*/
PUGL_API PuglStatus
puglProcessEvents(PuglView* view);

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

/**
Destroy a GL window.
*/
PUGL_API void
puglDestroy(PuglView* view);

/**
@}
*/

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

#endif /* PUGL_H_INCLUDED */

+ 0
- 350
dgl/src/pugl/pugl_internal.h View File

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

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

THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

/**
@file pugl_internal.h Private platform-independent definitions.

Note this file contains function definitions, so it must be compiled into
the final binary exactly once. Each platform specific implementation file
including it once should achieve this.

If you are copying the pugl code into your source tree, the following
symbols can be defined to tweak pugl behaviour:

PUGL_HAVE_CAIRO: Include Cairo support code.
PUGL_HAVE_GL: Include OpenGL support code.
PUGL_GRAB_FOCUS: Work around reparent keyboard issues by grabbing focus.
PUGL_VERBOSE: Print GL information to console.
*/

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

#ifdef PUGL_VERBOSE
# include <stdio.h>
# define PUGL_LOG(str) fprintf(stderr, "pugl: " str)
# define PUGL_LOGF(fmt, ...) fprintf(stderr, "pugl: " fmt, __VA_ARGS__)
#else
# define PUGL_LOG(str)
# define PUGL_LOGF(fmt, ...)
#endif

typedef struct PuglInternalsImpl PuglInternals;

struct PuglViewImpl {
PuglHandle handle;
PuglCloseFunc closeFunc;
PuglDisplayFunc displayFunc;
PuglKeyboardFunc keyboardFunc;
PuglMotionFunc motionFunc;
PuglMouseFunc mouseFunc;
PuglReshapeFunc reshapeFunc;
PuglScrollFunc scrollFunc;
PuglSpecialFunc specialFunc;
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;
bool redisplay;
bool resizable;
uint32_t event_timestamp_ms;
};

PuglInternals* puglInitInternals(void);

PuglView*
puglInit(void)
{
PuglView* view = (PuglView*)calloc(1, sizeof(PuglView));
if (!view) {
return NULL;
}

PuglInternals* impl = puglInitInternals();
if (!impl) {
free(view);
return NULL;
}

view->impl = impl;
view->width = 640;
view->height = 480;

return view;
}

void
puglInitWindowSize(PuglView* view, int width, int height)
{
view->width = width;
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)
{
view->parent = parent;
}

void
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)
{
view->handle = handle;
}

PuglHandle
puglGetHandle(PuglView* view)
{
return view->handle;
}

uint32_t
puglGetEventTimestamp(PuglView* view)
{
return view->event_timestamp_ms;
}

int
puglGetModifiers(PuglView* view)
{
return view->mods;
}

void
puglIgnoreKeyRepeat(PuglView* view, bool ignore)
{
view->ignoreKeyRepeat = ignore;
}

void
puglSetCloseFunc(PuglView* view, PuglCloseFunc closeFunc)
{
view->closeFunc = closeFunc;
}

void
puglSetDisplayFunc(PuglView* view, PuglDisplayFunc displayFunc)
{
view->displayFunc = displayFunc;
}

void
puglSetKeyboardFunc(PuglView* view, PuglKeyboardFunc keyboardFunc)
{
view->keyboardFunc = keyboardFunc;
}

void
puglSetMotionFunc(PuglView* view, PuglMotionFunc motionFunc)
{
view->motionFunc = motionFunc;
}

void
puglSetMouseFunc(PuglView* view, PuglMouseFunc mouseFunc)
{
view->mouseFunc = mouseFunc;
}

void
puglSetReshapeFunc(PuglView* view, PuglReshapeFunc reshapeFunc)
{
view->reshapeFunc = reshapeFunc;
}

void
puglSetScrollFunc(PuglView* view, PuglScrollFunc scrollFunc)
{
view->scrollFunc = scrollFunc;
}

void
puglSetSpecialFunc(PuglView* view, PuglSpecialFunc specialFunc)
{
view->specialFunc = specialFunc;
}

void
puglSetFileSelectedFunc(PuglView* view, PuglFileSelectedFunc fileSelectedFunc)
{
view->fileSelectedFunc = fileSelectedFunc;
}

void
puglEnterContext(PuglView* view);

void
puglLeaveContext(PuglView* view, bool flush);

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

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

+ 0
- 573
dgl/src/pugl/pugl_osx.m View File

@@ -1,573 +0,0 @@
/*
Copyright 2012 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 pugl_osx.m OSX/Cocoa Pugl Implementation.
*/

#include <stdlib.h>

#import <Cocoa/Cocoa.h>

#include "pugl_internal.h"

@interface PuglWindow : NSWindow
{
@public
PuglView* puglview;
}

- (id) initWithContentRect:(NSRect)contentRect
styleMask:(unsigned int)aStyle
backing:(NSBackingStoreType)bufferingType
defer:(BOOL)flag;
- (void) setPuglview:(PuglView*)view;
- (BOOL) canBecomeKeyWindow;
- (BOOL) windowShouldClose:(id)sender;
@end

@implementation PuglWindow

- (id)initWithContentRect:(NSRect)contentRect
styleMask:(unsigned int)aStyle
backing:(NSBackingStoreType)bufferingType
defer:(BOOL)flag
{
NSWindow* result = [super initWithContentRect:contentRect
styleMask:(NSClosableWindowMask |
NSTitledWindowMask |
NSResizableWindowMask)
backing:NSBackingStoreBuffered defer:NO];

[result setAcceptsMouseMovedEvents:YES];
[result setLevel: CGShieldingWindowLevel() + 1];

return (PuglWindow*)result;

// unused
(void)aStyle; (void)bufferingType; (void)flag;
}

- (void)setPuglview:(PuglView*)view
{
puglview = view;
[self setContentSize:NSMakeSize(view->width, view->height)];
}

- (BOOL)canBecomeKeyWindow
{
return YES;
}

- (BOOL)windowShouldClose:(id)sender
{
if (puglview->closeFunc)
puglview->closeFunc(puglview);
return YES;

// unused
(void)sender;
}

@end

static void
puglDisplay(PuglView* view)
{
view->redisplay = false;
if (view->displayFunc) {
view->displayFunc(view);
}
}

@interface PuglOpenGLView : NSOpenGLView
{
@public
PuglView* puglview;
NSTrackingArea* trackingArea;
bool doubleBuffered;
}

- (BOOL) acceptsFirstMouse:(NSEvent*)e;
- (BOOL) acceptsFirstResponder;
- (BOOL) isFlipped;
- (BOOL) isOpaque;
- (BOOL) preservesContentInLiveResize;
- (id) initWithFrame:(NSRect)frame;
- (void) reshape;
- (void) drawRect:(NSRect)r;
- (void) cursorUpdate:(NSEvent*)e;
- (void) updateTrackingAreas;
- (void) viewWillMoveToWindow:(NSWindow*)newWindow;
- (void) mouseMoved:(NSEvent*)event;
- (void) mouseDragged:(NSEvent*)event;
- (void) rightMouseDragged:(NSEvent*)event;
- (void) otherMouseDragged:(NSEvent*)event;
- (void) mouseDown:(NSEvent*)event;
- (void) rightMouseDown:(NSEvent*)event;
- (void) otherMouseDown:(NSEvent*)event;
- (void) mouseUp:(NSEvent*)event;
- (void) rightMouseUp:(NSEvent*)event;
- (void) otherMouseUp:(NSEvent*)event;
- (void) scrollWheel:(NSEvent*)event;
- (void) keyDown:(NSEvent*)event;
- (void) keyUp:(NSEvent*)event;
- (void) flagsChanged:(NSEvent*)event;

@end

@implementation PuglOpenGLView

- (BOOL) acceptsFirstMouse:(NSEvent*)e
{
return YES;

// unused
(void)e;
}

- (BOOL) acceptsFirstResponder
{
return YES;
}

- (BOOL) isFlipped
{
return YES;
}

- (BOOL) isOpaque
{
return YES;
}

- (BOOL) preservesContentInLiveResize
{
return NO;
}

- (id) initWithFrame:(NSRect)frame
{
puglview = nil;
trackingArea = nil;
doubleBuffered = true;

NSOpenGLPixelFormatAttribute pixelAttribs[] = {
NSOpenGLPFAColorSize, 24,
NSOpenGLPFAAlphaSize, 8,
NSOpenGLPFADepthSize, 16,
NSOpenGLPFADoubleBuffer,
NSOpenGLPFAAccelerated,
0
};

NSOpenGLPixelFormat* pixelFormat = [[NSOpenGLPixelFormat alloc]
initWithAttributes:pixelAttribs];

if (pixelFormat) {
self = [super initWithFrame:frame pixelFormat:pixelFormat];
[pixelFormat release];
printf("Is doubleBuffered? TRUE\n");
} else {
self = [super initWithFrame:frame];
doubleBuffered = false;
printf("Is doubleBuffered? FALSE\n");
}

if (self) {
GLint swapInterval = 1;
[[self openGLContext] setValues:&swapInterval forParameter:NSOpenGLCPSwapInterval];

[self reshape];
}

return self;
}

- (void) reshape
{
[[self openGLContext] update];

if (!puglview) {
/* NOTE: Apparently reshape gets called when the GC gets around to
deleting the view (?), so we must have reset puglview to NULL when
this comes around.
*/
return;
}

NSRect bounds = [self bounds];
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);
puglLeaveContext(puglview, true);

// unused
return; (void)r;
}

- (void) cursorUpdate:(NSEvent*)e
{
[[NSCursor arrowCursor] set];

// unused
return; (void)e;
}

- (void) updateTrackingAreas
{
static const int opts = NSTrackingMouseEnteredAndExited
| NSTrackingMouseMoved
| NSTrackingEnabledDuringMouseDrag
| NSTrackingInVisibleRect
| NSTrackingActiveAlways
| NSTrackingCursorUpdate;

if (trackingArea != nil) {
[self removeTrackingArea:trackingArea];
[trackingArea release];
}

trackingArea = [[NSTrackingArea alloc] initWithRect:[self bounds]
options:opts
owner:self
userInfo:nil];
[self addTrackingArea:trackingArea];
[super updateTrackingAreas];
}

- (void) viewWillMoveToWindow:(NSWindow*)newWindow
{
if (newWindow != nil) {
[newWindow setAcceptsMouseMovedEvents:YES];
[newWindow makeFirstResponder:self];
}

[super viewWillMoveToWindow:newWindow];
}

static unsigned
getModifiers(PuglView* view, NSEvent* ev)
{
const unsigned modifierFlags = [ev modifierFlags];

view->event_timestamp_ms = fmod([ev timestamp] * 1000.0, UINT32_MAX);

unsigned mods = 0;
mods |= (modifierFlags & NSShiftKeyMask) ? PUGL_MOD_SHIFT : 0;
mods |= (modifierFlags & NSControlKeyMask) ? PUGL_MOD_CTRL : 0;
mods |= (modifierFlags & NSAlternateKeyMask) ? PUGL_MOD_ALT : 0;
mods |= (modifierFlags & NSCommandKeyMask) ? PUGL_MOD_SUPER : 0;
return mods;
}

static int
getFixedAppKitButton(NSInteger button)
{
switch (button) {
case 0: return 1;
case 1: return 3;
case 2: return 2;
default: return button;
}
}

- (void) mouseMoved:(NSEvent*)event
{
if (puglview->motionFunc) {
NSPoint loc = [self convertPoint:[event locationInWindow] fromView:nil];
puglview->mods = getModifiers(puglview, event);
puglview->motionFunc(puglview, loc.x, loc.y);
}
}

- (void) mouseDragged:(NSEvent*)event
{
[self mouseMoved:event];
}

- (void) rightMouseDragged:(NSEvent*)event
{
[self mouseDragged:event];
}

- (void) otherMouseDragged:(NSEvent*)event
{
[self mouseDragged:event];
}

- (void) mouseDown:(NSEvent*)event
{
if (puglview->mouseFunc) {
NSPoint loc = [self convertPoint:[event locationInWindow] fromView:nil];
puglview->mods = getModifiers(puglview, event);
puglview->mouseFunc(puglview, getFixedAppKitButton([event buttonNumber]), true, loc.x, loc.y);
}
}

- (void) rightMouseDown:(NSEvent*)event
{
[self mouseDown:event];
}

- (void) otherMouseDown:(NSEvent*)event
{
[self mouseDown:event];
}

- (void) mouseUp:(NSEvent*)event
{
if (puglview->mouseFunc) {
NSPoint loc = [self convertPoint:[event locationInWindow] fromView:nil];
puglview->mods = getModifiers(puglview, event);
puglview->mouseFunc(puglview, getFixedAppKitButton([event buttonNumber]), false, loc.x, loc.y);
}
}

- (void) rightMouseUp:(NSEvent*)event
{
[self mouseUp:event];
}

- (void) otherMouseUp:(NSEvent*)event
{
[self mouseUp:event];
}

- (void) scrollWheel:(NSEvent*)event
{
if (puglview->scrollFunc) {
NSPoint loc = [self convertPoint:[event locationInWindow] fromView:nil];
puglview->mods = getModifiers(puglview, event);
puglview->scrollFunc(puglview,
loc.x, loc.y,
[event deltaX], [event deltaY]);
}
}

- (void) keyDown:(NSEvent*)event
{
if (puglview->keyboardFunc && !(puglview->ignoreKeyRepeat && [event isARepeat])) {
NSString* chars = [event characters];
puglview->mods = getModifiers(puglview, event);
puglview->keyboardFunc(puglview, true, [chars characterAtIndex:0]);
}
}

- (void) keyUp:(NSEvent*)event
{
if (puglview->keyboardFunc) {
NSString* chars = [event characters];
puglview->mods = getModifiers(puglview, event);
puglview->keyboardFunc(puglview, false, [chars characterAtIndex:0]);
}
}

- (void) flagsChanged:(NSEvent*)event
{
if (puglview->specialFunc) {
const unsigned mods = getModifiers(puglview, event);
if ((mods & PUGL_MOD_SHIFT) != (puglview->mods & PUGL_MOD_SHIFT)) {
puglview->specialFunc(puglview, mods & PUGL_MOD_SHIFT, PUGL_KEY_SHIFT);
} else if ((mods & PUGL_MOD_CTRL) != (puglview->mods & PUGL_MOD_CTRL)) {
puglview->specialFunc(puglview, mods & PUGL_MOD_CTRL, PUGL_KEY_CTRL);
} else if ((mods & PUGL_MOD_ALT) != (puglview->mods & PUGL_MOD_ALT)) {
puglview->specialFunc(puglview, mods & PUGL_MOD_ALT, PUGL_KEY_ALT);
} else if ((mods & PUGL_MOD_SUPER) != (puglview->mods & PUGL_MOD_SUPER)) {
puglview->specialFunc(puglview, mods & PUGL_MOD_SUPER, PUGL_KEY_SUPER);
}
puglview->mods = mods;
}
}

@end

struct PuglInternalsImpl {
PuglOpenGLView* glview;
id window;
};

PuglInternals*
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)
{
PuglInternals* impl = view->impl;

[NSAutoreleasePool new];
[NSApplication sharedApplication];

impl->glview = [PuglOpenGLView new];

if (!impl->glview) {
return 1;
}
impl->glview->puglview = view;

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

if (view->parent) {
[impl->glview retain];
NSView* pview = (NSView*)view->parent;
[pview addSubview:impl->glview];
return 0;
}

id window = [[PuglWindow new]retain];

if (title) {
NSString* titleString = [[NSString alloc]
initWithBytes:title
length:strlen(title)
encoding:NSUTF8StringEncoding];

[window setTitle:titleString];
}

[window setPuglview:view];
[window setContentView:impl->glview];
[window makeFirstResponder:impl->glview];
[window makeKeyAndOrderFront:window];

// wait for first puglShowWindow
[window setIsVisible:NO];

[NSApp activateIgnoringOtherApps:YES];
[window center];

impl->window = window;

return 0;
}

void
puglShowWindow(PuglView* view)
{
PuglInternals* impl = view->impl;

if (impl->window) {
[impl->window setIsVisible:YES];
} else {
[view->impl->glview setHidden:NO];
}
}

void
puglHideWindow(PuglView* view)
{
PuglInternals* impl = view->impl;

if (impl->window) {
[impl->window setIsVisible:NO];
} else {
[impl->glview setHidden:YES];
}
}

void
puglDestroy(PuglView* view)
{
view->impl->glview->puglview = NULL;

if (view->impl->window) {
[view->impl->window close];
[view->impl->glview release];
[view->impl->window release];
} else {
[view->impl->glview release];
}

free(view->impl);
free(view);
}

PuglStatus
puglProcessEvents(PuglView* view)
{
return PUGL_SUCCESS;

// unused
(void)view;
}

void
puglPostRedisplay(PuglView* view)
{
view->redisplay = true;
[view->impl->glview setNeedsDisplay:YES];
}

PuglNativeWindow
puglGetNativeWindow(PuglView* view)
{
return (PuglNativeWindow)view->impl->glview;
}

void*
puglGetContext(PuglView* view)
{
return NULL;
}

+ 0
- 481
dgl/src/pugl/pugl_win.cpp View File

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

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

THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

/**
@file pugl_win.cpp Windows/WGL Pugl Implementation.
*/

#include <windows.h>
#include <windowsx.h>
#include <GL/gl.h>

#include <ctime>
#include <stdio.h>
#include <stdlib.h>

#include "pugl/pugl_internal.h"

#ifndef WM_MOUSEWHEEL
# define WM_MOUSEWHEEL 0x020A
#endif
#ifndef WM_MOUSEHWHEEL
# define WM_MOUSEHWHEEL 0x020E
#endif
#ifndef WHEEL_DELTA
# define WHEEL_DELTA 120
#endif
#ifndef GWLP_USERDATA
# define GWLP_USERDATA (-21)
#endif

#define PUGL_LOCAL_CLOSE_MSG (WM_USER + 50)

HINSTANCE hInstance = NULL;

struct PuglInternalsImpl {
HWND hwnd;
HDC hdc;
HGLRC hglrc;
WNDCLASS wc;
};

LRESULT CALLBACK
wndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);

#if 0
extern "C" {
BOOL WINAPI
DllMain(HINSTANCE hInst, DWORD, LPVOID)
{
hInstance = hInst;
return 1;
}
} // extern "C"
#endif

PuglInternals*
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)
{
PuglInternals* impl = view->impl;

if (!title) {
title = "Window";
}

// FIXME: This is nasty, and pugl should not have static anything.
// Should class be a parameter? Does this make sense on other platforms?
static int wc_count = 0;
char classNameBuf[256];
std::srand((std::time(NULL)));
_snprintf(classNameBuf, sizeof(classNameBuf), "%s_%d-%d", title, std::rand(), ++wc_count);
classNameBuf[sizeof(classNameBuf)-1] = '\0';

impl->wc.style = CS_OWNDC;
impl->wc.lpfnWndProc = wndProc;
impl->wc.cbClsExtra = 0;
impl->wc.cbWndExtra = 0;
impl->wc.hInstance = hInstance;
impl->wc.hIcon = LoadIcon(hInstance, IDI_APPLICATION);
impl->wc.hCursor = LoadCursor(hInstance, IDC_ARROW);
impl->wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
impl->wc.lpszMenuName = NULL;
impl->wc.lpszClassName = strdup(classNameBuf);

if (!RegisterClass(&impl->wc)) {
free((void*)impl->wc.lpszClassName);
free(impl);
free(view);
return 1;
}

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

impl->hwnd = CreateWindowEx(
WS_EX_TOPMOST,
classNameBuf, title,
view->parent ? (WS_CHILD | WS_VISIBLE) : winFlags,
CW_USEDEFAULT, CW_USEDEFAULT, wr.right-wr.left, wr.bottom-wr.top,
(HWND)view->parent, NULL, hInstance, NULL);

if (!impl->hwnd) {
UnregisterClass(impl->wc.lpszClassName, NULL);
free((void*)impl->wc.lpszClassName);
free(impl);
free(view);
return 1;
}

SetWindowLongPtr(impl->hwnd, GWLP_USERDATA, (LONG_PTR)view);

impl->hdc = GetDC(impl->hwnd);

PIXELFORMATDESCRIPTOR pfd;
ZeroMemory(&pfd, sizeof(pfd));
pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 24;
pfd.cDepthBits = 16;
pfd.iLayerType = PFD_MAIN_PLANE;

int format = ChoosePixelFormat(impl->hdc, &pfd);
SetPixelFormat(impl->hdc, format, &pfd);

impl->hglrc = wglCreateContext(impl->hdc);
if (!impl->hglrc) {
ReleaseDC (impl->hwnd, impl->hdc);
DestroyWindow (impl->hwnd);
UnregisterClass (impl->wc.lpszClassName, NULL);
free((void*)impl->wc.lpszClassName);
free(impl);
free(view);
return 1;
}

return PUGL_SUCCESS;
}

void
puglShowWindow(PuglView* view)
{
ShowWindow(view->impl->hwnd, SW_SHOWNORMAL);
}

void
puglHideWindow(PuglView* view)
{
ShowWindow(view->impl->hwnd, SW_HIDE);
}

void
puglDestroy(PuglView* view)
{
wglMakeCurrent(NULL, NULL);
wglDeleteContext(view->impl->hglrc);
ReleaseDC(view->impl->hwnd, view->impl->hdc);
DestroyWindow(view->impl->hwnd);
UnregisterClass(view->impl->wc.lpszClassName, NULL);
free((void*)view->impl->wc.lpszClassName);
free(view->impl);
free(view);
}

static void
puglReshape(PuglView* view, int width, int height)
{
puglEnterContext(view);

if (view->reshapeFunc) {
view->reshapeFunc(view, width, height);
} else {
puglDefaultReshape(view, width, height);
}

view->width = width;
view->height = height;
}

static void
puglDisplay(PuglView* view)
{
puglEnterContext(view);

view->redisplay = false;
if (view->displayFunc) {
view->displayFunc(view);
}

puglLeaveContext(view, true);
}

static PuglKey
keySymToSpecial(int sym)
{
switch (sym) {
case VK_F1: return PUGL_KEY_F1;
case VK_F2: return PUGL_KEY_F2;
case VK_F3: return PUGL_KEY_F3;
case VK_F4: return PUGL_KEY_F4;
case VK_F5: return PUGL_KEY_F5;
case VK_F6: return PUGL_KEY_F6;
case VK_F7: return PUGL_KEY_F7;
case VK_F8: return PUGL_KEY_F8;
case VK_F9: return PUGL_KEY_F9;
case VK_F10: return PUGL_KEY_F10;
case VK_F11: return PUGL_KEY_F11;
case VK_F12: return PUGL_KEY_F12;
case VK_LEFT: return PUGL_KEY_LEFT;
case VK_UP: return PUGL_KEY_UP;
case VK_RIGHT: return PUGL_KEY_RIGHT;
case VK_DOWN: return PUGL_KEY_DOWN;
case VK_PRIOR: return PUGL_KEY_PAGE_UP;
case VK_NEXT: return PUGL_KEY_PAGE_DOWN;
case VK_HOME: return PUGL_KEY_HOME;
case VK_END: return PUGL_KEY_END;
case VK_INSERT: return PUGL_KEY_INSERT;
case VK_SHIFT: return PUGL_KEY_SHIFT;
case VK_CONTROL: return PUGL_KEY_CTRL;
case VK_MENU: return PUGL_KEY_ALT;
case VK_LWIN: return PUGL_KEY_SUPER;
case VK_RWIN: return PUGL_KEY_SUPER;
}
return (PuglKey)0;
}

static void
processMouseEvent(PuglView* view, int button, bool press, LPARAM lParam)
{
view->event_timestamp_ms = GetMessageTime();
if (press) {
SetCapture(view->impl->hwnd);
} else {
ReleaseCapture();
}

if (view->mouseFunc) {
view->mouseFunc(view, button, press,
GET_X_LPARAM(lParam),
GET_Y_LPARAM(lParam));
}
}

static void
setModifiers(PuglView* view)
{
view->mods = 0;
view->mods |= (GetKeyState(VK_SHIFT) < 0) ? PUGL_MOD_SHIFT : 0;
view->mods |= (GetKeyState(VK_CONTROL) < 0) ? PUGL_MOD_CTRL : 0;
view->mods |= (GetKeyState(VK_MENU) < 0) ? PUGL_MOD_ALT : 0;
view->mods |= (GetKeyState(VK_LWIN) < 0) ? PUGL_MOD_SUPER : 0;
view->mods |= (GetKeyState(VK_RWIN) < 0) ? PUGL_MOD_SUPER : 0;
}

static LRESULT
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:
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);
EndPaint(view->impl->hwnd, &ps);
break;
case WM_MOUSEMOVE:
if (view->motionFunc) {
view->event_timestamp_ms = GetMessageTime();
view->motionFunc(view, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
}
break;
case WM_LBUTTONDOWN:
processMouseEvent(view, 1, true, lParam);
break;
case WM_MBUTTONDOWN:
processMouseEvent(view, 2, true, lParam);
break;
case WM_RBUTTONDOWN:
processMouseEvent(view, 3, true, lParam);
break;
case WM_LBUTTONUP:
processMouseEvent(view, 1, false, lParam);
break;
case WM_MBUTTONUP:
processMouseEvent(view, 2, false, lParam);
break;
case WM_RBUTTONUP:
processMouseEvent(view, 3, false, lParam);
break;
case WM_MOUSEWHEEL:
if (view->scrollFunc) {
view->event_timestamp_ms = GetMessageTime();
POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
ScreenToClient(view->impl->hwnd, &pt);
view->scrollFunc(
view, pt.x, pt.y,
0.0f, GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA);
}
break;
case WM_MOUSEHWHEEL:
if (view->scrollFunc) {
view->event_timestamp_ms = GetMessageTime();
POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
ScreenToClient(view->impl->hwnd, &pt);
view->scrollFunc(
view, pt.x, pt.y,
GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA, 0.0f);
}
break;
case WM_KEYDOWN:
if (view->ignoreKeyRepeat && (lParam & (1 << 30))) {
break;
} // else nobreak
case WM_KEYUP:
view->event_timestamp_ms = GetMessageTime();
if ((key = keySymToSpecial(wParam))) {
if (view->specialFunc) {
view->specialFunc(view, message == WM_KEYDOWN, key);
}
} else if (view->keyboardFunc) {
static BYTE kbs[256];
if (GetKeyboardState(kbs) != FALSE) {
char lb[2];
UINT scanCode = (lParam >> 8) & 0xFFFFFF00;
if ( 1 == ToAscii(wParam, scanCode, kbs, (LPWORD)lb, 0)) {
view->keyboardFunc(view, message == WM_KEYDOWN, (char)lb[0]);
}
}
}
break;
case WM_QUIT:
case PUGL_LOCAL_CLOSE_MSG:
if (view->closeFunc) {
view->closeFunc(view);
view->redisplay = false;
}
break;
default:
return DefWindowProc(
view->impl->hwnd, message, wParam, lParam);
}

return 0;
}

void
puglGrabFocus(PuglView* view)
{
// TODO
}

PuglStatus
puglProcessEvents(PuglView* view)
{
MSG msg;
while (PeekMessage(&msg, view->impl->hwnd, 0, 0, PM_REMOVE)) {
handleMessage(view, msg.message, msg.wParam, msg.lParam);
}

if (view->redisplay) {
InvalidateRect(view->impl->hwnd, NULL, FALSE);
}

return PUGL_SUCCESS;
}

LRESULT CALLBACK
wndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PuglView* view = (PuglView*)GetWindowLongPtr(hwnd, GWLP_USERDATA);

switch (message) {
case WM_CREATE:
PostMessage(hwnd, WM_SHOWWINDOW, TRUE, 0);
return 0;
case WM_CLOSE:
PostMessage(hwnd, PUGL_LOCAL_CLOSE_MSG, wParam, lParam);
return 0;
case WM_DESTROY:
return 0;
default:
if (view && hwnd == view->impl->hwnd) {
return handleMessage(view, message, wParam, lParam);
} else {
return DefWindowProc(hwnd, message, wParam, lParam);
}
}
}

void
puglPostRedisplay(PuglView* view)
{
view->redisplay = true;
}

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

+ 0
- 606
dgl/src/pugl/pugl_x11.c View File

@@ -1,606 +0,0 @@
/*
Copyright 2012-2014 David Robillard <http://drobilla.net>
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
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 pugl_x11.c X11 Pugl Implementation.
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

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

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

#ifdef PUGL_HAVE_CAIRO
#include <cairo/cairo.h>
#include <cairo/cairo-xlib.h>
#endif

#include "pugl/pugl_internal.h"

#define SOFD_HAVE_X11
#include "../sofd/libsofd.h"
#include "../sofd/libsofd.c"

struct PuglInternalsImpl {
Display* display;
int screen;
Window win;
XIM xim;
XIC xic;
#ifdef PUGL_HAVE_CAIRO
cairo_t* cr;
cairo_surface_t* surface;
#endif
#ifdef PUGL_HAVE_GL
GLXContext ctx;
Bool doubleBuffered;
#endif
};

PuglInternals*
puglInitInternals(void)
{
return (PuglInternals*)calloc(1, sizeof(PuglInternals));
}

static XVisualInfo*
getVisual(PuglView* view)
{
PuglInternals* const impl = view->impl;
XVisualInfo* vi = NULL;

#ifdef PUGL_HAVE_GL
if (view->ctx_type == PUGL_GL) {
/**
Attributes for single-buffered RGBA with at least
4 bits per color and a 16 bit depth buffer.
*/
int attrListSgl[] = {
GLX_RGBA,
GLX_RED_SIZE, 4,
GLX_GREEN_SIZE, 4,
GLX_BLUE_SIZE, 4,
GLX_DEPTH_SIZE, 16,
GLX_ARB_multisample, 1,
None
};

/**
Attributes for double-buffered RGBA with at least
4 bits per color and a 16 bit depth buffer.
*/
int attrListDbl[] = {
GLX_RGBA,
GLX_DOUBLEBUFFER,
GLX_RED_SIZE, 4,
GLX_GREEN_SIZE, 4,
GLX_BLUE_SIZE, 4,
GLX_DEPTH_SIZE, 16,
GLX_ARB_multisample, 1,
None
};

/**
Attributes for double-buffered RGBA with multi-sampling
(antialiasing)
*/
int attrListDblMS[] = {
GLX_RGBA,
GLX_DOUBLEBUFFER,
GLX_RED_SIZE, 4,
GLX_GREEN_SIZE, 4,
GLX_BLUE_SIZE, 4,
GLX_ALPHA_SIZE, 4,
GLX_DEPTH_SIZE, 16,
GLX_SAMPLE_BUFFERS, 1,
GLX_SAMPLES, 4,
None
};

impl->doubleBuffered = True;

vi = glXChooseVisual(impl->display, impl->screen, attrListDblMS);

if (vi == NULL) {
vi = glXChooseVisual(impl->display, impl->screen, attrListDbl);
PUGL_LOG("multisampling (antialiasing) is not available\n");
}

if (vi == NULL) {
vi = glXChooseVisual(impl->display, impl->screen, attrListSgl);
impl->doubleBuffered = False;
PUGL_LOG("singlebuffered rendering will be used, no doublebuffering available\n");
}
}
#endif
#ifdef PUGL_HAVE_CAIRO
if (view->ctx_type == PUGL_CAIRO) {
XVisualInfo pat;
int n;
pat.screen = impl->screen;
vi = XGetVisualInfo(impl->display, VisualScreenMask, &pat, &n);
}
#endif

return vi;
}

static bool
createContext(PuglView* view, XVisualInfo* vi)
{
PuglInternals* const impl = view->impl;

#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* const impl = view->impl;

impl->display = XOpenDisplay(NULL);
impl->screen = DefaultScreen(impl->display);

XVisualInfo* const vi = getVisual(view);
if (!vi) {
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);
#endif

Window xParent = view->parent
? (Window)view->parent
: RootWindow(impl->display, impl->screen);

Colormap cmap = XCreateColormap(
impl->display, xParent, vi->visual, AllocNone);

XSetWindowAttributes attr;
memset(&attr, 0, sizeof(XSetWindowAttributes));
attr.background_pixel = BlackPixel(impl->display, impl->screen);
attr.border_pixel = BlackPixel(impl->display, impl->screen);
attr.colormap = cmap;
attr.event_mask = (ExposureMask | StructureNotifyMask |
EnterWindowMask | LeaveWindowMask |
KeyPressMask | KeyReleaseMask |
ButtonPressMask | ButtonReleaseMask |
PointerMotionMask | FocusChangeMask);

impl->win = XCreateWindow(
impl->display, xParent,
0, 0, view->width, view->height, 0, vi->depth, InputOutput, vi->visual,
CWBackPixel | CWBorderPixel | CWColormap | CWEventMask, &attr);

if (!createContext(view, vi)) {
XDestroyWindow(impl->display, impl->win);
impl->win = 0;

XCloseDisplay(impl->display);
impl->display = NULL;

return 1;
}

XSizeHints sizeHints;
memset(&sizeHints, 0, sizeof(sizeHints));
if (!view->resizable) {
sizeHints.flags = PMinSize|PMaxSize;
sizeHints.min_width = view->width;
sizeHints.min_height = view->height;
sizeHints.max_width = view->width;
sizeHints.max_height = view->height;
XSetNormalHints(impl->display, impl->win, &sizeHints);
} else if (view->min_width > 0 && view->min_height > 0) {
sizeHints.flags = PMinSize;
sizeHints.min_width = view->min_width;
sizeHints.min_height = view->min_height;
XSetNormalHints(impl->display, impl->win, &sizeHints);
}

if (title) {
XStoreName(impl->display, impl->win, title);
}

if (!view->parent) {
Atom wmDelete = XInternAtom(impl->display, "WM_DELETE_WINDOW", True);
XSetWMProtocols(impl->display, impl->win, &wmDelete, 1);
}

if (glXIsDirect(impl->display, impl->ctx)) {
PUGL_LOG("DRI enabled (to disable, set LIBGL_ALWAYS_INDIRECT=1\n");
} else {
PUGL_LOG("No DRI available\n");
}

XFree(vi);

return PUGL_SUCCESS;
}

void
puglShowWindow(PuglView* view)
{
XMapRaised(view->impl->display, view->impl->win);
}

void
puglHideWindow(PuglView* view)
{
XUnmapWindow(view->impl->display, view->impl->win);
}

void
puglDestroy(PuglView* view)
{
if (!view) {
return;
}

x_fib_close(view->impl->display);

destroyContext(view);
XDestroyWindow(view->impl->display, view->impl->win);
XCloseDisplay(view->impl->display);
free(view->impl);
free(view);
}

static void
puglReshape(PuglView* view, int width, int height)
{
puglEnterContext(view);

if (view->reshapeFunc) {
view->reshapeFunc(view, width, height);
} else {
puglDefaultReshape(view, width, height);
}

puglLeaveContext(view, false);

view->width = width;
view->height = height;
}

static void
puglDisplay(PuglView* view)
{
puglEnterContext(view);

view->redisplay = false;

if (view->displayFunc) {
view->displayFunc(view);
}

puglLeaveContext(view, true);
}

static PuglKey
keySymToSpecial(KeySym sym)
{
switch (sym) {
case XK_F1: return PUGL_KEY_F1;
case XK_F2: return PUGL_KEY_F2;
case XK_F3: return PUGL_KEY_F3;
case XK_F4: return PUGL_KEY_F4;
case XK_F5: return PUGL_KEY_F5;
case XK_F6: return PUGL_KEY_F6;
case XK_F7: return PUGL_KEY_F7;
case XK_F8: return PUGL_KEY_F8;
case XK_F9: return PUGL_KEY_F9;
case XK_F10: return PUGL_KEY_F10;
case XK_F11: return PUGL_KEY_F11;
case XK_F12: return PUGL_KEY_F12;
case XK_Left: return PUGL_KEY_LEFT;
case XK_Up: return PUGL_KEY_UP;
case XK_Right: return PUGL_KEY_RIGHT;
case XK_Down: return PUGL_KEY_DOWN;
case XK_Page_Up: return PUGL_KEY_PAGE_UP;
case XK_Page_Down: return PUGL_KEY_PAGE_DOWN;
case XK_Home: return PUGL_KEY_HOME;
case XK_End: return PUGL_KEY_END;
case XK_Insert: return PUGL_KEY_INSERT;
case XK_Shift_L: return PUGL_KEY_SHIFT;
case XK_Shift_R: return PUGL_KEY_SHIFT;
case XK_Control_L: return PUGL_KEY_CTRL;
case XK_Control_R: return PUGL_KEY_CTRL;
case XK_Alt_L: return PUGL_KEY_ALT;
case XK_Alt_R: return PUGL_KEY_ALT;
case XK_Super_L: return PUGL_KEY_SUPER;
case XK_Super_R: return PUGL_KEY_SUPER;
}
return (PuglKey)0;
}

static void
setModifiers(PuglView* view, unsigned xstate, unsigned xtime)
{
view->event_timestamp_ms = xtime;

view->mods = 0;
view->mods |= (xstate & ShiftMask) ? PUGL_MOD_SHIFT : 0;
view->mods |= (xstate & ControlMask) ? PUGL_MOD_CTRL : 0;
view->mods |= (xstate & Mod1Mask) ? PUGL_MOD_ALT : 0;
view->mods |= (xstate & Mod4Mask) ? PUGL_MOD_SUPER : 0;
}

static void
dispatchKey(PuglView* view, XEvent* event, bool press)
{
KeySym sym;
char str[5];
const int n = XLookupString(&event->xkey, str, 4, &sym, NULL);

if (sym == XK_Escape && view->closeFunc && !press && !view->parent) {
view->closeFunc(view);
view->redisplay = false;
return;
}
if (n == 0) {
return;
}
if (n > 1) {
fprintf(stderr, "warning: Unsupported multi-byte key %X\n", (int)sym);
return;
}

const PuglKey special = keySymToSpecial(sym);
if (special && view->specialFunc) {
view->specialFunc(view, press, special);
} else if (!special && view->keyboardFunc) {
view->keyboardFunc(view, press, str[0]);
}
}

PuglStatus
puglProcessEvents(PuglView* view)
{
XEvent event;
while (XPending(view->impl->display) > 0) {
XNextEvent(view->impl->display, &event);

if (x_fib_handle_events(view->impl->display, &event)) {
const int status = x_fib_status();

if (status > 0) {
char* const filename = x_fib_filename();
x_fib_close(view->impl->display);
if (view->fileSelectedFunc) {
view->fileSelectedFunc(view, filename);
}
free(filename);
} else if (status < 0) {
x_fib_close(view->impl->display);
if (view->fileSelectedFunc) {
view->fileSelectedFunc(view, NULL);
}
}
break;
}

if (event.xany.window != view->impl->win) {
continue;
}

switch (event.type) {
case MapNotify:
puglReshape(view, view->width, view->height);
break;
case ConfigureNotify:
if ((event.xconfigure.width != view->width) ||
(event.xconfigure.height != view->height)) {
puglReshape(view,
event.xconfigure.width,
event.xconfigure.height);
}
break;
case Expose:
if (event.xexpose.count != 0) {
break;
}
puglDisplay(view);
break;
case MotionNotify:
setModifiers(view, event.xmotion.state, event.xmotion.time);
if (view->motionFunc) {
view->motionFunc(view, event.xmotion.x, event.xmotion.y);
}
break;
case ButtonPress:
setModifiers(view, event.xbutton.state, event.xbutton.time);
if (event.xbutton.button >= 4 && event.xbutton.button <= 7) {
if (view->scrollFunc) {
float dx = 0, dy = 0;
switch (event.xbutton.button) {
case 4: dy = 1.0f; break;
case 5: dy = -1.0f; break;
case 6: dx = -1.0f; break;
case 7: dx = 1.0f; break;
}
view->scrollFunc(view, event.xbutton.x, event.xbutton.y, dx, dy);
}
break;
}
// nobreak
case ButtonRelease:
setModifiers(view, event.xbutton.state, event.xbutton.time);
if (view->mouseFunc &&
(event.xbutton.button < 4 || event.xbutton.button > 7)) {
view->mouseFunc(view,
event.xbutton.button, event.type == ButtonPress,
event.xbutton.x, event.xbutton.y);
}
break;
case KeyPress:
setModifiers(view, event.xkey.state, event.xkey.time);
dispatchKey(view, &event, true);
break;
case KeyRelease: {
setModifiers(view, event.xkey.state, event.xkey.time);
bool repeated = false;
if (view->ignoreKeyRepeat &&
XEventsQueued(view->impl->display, QueuedAfterReading)) {
XEvent next;
XPeekEvent(view->impl->display, &next);
if (next.type == KeyPress &&
next.xkey.time == event.xkey.time &&
next.xkey.keycode == event.xkey.keycode) {
XNextEvent(view->impl->display, &event);
repeated = true;
}
}
if (!repeated) {
dispatchKey(view, &event, false);
}
} break;
case ClientMessage: {
char* type = XGetAtomName(view->impl->display,
event.xclient.message_type);
if (!strcmp(type, "WM_PROTOCOLS")) {
if (view->closeFunc) {
view->closeFunc(view);
view->redisplay = false;
}
}
XFree(type);
} break;
#ifdef PUGL_GRAB_FOCUS
case EnterNotify:
XSetInputFocus(view->impl->display, view->impl->win, RevertToPointerRoot, CurrentTime);
break;
#endif
default:
break;
}
}

if (view->redisplay) {
puglDisplay(view);
}

return PUGL_SUCCESS;
}

void
puglPostRedisplay(PuglView* view)
{
view->redisplay = true;
}

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

+ 0
- 2431
dgl/src/sofd/libsofd.c
File diff suppressed because it is too large
View File


+ 0
- 175
dgl/src/sofd/libsofd.h View File

@@ -1,175 +0,0 @@
/* libSOFD - Simple Open File Dialog [for X11 without toolkit]
*
* Copyright (C) 2014 Robin Gareus <robin@gareus.org>
*
* 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.
*/

#ifdef SOFD_HAVE_X11
#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
* @param x if >0 set explict initial width of the window
* @param y if >0 set explict initial height of the window
* @return 0 on success
*/
int x_fib_show (Display *dpy, Window parent, int x, int y);

/** force close the dialog.
* This is normally not needed, the dialog closes itself
* when a file is selected or the user cancels selection.
* @param dpy X Display connection
*/
void x_fib_close (Display *dpy);

/** non-blocking X11 event handler.
* It is safe to run this function even if the dialog is
* closed or was not initialized.
*
* @param dpy X Display connection
* @param event the XEvent to process
* @return status
* 0: the event was not for this window, or file-dialog still
* active, or the dialog window is not displayed.
* >0: file was selected, dialog closed
* <0: file selection was cancelled.
*/
int x_fib_handle_events (Display *dpy, XEvent *event);

/** last status of the dialog
* @return >0: file was selected, <0: canceled or inactive. 0: active
*/
int x_fib_status ();

/** query the selected filename
* @return NULL if none set, or allocated string to be free()ed by the called
*/
char *x_fib_filename ();

/** customize/configure the dialog before calling \ref x_fib_show
* changes only have any effect if the dialog is not visible.
* @param k key to change
* 0: set current dir to display (must end with slash)
* 1: set title of dialog window
* 2: specify a custom X11 font to use
* 3: specify a custom 'places' file to include
* (following gtk-bookmark convention)
* @param v value
* @return 0 on success.
*/
int x_fib_configure (int k, const char *v);

/** customize/configure the dialog before calling \ref x_fib_show
* changes only have any effect if the dialog is not visible.
*
* @param k button to change:
* 1: show hidden files
* 2: show places
* 3: show filter/list all (automatically hidden if there is no
* filter function)
* @param v <0 to hide the button >=0 show button,
* 0: set button-state to not-checked
* 1: set button-state to checked
* >1: retain current state
* @return 0 on success.
*/
int x_fib_cfg_buttons (int k, int v);

/** set custom callback to filter file-names.
* NULL will disable the filter and hide the 'show all' button.
* changes only have any effect if the dialog is not visible.
*
* @param cb callback function to check file
* the callback function is called with the file name (basename only)
* and is expected to return 1 if the file passes the filter
* and 0 if the file should not be listed by default.
* @return 0 on success.
*/
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
* parallel from different threads.
*/

/** release static resources of 'recently used files'
*/
void x_fib_free_recent ();

/** add an entry to the recently used list
*
* The dialog does not add files automatically on open,
* if the application succeeds to open a selected file,
* this function should be called.
*
* @param path complete path to file
* @param atime time of last use, 0: NOW
* @return -1 on error, number of current entries otherwise
*/
int x_fib_add_recent (const char *path, time_t atime);

/** get a platform specific path to a good location for
* saving the recently used file list.
* (follows XDG_DATA_HOME on Unix, and CSIDL_LOCAL_APPDATA spec)
*
* @param application-name to use to include in file
* @return pointer to static path or NULL
*/
const char *x_fib_recent_file(const char *appname);

/** save the current list of recently used files to the given filename
* (the format is one file per line, filename URL encoded and space separated
* with last-used timestamp)
*
* This function tries to creates the containing directory if it does
* not exist.
*
* @param fn file to save the list to
* @return 0: on success
*/
int x_fib_save_recent (const char *fn);

/** load a recently used file list.
*
* @param fn file to load the list from
* @return 0: on success
*/
int x_fib_load_recent (const char *fn);

/** get number of entries in the current list
* @return number of entries in the recently used list
*/
unsigned int x_fib_recent_count ();

/** get recently used entry at given position
*
* @param i entry to query
* @return pointer to static string
*/
const char *x_fib_recent_at (unsigned int i);

+ 0
- 800
distrho/DistrhoPlugin.hpp View File

@@ -1,800 +0,0 @@
/*
* 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_PLUGIN_HPP_INCLUDED
#define DISTRHO_PLUGIN_HPP_INCLUDED

#include "extra/d_string.hpp"
#include "src/DistrhoPluginChecks.h"

#include <cmath>

#ifdef DISTRHO_PROPER_CPP11_SUPPORT
# include <cstdint>
#else
# include <stdint.h>
#endif

#ifndef M_PI
# define M_PI 3.14159265358979323846
#endif

START_NAMESPACE_DISTRHO

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

@section Macros
You start by creating a "DistrhoPluginInfo.h" file describing the plugin via macros, see @ref PluginMacros.

@section Plugin
TODO

@section Parameters
describe input and output, automable and rt safe, boolean etc, cv
*/

/* ------------------------------------------------------------------------------------------------------------
* Plugin Macros */

#ifdef DOXYGEN

/**
@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 file 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::d_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::d_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::d_writeMidiEvent(const MidiEvent&)
*/
#define DISTRHO_PLUGIN_WANT_MIDI_OUTPUT 1

/**
Wherever the plugin provides its own internal programs.
@see Plugin::d_initProgramName(uint32_t, d_string&)
@see Plugin::d_setProgram(uint32_t)
*/
#define DISTRHO_PLUGIN_WANT_PROGRAMS 1

/**
Wherever the plugin uses internal non-parameter data.
@see Plugin::d_initState(uint32_t, d_string&, d_string&)
@see Plugin::d_setState(const char*, const char*)
*/
#define DISTRHO_PLUGIN_WANT_STATE 1

/**
Wherever the plugin wants time position information from the host.
@see Plugin::d_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"

/** @} */

#endif

/* ------------------------------------------------------------------------------------------------------------
* Parameter Hints */

/**
@defgroup ParameterHints Parameter Hints

Various parameter hints.
@see Parameter::hints
@{
*/

/**
Parameter is automable (real-time safe).
@see Plugin::d_setParameterValue()
*/
static const uint32_t kParameterIsAutomable = 0x01;

/**
Parameter value is boolean.
It's always at either minimum or maximum value.
*/
static const uint32_t kParameterIsBoolean = 0x02;

/**
Parameter value is integer.
*/
static const uint32_t kParameterIsInteger = 0x04;

/**
Parameter value is logarithmic.
*/
static const uint32_t kParameterIsLogarithmic = 0x08;

/**
Parameter is of output type.
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().
Outputs are changed by the plugin and never modified by the host.
*/
static const uint32_t kParameterIsOutput = 0x10;

/**
Parameter can be used as control voltage (LV2 only).
*/
static const uint32_t kParameterIsCV = 0x20;

/** @} */

/* ------------------------------------------------------------------------------------------------------------
* DPF Base structs */

/**
@defgroup BaseStructs Base Structs
@{
*/

/**
Parameter ranges.
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.
When changing this struct values you must ensure maximum > minimum and default is within range.
*/
struct ParameterRanges {
/**
Default value.
*/
float def;

/**
Minimum value.
*/
float min;

/**
Maximum value.
*/
float max;

/**
Default constructor.
*/
ParameterRanges() noexcept
: def(0.0f),
min(0.0f),
max(1.0f) {}

/**
Constructor using custom values.
*/
ParameterRanges(const float df, const float mn, const float mx) noexcept
: def(df),
min(mn),
max(mx) {}

/**
Fix the default value within range.
*/
void fixDefault() noexcept
{
fixValue(def);
}

/**
Fix a value within range.
*/
void fixValue(float& value) const noexcept
{
if (value < min)
value = min;
else if (value > max)
value = max;
}

/**
Get a fixed value within range.
*/
const float& getFixedValue(const float& value) const noexcept
{
if (value <= min)
return min;
if (value >= max)
return max;
return value;
}

/**
Get a value normalized to 0.0<->1.0.
*/
float getNormalizedValue(const float& value) const noexcept
{
const float normValue((value - min) / (max - min));

if (normValue <= 0.0f)
return 0.0f;
if (normValue >= 1.0f)
return 1.0f;
return normValue;
}

/**
Get a value normalized to 0.0<->1.0, fixed within range.
*/
float getFixedAndNormalizedValue(const float& value) const noexcept
{
if (value <= min)
return 0.0f;
if (value >= max)
return 1.0f;

const float normValue((value - min) / (max - min));

if (normValue <= 0.0f)
return 0.0f;
if (normValue >= 1.0f)
return 1.0f;

return normValue;
}

/**
Get a proper value previously normalized to 0.0<->1.0.
*/
float getUnnormalizedValue(const float& value) const noexcept
{
if (value <= 0.0f)
return min;
if (value >= 1.0f)
return max;

return value * (max - min) + min;
}
};

/**
Parameter.
*/
struct Parameter {
/**
Hints describing this parameter.
@see ParameterHints
*/
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 doesn't have to be unique within a plugin instance, but it's recommended.
*/
d_string name;

/**
The symbol of this parameter.
A parameter symbol is a short restricted name used as a machine and human readable identifier.
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.
*/
d_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.
*/
d_string unit;

/**
Ranges of this parameter.
The ranges describe the default, minimum and maximum values.
*/
ParameterRanges ranges;

/**
Default constructor for a null parameter.
*/
Parameter() noexcept
: hints(0x0),
name(),
symbol(),
unit(),
ranges() {}
};

/**
MIDI event.
*/
struct MidiEvent {
/**
Size of internal data.
*/
static const uint32_t kDataSize = 4;

/**
Time offset in frames.
*/
uint32_t frame;

/**
Number of bytes used.
*/
uint32_t size;

/**
MIDI data.
If size > kDataSize, dataExt is used (otherwise null).
*/
uint8_t data[kDataSize];
const uint8_t* dataExt;
};

/**
Time position.
The @a playing and @a frame values are always valid.
BBT values are only valid when @a bbt.valid is true.

This struct is inspired by the JACK Transport API.
*/
struct TimePosition {
/**
Wherever the host transport is playing/rolling.
*/
bool playing;

/**
Current host transport position in frames.
*/
uint64_t frame;

/**
Bar-Beat-Tick time position.
*/
struct BarBeatTick {
/**
Wherever the host transport is using BBT.
If false you must not read from this struct.
*/
bool valid;

/**
Current bar.
Should always be > 0.
The first bar is bar '1'.
*/
int32_t bar;

/**
Current beat within bar.
Should always be > 0 and <= @a beatsPerBar.
The first beat is beat '1'.
*/
int32_t beat;

/**
Current tick within beat.
Should always be > 0 and <= @a ticksPerBeat.
The first tick is tick '0'.
*/
int32_t tick;

/**
Number of ticks that have elapsed between frame 0 and the first beat of the current measure.
*/
double barStartTick;

/**
Time signature "numerator".
*/
float beatsPerBar;

/**
Time signature "denominator".
*/
float beatType;

/**
Number of ticks within a bar.
Usually a moderately large integer with many denominators, such as 1920.0.
*/
double ticksPerBeat;

/**
Number of beats per minute.
*/
double beatsPerMinute;

/**
Default constructor for a null BBT time position.
*/
BarBeatTick() noexcept
: valid(false),
bar(0),
beat(0),
tick(0),
barStartTick(0.0),
beatsPerBar(0.0f),
beatType(0.0f),
ticksPerBeat(0.0),
beatsPerMinute(0.0) {}
} bbt;

/**
Default constructor for a time position.
*/
TimePosition() noexcept
: playing(false),
frame(0),
bbt() {}
};

/** @} */

/* ------------------------------------------------------------------------------------------------------------
* DPF Plugin */

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

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.

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_STATE activates internal state features.
When enabled you need to implement d_initStateKey() and d_setState().

The process function d_run() changes wherever DISTRHO_PLUGIN_WANT_MIDI_INPUT is enabled or not.
When enabled it provides midi input events.
*/
class Plugin
{
public:
/**
Plugin class constructor.
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);

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

/* --------------------------------------------------------------------------------------------------------
* Host state */

/**
Get the current buffer size that will probably be used during processing, in frames.
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)
*/
uint32_t d_getBufferSize() const noexcept;

/**
Get the current sample rate that will be used during processing.
This value will remain constant between activate and deactivate.
@see d_sampleRateChanged(double)
*/
double d_getSampleRate() const noexcept;

#if DISTRHO_PLUGIN_WANT_TIMEPOS
/**
Get the current host transport time position.
This function should only be called during d_run().
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.
*/
const TimePosition& d_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().
@note This function is only available if DISTRHO_PLUGIN_WANT_LATENCY is enabled.
*/
void d_setLatency(uint32_t frames) noexcept;
#endif

#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().
*/
bool d_writeMidiEvent(const MidiEvent& midiEvent) noexcept;
#endif

protected:
/* --------------------------------------------------------------------------------------------------------
* Information */

/**
Get the plugin name.
Returns DISTRHO_PLUGIN_NAME by default.
*/
virtual const char* d_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.
*/
virtual const char* d_getLabel() const = 0;

/**
Get the plugin author/maker.
*/
virtual const char* d_getMaker() const = 0;

/**
Get the plugin license name (a single line of text).
*/
virtual const char* d_getLicense() const = 0;

/**
Get the plugin version, in hexadecimal.
TODO format to be defined
*/
virtual uint32_t d_getVersion() const = 0;

/**
Get the plugin unique Id.
This value is used by LADSPA, DSSI and VST plugin formats.
*/
virtual int64_t d_getUniqueId() const = 0;

/* --------------------------------------------------------------------------------------------------------
* Init */

/**
Initialize the parameter @a index.
This function will be called once, shortly after the plugin is created.
*/
virtual void d_initParameter(uint32_t index, Parameter& parameter) = 0;

#if DISTRHO_PLUGIN_WANT_PROGRAMS
/**
Set the name of the program @a index.
This function will be called once, shortly after the plugin is created.
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;
#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.
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;
#endif

/* --------------------------------------------------------------------------------------------------------
* Internal data */

/**
Get the current value of a parameter.
The host may call this function from any context, including realtime processing.
*/
virtual float d_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.
@note This function will only be called for parameter inputs.
*/
virtual void d_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.
Must be implemented by your plugin class only if DISTRHO_PLUGIN_WANT_PROGRAMS is enabled.
*/
virtual void d_setProgram(uint32_t index) = 0;
#endif

#if DISTRHO_PLUGIN_WANT_STATE
/**
Change an internal state @a key to @a value.
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;
#endif

/* --------------------------------------------------------------------------------------------------------
* Process */

/**
Activate this plugin.
*/
virtual void d_activate() {}

/**
Deactivate this plugin.
*/
virtual void d_deactivate() {}

#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.
*/
virtual void d_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.
*/
virtual void d_run(const float** inputs, float** outputs, uint32_t frames) = 0;
#endif

/* --------------------------------------------------------------------------------------------------------
* Callbacks (optional) */

/**
Optional callback to inform the plugin about a buffer size change.
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()
*/
virtual void d_bufferSizeChanged(uint32_t newBufferSize);

/**
Optional callback to inform the plugin about a sample rate change.
This function will only be called when the plugin is deactivated.
@see d_getSampleRate()
*/
virtual void d_sampleRateChanged(double newSampleRate);

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

private:
struct PrivateData;
PrivateData* const pData;
friend class PluginExporter;

DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(Plugin)
};

/* ------------------------------------------------------------------------------------------------------------
* Create plugin, entry point */

/**
TODO.
*/
extern Plugin* createPlugin();

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

END_NAMESPACE_DISTRHO

#endif // DISTRHO_PLUGIN_HPP_INCLUDED

+ 0
- 30
distrho/DistrhoPluginMain.cpp View File

@@ -1,30 +0,0 @@
/*
* 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 "src/DistrhoPlugin.cpp"

#if defined(DISTRHO_PLUGIN_TARGET_CARLA)
# include "src/DistrhoPluginCarla.cpp"
#elif defined(DISTRHO_PLUGIN_TARGET_JACK)
# include "src/DistrhoPluginJack.cpp"
#elif (defined(DISTRHO_PLUGIN_TARGET_LADSPA) || defined(DISTRHO_PLUGIN_TARGET_DSSI))
# include "src/DistrhoPluginLADSPA+DSSI.cpp"
#elif defined(DISTRHO_PLUGIN_TARGET_LV2)
# include "src/DistrhoPluginLV2.cpp"
# include "src/DistrhoPluginLV2export.cpp"
#elif defined(DISTRHO_PLUGIN_TARGET_VST)
# include "src/DistrhoPluginVST.cpp"
#endif

+ 0
- 196
distrho/DistrhoUI.hpp View File

@@ -1,196 +0,0 @@
/*
* 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_UI_HPP_INCLUDED
#define DISTRHO_UI_HPP_INCLUDED

#include "extra/d_leakdetector.hpp"
#include "src/DistrhoPluginChecks.h"

#if DISTRHO_UI_USE_NANOVG
# include "../dgl/NanoVG.hpp"
typedef DGL::NanoWidget UIWidget;
#else
# include "../dgl/Widget.hpp"
typedef DGL::Widget UIWidget;
#endif

START_NAMESPACE_DISTRHO

/* ------------------------------------------------------------------------------------------------------------
* DPF UI */

/**
DPF UI class from where UI instances are created.

TODO.

must call setSize during construction,
*/
class UI : public UIWidget
{
public:
/**
UI class constructor.
The UI should be initialized to a default state that matches the plugin side.
*/
UI(uint width = 0, uint height = 0);

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

/* --------------------------------------------------------------------------------------------------------
* Host state */

/**
Get the current sample rate used in plugin processing.
@see d_sampleRateChanged(double)
*/
double d_getSampleRate() const noexcept;

/**
TODO: Document this.
*/
void d_editParameter(const uint32_t index, const bool started);

/**
TODO: Document this.
*/
void d_setParameterValue(const uint32_t index, const float value);

#if DISTRHO_PLUGIN_WANT_STATE
/**
TODO: Document this.
*/
void d_setState(const char* const key, const char* const 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);
#endif

#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
/* --------------------------------------------------------------------------------------------------------
* Direct DSP access - DO NOT USE THIS UNLESS STRICTLY NECESSARY!! */

/**
TODO: Document this.
*/
void* d_getPluginInstancePointer() const noexcept;
#endif

protected:
/* --------------------------------------------------------------------------------------------------------
* DSP/Plugin Callbacks */

/**
A parameter has changed on the plugin side.
This is called by the host to inform the UI about parameter changes.
*/
virtual void d_parameterChanged(uint32_t index, float value) = 0;

#if DISTRHO_PLUGIN_WANT_PROGRAMS
/**
The current program has changed on the plugin side.
This is called by the host to inform the UI about program changes.
*/
virtual void d_programChanged(uint32_t index) = 0;
#endif

#if DISTRHO_PLUGIN_WANT_STATE
/**
A state has changed on the plugin side.
This is called by the host to inform the UI about state changes.
*/
virtual void d_stateChanged(const char* key, const char* value) = 0;
#endif

/* --------------------------------------------------------------------------------------------------------
* DSP/Plugin Callbacks (optional) */

/**
Optional callback to inform the UI about a sample rate change on the plugin side.
@see d_getSampleRate()
*/
virtual void d_sampleRateChanged(double newSampleRate);

/* --------------------------------------------------------------------------------------------------------
* UI Callbacks (optional) */

/**
TODO: Document this.
*/
virtual void d_uiIdle() {}

/**
File browser selected function.
@see Window::fileBrowserSelected(const char*)
*/
virtual void d_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);

/* --------------------------------------------------------------------------------------------------------
* UI Resize Handling, internal */

/**
OpenGL widget resize function, called when the widget is resized.
This is overriden here so the host knows when the UI is resized by you.
@see Widget::onResize(const ResizeEvent&)
*/
void onResize(const ResizeEvent& ev) override;

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

private:
struct PrivateData;
PrivateData* const pData;
friend class UIExporter;
friend class UIExporterWindow;

// these should not be used
void setAbsoluteX(int) const noexcept {}
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 */

/**
TODO.
*/
extern UI* createUI();

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

END_NAMESPACE_DISTRHO

#endif // DISTRHO_UI_HPP_INCLUDED

+ 0
- 29
distrho/DistrhoUIMain.cpp View File

@@ -1,29 +0,0 @@
/*
* 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 "src/DistrhoUI.cpp"

#if defined(DISTRHO_PLUGIN_TARGET_CARLA)
// nothing
#elif defined(DISTRHO_PLUGIN_TARGET_JACK)
// nothing
#elif defined(DISTRHO_PLUGIN_TARGET_DSSI)
# include "src/DistrhoUIDSSI.cpp"
#elif defined(DISTRHO_PLUGIN_TARGET_LV2)
# include "src/DistrhoUILV2.cpp"
#elif defined(DISTRHO_PLUGIN_TARGET_VST)
// nothing
#endif

+ 0
- 202
distrho/DistrhoUtils.hpp View File

@@ -1,202 +0,0 @@
/*
* 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_UTILS_HPP_INCLUDED
#define DISTRHO_UTILS_HPP_INCLUDED

#include "src/DistrhoDefines.h"

#include <cstdarg>
#include <cstdio>
#include <cstdlib>
#include <cstring>

#include <cmath>
#include <limits>

#ifdef DISTRHO_PROPER_CPP11_SUPPORT
# include <cstdint>
#else
# include <stdint.h>
#endif

#if defined(DISTRHO_OS_MAC) && ! defined(CARLA_OS_MAC)
namespace std {
inline float fmin(float __x, float __y)
{ return __builtin_fminf(__x, __y); }
inline float fmax(float __x, float __y)
{ return __builtin_fmaxf(__x, __y); }
inline float rint(float __x)
{ return __builtin_rintf(__x); }
inline float round(float __x)
{ return __builtin_roundf(__x); }
}
#endif

// -----------------------------------------------------------------------
// misc functions

/*
* Return a 64-bit number from 4 8-bit numbers.
*/
static inline
int64_t d_cconst(const uint8_t a, const uint8_t b, const uint8_t c, const uint8_t d) noexcept
{
return (a << 24) | (b << 16) | (c << 8) | (d << 0);
}

/*
* Dummy function.
*/
static inline
void d_pass() noexcept {}

// -----------------------------------------------------------------------
// string print functions

/*
* Print a string to stdout with newline (gray color).
* Does nothing if DEBUG is not defined.
*/
#ifndef DEBUG
# define d_debug(...)
#else
static inline
void d_debug(const char* const fmt, ...) noexcept
{
try {
::va_list args;
::va_start(args, fmt);
std::fprintf(stdout, "\x1b[30;1m");
std::vfprintf(stdout, fmt, args);
std::fprintf(stdout, "\x1b[0m\n");
::va_end(args);
} catch (...) {}
}
#endif

/*
* Print a string to stdout with newline.
*/
static inline
void d_stdout(const char* const fmt, ...) noexcept
{
try {
::va_list args;
::va_start(args, fmt);
std::vfprintf(stdout, fmt, args);
std::fprintf(stdout, "\n");
::va_end(args);
} catch (...) {}
}

/*
* Print a string to stderr with newline.
*/
static inline
void d_stderr(const char* const fmt, ...) noexcept
{
try {
::va_list args;
::va_start(args, fmt);
std::vfprintf(stderr, fmt, args);
std::fprintf(stderr, "\n");
::va_end(args);
} catch (...) {}
}

/*
* Print a string to stderr with newline (red color).
*/
static inline
void d_stderr2(const char* const fmt, ...) noexcept
{
try {
::va_list args;
::va_start(args, fmt);
std::fprintf(stderr, "\x1b[31m");
std::vfprintf(stderr, fmt, args);
std::fprintf(stderr, "\x1b[0m\n");
::va_end(args);
} catch (...) {}
}

/*
* Print a safe assertion error message.
*/
static inline
void d_safe_assert(const char* const assertion, const char* const file, const int line) noexcept
{
d_stderr2("assertion failure: \"%s\" in file %s, line %i", assertion, file, line);
}

/*
* Print a safe exception error message.
*/
static inline
void d_safe_exception(const char* const exception, const char* const file, const int line) noexcept
{
d_stderr2("exception caught: \"%s\" in file %s, line %i", exception, file, line);
}

// -----------------------------------------------------------------------
// math functions

/*
* Safely compare two floating point numbers.
* Returns true if they match.
*/
template<typename T>
static inline
bool d_isEqual(const T& v1, const T& v2)
{
return std::abs(v1-v2) < std::numeric_limits<T>::epsilon();
}

/*
* Safely compare two floating point numbers.
* Returns true if they don't match.
*/
template<typename T>
static inline
bool d_isNotEqual(const T& v1, const T& v2)
{
return std::abs(v1-v2) >= std::numeric_limits<T>::epsilon();
}

/*
* Safely check if a floating point number is zero.
*/
template<typename T>
static inline
bool d_isZero(const T& value)
{
return std::abs(value) < std::numeric_limits<T>::epsilon();
}

/*
* Safely check if a floating point number is not zero.
*/
template<typename T>
static inline
bool d_isNotZero(const T& value)
{
return std::abs(value) >= std::numeric_limits<T>::epsilon();
}

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

#endif // DISTRHO_UTILS_HPP_INCLUDED

+ 0
- 141
distrho/extra/d_leakdetector.hpp View File

@@ -1,141 +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.
*/

#ifndef DISTRHO_LEAK_DETECTOR_HPP_INCLUDED
#define DISTRHO_LEAK_DETECTOR_HPP_INCLUDED

#include "../DistrhoUtils.hpp"

START_NAMESPACE_DISTRHO

// -----------------------------------------------------------------------
// The following code was based from juce-core LeakDetector class
// Copyright (C) 2013 Raw Material Software Ltd.

/** A good old-fashioned C macro concatenation helper.
This combines two items (which may themselves be macros) into a single string,
avoiding the pitfalls of the ## macro operator.
*/
#define DISTRHO_JOIN_MACRO_HELPER(a, b) a ## b
#define DISTRHO_JOIN_MACRO(item1, item2) DISTRHO_JOIN_MACRO_HELPER(item1, item2)

/** 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.
\code
class MyClass
{
public:
MyClass();
void blahBlah();

private:
DISTRHO_LEAK_DETECTOR(MyClass)
};
\endcode
*/
#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) \
DISTRHO_LEAK_DETECTOR(ClassName)

//==============================================================================
/**
Embedding an instance of this class inside another class can be used as a low-overhead
way of detecting leaked instances.

This class keeps an internal static count of the number of instances that are
active, so that when the app is shutdown and the static destructors are called,
it can check whether there are any left-over instances that may have been leaked.

To use it, use the DISTRHO_LEAK_DETECTOR macro as a simple way to put one in your
class declaration.
*/
template<class OwnerClass>
class LeakedObjectDetector
{
public:
//==============================================================================
LeakedObjectDetector() noexcept { ++(getCounter().numObjects); }
LeakedObjectDetector(const LeakedObjectDetector&) noexcept { ++(getCounter().numObjects); }

~LeakedObjectDetector() noexcept
{
if (--(getCounter().numObjects) < 0)
{
/** If you hit this, then you've managed to delete more instances of this class than you've
created.. That indicates that you're deleting some dangling pointers.

Note that although this assertion will have been triggered during a destructor, it might
not be this particular deletion that's at fault - the incorrect one may have happened
at an earlier point in the program, and simply not been detected until now.

Most errors like this are caused by using old-fashioned, non-RAII techniques for
your object management. Tut, tut. Always, always use ScopedPointers, OwnedArrays,
ReferenceCountedObjects, etc, and avoid the 'delete' operator at all costs!
*/
d_stderr2("*** Dangling pointer deletion! Class: '%s', Count: %i", getLeakedObjectClassName(), getCounter().numObjects);
}
}

private:
//==============================================================================
class LeakCounter
{
public:
LeakCounter() noexcept
: numObjects(0) {}

~LeakCounter() noexcept
{
if (numObjects > 0)
{
/** If you hit this, then you've leaked one or more objects of the type specified by
the 'OwnerClass' template parameter - the name should have been printed by the line above.

If you're leaking, it's probably because you're using old-fashioned, non-RAII techniques for
your object management. Tut, tut. Always, always use ScopedPointers, OwnedArrays,
ReferenceCountedObjects, etc, and avoid the 'delete' operator at all costs!
*/
d_stderr2("*** Leaked objects detected: %i instance(s) of class '%s'", numObjects, getLeakedObjectClassName());
}
}

// this should be an atomic...
volatile int numObjects;
};

static const char* getLeakedObjectClassName() noexcept
{
return OwnerClass::getLeakedObjectClassName();
}

static LeakCounter& getCounter() noexcept
{
static LeakCounter counter;
return counter;
}
};

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

END_NAMESPACE_DISTRHO

#endif // DISTRHO_LEAK_DETECTOR_HPP_INCLUDED

+ 0
- 230
distrho/extra/d_mutex.hpp View File

@@ -1,230 +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.
*/

#ifndef DISTRHO_MUTEX_HPP_INCLUDED
#define DISTRHO_MUTEX_HPP_INCLUDED

#include "../DistrhoUtils.hpp"

#ifdef DISTRHO_OS_WINDOWS
# include <winsock2.h>
# include <windows.h>
#endif

#include <pthread.h>

START_NAMESPACE_DISTRHO

// -----------------------------------------------------------------------
// Mutex class

class Mutex
{
public:
/*
* Constructor.
*/
Mutex() noexcept
{
pthread_mutex_init(&fMutex, nullptr);
}

/*
* Destructor.
*/
~Mutex() noexcept
{
pthread_mutex_destroy(&fMutex);
}

/*
* Lock the mutex.
*/
void lock() const noexcept
{
pthread_mutex_lock(&fMutex);
}

/*
* Try to lock the mutex.
* Returns true if successful.
*/
bool tryLock() const noexcept
{
return (pthread_mutex_trylock(&fMutex) == 0);
}

/*
* Unlock the mutex.
*/
void unlock() const noexcept
{
pthread_mutex_unlock(&fMutex);
}

private:
mutable pthread_mutex_t fMutex;

DISTRHO_PREVENT_HEAP_ALLOCATION
DISTRHO_DECLARE_NON_COPY_CLASS(Mutex)
};

// -----------------------------------------------------------------------
// RecursiveMutex class

class RecursiveMutex
{
public:
/*
* Constructor.
*/
RecursiveMutex() noexcept
{
#ifdef DISTRHO_OS_WINDOWS
InitializeCriticalSection(&fSection);
#else
pthread_mutexattr_t atts;
pthread_mutexattr_init(&atts);
pthread_mutexattr_settype(&atts, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&fMutex, &atts);
pthread_mutexattr_destroy(&atts);
#endif
}

/*
* Destructor.
*/
~RecursiveMutex() noexcept
{
#ifdef DISTRHO_OS_WINDOWS
DeleteCriticalSection(&fSection);
#else
pthread_mutex_destroy(&fMutex);
#endif
}

/*
* Lock the mutex.
*/
void lock() const noexcept
{
#ifdef DISTRHO_OS_WINDOWS
EnterCriticalSection(&fSection);
#else
pthread_mutex_lock(&fMutex);
#endif
}

/*
* Try to lock the mutex.
* Returns true if successful.
*/
bool tryLock() const noexcept
{
#ifdef DISTRHO_OS_WINDOWS
return (TryEnterCriticalSection(&fSection) != FALSE);
#else
return (pthread_mutex_trylock(&fMutex) == 0);
#endif
}

/*
* Unlock the mutex.
*/
void unlock() const noexcept
{
#ifdef DISTRHO_OS_WINDOWS
LeaveCriticalSection(&fSection);
#else
pthread_mutex_unlock(&fMutex);
#endif
}

private:
#ifdef DISTRHO_OS_WINDOWS
mutable CRITICAL_SECTION fSection;
#else
mutable pthread_mutex_t fMutex;
#endif

DISTRHO_PREVENT_HEAP_ALLOCATION
DISTRHO_DECLARE_NON_COPY_CLASS(RecursiveMutex)
};

// -----------------------------------------------------------------------
// Helper class to lock&unlock a mutex during a function scope.

template <class Mutex>
class ScopedLocker
{
public:
ScopedLocker(const Mutex& mutex) noexcept
: fMutex(mutex)
{
fMutex.lock();
}

~ScopedLocker() noexcept
{
fMutex.unlock();
}

private:
const Mutex& fMutex;

DISTRHO_PREVENT_HEAP_ALLOCATION
DISTRHO_DECLARE_NON_COPY_CLASS(ScopedLocker)
};

// -----------------------------------------------------------------------
// Helper class to unlock&lock a mutex during a function scope.

template <class Mutex>
class ScopedUnlocker
{
public:
ScopedUnlocker(const Mutex& mutex) noexcept
: fMutex(mutex)
{
fMutex.unlock();
}

~ScopedUnlocker() noexcept
{
fMutex.lock();
}

private:
const Mutex& fMutex;

DISTRHO_PREVENT_HEAP_ALLOCATION
DISTRHO_DECLARE_NON_COPY_CLASS(ScopedUnlocker)
};

// -----------------------------------------------------------------------
// Define types

typedef ScopedLocker<Mutex> MutexLocker;
typedef ScopedLocker<RecursiveMutex> RecursiveMutexLocker;

typedef ScopedUnlocker<Mutex> MutexUnlocker;
typedef ScopedUnlocker<RecursiveMutex> RecursiveMutexUnlocker;

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

END_NAMESPACE_DISTRHO

#endif // DISTRHO_MUTEX_HPP_INCLUDED

+ 0
- 247
distrho/extra/d_scopedpointer.hpp View File

@@ -1,247 +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.
*/

#ifndef DISTRHO_SCOPED_POINTER_HPP_INCLUDED
#define DISTRHO_SCOPED_POINTER_HPP_INCLUDED

#include "../DistrhoUtils.hpp"

#include <algorithm>

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
out of scope.

Once a pointer has been passed to a ScopedPointer, it will make sure that the pointer
gets deleted when the ScopedPointer is deleted. Using the ScopedPointer on the stack or
as member variables is a good way to use RAII to avoid accidentally leaking dynamically
created objects.

A ScopedPointer can be used in pretty much the same way that you'd use a normal pointer
to an object. If you use the assignment operator to assign a different object to a
ScopedPointer, the old one will be automatically deleted.

A const ScopedPointer is guaranteed not to lose ownership of its object or change the
object to which it points during its lifetime. This means that making a copy of a const
ScopedPointer is impossible, as that would involve the new copy taking ownership from the
old one.

If you need to get a pointer out of a ScopedPointer without it being deleted, you
can use the release() method.

Something to note is the main difference between this class and the std::auto_ptr class,
which is that ScopedPointer provides a cast-to-object operator, wheras std::auto_ptr
requires that you always call get() to retrieve the pointer. The advantages of providing
the cast is that you don't need to call get(), so can use the ScopedPointer in pretty much
exactly the same way as a raw pointer. The disadvantage is that the compiler is free to
use the cast in unexpected and sometimes dangerous ways - in particular, it becomes difficult
to return a ScopedPointer as the result of a function. To avoid this causing errors,
ScopedPointer contains an overloaded constructor that should cause a syntax error in these
circumstances, but it does mean that instead of returning a ScopedPointer from a function,
you'd need to return a raw pointer (or use a std::auto_ptr instead).
*/
template<class ObjectType>
class ScopedPointer
{
public:
//==============================================================================
/** Creates a ScopedPointer containing a null pointer. */
ScopedPointer() noexcept
: object(nullptr) {}

/** Creates a ScopedPointer that owns the specified object. */
ScopedPointer(ObjectType* const objectToTakePossessionOf) noexcept
: object(objectToTakePossessionOf) {}

/** Creates a ScopedPointer that takes its pointer from another ScopedPointer.

Because a pointer can only belong to one ScopedPointer, this transfers
the pointer from the other object to this one, and the other object is reset to
be a null pointer.
*/
ScopedPointer(ScopedPointer& objectToTransferFrom) noexcept
: object(objectToTransferFrom.object)
{
objectToTransferFrom.object = nullptr;
}

/** Destructor.
This will delete the object that this ScopedPointer currently refers to.
*/
~ScopedPointer()
{
ContainerDeletePolicy<ObjectType>::destroy(object);
}

/** Changes this ScopedPointer to point to a new object.

Because a pointer can only belong to one ScopedPointer, this transfers
the pointer from the other object to this one, and the other object is reset to
be a null pointer.

If this ScopedPointer already points to an object, that object
will first be deleted.
*/
ScopedPointer& operator=(ScopedPointer& objectToTransferFrom)
{
if (this != objectToTransferFrom.getAddress())
{
// Two ScopedPointers should never be able to refer to the same object - if
// this happens, you must have done something dodgy!
DISTRHO_SAFE_ASSERT_RETURN(object == nullptr || object != objectToTransferFrom.object, *this);

ObjectType* const oldObject = object;
object = objectToTransferFrom.object;
objectToTransferFrom.object = nullptr;
ContainerDeletePolicy<ObjectType>::destroy(oldObject);
}

return *this;
}

/** Changes this ScopedPointer to point to a new object.

If this ScopedPointer already points to an object, that object
will first be deleted.

The pointer that you pass in may be a nullptr.
*/
ScopedPointer& operator=(ObjectType* const newObjectToTakePossessionOf)
{
if (object != newObjectToTakePossessionOf)
{
ObjectType* const oldObject = object;
object = newObjectToTakePossessionOf;
ContainerDeletePolicy<ObjectType>::destroy(oldObject);
}

return *this;
}

//==============================================================================
/** Returns the object that this ScopedPointer refers to. */
operator ObjectType*() const noexcept { return object; }

/** Returns the object that this ScopedPointer refers to. */
ObjectType* get() const noexcept { return object; }

/** Returns the object that this ScopedPointer refers to. */
ObjectType& operator*() const noexcept { return *object; }

/** Lets you access methods and properties of the object that this ScopedPointer refers to. */
ObjectType* operator->() const noexcept { return object; }

//==============================================================================
/** Removes the current object from this ScopedPointer without deleting it.
This will return the current object, and set the ScopedPointer to a null pointer.
*/
ObjectType* release() noexcept { ObjectType* const o = object; object = nullptr; return o; }

//==============================================================================
/** Swaps this object with that of another ScopedPointer.
The two objects simply exchange their pointers.
*/
void swapWith(ScopedPointer<ObjectType>& other) noexcept
{
// Two ScopedPointers should never be able to refer to the same object - if
// this happens, you must have done something dodgy!
DISTRHO_SAFE_ASSERT_RETURN(object != other.object || this == other.getAddress() || object == nullptr,);

std::swap(object, other.object);
}

private:
//==============================================================================
ObjectType* object;

// (Required as an alternative to the overloaded & operator).
const ScopedPointer* getAddress() const noexcept { return this; }

#ifndef _MSC_VER // (MSVC can't deal with multiple copy constructors)
/* The copy constructors are private to stop people accidentally copying a const ScopedPointer
(the compiler would let you do so by implicitly casting the source to its raw object pointer).

A side effect of this is that in a compiler that doesn't support C++11, you may hit an
error when you write something like this:

ScopedPointer<MyClass> m = new MyClass(); // Compile error: copy constructor is private.

Even though the compiler would normally ignore the assignment here, it can't do so when the
copy constructor is private. It's very easy to fix though - just write it like this:

ScopedPointer<MyClass> m (new MyClass()); // Compiles OK

It's probably best to use the latter form when writing your object declarations anyway, as
this is a better representation of the code that you actually want the compiler to produce.
*/
# ifdef DISTRHO_PROPER_CPP11_SUPPORT
ScopedPointer(const ScopedPointer&) = delete;
ScopedPointer& operator=(const ScopedPointer&) = delete;
# else
ScopedPointer(const ScopedPointer&);
ScopedPointer& operator=(const ScopedPointer&);
# endif
#endif
};

//==============================================================================
/** Compares a ScopedPointer with another pointer.
This can be handy for checking whether this is a null pointer.
*/
template<class ObjectType>
bool operator==(const ScopedPointer<ObjectType>& pointer1, ObjectType* const pointer2) noexcept
{
return static_cast<ObjectType*>(pointer1) == pointer2;
}

/** Compares a ScopedPointer with another pointer.
This can be handy for checking whether this is a null pointer.
*/
template<class ObjectType>
bool operator!=(const ScopedPointer<ObjectType>& pointer1, ObjectType* const pointer2) noexcept
{
return static_cast<ObjectType*>(pointer1) != pointer2;
}

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

END_NAMESPACE_DISTRHO

#endif // DISTRHO_SCOPED_POINTER_HPP_INCLUDED

+ 0
- 62
distrho/extra/d_sleep.hpp View File

@@ -1,62 +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.
*/

#ifndef DISTRHO_SLEEP_HPP_INCLUDED
#define DISTRHO_SLEEP_HPP_INCLUDED

#include "../DistrhoUtils.hpp"

#ifdef DISTRHO_OS_WINDOWS
# include <winsock2.h>
# include <windows.h>
#else
# include <unistd.h>
#endif

// -----------------------------------------------------------------------
// d_*sleep

static inline
void d_sleep(const uint secs) noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(secs > 0,);

try {
#ifdef DISTRHO_OS_WINDOWS
::Sleep(secs * 1000);
#else
::sleep(secs);
#endif
} DISTRHO_SAFE_EXCEPTION("d_sleep");
}

static inline
void d_msleep(const uint msecs) noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(msecs > 0,);

try {
#ifdef DISTRHO_OS_WINDOWS
::Sleep(msecs);
#else
::usleep(msecs * 1000);
#endif
} DISTRHO_SAFE_EXCEPTION("d_msleep");
}

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

#endif // DISTRHO_SLEEP_HPP_INCLUDED

+ 0
- 750
distrho/extra/d_string.hpp View File

@@ -1,750 +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.
*/

#ifndef DISTRHO_STRING_HPP_INCLUDED
#define DISTRHO_STRING_HPP_INCLUDED

#include "d_leakdetector.hpp"

START_NAMESPACE_DISTRHO

// -----------------------------------------------------------------------
// d_string class

class d_string
{
public:
// -------------------------------------------------------------------
// constructors (no explicit conversions allowed)

/*
* Empty string.
*/
explicit d_string() noexcept
{
_init();
}

/*
* Simple character.
*/
explicit d_string(const char c) noexcept
{
char ch[2];
ch[0] = c;
ch[1] = '\0';

_init();
_dup(ch);
}

/*
* Simple char string.
*/
explicit d_string(char* const strBuf) noexcept
{
_init();
_dup(strBuf);
}

/*
* Simple const char string.
*/
explicit d_string(const char* const strBuf) noexcept
{
_init();
_dup(strBuf);
}

/*
* Integer.
*/
explicit d_string(const int value) noexcept
{
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
{
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
{
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
{
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
{
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
{
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
{
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
{
char strBuf[0xff+1];
std::snprintf(strBuf, 0xff, "%g", value);
strBuf[0xff] = '\0';

_init();
_dup(strBuf);
}

// -------------------------------------------------------------------
// non-explicit constructor

/*
* Create string from another string.
*/
d_string(const d_string& str) noexcept
{
_init();
_dup(str.fBuffer);
}

// -------------------------------------------------------------------
// destructor

/*
* Destructor.
*/
~d_string() noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(fBuffer != nullptr,);

if (fBuffer == _null())
return;

std::free(fBuffer);

fBuffer = nullptr;
fBufferLen = 0;
}

// -------------------------------------------------------------------
// public methods

/*
* Get length of the string.
*/
size_t length() const noexcept
{
return fBufferLen;
}

/*
* Check if the string is empty.
*/
bool isEmpty() const noexcept
{
return (fBufferLen == 0);
}

/*
* Check if the string is not empty.
*/
bool isNotEmpty() const noexcept
{
return (fBufferLen != 0);
}

/*
* Check if the string contains another string, optionally ignoring case.
*/
bool contains(const char* const strBuf, const bool ignoreCase = false) const noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(strBuf != nullptr, false);

if (ignoreCase)
{
#ifdef __USE_GNU
return (strcasestr(fBuffer, strBuf) != nullptr);
#else
d_string tmp1(fBuffer), tmp2(strBuf);

// memory allocation failed or empty string(s)
if (tmp1.fBuffer == _null() || tmp2.fBuffer == _null())
return false;

tmp1.toLower();
tmp2.toLower();
return (std::strstr(tmp1, tmp2) != nullptr);
#endif
}

return (std::strstr(fBuffer, strBuf) != nullptr);
}

/*
* Check if character at 'pos' is a digit.
*/
bool isDigit(const size_t pos) const noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(pos < fBufferLen, false);

return (fBuffer[pos] >= '0' && fBuffer[pos] <= '9');
}

/*
* Check if the string starts with the character 'c'.
*/
bool startsWith(const char c) const noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(c != '\0', false);

return (fBufferLen > 0 && fBuffer[0] == c);
}

/*
* Check if the string starts with the string 'prefix'.
*/
bool startsWith(const char* const prefix) const noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(prefix != nullptr, false);

const size_t prefixLen(std::strlen(prefix));

if (fBufferLen < prefixLen)
return false;

return (std::strncmp(fBuffer, prefix, prefixLen) == 0);
}

/*
* Check if the string ends with the character 'c'.
*/
bool endsWith(const char c) const noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(c != '\0', false);

return (fBufferLen > 0 && fBuffer[fBufferLen-1] == c);
}

/*
* Check if the string ends with the string 'suffix'.
*/
bool endsWith(const char* const suffix) const noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(suffix != nullptr, false);

const size_t suffixLen(std::strlen(suffix));

if (fBufferLen < suffixLen)
return false;

return (std::strncmp(fBuffer + (fBufferLen-suffixLen), suffix, suffixLen) == 0);
}

/*
* 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
{
if (fBufferLen == 0 || c == '\0')
{
if (found != nullptr)
*found = false;
return fBufferLen;
}

for (size_t i=0; i < fBufferLen; ++i)
{
if (fBuffer[i] == c)
{
if (found != nullptr)
*found = true;
return i;
}
}

if (found != nullptr)
*found = false;
return fBufferLen;
}

/*
* 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
{
if (fBufferLen == 0 || strBuf == nullptr || strBuf[0] == '\0')
{
if (found != nullptr)
*found = false;
return fBufferLen;
}

if (char* const subStrBuf = std::strstr(fBuffer, strBuf))
{
const ssize_t ret(subStrBuf - fBuffer);

if (ret < 0)
{
// should never happen!
d_safe_assert("ret >= 0", __FILE__, __LINE__);

if (found != nullptr)
*found = false;
return fBufferLen;
}

if (found != nullptr)
*found = true;
return static_cast<size_t>(ret);
}

if (found != nullptr)
*found = false;
return fBufferLen;
}

/*
* 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
{
if (fBufferLen == 0 || c == '\0')
{
if (found != nullptr)
*found = false;
return fBufferLen;
}

for (size_t i=fBufferLen; i > 0; --i)
{
if (fBuffer[i-1] == c)
{
if (found != nullptr)
*found = true;
return i-1;
}
}

if (found != nullptr)
*found = false;
return fBufferLen;
}

/*
* 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
{
if (found != nullptr)
*found = false;

if (fBufferLen == 0 || strBuf == nullptr || strBuf[0] == '\0')
return fBufferLen;

const size_t strBufLen(std::strlen(strBuf));

size_t ret = fBufferLen;
const char* tmpBuf = fBuffer;

for (size_t i=0; i < fBufferLen; ++i)
{
if (std::strstr(tmpBuf+1, strBuf) == nullptr && std::strncmp(tmpBuf, strBuf, strBufLen) == 0)
{
if (found != nullptr)
*found = true;
break;
}

--ret;
++tmpBuf;
}

return fBufferLen-ret;
}

/*
* Clear the string.
*/
void clear() noexcept
{
truncate(0);
}

/*
* Replace all occurrences of character 'before' with character 'after'.
*/
void replace(const char before, const char after) noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(before != '\0' && after != '\0',);

for (size_t i=0; i < fBufferLen; ++i)
{
if (fBuffer[i] == before)
fBuffer[i] = after;
}
}

/*
* Truncate the string to size 'n'.
*/
void truncate(const size_t n) noexcept
{
if (n >= fBufferLen)
return;

for (size_t i=n; i < fBufferLen; ++i)
fBuffer[i] = '\0';

fBufferLen = n;
}

/*
* Convert all non-basic characters to '_'.
*/
void toBasic() noexcept
{
for (size_t i=0; i < fBufferLen; ++i)
{
if (fBuffer[i] >= '0' && fBuffer[i] <= '9')
continue;
if (fBuffer[i] >= 'A' && fBuffer[i] <= 'Z')
continue;
if (fBuffer[i] >= 'a' && fBuffer[i] <= 'z')
continue;
if (fBuffer[i] == '_')
continue;

fBuffer[i] = '_';
}
}

/*
* Convert to all ascii characters to lowercase.
*/
void toLower() noexcept
{
static const char kCharDiff('a' - 'A');

for (size_t i=0; i < fBufferLen; ++i)
{
if (fBuffer[i] >= 'A' && fBuffer[i] <= 'Z')
fBuffer[i] = static_cast<char>(fBuffer[i] + kCharDiff);
}
}

/*
* Convert to all ascii characters to uppercase.
*/
void toUpper() noexcept
{
static const char kCharDiff('a' - 'A');

for (size_t i=0; i < fBufferLen; ++i)
{
if (fBuffer[i] >= 'a' && fBuffer[i] <= 'z')
fBuffer[i] = static_cast<char>(fBuffer[i] - kCharDiff);
}
}

/*
* Direct access to the string buffer (read-only).
*/
const char* buffer() const noexcept
{
return fBuffer;
}

// -------------------------------------------------------------------
// public operators

operator const char*() const noexcept
{
return fBuffer;
}

char operator[](const size_t pos) const noexcept
{
if (pos < fBufferLen)
return fBuffer[pos];

d_safe_assert("pos < fBufferLen", __FILE__, __LINE__);

static char fallback;
fallback = '\0';
return fallback;
}

char& operator[](const size_t pos) noexcept
{
if (pos < fBufferLen)
return fBuffer[pos];

d_safe_assert("pos < fBufferLen", __FILE__, __LINE__);

static char fallback;
fallback = '\0';
return fallback;
}

bool operator==(const char* const strBuf) const noexcept
{
return (strBuf != nullptr && std::strcmp(fBuffer, strBuf) == 0);
}

bool operator==(const d_string& str) const noexcept
{
return operator==(str.fBuffer);
}

bool operator!=(const char* const strBuf) const noexcept
{
return !operator==(strBuf);
}

bool operator!=(const d_string& str) const noexcept
{
return !operator==(str.fBuffer);
}

d_string& operator=(const char* const strBuf) noexcept
{
_dup(strBuf);

return *this;
}

d_string& operator=(const d_string& str) noexcept
{
_dup(str.fBuffer);

return *this;
}

d_string& operator+=(const char* const strBuf) noexcept
{
if (strBuf == nullptr)
return *this;

const size_t newBufSize = fBufferLen + std::strlen(strBuf) + 1;
char newBuf[newBufSize];

std::strcpy(newBuf, fBuffer);
std::strcat(newBuf, strBuf);

_dup(newBuf, newBufSize-1);

return *this;
}

d_string& operator+=(const d_string& str) noexcept
{
return operator+=(str.fBuffer);
}

d_string operator+(const char* const strBuf) noexcept
{
const 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);
}

d_string operator+(const d_string& str) noexcept
{
return operator+(str.fBuffer);
}

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

private:
char* fBuffer; // the actual string buffer
size_t fBufferLen; // string length

/*
* Static null string.
* Prevents allocation for new and/or empty strings.
*/
static char* _null() noexcept
{
static char sNull = '\0';
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.
*
* Notes:
* - 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
{
if (strBuf != nullptr)
{
// don't recreate string if contents match
if (std::strcmp(fBuffer, strBuf) == 0)
return;

if (fBuffer != _null())
std::free(fBuffer);

fBufferLen = (size > 0) ? size : std::strlen(strBuf);
fBuffer = (char*)std::malloc(fBufferLen+1);

if (fBuffer == nullptr)
return _init();

std::strcpy(fBuffer, strBuf);

fBuffer[fBufferLen] = '\0';
}
else
{
DISTRHO_SAFE_ASSERT(size == 0);

// don't recreate null string
if (fBuffer == _null())
return;

DISTRHO_SAFE_ASSERT(fBuffer != nullptr);
std::free(fBuffer);

_init();
}
}

DISTRHO_LEAK_DETECTOR(d_string)
DISTRHO_PREVENT_HEAP_ALLOCATION
};

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

static inline
d_string operator+(const d_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;
char newBuf[newBufSize];

std::strcpy(newBuf, strBufBefore);
std::strcat(newBuf, strBufAfter);

return d_string(newBuf);
}

static inline
d_string operator+(const char* const strBufBefore, const d_string& strAfter) noexcept
{
const char* const strBufAfter = strAfter.buffer();
const 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);
}

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

END_NAMESPACE_DISTRHO

#endif // DISTRHO_STRING_HPP_INCLUDED

+ 0
- 291
distrho/extra/d_thread.hpp View File

@@ -1,291 +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.
*/

#ifndef DISTRHO_THREAD_HPP_INCLUDED
#define DISTRHO_THREAD_HPP_INCLUDED

#include "d_mutex.hpp"
#include "d_sleep.hpp"
#include "d_string.hpp"

#if defined(__GLIBC__) && (__GLIBC__ * 1000 + __GLIBC_MINOR__) >= 2012
// has pthread_setname_np
#elif defined(DISTRHO_OS_LINUX)
# include <sys/prctl.h>
#endif

START_NAMESPACE_DISTRHO

// -----------------------------------------------------------------------
// Thread class

class Thread
{
protected:
/*
* Constructor.
*/
Thread(const char* const threadName = nullptr) noexcept
: fLock(),
fName(threadName),
#ifdef PTW32_DLLPORT
fHandle({nullptr, 0}),
#else
fHandle(0),
#endif
fShouldExit(false) {}

/*
* Destructor.
*/
virtual ~Thread() /*noexcept*/
{
DISTRHO_SAFE_ASSERT(! isThreadRunning());

stopThread(-1);
}

/*
* Virtual function to be implemented by the subclass.
*/
virtual void run() = 0;

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

public:
/*
* Check if the thread is running.
*/
bool isThreadRunning() const noexcept
{
#ifdef PTW32_DLLPORT
return (fHandle.p != nullptr);
#else
return (fHandle != 0);
#endif
}

/*
* Check if the thread should exit.
*/
bool shouldThreadExit() const noexcept
{
return fShouldExit;
}

/*
* Start the thread.
*/
bool startThread() noexcept
{
// check if already running
DISTRHO_SAFE_ASSERT_RETURN(! isThreadRunning(), true);

const MutexLocker cml(fLock);

fShouldExit = false;

pthread_t handle;

if (pthread_create(&handle, nullptr, _entryPoint, this) == 0)
{
#ifdef PTW32_DLLPORT
DISTRHO_SAFE_ASSERT_RETURN(handle.p != nullptr, false);
#else
DISTRHO_SAFE_ASSERT_RETURN(handle != 0, false);
#endif
pthread_detach(handle);
_copyFrom(handle);

// wait for thread to start
fLock.lock();

return true;
}

return false;
}

/*
* Stop the thread.
* In the 'timeOutMilliseconds':
* = 0 -> no wait
* > 0 -> wait timeout value
* < 0 -> wait forever
*/
bool stopThread(const int timeOutMilliseconds) noexcept
{
const MutexLocker cml(fLock);

if (isThreadRunning())
{
signalThreadShouldExit();

if (timeOutMilliseconds != 0)
{
// Wait for the thread to stop
int timeOutCheck = (timeOutMilliseconds == 1 || timeOutMilliseconds == -1) ? timeOutMilliseconds : timeOutMilliseconds/2;

for (; isThreadRunning();)
{
d_msleep(2);

if (timeOutCheck < 0)
continue;

if (timeOutCheck > 0)
timeOutCheck -= 1;
else
break;
}
}

if (isThreadRunning())
{
// should never happen!
d_stderr2("Carla assertion failure: \"! isThreadRunning()\" in file %s, line %i", __FILE__, __LINE__);

// copy thread id so we can clear our one
pthread_t threadId;
_copyTo(threadId);
_init();

try {
pthread_cancel(threadId);
} DISTRHO_SAFE_EXCEPTION("pthread_cancel");

return false;
}
}

return true;
}

/*
* Tell the thread to stop as soon as possible.
*/
void signalThreadShouldExit() noexcept
{
fShouldExit = true;
}

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

/*
* Returns the name of the thread.
* This is the name that gets set in the constructor.
*/
const d_string& getThreadName() const noexcept
{
return fName;
}

/*
* Changes the name of the caller thread.
*/
static void setCurrentThreadName(const char* const name) noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0',);

#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
}

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

private:
Mutex fLock; // Thread lock
const d_string fName; // Thread name
volatile pthread_t fHandle; // Handle for this thread
volatile bool fShouldExit; // true if thread should exit

/*
* Init pthread type.
*/
void _init() noexcept
{
#ifdef PTW32_DLLPORT
fHandle.p = nullptr;
fHandle.x = 0;
#else
fHandle = 0;
#endif
}

/*
* Copy our pthread type from another var.
*/
void _copyFrom(const pthread_t& handle) noexcept
{
#ifdef PTW32_DLLPORT
fHandle.p = handle.p;
fHandle.x = handle.x;
#else
fHandle = handle;
#endif
}

/*
* Copy our pthread type to another var.
*/
void _copyTo(volatile pthread_t& handle) const noexcept
{
#ifdef PTW32_DLLPORT
handle.p = fHandle.p;
handle.x = fHandle.x;
#else
handle = fHandle;
#endif
}

/*
* Thread entry point.
*/
void _runEntryPoint() noexcept
{
// report ready
fLock.unlock();

setCurrentThreadName(fName);

try {
run();
} catch(...) {}

// done
_init();
}

/*
* Thread entry point.
*/
static void* _entryPoint(void* userData) noexcept
{
static_cast<Thread*>(userData)->_runEntryPoint();
return nullptr;
}

DISTRHO_DECLARE_NON_COPY_CLASS(Thread)
};

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

END_NAMESPACE_DISTRHO

#endif // DISTRHO_THREAD_HPP_INCLUDED

+ 0
- 134
distrho/src/DistrhoDefines.h View File

@@ -1,134 +0,0 @@
/*
* 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_DEFINES_H_INCLUDED
#define DISTRHO_DEFINES_H_INCLUDED

/* Compatibility with non-clang compilers */
#ifndef __has_feature
# define __has_feature(x) 0
#endif
#ifndef __has_extension
# define __has_extension __has_feature
#endif

/* Check OS */
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
# define DISTRHO_PLUGIN_EXPORT extern "C" __declspec (dllexport)
# define DISTRHO_OS_WINDOWS 1
# define DISTRHO_DLL_EXTENSION "dll"
#else
# define DISTRHO_PLUGIN_EXPORT extern "C" __attribute__ ((visibility("default")))
# if defined(__APPLE__)
# define DISTRHO_OS_MAC 1
# define DISTRHO_DLL_EXTENSION "dylib"
# elif defined(__HAIKU__)
# define DISTRHO_OS_HAIKU 1
# elif defined(__linux__)
# define DISTRHO_OS_LINUX 1
# endif
#endif

#ifndef DISTRHO_DLL_EXTENSION
# define DISTRHO_DLL_EXTENSION "so"
#endif

/* Check for C++11 support */
#if defined(HAVE_CPP11_SUPPORT)
# define DISTRHO_PROPER_CPP11_SUPPORT
#elif __cplusplus >= 201103L || (defined(__GNUC__) && defined(__GXX_EXPERIMENTAL_CXX0X__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 405) || __has_extension(cxx_noexcept)
# define DISTRHO_PROPER_CPP11_SUPPORT
# if (defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) < 407 && ! defined(__clang__)) || (defined(__clang__) && ! __has_extension(cxx_override_control))
# define override // gcc4.7+ only
# define final // gcc4.7+ only
# endif
#endif

#ifndef DISTRHO_PROPER_CPP11_SUPPORT
# define noexcept throw()
# define override
# define final
# define nullptr NULL
#endif

/* Define DISTRHO_SAFE_ASSERT* */
#define DISTRHO_SAFE_ASSERT(cond) if (! (cond)) d_safe_assert(#cond, __FILE__, __LINE__);
#define DISTRHO_SAFE_ASSERT_BREAK(cond) if (! (cond)) { d_safe_assert(#cond, __FILE__, __LINE__); break; }
#define DISTRHO_SAFE_ASSERT_CONTINUE(cond) if (! (cond)) { d_safe_assert(#cond, __FILE__, __LINE__); continue; }
#define DISTRHO_SAFE_ASSERT_RETURN(cond, ret) if (! (cond)) { d_safe_assert(#cond, __FILE__, __LINE__); return ret; }

/* Define DISTRHO_SAFE_EXCEPTION */
#define DISTRHO_SAFE_EXCEPTION(msg) catch(...) { d_safe_exception(msg, __FILE__, __LINE__); }
#define DISTRHO_SAFE_EXCEPTION_BREAK(msg) catch(...) { d_safe_exception(msg, __FILE__, __LINE__); break; }
#define DISTRHO_SAFE_EXCEPTION_CONTINUE(msg) catch(...) { d_safe_exception(msg, __FILE__, __LINE__); continue; }
#define DISTRHO_SAFE_EXCEPTION_RETURN(msg, ret) catch(...) { d_safe_exception(msg, __FILE__, __LINE__); return ret; }

/* Define DISTRHO_DECLARE_NON_COPY_CLASS */
#ifdef DISTRHO_PROPER_CPP11_SUPPORT
# define DISTRHO_DECLARE_NON_COPY_CLASS(ClassName) \
private: \
ClassName(ClassName&) = delete; \
ClassName(const ClassName&) = delete; \
ClassName& operator=(ClassName&) = delete ; \
ClassName& operator=(const ClassName&) = delete;
#else
# define DISTRHO_DECLARE_NON_COPY_CLASS(ClassName) \
private: \
ClassName(ClassName&); \
ClassName(const ClassName&); \
ClassName& operator=(ClassName&); \
ClassName& operator=(const ClassName&);
#endif

/* Define DISTRHO_DECLARE_NON_COPY_STRUCT */
#ifdef DISTRHO_PROPER_CPP11_SUPPORT
# define DISTRHO_DECLARE_NON_COPY_STRUCT(StructName) \
StructName(StructName&) = delete; \
StructName(const StructName&) = delete; \
StructName& operator=(StructName&) = delete; \
StructName& operator=(const StructName&) = delete;
#else
# define DISTRHO_DECLARE_NON_COPY_STRUCT(StructName)
#endif

/* Define DISTRHO_PREVENT_HEAP_ALLOCATION */
#ifdef DISTRHO_PROPER_CPP11_SUPPORT
# define DISTRHO_PREVENT_HEAP_ALLOCATION \
private: \
static void* operator new(size_t) = delete; \
static void operator delete(void*) = delete;
#else
# define DISTRHO_PREVENT_HEAP_ALLOCATION \
private: \
static void* operator new(size_t); \
static void operator delete(void*);
#endif

/* Define namespace */
#ifndef DISTRHO_NAMESPACE
# define DISTRHO_NAMESPACE DISTRHO
#endif
#define START_NAMESPACE_DISTRHO namespace DISTRHO_NAMESPACE {
#define END_NAMESPACE_DISTRHO }
#define USE_NAMESPACE_DISTRHO using namespace DISTRHO_NAMESPACE;

/* Useful typedefs */
typedef unsigned char uchar;
typedef unsigned short int ushort;
typedef unsigned int uint;
typedef unsigned long int ulong;

#endif // DISTRHO_DEFINES_H_INCLUDED

+ 0
- 115
distrho/src/DistrhoPlugin.cpp View File

@@ -1,115 +0,0 @@
/*
* 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 "DistrhoPluginInternal.hpp"

START_NAMESPACE_DISTRHO

/* ------------------------------------------------------------------------------------------------------------
* Static data, see DistrhoPluginInternal.hpp */

uint32_t d_lastBufferSize = 0;
double d_lastSampleRate = 0.0;

/* ------------------------------------------------------------------------------------------------------------
* Static fallback data, see DistrhoPluginInternal.hpp */

const d_string PluginExporter::sFallbackString;
const ParameterRanges PluginExporter::sFallbackRanges;

/* ------------------------------------------------------------------------------------------------------------
* Plugin */

Plugin::Plugin(const uint32_t parameterCount, const uint32_t programCount, const uint32_t stateCount)
: pData(new PrivateData())
{
if (parameterCount > 0)
{
pData->parameterCount = parameterCount;
pData->parameters = new Parameter[parameterCount];
}

#if DISTRHO_PLUGIN_WANT_PROGRAMS
if (programCount > 0)
{
pData->programCount = programCount;
pData->programNames = new d_string[programCount];
}
#else
DISTRHO_SAFE_ASSERT(programCount == 0);
#endif

#if DISTRHO_PLUGIN_WANT_STATE
if (stateCount > 0)
{
pData->stateCount = stateCount;
pData->stateKeys = new d_string[stateCount];
pData->stateDefValues = new d_string[stateCount];
}
#else
DISTRHO_SAFE_ASSERT(stateCount == 0);
#endif
}

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

/* ------------------------------------------------------------------------------------------------------------
* Host state */

uint32_t Plugin::d_getBufferSize() const noexcept
{
return pData->bufferSize;
}

double Plugin::d_getSampleRate() const noexcept
{
return pData->sampleRate;
}

#if DISTRHO_PLUGIN_WANT_TIMEPOS
const TimePosition& Plugin::d_getTimePosition() const noexcept
{
return pData->timePosition;
}
#endif

#if DISTRHO_PLUGIN_WANT_LATENCY
void Plugin::d_setLatency(const uint32_t frames) noexcept
{
pData->latency = frames;
}
#endif

#if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT
bool Plugin::d_writeMidiEvent(const MidiEvent& /*midiEvent*/) noexcept
{
// TODO
return false;
}
#endif

/* ------------------------------------------------------------------------------------------------------------
* Callbacks (optional) */

void Plugin::d_bufferSizeChanged(uint32_t) {}
void Plugin::d_sampleRateChanged(double) {}

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

END_NAMESPACE_DISTRHO

+ 0
- 480
distrho/src/DistrhoPluginCarla.cpp View File

@@ -1,480 +0,0 @@
/*
* DISTRHO Plugin Framework (DPF)
* 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
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* For a full copy of the license see the LGPL.txt file
*/

#include "DistrhoPluginInternal.hpp"

#if DISTRHO_PLUGIN_HAS_UI
# include "DistrhoUIInternal.hpp"
#endif

#include "CarlaNative.hpp"

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

START_NAMESPACE_DISTRHO

#if DISTRHO_PLUGIN_HAS_UI
// -----------------------------------------------------------------------
// Carla UI

#if ! DISTRHO_PLUGIN_WANT_STATE
static const setStateFunc setStateCallback = nullptr;
#endif
#if ! DISTRHO_PLUGIN_IS_SYNTH
static const sendNoteFunc sendNoteCallback = nullptr;
#endif

class UICarla
{
public:
UICarla(const NativeHostDescriptor* const host, PluginExporter* const plugin)
: fHost(host),
fPlugin(plugin),
fUI(this, 0, editParameterCallback, setParameterCallback, setStateCallback, sendNoteCallback, setSizeCallback, plugin->getInstancePointer())
{
fUI.setWindowTitle(host->uiName);

if (host->uiParentId != 0)
fUI.setWindowTransientWinId(host->uiParentId);
}

~UICarla()
{
fUI.quit();
}

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

void carla_show(const bool yesNo)
{
fUI.setWindowVisible(yesNo);
}

bool carla_idle()
{
return fUI.idle();
}

void carla_setParameterValue(const uint32_t index, const float value)
{
fUI.parameterChanged(index, value);
}

#if DISTRHO_PLUGIN_WANT_PROGRAMS
void carla_setMidiProgram(const uint32_t realProgram)
{
fUI.programChanged(realProgram);
}
#endif

#if DISTRHO_PLUGIN_WANT_STATE
void carla_setCustomData(const char* const key, const char* const value)
{
fUI.stateChanged(key, value);
}
#endif

void carla_setUiTitle(const char* const uiTitle)
{
fUI.setWindowTitle(uiTitle);
}

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

protected:
void handleEditParameter(const uint32_t, const bool)
{
// TODO
}

void handleSetParameterValue(const uint32_t rindex, const float value)
{
fHost->ui_parameter_changed(fHost->handle, rindex, value);
}

void handleSetState(const char* const key, const char* const value)
{
fHost->ui_custom_data_changed(fHost->handle, key, value);
}

void handleSendNote(const uint8_t, const uint8_t, const uint8_t)
{
// TODO
}

void handleSetSize(const uint width, const uint height)
{
fUI.setWindowSize(width, height);
}

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

private:
// Plugin stuff
const NativeHostDescriptor* const fHost;
PluginExporter* const fPlugin;

// UI
UIExporter fUI;

// ---------------------------------------------
// Callbacks

#define handlePtr ((UICarla*)ptr)

static void editParameterCallback(void* ptr, uint32_t index, bool started)
{
handlePtr->handleEditParameter(index, started);
}

static void setParameterCallback(void* ptr, uint32_t rindex, float value)
{
handlePtr->handleSetParameterValue(rindex, value);
}

#if DISTRHO_PLUGIN_WANT_STATE
static void setStateCallback(void* ptr, const char* key, const char* value)
{
handlePtr->handleSetState(key, value);
}
#endif

#if DISTRHO_PLUGIN_IS_SYNTH
static void sendNoteCallback(void* ptr, uint8_t channel, uint8_t note, uint8_t velocity)
{
handlePtr->handleSendNote(channel, note, velocity);
}
#endif

static void setSizeCallback(void* ptr, uint width, uint height)
{
handlePtr->handleSetSize(width, height);
}

#undef handlePtr

CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(UICarla)
};
#endif // DISTRHO_PLUGIN_HAS_UI

// -----------------------------------------------------------------------
// Carla Plugin

class PluginCarla : public NativePluginClass
{
public:
PluginCarla(const NativeHostDescriptor* const host)
: NativePluginClass(host)
{
#if DISTRHO_PLUGIN_HAS_UI
fUiPtr = nullptr;
#endif
}

~PluginCarla() override
{
#if DISTRHO_PLUGIN_HAS_UI
if (fUiPtr != nullptr)
{
delete fUiPtr;
fUiPtr = nullptr;
}
#endif
}

protected:
// -------------------------------------------------------------------
// Plugin parameter calls

uint32_t getParameterCount() const override
{
return fPlugin.getParameterCount();
}

const NativeParameter* getParameterInfo(const uint32_t index) const override
{
CARLA_SAFE_ASSERT_RETURN(index < getParameterCount(), nullptr);

static NativeParameter param;

param.scalePointCount = 0;
param.scalePoints = nullptr;

{
int nativeParamHints = ::NATIVE_PARAMETER_IS_ENABLED;
const uint32_t paramHints = fPlugin.getParameterHints(index);

if (paramHints & kParameterIsAutomable)
nativeParamHints |= ::NATIVE_PARAMETER_IS_AUTOMABLE;
if (paramHints & kParameterIsBoolean)
nativeParamHints |= ::NATIVE_PARAMETER_IS_BOOLEAN;
if (paramHints & kParameterIsInteger)
nativeParamHints |= ::NATIVE_PARAMETER_IS_INTEGER;
if (paramHints & kParameterIsLogarithmic)
nativeParamHints |= ::NATIVE_PARAMETER_IS_LOGARITHMIC;
if (paramHints & kParameterIsOutput)
nativeParamHints |= ::NATIVE_PARAMETER_IS_OUTPUT;

param.hints = static_cast<NativeParameterHints>(nativeParamHints);
}

param.name = fPlugin.getParameterName(index);
param.unit = fPlugin.getParameterUnit(index);

{
const ParameterRanges& ranges(fPlugin.getParameterRanges(index));

param.ranges.def = ranges.def;
param.ranges.min = ranges.min;
param.ranges.max = ranges.max;
}

return &param;
}

float getParameterValue(const uint32_t index) const override
{
CARLA_SAFE_ASSERT_RETURN(index < getParameterCount(), 0.0f);

return fPlugin.getParameterValue(index);
}

// -------------------------------------------------------------------
// Plugin midi-program calls

#if DISTRHO_PLUGIN_WANT_PROGRAMS
uint32_t getMidiProgramCount() const override
{
return fPlugin.getProgramCount();
}

const NativeMidiProgram* getMidiProgramInfo(const uint32_t index) const override
{
CARLA_SAFE_ASSERT_RETURN(index < getMidiProgramCount(), nullptr);

static NativeMidiProgram midiProgram;

midiProgram.bank = index / 128;
midiProgram.program = index % 128;
midiProgram.name = fPlugin.getProgramName(index);

return &midiProgram;
}
#endif

// -------------------------------------------------------------------
// Plugin state calls

void setParameterValue(const uint32_t index, const float value) override
{
CARLA_SAFE_ASSERT_RETURN(index < getParameterCount(),);

fPlugin.setParameterValue(index, value);
}

#if DISTRHO_PLUGIN_WANT_PROGRAMS
void setMidiProgram(const uint8_t, const uint32_t bank, const uint32_t program) override
{
const uint32_t realProgram(bank * 128 + program);

CARLA_SAFE_ASSERT_RETURN(realProgram < getMidiProgramCount(),);

fPlugin.setProgram(realProgram);
}
#endif

#if DISTRHO_PLUGIN_WANT_STATE
void setCustomData(const char* const key, const char* const value) override
{
CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',);
CARLA_SAFE_ASSERT_RETURN(value != nullptr,);

fPlugin.setState(key, value);
}
#endif

// -------------------------------------------------------------------
// Plugin process calls

void activate() override
{
fPlugin.activate();
}

void deactivate() override
{
fPlugin.deactivate();
}

#if DISTRHO_PLUGIN_IS_SYNTH
void process(float** const inBuffer, float** const outBuffer, const uint32_t frames, const NativeMidiEvent* const midiEvents, const uint32_t midiEventCount) override
{
MidiEvent realMidiEvents[midiEventCount];

for (uint32_t i=0; i < midiEventCount; ++i)
{
const NativeMidiEvent& midiEvent(midiEvents[i]);
MidiEvent& realMidiEvent(realMidiEvents[i]);

realMidiEvent.frame = midiEvent.time;
realMidiEvent.size = midiEvent.size;

uint8_t j=0;
for (; j<midiEvent.size; ++j)
realMidiEvent.data[j] = midiEvent.data[j];
for (; j<midiEvent.size; ++j)
realMidiEvent.data[j] = midiEvent.data[j];

realMidiEvent.dataExt = nullptr;
}

fPlugin.run(const_cast<const float**>(inBuffer), outBuffer, frames, realMidiEvents, midiEventCount);
}
#else
void process(float** const inBuffer, float** const outBuffer, const uint32_t frames, const NativeMidiEvent* const, const uint32_t) override
{
fPlugin.run(const_cast<const float**>(inBuffer), outBuffer, frames);
}
#endif

// -------------------------------------------------------------------
// Plugin UI calls

#if DISTRHO_PLUGIN_HAS_UI
void uiShow(const bool show) override
{
if (show)
{
createUiIfNeeded();
CARLA_SAFE_ASSERT_RETURN(fUiPtr != nullptr,);

fUiPtr->carla_show(show);
}
else if (fUiPtr != nullptr)
{
delete fUiPtr;
fUiPtr = nullptr;
}
}

void uiIdle() override
{
CARLA_SAFE_ASSERT_RETURN(fUiPtr != nullptr,);

if (! fUiPtr->carla_idle())
{
uiClosed();

delete fUiPtr;
fUiPtr = nullptr;
}
}

void uiSetParameterValue(const uint32_t index, const float value) override
{
CARLA_SAFE_ASSERT_RETURN(fUiPtr != nullptr,);
CARLA_SAFE_ASSERT_RETURN(index < getParameterCount(),);

fUiPtr->carla_setParameterValue(index, value);
}

# if DISTRHO_PLUGIN_WANT_PROGRAMS
void uiSetMidiProgram(const uint8_t, const uint32_t bank, const uint32_t program) override
{
CARLA_SAFE_ASSERT_RETURN(fUiPtr != nullptr,);

const uint32_t realProgram(bank * 128 + program);

CARLA_SAFE_ASSERT_RETURN(realProgram < getMidiProgramCount(),);

fUiPtr->carla_setMidiProgram(realProgram);
}
# endif

# if DISTRHO_PLUGIN_WANT_STATE
void uiSetCustomData(const char* const key, const char* const value) override
{
CARLA_SAFE_ASSERT_RETURN(fUiPtr != nullptr,);
CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',);
CARLA_SAFE_ASSERT_RETURN(value != nullptr,);

fUiPtr->carla_setCustomData(key, value);
}
# endif
#endif

// -------------------------------------------------------------------
// Plugin dispatcher calls

void bufferSizeChanged(const uint32_t bufferSize) override
{
fPlugin.setBufferSize(bufferSize, true);
}

void sampleRateChanged(const double sampleRate) override
{
fPlugin.setSampleRate(sampleRate, true);
}

#if DISTRHO_PLUGIN_HAS_UI
void uiNameChanged(const char* const uiName) override
{
CARLA_SAFE_ASSERT_RETURN(fUiPtr != nullptr,);

fUiPtr->carla_setUiTitle(uiName);
}
#endif

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

private:
PluginExporter fPlugin;

#if DISTRHO_PLUGIN_HAS_UI
// UI
UICarla* fUiPtr;

void createUiIfNeeded()
{
if (fUiPtr == nullptr)
{
d_lastUiSampleRate = getSampleRate();
fUiPtr = new UICarla(getHostHandle(), &fPlugin);
}
}
#endif

CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PluginCarla)

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

public:
static NativePluginHandle _instantiate(const NativeHostDescriptor* host)
{
d_lastBufferSize = host->get_buffer_size(host->handle);
d_lastSampleRate = host->get_sample_rate(host->handle);
return new PluginCarla(host);
}

static void _cleanup(NativePluginHandle handle)
{
delete (PluginCarla*)handle;
}
};

END_NAMESPACE_DISTRHO

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

+ 0
- 109
distrho/src/DistrhoPluginChecks.h View File

@@ -1,109 +0,0 @@
/*
* 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_PLUGIN_CHECKS_H_INCLUDED
#define DISTRHO_PLUGIN_CHECKS_H_INCLUDED

#include "DistrhoPluginInfo.h"

// -----------------------------------------------------------------------
// Check if all required macros are defined

#ifndef DISTRHO_PLUGIN_NAME
# error DISTRHO_PLUGIN_NAME undefined!
#endif

#ifndef DISTRHO_PLUGIN_NUM_INPUTS
# error DISTRHO_PLUGIN_NUM_INPUTS undefined!
#endif

#ifndef DISTRHO_PLUGIN_NUM_OUTPUTS
# error DISTRHO_PLUGIN_NUM_OUTPUTS undefined!
#endif

#ifndef DISTRHO_PLUGIN_URI
# error DISTRHO_PLUGIN_URI undefined!
#endif

// -----------------------------------------------------------------------
// Define optional macros if not done yet

#ifndef DISTRHO_PLUGIN_HAS_UI
# define DISTRHO_PLUGIN_HAS_UI 0
#endif

#ifndef DISTRHO_PLUGIN_IS_RT_SAFE
# define DISTRHO_PLUGIN_IS_RT_SAFE 0
#endif

#ifndef DISTRHO_PLUGIN_IS_SYNTH
# define DISTRHO_PLUGIN_IS_SYNTH 0
#endif

#ifndef DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
# define DISTRHO_PLUGIN_WANT_DIRECT_ACCESS 0
#endif

#ifndef DISTRHO_PLUGIN_WANT_LATENCY
# define DISTRHO_PLUGIN_WANT_LATENCY 0
#endif

#ifndef DISTRHO_PLUGIN_WANT_MIDI_OUTPUT
# define DISTRHO_PLUGIN_WANT_MIDI_OUTPUT 0
#endif

#ifndef DISTRHO_PLUGIN_WANT_PROGRAMS
# define DISTRHO_PLUGIN_WANT_PROGRAMS 0
#endif

#ifndef DISTRHO_PLUGIN_WANT_STATE
# define DISTRHO_PLUGIN_WANT_STATE 0
#endif

#ifndef DISTRHO_PLUGIN_WANT_TIMEPOS
# define DISTRHO_PLUGIN_WANT_TIMEPOS 0
#endif

#ifndef DISTRHO_UI_USE_NANOVG
# define DISTRHO_UI_USE_NANOVG 0
#endif

// -----------------------------------------------------------------------
// Define DISTRHO_UI_URI if needed

#ifndef DISTRHO_UI_URI
# 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

+ 0
- 471
distrho/src/DistrhoPluginInternal.hpp View File

@@ -1,471 +0,0 @@
/*
* 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_PLUGIN_INTERNAL_HPP_INCLUDED
#define DISTRHO_PLUGIN_INTERNAL_HPP_INCLUDED

#include "../DistrhoPlugin.hpp"

START_NAMESPACE_DISTRHO

// -----------------------------------------------------------------------
// Maxmimum values

static const uint32_t kMaxMidiEvents = 512;

// -----------------------------------------------------------------------
// Static data, see DistrhoPlugin.cpp

extern uint32_t d_lastBufferSize;
extern double d_lastSampleRate;

// -----------------------------------------------------------------------
// Plugin private data

struct Plugin::PrivateData {
bool isProcessing;

uint32_t parameterCount;
Parameter* parameters;

#if DISTRHO_PLUGIN_WANT_PROGRAMS
uint32_t programCount;
d_string* programNames;
#endif

#if DISTRHO_PLUGIN_WANT_STATE
uint32_t stateCount;
d_string* stateKeys;
d_string* stateDefValues;
#endif

#if DISTRHO_PLUGIN_WANT_LATENCY
uint32_t latency;
#endif

#if DISTRHO_PLUGIN_WANT_TIMEPOS
TimePosition timePosition;
#endif

uint32_t bufferSize;
double sampleRate;

PrivateData() noexcept
: isProcessing(false),
parameterCount(0),
parameters(nullptr),
#if DISTRHO_PLUGIN_WANT_PROGRAMS
programCount(0),
programNames(nullptr),
#endif
#if DISTRHO_PLUGIN_WANT_STATE
stateCount(0),
stateKeys(nullptr),
stateDefValues(nullptr),
#endif
#if DISTRHO_PLUGIN_WANT_LATENCY
latency(0),
#endif
bufferSize(d_lastBufferSize),
sampleRate(d_lastSampleRate)
{
DISTRHO_SAFE_ASSERT(bufferSize != 0);
DISTRHO_SAFE_ASSERT(d_isNotZero(sampleRate));
}

~PrivateData() noexcept
{
if (parameters != nullptr)
{
delete[] parameters;
parameters = nullptr;
}

#if DISTRHO_PLUGIN_WANT_PROGRAMS
if (programNames != nullptr)
{
delete[] programNames;
programNames = nullptr;
}
#endif

#if DISTRHO_PLUGIN_WANT_STATE
if (stateKeys != nullptr)
{
delete[] stateKeys;
stateKeys = nullptr;
}

if (stateDefValues != nullptr)
{
delete[] stateDefValues;
stateDefValues = nullptr;
}
#endif
}
};

// -----------------------------------------------------------------------
// Plugin exporter class

class PluginExporter
{
public:
PluginExporter()
: fPlugin(createPlugin()),
fData((fPlugin != nullptr) ? fPlugin->pData : nullptr),
fIsActive(false)
{
DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,);

for (uint32_t i=0, count=fData->parameterCount; i < count; ++i)
fPlugin->d_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]);
#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]);
#endif
}

~PluginExporter()
{
delete fPlugin;
}

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

const char* getName() const noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, "");

return fPlugin->d_getName();
}

const char* getLabel() const noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, "");

return fPlugin->d_getLabel();
}

const char* getMaker() const noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, "");

return fPlugin->d_getMaker();
}

const char* getLicense() const noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, "");

return fPlugin->d_getLicense();
}

uint32_t getVersion() const noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, 0);

return fPlugin->d_getVersion();
}

long getUniqueId() const noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, 0);

return fPlugin->d_getUniqueId();
}

void* getInstancePointer() const noexcept
{
return fPlugin;
}

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

#if DISTRHO_PLUGIN_WANT_LATENCY
uint32_t getLatency() const noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0);

return fData->latency;
}
#endif

uint32_t getParameterCount() const noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0);

return fData->parameterCount;
}

uint32_t getParameterHints(const uint32_t index) const noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, 0x0);

return fData->parameters[index].hints;
}

bool isParameterOutput(const uint32_t index) const noexcept
{
return (getParameterHints(index) & kParameterIsOutput);
}

const d_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
{
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
{
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, sFallbackString);

return fData->parameters[index].unit;
}

const ParameterRanges& getParameterRanges(const uint32_t index) const noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, sFallbackRanges);

return fData->parameters[index].ranges;
}

float getParameterValue(const uint32_t index) const
{
DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, 0.0f);
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, 0.0f);

return fPlugin->d_getParameterValue(index);
}

void setParameterValue(const uint32_t index, const float value)
{
DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount,);

fPlugin->d_setParameterValue(index, value);
}

#if DISTRHO_PLUGIN_WANT_PROGRAMS
uint32_t getProgramCount() const noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0);

return fData->programCount;
}

const d_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)
{
DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->programCount,);

fPlugin->d_setProgram(index);
}
#endif

#if DISTRHO_PLUGIN_WANT_STATE
uint32_t getStateCount() const noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0);

return fData->stateCount;
}

const d_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
{
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->stateCount, sFallbackString);

return fData->stateDefValues[index];
}

void setState(const char* const key, const char* const value)
{
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,);
DISTRHO_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',);
DISTRHO_SAFE_ASSERT_RETURN(value != nullptr,);

fPlugin->d_setState(key, value);
}

bool wantStateKey(const char* const key) const noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, false);
DISTRHO_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0', false);

for (uint32_t i=0; i < fData->stateCount; ++i)
{
if (fData->stateKeys[i] == key)
return true;
}

return false;
}
#endif

#if DISTRHO_PLUGIN_WANT_TIMEPOS
void setTimePosition(const TimePosition& timePosition) noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,);

std::memcpy(&fData->timePosition, &timePosition, sizeof(TimePosition));
}
#endif

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

void activate()
{
DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,);

fIsActive = true;
fPlugin->d_activate();
}

void deactivate()
{
DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,);

fIsActive = false;
fPlugin->d_deactivate();
}

#if DISTRHO_PLUGIN_IS_SYNTH
void run(const float** const inputs, float** const outputs, const uint32_t frames,
const MidiEvent* const midiEvents, const uint32_t midiEventCount)
{
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,);
DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,);

fData->isProcessing = true;
fPlugin->d_run(inputs, outputs, frames, midiEvents, midiEventCount);
fData->isProcessing = false;
}
#else
void run(const float** const inputs, float** const outputs, const uint32_t frames)
{
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,);
DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,);

fData->isProcessing = true;
fPlugin->d_run(inputs, outputs, frames);
fData->isProcessing = false;
}
#endif

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

uint32_t getBufferSize() const noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0);
return fData->bufferSize;
}

double getSampleRate() const noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0.0);
return fData->sampleRate;
}

void setBufferSize(const uint32_t bufferSize, const bool doCallback = false)
{
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,);
DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
DISTRHO_SAFE_ASSERT(bufferSize >= 2);

if (fData->bufferSize == bufferSize)
return;

fData->bufferSize = bufferSize;

if (doCallback)
{
if (fIsActive) fPlugin->d_deactivate();
fPlugin->d_bufferSizeChanged(bufferSize);
if (fIsActive) fPlugin->d_activate();
}
}

void setSampleRate(const double sampleRate, const bool doCallback = false)
{
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,);
DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
DISTRHO_SAFE_ASSERT(sampleRate > 0.0);

if (d_isEqual(fData->sampleRate, sampleRate))
return;

fData->sampleRate = sampleRate;

if (doCallback)
{
if (fIsActive) fPlugin->d_deactivate();
fPlugin->d_sampleRateChanged(sampleRate);
if (fIsActive) fPlugin->d_activate();
}
}

private:
// -------------------------------------------------------------------
// Plugin and DistrhoPlugin data

Plugin* const fPlugin;
Plugin::PrivateData* const fData;
bool fIsActive;

// -------------------------------------------------------------------
// Static fallback data, see DistrhoPlugin.cpp

static const d_string sFallbackString;
static const ParameterRanges sFallbackRanges;

DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PluginExporter)
DISTRHO_PREVENT_HEAP_ALLOCATION
};

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

END_NAMESPACE_DISTRHO

#endif // DISTRHO_PLUGIN_INTERNAL_HPP_INCLUDED

+ 0
- 434
distrho/src/DistrhoPluginJack.cpp View File

@@ -1,434 +0,0 @@
/*
* DISTRHO Plugin Framework (DPF)
* 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
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* For a full copy of the license see the LGPL.txt file
*/

#include "DistrhoPluginInternal.hpp"

#if ! DISTRHO_PLUGIN_HAS_UI
# error JACK export requires an UI
#endif

#include "DistrhoUIInternal.hpp"

#include "jack/jack.h"
#include "jack/midiport.h"
#include "jack/transport.h"

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

START_NAMESPACE_DISTRHO

#if ! DISTRHO_PLUGIN_WANT_STATE
static const setStateFunc setStateCallback = nullptr;
#endif

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

class PluginJack : public IdleCallback
{
public:
PluginJack(jack_client_t* const client)
: fPlugin(),
fUI(this, 0, nullptr, setParameterValueCallback, setStateCallback, nullptr, setSizeCallback, fPlugin.getInstancePointer()),
fClient(client)
{
char strBuf[0xff+1];
strBuf[0xff] = '\0';

#if DISTRHO_PLUGIN_NUM_INPUTS > 0
for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i)
{
std::snprintf(strBuf, 0xff, "in%i", i+1);
fPortAudioIns[i] = jack_port_register(fClient, strBuf, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
}
#endif

#if DISTRHO_PLUGIN_NUM_OUTPUTS > 0
for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i)
{
std::snprintf(strBuf, 0xff, "out%i", i+1);
fPortAudioOuts[i] = jack_port_register(fClient, strBuf, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
}
#endif

#if DISTRHO_PLUGIN_IS_SYNTH
fPortMidiIn = jack_port_register(fClient, "midi-in", JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0);
#endif

#if DISTRHO_PLUGIN_WANT_PROGRAMS
if (fPlugin.getProgramCount() > 0)
{
fPlugin.setProgram(0);
fUI.programChanged(0);
}
#endif

if (const uint32_t count = fPlugin.getParameterCount())
{
fLastOutputValues = new float[count];

for (uint32_t i=0; i < count; ++i)
{
if (fPlugin.isParameterOutput(i))
{
fLastOutputValues[i] = fPlugin.getParameterValue(i);
}
else
{
fLastOutputValues[i] = 0.0f;
fUI.parameterChanged(i, fPlugin.getParameterValue(i));
}
}
}
else
{
fLastOutputValues = nullptr;
}

jack_set_buffer_size_callback(fClient, jackBufferSizeCallback, this);
jack_set_sample_rate_callback(fClient, jackSampleRateCallback, this);
jack_set_process_callback(fClient, jackProcessCallback, this);
jack_on_shutdown(fClient, jackShutdownCallback, this);

jack_activate(fClient);

if (const char* const name = jack_get_client_name(fClient))
fUI.setWindowTitle(name);
else
fUI.setWindowTitle(fPlugin.getName());

fUI.exec(this);
}

~PluginJack()
{
if (fClient == nullptr)
return;

jack_deactivate(fClient);

#if DISTRHO_PLUGIN_IS_SYNTH
jack_port_unregister(fClient, fPortMidiIn);
fPortMidiIn = nullptr;
#endif

#if DISTRHO_PLUGIN_NUM_INPUTS > 0
for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i)
{
jack_port_unregister(fClient, fPortAudioIns[i]);
fPortAudioIns[i] = nullptr;
}
#endif

#if DISTRHO_PLUGIN_NUM_OUTPUTS > 0
for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i)
{
jack_port_unregister(fClient, fPortAudioOuts[i]);
fPortAudioOuts[i] = nullptr;
}
#endif

jack_client_close(fClient);
}

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

protected:
void idleCallback() override
{
float value;

for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i)
{
if (! fPlugin.isParameterOutput(i))
continue;

value = fPlugin.getParameterValue(i);

if (fLastOutputValues[i] == value)
continue;

fLastOutputValues[i] = value;
fUI.parameterChanged(i, value);
}

fUI.exec_idle();
}

void jackBufferSize(const jack_nframes_t nframes)
{
fPlugin.setBufferSize(nframes, true);
}

void jackSampleRate(const jack_nframes_t nframes)
{
fPlugin.setSampleRate(nframes, true);
}

void jackProcess(const jack_nframes_t nframes)
{
#if DISTRHO_PLUGIN_NUM_INPUTS > 0
const float* audioIns[DISTRHO_PLUGIN_NUM_INPUTS];

for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i)
audioIns[i] = (const float*)jack_port_get_buffer(fPortAudioIns[i], nframes);
#else
static const float** audioIns = nullptr;
#endif

#if DISTRHO_PLUGIN_NUM_OUTPUTS > 0
float* audioOuts[DISTRHO_PLUGIN_NUM_OUTPUTS];

for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i)
audioOuts[i] = (float*)jack_port_get_buffer(fPortAudioOuts[i], nframes);
#else
static float** audioOuts = nullptr;
#endif

#if DISTRHO_PLUGIN_WANT_TIMEPOS
jack_position_t pos;
fTimePosition.playing = (jack_transport_query(fClient, &pos) == JackTransportRolling);

if (pos.unique_1 == pos.unique_2)
{
fTimePosition.frame = pos.frame;

if (pos.valid & JackTransportBBT)
{
fTimePosition.bbt.valid = true;

fTimePosition.bbt.bar = pos.bar;
fTimePosition.bbt.beat = pos.beat;
fTimePosition.bbt.tick = pos.tick;
fTimePosition.bbt.barStartTick = pos.bar_start_tick;

fTimePosition.bbt.beatsPerBar = pos.beats_per_bar;
fTimePosition.bbt.beatType = pos.beat_type;

fTimePosition.bbt.ticksPerBeat = pos.ticks_per_beat;
fTimePosition.bbt.beatsPerMinute = pos.beats_per_minute;
}
else
fTimePosition.bbt.valid = false;
}
else
{
fTimePosition.bbt.valid = false;
fTimePosition.frame = 0;
}

fPlugin.setTimePosition(fTimePosition);
#endif

#if DISTRHO_PLUGIN_IS_SYNTH
void* const midiBuf = jack_port_get_buffer(fPortMidiIn, nframes);

if (const uint32_t eventCount = jack_midi_get_event_count(midiBuf))
{
uint32_t midiEventCount = 0;
MidiEvent midiEvents[eventCount];

jack_midi_event_t jevent;

for (uint32_t i=0; i < eventCount; ++i)
{
if (jack_midi_event_get(&jevent, midiBuf, i) != 0)
break;

MidiEvent& midiEvent(midiEvents[midiEventCount++]);

midiEvent.frame = jevent.time;
midiEvent.size = jevent.size;

if (midiEvent.size > MidiEvent::kDataSize)
midiEvent.dataExt = jevent.buffer;
else
std::memcpy(midiEvent.data, jevent.buffer, midiEvent.size);
}

fPlugin.run(audioIns, audioOuts, nframes, midiEvents, midiEventCount);
}
else
{
fPlugin.run(audioIns, audioOuts, nframes, nullptr, 0);
}
#else
fPlugin.run(audioIns, audioOuts, nframes);
#endif
}

void jackShutdown()
{
d_stderr("jack has shutdown, quitting now...");
fClient = nullptr;
fUI.quit();
}

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

void setParameterValue(const uint32_t index, const float value)
{
fPlugin.setParameterValue(index, value);
}

#if DISTRHO_PLUGIN_WANT_STATE
void setState(const char* const key, const char* const value)
{
fPlugin.setState(key, value);
}
#endif

void setSize(const uint width, const uint height)
{
fUI.setWindowSize(width, height);
}

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

private:
PluginExporter fPlugin;
UIExporter fUI;

jack_client_t* fClient;

#if DISTRHO_PLUGIN_NUM_INPUTS > 0
jack_port_t* fPortAudioIns[DISTRHO_PLUGIN_NUM_INPUTS];
#endif
#if DISTRHO_PLUGIN_NUM_OUTPUTS > 0
jack_port_t* fPortAudioOuts[DISTRHO_PLUGIN_NUM_OUTPUTS];
#endif
#if DISTRHO_PLUGIN_IS_SYNTH
jack_port_t* fPortMidiIn;
#endif
#if DISTRHO_PLUGIN_WANT_TIMEPOS
TimePosition fTimePosition;
#endif

// Temporary data
float* fLastOutputValues;

// -------------------------------------------------------------------
// Callbacks

#define uiPtr ((PluginJack*)ptr)

static int jackBufferSizeCallback(jack_nframes_t nframes, void* ptr)
{
uiPtr->jackBufferSize(nframes);
return 0;
}

static int jackSampleRateCallback(jack_nframes_t nframes, void* ptr)
{
uiPtr->jackSampleRate(nframes);
return 0;
}

static int jackProcessCallback(jack_nframes_t nframes, void* ptr)
{
uiPtr->jackProcess(nframes);
return 0;
}

static void jackShutdownCallback(void* ptr)
{
uiPtr->jackShutdown();
}

static void setParameterValueCallback(void* ptr, uint32_t index, float value)
{
uiPtr->setParameterValue(index, value);
}

#if DISTRHO_PLUGIN_WANT_STATE
static void setStateCallback(void* ptr, const char* key, const char* value)
{
uiPtr->setState(key, value);
}
#endif

static void setSizeCallback(void* ptr, uint width, uint height)
{
uiPtr->setSize(width, height);
}

#undef uiPtr
};

END_NAMESPACE_DISTRHO

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

int main()
{
USE_NAMESPACE_DISTRHO;

jack_status_t status = jack_status_t(0x0);
jack_client_t* client = jack_client_open(DISTRHO_PLUGIN_NAME, JackNoStartServer, &status);

if (client == nullptr)
{
d_string errorString;

if (status & JackFailure)
errorString += "Overall operation failed;\n";
if (status & JackInvalidOption)
errorString += "The operation contained an invalid or unsupported option;\n";
if (status & JackNameNotUnique)
errorString += "The desired client name was not unique;\n";
if (status & JackServerStarted)
errorString += "The JACK server was started as a result of this operation;\n";
if (status & JackServerFailed)
errorString += "Unable to connect to the JACK server;\n";
if (status & JackServerError)
errorString += "Communication error with the JACK server;\n";
if (status & JackNoSuchClient)
errorString += "Requested client does not exist;\n";
if (status & JackLoadFailure)
errorString += "Unable to load internal client;\n";
if (status & JackInitFailure)
errorString += "Unable to initialize client;\n";
if (status & JackShmFailure)
errorString += "Unable to access shared memory;\n";
if (status & JackVersionError)
errorString += "Client's protocol version does not match;\n";
if (status & JackBackendError)
errorString += "Backend Error;\n";
if (status & JackClientZombie)
errorString += "Client is being shutdown against its will;\n";

if (errorString.isNotEmpty())
{
errorString[errorString.length()-2] = '.';
d_stderr("Failed to create jack client, reason was:\n%s", errorString.buffer());
}
else
d_stderr("Failed to create jack client, cannot continue!");

return 1;
}

USE_NAMESPACE_DISTRHO;

d_lastBufferSize = jack_get_buffer_size(client);
d_lastSampleRate = jack_get_sample_rate(client);
d_lastUiSampleRate = d_lastSampleRate;

const PluginJack p(client);

return 0;
}

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

+ 0
- 713
distrho/src/DistrhoPluginLADSPA+DSSI.cpp View File

@@ -1,713 +0,0 @@
/*
* 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 "DistrhoPluginInternal.hpp"

#if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT
# error Cannot use MIDI Output with LADSPA or DSSI
#endif

#ifdef DISTRHO_PLUGIN_TARGET_DSSI
# include "dssi/dssi.h"
#else
# include "ladspa/ladspa.h"
# if DISTRHO_PLUGIN_WANT_MIDI_INPUT
# error Cannot use MIDI with LADSPA
# endif
# if DISTRHO_PLUGIN_WANT_STATE
# warning LADSPA cannot handle states
# endif
#endif

#if DISTRHO_PLUGIN_WANT_TIMEPOS
# warning LADSPA/DSSI does not support TimePos
#endif

START_NAMESPACE_DISTRHO

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

class PluginLadspaDssi
{
public:
PluginLadspaDssi()
: fPortControls(nullptr),
fLastControlValues(nullptr)
{
#if DISTRHO_PLUGIN_NUM_INPUTS > 0
for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i)
fPortAudioIns[i] = nullptr;
#else
fPortAudioIns = nullptr;
#endif

#if DISTRHO_PLUGIN_NUM_OUTPUTS > 0
for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i)
fPortAudioOuts[i] = nullptr;
#else
fPortAudioOuts = nullptr;
#endif

if (const uint32_t count = fPlugin.getParameterCount())
{
fPortControls = new LADSPA_Data*[count];
fLastControlValues = new LADSPA_Data[count];

for (uint32_t i=0; i < count; ++i)
{
fPortControls[i] = nullptr;
fLastControlValues[i] = fPlugin.getParameterValue(i);
}
}
else
{
fPortControls = nullptr;
fLastControlValues = nullptr;
}

#if DISTRHO_PLUGIN_WANT_LATENCY
fPortLatency = nullptr;
#endif
}

~PluginLadspaDssi() noexcept
{
if (fPortControls != nullptr)
{
delete[] fPortControls;
fPortControls = nullptr;
}

if (fLastControlValues != nullptr)
{
delete[] fLastControlValues;
fLastControlValues = nullptr;
}
}

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

void ladspa_activate()
{
fPlugin.activate();
}

void ladspa_deactivate()
{
fPlugin.deactivate();
}

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

void ladspa_connect_port(const ulong port, LADSPA_Data* const dataLocation) noexcept
{
ulong index = 0;

#if DISTRHO_PLUGIN_NUM_INPUTS > 0
for (ulong i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i)
{
if (port == index++)
{
fPortAudioIns[i] = dataLocation;
return;
}
}
#endif

#if DISTRHO_PLUGIN_NUM_OUTPUTS > 0
for (ulong i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i)
{
if (port == index++)
{
fPortAudioOuts[i] = dataLocation;
return;
}
}
#endif

#if DISTRHO_PLUGIN_WANT_LATENCY
if (port == index++)
{
fPortLatency = dataLocation;
return;
}
#endif

for (ulong i=0, count=fPlugin.getParameterCount(); i < count; ++i)
{
if (port == index++)
{
fPortControls[i] = dataLocation;
return;
}
}
}

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

#ifdef DISTRHO_PLUGIN_TARGET_DSSI
void ladspa_run(const ulong sampleCount)
{
dssi_run_synth(sampleCount, nullptr, 0);
}

void dssi_run_synth(const ulong sampleCount, snd_seq_event_t* const events, const ulong eventCount)
#else
void ladspa_run(const ulong sampleCount)
#endif
{
// pre-roll
if (sampleCount == 0)
return updateParameterOutputs();

// Check for updated parameters
float curValue;

for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i)
{
if (fPortControls[i] == nullptr)
continue;

curValue = *fPortControls[i];

if (fLastControlValues[i] != curValue && ! fPlugin.isParameterOutput(i))
{
fLastControlValues[i] = curValue;
fPlugin.setParameterValue(i, curValue);
}
}

#if DISTRHO_PLUGIN_WANT_MIDI_INPUT
// Get MIDI Events
uint32_t midiEventCount = 0;
MidiEvent midiEvents[eventCount];

for (uint32_t i=0, j; i < eventCount; ++i)
{
const snd_seq_event_t& seqEvent(events[i]);

// FIXME
if (seqEvent.data.note.channel > 0xF || seqEvent.data.control.channel > 0xF)
continue;

switch (seqEvent.type)
{
case SND_SEQ_EVENT_NOTEOFF:
j = midiEventCount++;
midiEvents[j].frame = seqEvent.time.tick;
midiEvents[j].size = 3;
midiEvents[j].data[0] = 0x80 + seqEvent.data.note.channel;
midiEvents[j].data[1] = seqEvent.data.note.note;
midiEvents[j].data[2] = 0;
midiEvents[j].data[3] = 0;
break;
case SND_SEQ_EVENT_NOTEON:
j = midiEventCount++;
midiEvents[j].frame = seqEvent.time.tick;
midiEvents[j].size = 3;
midiEvents[j].data[0] = 0x90 + seqEvent.data.note.channel;
midiEvents[j].data[1] = seqEvent.data.note.note;
midiEvents[j].data[2] = seqEvent.data.note.velocity;
midiEvents[j].data[3] = 0;
break;
case SND_SEQ_EVENT_KEYPRESS:
j = midiEventCount++;
midiEvents[j].frame = seqEvent.time.tick;
midiEvents[j].size = 3;
midiEvents[j].data[0] = 0xA0 + seqEvent.data.note.channel;
midiEvents[j].data[1] = seqEvent.data.note.note;
midiEvents[j].data[2] = seqEvent.data.note.velocity;
midiEvents[j].data[3] = 0;
break;
case SND_SEQ_EVENT_CONTROLLER:
j = midiEventCount++;
midiEvents[j].frame = seqEvent.time.tick;
midiEvents[j].size = 3;
midiEvents[j].data[0] = 0xB0 + seqEvent.data.control.channel;
midiEvents[j].data[1] = seqEvent.data.control.param;
midiEvents[j].data[2] = seqEvent.data.control.value;
midiEvents[j].data[3] = 0;
break;
case SND_SEQ_EVENT_CHANPRESS:
j = midiEventCount++;
midiEvents[j].frame = seqEvent.time.tick;
midiEvents[j].size = 2;
midiEvents[j].data[0] = 0xD0 + seqEvent.data.control.channel;
midiEvents[j].data[1] = seqEvent.data.control.value;
midiEvents[j].data[2] = 0;
midiEvents[j].data[3] = 0;
break;
#if 0 // TODO
case SND_SEQ_EVENT_PITCHBEND:
j = midiEventCount++;
midiEvents[j].frame = seqEvent.time.tick;
midiEvents[j].size = 3;
midiEvents[j].data[0] = 0xE0 + seqEvent.data.control.channel;
midiEvents[j].data[1] = 0;
midiEvents[j].data[2] = 0;
midiEvents[j].data[3] = 0;
break;
#endif
}
}

fPlugin.run(fPortAudioIns, fPortAudioOuts, sampleCount, midiEvents, midiEventCount);
#else
fPlugin.run(fPortAudioIns, fPortAudioOuts, sampleCount);
#endif

updateParameterOutputs();

#if defined(DISTRHO_PLUGIN_TARGET_DSSI) && ! DISTRHO_PLUGIN_WANT_MIDI_INPUT
return; // unused
(void)events; (void)eventCount;
#endif
}

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

#ifdef DISTRHO_PLUGIN_TARGET_DSSI
# if DISTRHO_PLUGIN_WANT_STATE
char* dssi_configure(const char* const key, const char* const value)
{
if (std::strncmp(key, DSSI_RESERVED_CONFIGURE_PREFIX, std::strlen(DSSI_RESERVED_CONFIGURE_PREFIX) == 0))
return nullptr;
if (std::strncmp(key, DSSI_GLOBAL_CONFIGURE_PREFIX, std::strlen(DSSI_GLOBAL_CONFIGURE_PREFIX) == 0))
return nullptr;

fPlugin.setState(key, value);
return nullptr;
}
# endif

# if DISTRHO_PLUGIN_WANT_PROGRAMS
const DSSI_Program_Descriptor* dssi_get_program(const ulong index)
{
if (index >= fPlugin.getProgramCount())
return nullptr;

static DSSI_Program_Descriptor desc;

desc.Bank = index / 128;
desc.Program = index % 128;
desc.Name = fPlugin.getProgramName(index);

return &desc;
}

void dssi_select_program(const ulong bank, const ulong program)
{
const ulong realProgram(bank * 128 + program);

DISTRHO_SAFE_ASSERT_RETURN(realProgram < fPlugin.getProgramCount(),);

fPlugin.setProgram(realProgram);

// Update control inputs
for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i)
{
if (fPlugin.isParameterOutput(i))
continue;

fLastControlValues[i] = fPlugin.getParameterValue(i);

if (fPortControls[i] != nullptr)
*fPortControls[i] = fLastControlValues[i];
}
}
# endif
#endif

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

private:
PluginExporter fPlugin;

// LADSPA ports
#if DISTRHO_PLUGIN_NUM_INPUTS > 0
const LADSPA_Data* fPortAudioIns[DISTRHO_PLUGIN_NUM_INPUTS];
#else
const LADSPA_Data** fPortAudioIns;
#endif
#if DISTRHO_PLUGIN_NUM_OUTPUTS > 0
LADSPA_Data* fPortAudioOuts[DISTRHO_PLUGIN_NUM_OUTPUTS];
#else
LADSPA_Data** fPortAudioOuts;
#endif
LADSPA_Data** fPortControls;
#if DISTRHO_PLUGIN_WANT_LATENCY
LADSPA_Data* fPortLatency;
#endif

// Temporary data
LADSPA_Data* fLastControlValues;

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

void updateParameterOutputs()
{
for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i)
{
if (! fPlugin.isParameterOutput(i))
continue;

fLastControlValues[i] = fPlugin.getParameterValue(i);

if (fPortControls[i] != nullptr)
*fPortControls[i] = fLastControlValues[i];
}

#if DISTRHO_PLUGIN_WANT_LATENCY
if (fPortLatency != nullptr)
*fPortLatency = fPlugin.getLatency();
#endif
}
};

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

static LADSPA_Handle ladspa_instantiate(const LADSPA_Descriptor*, ulong sampleRate)
{
if (d_lastBufferSize == 0)
d_lastBufferSize = 2048;
d_lastSampleRate = sampleRate;

return new PluginLadspaDssi();
}

#define instancePtr ((PluginLadspaDssi*)instance)

static void ladspa_connect_port(LADSPA_Handle instance, ulong port, LADSPA_Data* dataLocation)
{
instancePtr->ladspa_connect_port(port, dataLocation);
}

static void ladspa_activate(LADSPA_Handle instance)
{
instancePtr->ladspa_activate();
}

static void ladspa_run(LADSPA_Handle instance, ulong sampleCount)
{
instancePtr->ladspa_run(sampleCount);
}

static void ladspa_deactivate(LADSPA_Handle instance)
{
instancePtr->ladspa_deactivate();
}

static void ladspa_cleanup(LADSPA_Handle instance)
{
delete instancePtr;
}

#ifdef DISTRHO_PLUGIN_TARGET_DSSI
# if DISTRHO_PLUGIN_WANT_STATE
static char* dssi_configure(LADSPA_Handle instance, const char* key, const char* value)
{
return instancePtr->dssi_configure(key, value);
}
# endif

# if DISTRHO_PLUGIN_WANT_PROGRAMS
static const DSSI_Program_Descriptor* dssi_get_program(LADSPA_Handle instance, ulong index)
{
return instancePtr->dssi_get_program(index);
}

static void dssi_select_program(LADSPA_Handle instance, ulong bank, ulong program)
{
instancePtr->dssi_select_program(bank, program);
}
# endif

# 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);
}
# endif
#endif

#undef instancePtr

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

static LADSPA_Descriptor sLadspaDescriptor = {
/* UniqueID */ 0,
/* Label */ nullptr,
#if DISTRHO_PLUGIN_IS_RT_SAFE
/* Properties */ LADSPA_PROPERTY_HARD_RT_CAPABLE,
#else
/* Properties */ 0x0,
#endif
/* Name */ nullptr,
/* Maker */ nullptr,
/* Copyright */ nullptr,
/* PortCount */ 0,
/* PortDescriptors */ nullptr,
/* PortNames */ nullptr,
/* PortRangeHints */ nullptr,
/* ImplementationData */ nullptr,
ladspa_instantiate,
ladspa_connect_port,
ladspa_activate,
ladspa_run,
/* run_adding */ nullptr,
/* set_run_adding_gain */ nullptr,
ladspa_deactivate,
ladspa_cleanup
};

#ifdef DISTRHO_PLUGIN_TARGET_DSSI
static DSSI_Descriptor sDssiDescriptor = {
1,
&sLadspaDescriptor,
# if DISTRHO_PLUGIN_WANT_STATE
dssi_configure,
# else
/* configure */ nullptr,
# endif
# if DISTRHO_PLUGIN_WANT_PROGRAMS
dssi_get_program,
dssi_select_program,
# else
/* get_program */ nullptr,
/* select_program */ nullptr,
# endif
/* get_midi_controller_for_port */ nullptr,
# if DISTRHO_PLUGIN_WANT_MIDI_INPUT
dssi_run_synth,
# else
/* run_synth */ nullptr,
# endif
/* run_synth_adding */ nullptr,
/* run_multiple_synths */ nullptr,
/* run_multiple_synths_adding */ nullptr,
nullptr, nullptr
};
#endif

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

class DescriptorInitializer
{
public:
DescriptorInitializer()
{
// Create dummy plugin to get data from
d_lastBufferSize = 512;
d_lastSampleRate = 44100.0;
PluginExporter plugin;
d_lastBufferSize = 0;
d_lastSampleRate = 0.0;

// Get port count, init
ulong port = 0;
ulong portCount = DISTRHO_PLUGIN_NUM_INPUTS + DISTRHO_PLUGIN_NUM_OUTPUTS + plugin.getParameterCount();
#if DISTRHO_PLUGIN_WANT_LATENCY
portCount += 1;
#endif
const char** const portNames = new const char*[portCount];
LADSPA_PortDescriptor* portDescriptors = new LADSPA_PortDescriptor[portCount];
LADSPA_PortRangeHint* portRangeHints = new LADSPA_PortRangeHint [portCount];

// Set ports
#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);

portNames[port] = strdup(portName);
portDescriptors[port] = LADSPA_PORT_AUDIO | LADSPA_PORT_INPUT;

portRangeHints[port].HintDescriptor = 0x0;
portRangeHints[port].LowerBound = 0.0f;
portRangeHints[port].UpperBound = 1.0f;
}
#endif

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

portNames[port] = strdup(portName);
portDescriptors[port] = LADSPA_PORT_AUDIO | LADSPA_PORT_OUTPUT;

portRangeHints[port].HintDescriptor = 0x0;
portRangeHints[port].LowerBound = 0.0f;
portRangeHints[port].UpperBound = 1.0f;
}
#endif

#if DISTRHO_PLUGIN_WANT_LATENCY
// Set latency port
portNames[port] = strdup("_latency");
portDescriptors[port] = LADSPA_PORT_CONTROL | LADSPA_PORT_OUTPUT;
portRangeHints[port].HintDescriptor = LADSPA_HINT_SAMPLE_RATE|LADSPA_HINT_INTEGER;
portRangeHints[port].LowerBound = 0.0f;
portRangeHints[port].UpperBound = 1.0f;
++port;
#endif

for (ulong i=0, count=plugin.getParameterCount(); i < count; ++i, ++port)
{
portNames[port] = strdup((const char*)plugin.getParameterName(i));
portDescriptors[port] = LADSPA_PORT_CONTROL;

if (plugin.isParameterOutput(i))
portDescriptors[port] |= LADSPA_PORT_OUTPUT;
else
portDescriptors[port] |= LADSPA_PORT_INPUT;

{
const ParameterRanges& ranges(plugin.getParameterRanges(i));
const float defValue(ranges.def);

portRangeHints[port].HintDescriptor = LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE;
portRangeHints[port].LowerBound = ranges.min;
portRangeHints[port].UpperBound = ranges.max;

if (defValue == 0.0f)
portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_0;
else if (defValue == 1.0f)
portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_1;
else if (defValue == 100.0f)
portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_100;
else if (defValue == 440.0f)
portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_440;
else if (ranges.min == defValue)
portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_MINIMUM;
else if (ranges.max == defValue)
portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_MAXIMUM;
else
{
const float middleValue = ranges.min/2.0f + ranges.max/2.0f;
const float middleLow = (ranges.min/2.0f + middleValue/2.0f)/2.0f + middleValue/2.0f;
const float middleHigh = (ranges.max/2.0f + middleValue/2.0f)/2.0f + middleValue/2.0f;

if (defValue < middleLow)
portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_LOW;
else if (defValue > middleHigh)
portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_HIGH;
else
portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_MIDDLE;
}
}

{
const uint32_t hints(plugin.getParameterHints(i));

if (hints & kParameterIsBoolean)
portRangeHints[port].HintDescriptor |= LADSPA_HINT_TOGGLED;
if (hints & kParameterIsInteger)
portRangeHints[port].HintDescriptor |= LADSPA_HINT_INTEGER;
if (hints & kParameterIsLogarithmic)
portRangeHints[port].HintDescriptor |= LADSPA_HINT_LOGARITHMIC;
}
}

// Set data
sLadspaDescriptor.UniqueID = plugin.getUniqueId();
sLadspaDescriptor.Label = strdup(plugin.getLabel());
sLadspaDescriptor.Name = strdup(plugin.getName());
sLadspaDescriptor.Maker = strdup(plugin.getMaker());
sLadspaDescriptor.Copyright = strdup(plugin.getLicense());
sLadspaDescriptor.PortCount = portCount;
sLadspaDescriptor.PortNames = portNames;
sLadspaDescriptor.PortDescriptors = portDescriptors;
sLadspaDescriptor.PortRangeHints = portRangeHints;
}

~DescriptorInitializer()
{
if (sLadspaDescriptor.Label != nullptr)
{
std::free((void*)sLadspaDescriptor.Label);
sLadspaDescriptor.Label = nullptr;
}

if (sLadspaDescriptor.Name != nullptr)
{
std::free((void*)sLadspaDescriptor.Name);
sLadspaDescriptor.Name = nullptr;
}

if (sLadspaDescriptor.Maker != nullptr)
{
std::free((void*)sLadspaDescriptor.Maker);
sLadspaDescriptor.Maker = nullptr;
}

if (sLadspaDescriptor.Copyright != nullptr)
{
std::free((void*)sLadspaDescriptor.Copyright);
sLadspaDescriptor.Copyright = nullptr;
}

if (sLadspaDescriptor.PortDescriptors != nullptr)
{
delete[] sLadspaDescriptor.PortDescriptors;
sLadspaDescriptor.PortDescriptors = nullptr;
}

if (sLadspaDescriptor.PortRangeHints != nullptr)
{
delete[] sLadspaDescriptor.PortRangeHints;
sLadspaDescriptor.PortRangeHints = nullptr;
}

if (sLadspaDescriptor.PortNames != nullptr)
{
for (ulong i=0; i < sLadspaDescriptor.PortCount; ++i)
{
if (sLadspaDescriptor.PortNames[i] != nullptr)
std::free((void*)sLadspaDescriptor.PortNames[i]);
}

delete[] sLadspaDescriptor.PortNames;
sLadspaDescriptor.PortNames = nullptr;
}
}
};

static DescriptorInitializer sDescInit;

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

END_NAMESPACE_DISTRHO

DISTRHO_PLUGIN_EXPORT
const LADSPA_Descriptor* ladspa_descriptor(ulong index)
{
USE_NAMESPACE_DISTRHO
return (index == 0) ? &sLadspaDescriptor : nullptr;
}

#ifdef DISTRHO_PLUGIN_TARGET_DSSI
DISTRHO_PLUGIN_EXPORT
const DSSI_Descriptor* dssi_descriptor(ulong index)
{
USE_NAMESPACE_DISTRHO
return (index == 0) ? &sDssiDescriptor : nullptr;
}
#endif

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

+ 0
- 1107
distrho/src/DistrhoPluginLV2.cpp
File diff suppressed because it is too large
View File


+ 0
- 410
distrho/src/DistrhoPluginLV2export.cpp View File

@@ -1,410 +0,0 @@
/*
* 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 "DistrhoPluginInternal.hpp"

#include "lv2/atom.h"
#include "lv2/buf-size.h"
#include "lv2/data-access.h"
#include "lv2/instance-access.h"
#include "lv2/midi.h"
#include "lv2/options.h"
#include "lv2/port-props.h"
#include "lv2/resize-port.h"
#include "lv2/state.h"
#include "lv2/time.h"
#include "lv2/ui.h"
#include "lv2/units.h"
#include "lv2/urid.h"
#include "lv2/worker.h"
#include "lv2/lv2_kxstudio_properties.h"
#include "lv2/lv2_programs.h"

#include <fstream>
#include <iostream>

#ifndef DISTRHO_PLUGIN_URI
# error DISTRHO_PLUGIN_URI undefined!
#endif

#ifndef DISTRHO_PLUGIN_MINIMUM_BUFFER_SIZE
# define DISTRHO_PLUGIN_MINIMUM_BUFFER_SIZE 2048
#endif

#if DISTRHO_PLUGIN_HAS_UI && ! defined(HAVE_DGL)
# undef DISTRHO_PLUGIN_HAS_UI
# define DISTRHO_PLUGIN_HAS_UI 0
#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))

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

DISTRHO_PLUGIN_EXPORT
void lv2_generate_ttl(const char* const basename)
{
USE_NAMESPACE_DISTRHO

// Dummy plugin to get data from
d_lastBufferSize = 512;
d_lastSampleRate = 44100.0;
PluginExporter plugin;
d_lastBufferSize = 0;
d_lastSampleRate = 0.0;

d_string pluginDLL(basename);
d_string pluginTTL(pluginDLL + ".ttl");

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

{
std::cout << "Writing manifest.ttl..."; std::cout.flush();
std::fstream manifestFile("manifest.ttl", std::ios::out);

d_string manifestString;
manifestString += "@prefix lv2: <" LV2_CORE_PREFIX "> .\n";
manifestString += "@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n";
#if DISTRHO_PLUGIN_HAS_UI
manifestString += "@prefix ui: <" LV2_UI_PREFIX "> .\n";
#endif
manifestString += "\n";

manifestString += "<" DISTRHO_PLUGIN_URI ">\n";
manifestString += " a lv2:Plugin ;\n";
manifestString += " lv2:binary <" + pluginDLL + "." DISTRHO_DLL_EXTENSION "> ;\n";
manifestString += " rdfs:seeAlso <" + pluginTTL + "> .\n";
manifestString += "\n";

#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 += " ui:binary <" + pluginUI + "." DISTRHO_DLL_EXTENSION "> ;\n";
# else
manifestString += " ui:binary <" + pluginDLL + "." DISTRHO_DLL_EXTENSION "> ;\n";
#endif
manifestString += " lv2:extensionData ui:idleInterface ,\n";
# if DISTRHO_PLUGIN_WANT_PROGRAMS
manifestString += " ui:showInterface ,\n";
manifestString += " <" LV2_PROGRAMS__Interface "> ;\n";
# else
manifestString += " ui:showInterface ;\n";
# endif
manifestString += " lv2:optionalFeature ui:noUserResize ,\n";
manifestString += " ui:resize ,\n";
manifestString += " ui:touch ;\n";
# if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
manifestString += " lv2:requiredFeature <" LV2_DATA_ACCESS_URI "> ,\n";
manifestString += " <" LV2_INSTANCE_ACCESS_URI "> ,\n";
manifestString += " <" LV2_OPTIONS__options "> ,\n";
# else
manifestString += " lv2:requiredFeature <" LV2_OPTIONS__options "> ,\n";
# endif
manifestString += " <" LV2_URID__map "> .\n";
#endif

manifestFile << manifestString << std::endl;
manifestFile.close();
std::cout << " done!" << std::endl;
}

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

{
std::cout << "Writing " << pluginTTL << "..."; std::cout.flush();
std::fstream pluginFile(pluginTTL, std::ios::out);

d_string pluginString;

// header
#if DISTRHO_LV2_USE_EVENTS_IN
pluginString += "@prefix atom: <" LV2_ATOM_PREFIX "> .\n";
#endif
pluginString += "@prefix doap: <http://usefulinc.com/ns/doap#> .\n";
pluginString += "@prefix foaf: <http://xmlns.com/foaf/0.1/> .\n";
pluginString += "@prefix lv2: <" LV2_CORE_PREFIX "> .\n";
pluginString += "@prefix rsz: <" LV2_RESIZE_PORT_PREFIX "> .\n";
#if DISTRHO_PLUGIN_HAS_UI
pluginString += "@prefix ui: <" LV2_UI_PREFIX "> .\n";
#endif
pluginString += "@prefix unit: <" LV2_UNITS_PREFIX "> .\n";
pluginString += "\n";

// plugin
pluginString += "<" DISTRHO_PLUGIN_URI ">\n";
#if DISTRHO_PLUGIN_IS_SYNTH
pluginString += " a lv2:InstrumentPlugin, lv2:Plugin ;\n";
#else
pluginString += " a lv2:Plugin ;\n";
#endif
pluginString += "\n";

// extensionData
pluginString += " lv2:extensionData <" LV2_STATE__interface "> ";
#if DISTRHO_PLUGIN_WANT_STATE
pluginString += ",\n <" LV2_OPTIONS__interface "> ";
pluginString += ",\n <" LV2_WORKER__interface "> ";
#endif
#if DISTRHO_PLUGIN_WANT_PROGRAMS
pluginString += ",\n <" LV2_PROGRAMS__Interface "> ";
#endif
pluginString += ";\n\n";

// optionalFeatures
#if DISTRHO_PLUGIN_IS_RT_SAFE
pluginString += " lv2:optionalFeature <" LV2_CORE__hardRTCapable "> ,\n";
pluginString += " <" LV2_BUF_SIZE__boundedBlockLength "> ;\n";
#else
pluginString += " lv2:optionalFeature <" LV2_BUF_SIZE__boundedBlockLength "> ;\n";
#endif
pluginString += "\n";

// requiredFeatures
pluginString += " lv2:requiredFeature <" LV2_OPTIONS__options "> ";
pluginString += ",\n <" LV2_URID__map "> ";
#if DISTRHO_PLUGIN_WANT_STATE
pluginString += ",\n <" LV2_WORKER__schedule "> ";
#endif
pluginString += ";\n\n";

// UI
#if DISTRHO_PLUGIN_HAS_UI
pluginString += " ui:ui <" DISTRHO_UI_URI "> ;\n";
pluginString += "\n";
#endif

{
uint32_t portIndex = 0;

#if DISTRHO_PLUGIN_NUM_INPUTS > 0
for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i, ++portIndex)
{
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 (i+1 == DISTRHO_PLUGIN_NUM_INPUTS)
pluginString += " ] ;\n\n";
else
pluginString += " ] ,\n";
}
pluginString += "\n";
#endif

#if DISTRHO_PLUGIN_NUM_OUTPUTS > 0
for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i, ++portIndex)
{
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 (i+1 == DISTRHO_PLUGIN_NUM_OUTPUTS)
pluginString += " ] ;\n\n";
else
pluginString += " ] ,\n";
}
pluginString += "\n";
#endif

#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:name \"Events Input\" ;\n";
pluginString += " lv2:symbol \"lv2_events_in\" ;\n";
pluginString += " rsz:minimumSize " + d_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_WANT_MIDI_INPUT
pluginString += " atom:supports <" LV2_MIDI__MidiEvent "> ;\n";
# endif
# if DISTRHO_PLUGIN_WANT_TIMEPOS
pluginString += " atom:supports <" LV2_TIME__Position "> ;\n";
# endif
pluginString += " ] ;\n\n";
++portIndex;
#endif

#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:name \"Events Output\" ;\n";
pluginString += " lv2:symbol \"lv2_events_out\" ;\n";
pluginString += " rsz:minimumSize " + d_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_WANT_MIDI_OUTPUT
pluginString += " atom:supports <" LV2_MIDI__MidiEvent "> ;\n";
# endif
pluginString += " ] ;\n\n";
++portIndex;
#endif

#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:name \"Latency\" ;\n";
pluginString += " lv2:symbol \"lv2_latency\" ;\n";
pluginString += " lv2:designation lv2:latency ;\n";
pluginString += " lv2:portProperty lv2:reportsLatency, lv2:integer ;\n";
pluginString += " ] ;\n\n";
++portIndex;
#endif

for (uint32_t i=0, count=plugin.getParameterCount(); i < count; ++i, ++portIndex)
{
if (i == 0)
pluginString += " lv2:port [\n";
else
pluginString += " [\n";

if (plugin.isParameterOutput(i))
pluginString += " a lv2:OutputPort, lv2:ControlPort ;\n";
else
pluginString += " a lv2:InputPort, lv2:ControlPort ;\n";

pluginString += " lv2:index " + d_string(portIndex) + " ;\n";
pluginString += " lv2:name \"" + plugin.getParameterName(i) + "\" ;\n";

// symbol
{
d_string symbol(plugin.getParameterSymbol(i));

if (symbol.isEmpty())
symbol = "lv2_port_" + d_string(portIndex-1);

pluginString += " lv2:symbol \"" + symbol + "\" ;\n";
}

// ranges
{
const ParameterRanges& ranges(plugin.getParameterRanges(i));

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

// unit
{
const d_string& unit(plugin.getParameterUnit(i));

if (! unit.isEmpty())
{
if (unit == "db" || unit == "dB")
{
pluginString += " unit:unit unit:db ;\n";
}
else if (unit == "hz" || unit == "Hz")
{
pluginString += " unit:unit unit:hz ;\n";
}
else if (unit == "khz" || unit == "kHz")
{
pluginString += " unit:unit unit:khz ;\n";
}
else if (unit == "mhz" || unit == "mHz")
{
pluginString += " unit:unit unit:mhz ;\n";
}
else if (unit == "%")
{
pluginString += " unit:unit unit:pc ;\n";
}
else
{
pluginString += " unit:unit [\n";
pluginString += " a unit:Unit ;\n";
pluginString += " unit:name \"" + unit + "\" ;\n";
pluginString += " unit:symbol \"" + unit + "\" ;\n";
pluginString += " unit:render \"%f " + unit + "\" ;\n";
pluginString += " ] ;\n";
}
}
}

// hints
{
const uint32_t hints(plugin.getParameterHints(i));

if (hints & kParameterIsBoolean)
pluginString += " lv2:portProperty lv2:toggled ;\n";
if (hints & kParameterIsInteger)
pluginString += " lv2:portProperty lv2:integer ;\n";
if (hints & kParameterIsLogarithmic)
pluginString += " lv2:portProperty <" LV2_PORT_PROPS__logarithmic "> ;\n";
if ((hints & kParameterIsAutomable) == 0 && ! plugin.isParameterOutput(i))
{
pluginString += " lv2:portProperty <" LV2_PORT_PROPS__expensive "> ,\n";
pluginString += " <" LV2_KXSTUDIO_PROPERTIES__NonAutomable "> ;\n";
}
}

if (i+1 == count)
pluginString += " ] ;\n\n";
else
pluginString += " ] ,\n";
}
}

pluginString += " doap:name \"" + d_string(plugin.getName()) + "\" ;\n";
pluginString += " doap:maintainer [ foaf:name \"" + d_string(plugin.getMaker()) + "\" ] .\n";

pluginFile << pluginString << std::endl;
pluginFile.close();
std::cout << " done!" << std::endl;
}
}

+ 0
- 1071
distrho/src/DistrhoPluginVST.cpp
File diff suppressed because it is too large
View File


+ 0
- 122
distrho/src/DistrhoUI.cpp View File

@@ -1,122 +0,0 @@
/*
* 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 "DistrhoUIInternal.hpp"

START_NAMESPACE_DISTRHO

/* ------------------------------------------------------------------------------------------------------------
* Static data, see DistrhoUIInternal.hpp */

double d_lastUiSampleRate = 0.0;
void* d_lastUiDspPtr = nullptr;
Window* d_lastUiWindow = nullptr;

/* ------------------------------------------------------------------------------------------------------------
* UI */

UI::UI(uint width, uint height)
: UIWidget(*d_lastUiWindow),
pData(new PrivateData())
{
UIWidget::setNeedsFullViewport(true);

if (width > 0 && height > 0)
setSize(width, height);
}

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

/* ------------------------------------------------------------------------------------------------------------
* Host state */

double UI::d_getSampleRate() const noexcept
{
return pData->sampleRate;
}

void UI::d_editParameter(const uint32_t index, const bool started)
{
pData->editParamCallback(index + pData->parameterOffset, started);
}

void UI::d_setParameterValue(const uint32_t index, const 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)
{
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)
{
pData->sendNoteCallback(channel, note, velocity);
}
#endif

#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
/* ------------------------------------------------------------------------------------------------------------
* Direct DSP access */

void* UI::d_getPluginInstancePointer() const noexcept
{
return pData->dspPtr;
}
#endif

/* ------------------------------------------------------------------------------------------------------------
* DSP/Plugin Callbacks (optional) */

void UI::d_sampleRateChanged(double) {}

/* ------------------------------------------------------------------------------------------------------------
* UI Callbacks (optional) */

void UI::d_uiFileBrowserSelected(const char*)
{
}

void UI::d_uiReshape(uint width, uint height)
{
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, static_cast<GLdouble>(width), static_cast<GLdouble>(height), 0.0, 0.0, 1.0);
glViewport(0, 0, static_cast<GLsizei>(width), static_cast<GLsizei>(height));
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}

/* ------------------------------------------------------------------------------------------------------------
* UI Resize Handling, internal */

void UI::onResize(const ResizeEvent& ev)
{
pData->setSizeCallback(ev.size.getWidth(), ev.size.getHeight());
}

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

END_NAMESPACE_DISTRHO

+ 0
- 511
distrho/src/DistrhoUIDSSI.cpp View File

@@ -1,511 +0,0 @@
/*
* 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 "DistrhoUIInternal.hpp"

#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
# error DSSI UIs do not support direct access!
#endif

#include "../extra/d_sleep.hpp"

#include <lo/lo.h>

START_NAMESPACE_DISTRHO

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

struct OscData {
lo_address addr;
const char* path;
lo_server server;

OscData()
: addr(nullptr),
path(nullptr),
server(nullptr) {}

void idle() const
{
if (server == nullptr)
return;

while (lo_server_recv_noblock(server, 0) != 0) {}
}

void send_configure(const char* const key, const char* const value) const
{
char targetPath[std::strlen(path)+11];
std::strcpy(targetPath, path);
std::strcat(targetPath, "/configure");
lo_send(addr, targetPath, "ss", key, value);
}

void send_control(const int32_t index, const float value) const
{
char targetPath[std::strlen(path)+9];
std::strcpy(targetPath, path);
std::strcat(targetPath, "/control");
lo_send(addr, targetPath, "if", index, value);
}

void send_midi(uchar data[4]) const
{
char targetPath[std::strlen(path)+6];
std::strcpy(targetPath, path);
std::strcat(targetPath, "/midi");
lo_send(addr, targetPath, "m", data);
}

void send_update(const char* const url) const
{
char targetPath[std::strlen(path)+8];
std::strcpy(targetPath, path);
std::strcat(targetPath, "/update");
lo_send(addr, targetPath, "s", url);
}

void send_exiting() const
{
char targetPath[std::strlen(path)+9];
std::strcpy(targetPath, path);
std::strcat(targetPath, "/exiting");
lo_send(addr, targetPath, "");
}
};

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

class UIDssi
{
public:
UIDssi(const OscData& oscData, const char* const uiTitle)
: fUI(this, 0, nullptr, setParameterCallback, setStateCallback, sendNoteCallback, setSizeCallback),
fHostClosed(false),
fOscData(oscData)
{
fUI.setWindowTitle(uiTitle);
}

~UIDssi()
{
if (fOscData.server != nullptr && ! fHostClosed)
fOscData.send_exiting();
}

void exec()
{
for (;;)
{
fOscData.idle();

if (fHostClosed || ! fUI.idle())
break;

d_msleep(30);
}
}

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

#if DISTRHO_PLUGIN_WANT_STATE
void dssiui_configure(const char* key, const char* value)
{
fUI.stateChanged(key, value);
}
#endif

void dssiui_control(ulong index, float value)
{
fUI.parameterChanged(index, value);
}

#if DISTRHO_PLUGIN_WANT_PROGRAMS
void dssiui_program(ulong bank, ulong program)
{
fUI.programChanged(bank * 128 + program);
}
#endif

void dssiui_samplerate(const double sampleRate)
{
fUI.setSampleRate(sampleRate, true);
}

void dssiui_show()
{
fUI.setWindowVisible(true);
}

void dssiui_hide()
{
fUI.setWindowVisible(false);
}

void dssiui_quit()
{
fHostClosed = true;
fUI.quit();
}

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

protected:
void setParameterValue(const uint32_t rindex, const float value)
{
if (fOscData.server == nullptr)
return;

fOscData.send_control(rindex, value);
}

void setState(const char* const key, const char* const value)
{
if (fOscData.server == nullptr)
return;

fOscData.send_configure(key, value);
}

void sendNote(const uint8_t channel, const uint8_t note, const uint8_t velocity)
{
if (fOscData.server == nullptr)
return;
if (channel > 0xF)
return;

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

fOscData.send_midi(mdata);
}

void setSize(const uint width, const uint height)
{
fUI.setWindowSize(width, height);
}

private:
UIExporter fUI;
bool fHostClosed;

const OscData& fOscData;

// -------------------------------------------------------------------
// Callbacks

#define uiPtr ((UIDssi*)ptr)

static void setParameterCallback(void* ptr, uint32_t rindex, float value)
{
uiPtr->setParameterValue(rindex, value);
}

static void setStateCallback(void* ptr, const char* key, const char* value)
{
uiPtr->setState(key, value);
}

static void sendNoteCallback(void* ptr, uint8_t channel, uint8_t note, uint8_t velocity)
{
uiPtr->sendNote(channel, note, velocity);
}

static void setSizeCallback(void* ptr, uint width, uint height)
{
uiPtr->setSize(width, height);
}

#undef uiPtr
};

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

static OscData gOscData;
static const char* gUiTitle = nullptr;
static UIDssi* globalUI = nullptr;

static void initUiIfNeeded()
{
if (globalUI != nullptr)
return;

if (d_lastUiSampleRate == 0.0)
d_lastUiSampleRate = 44100.0;

globalUI = new UIDssi(gOscData, gUiTitle);
}

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

int osc_debug_handler(const char* path, const char*, lo_arg**, int, lo_message, void*)
{
d_debug("osc_debug_handler(\"%s\")", path);
return 0;

#ifndef DEBUG
// unused
(void)path;
#endif
}

void osc_error_handler(int num, const char* msg, const char* path)
{
d_stderr("osc_error_handler(%i, \"%s\", \"%s\")", num, msg, path);
}

#if DISTRHO_PLUGIN_WANT_STATE
int osc_configure_handler(const char*, const char*, lo_arg** argv, int, lo_message, void*)
{
const char* const key = &argv[0]->s;
const char* const value = &argv[1]->s;
d_debug("osc_configure_handler(\"%s\", \"%s\")", key, value);

initUiIfNeeded();

globalUI->dssiui_configure(key, value);

return 0;
}
#endif

int osc_control_handler(const char*, const char*, lo_arg** argv, int, lo_message, void*)
{
const int32_t rindex = argv[0]->i;
const float value = argv[1]->f;
d_debug("osc_control_handler(%i, %f)", rindex, value);

int32_t index = rindex - DISTRHO_PLUGIN_NUM_INPUTS - DISTRHO_PLUGIN_NUM_OUTPUTS;

// latency
#if DISTRHO_PLUGIN_WANT_LATENCY
index -= 1;
#endif

if (index < 0)
return 0;

initUiIfNeeded();

globalUI->dssiui_control(index, value);

return 0;
}

#if DISTRHO_PLUGIN_WANT_PROGRAMS
int osc_program_handler(const char*, const char*, lo_arg** argv, int, lo_message, void*)
{
const int32_t bank = argv[0]->i;
const int32_t program = argv[1]->f;
d_debug("osc_program_handler(%i, %i)", bank, program);

initUiIfNeeded();

globalUI->dssiui_program(bank, program);

return 0;
}
#endif

int osc_sample_rate_handler(const char*, const char*, lo_arg** argv, int, lo_message, void*)
{
const int32_t sampleRate = argv[0]->i;
d_debug("osc_sample_rate_handler(%i)", sampleRate);

d_lastUiSampleRate = sampleRate;

if (globalUI != nullptr)
globalUI->dssiui_samplerate(sampleRate);

return 0;
}

int osc_show_handler(const char*, const char*, lo_arg**, int, lo_message, void*)
{
d_debug("osc_show_handler()");

initUiIfNeeded();

globalUI->dssiui_show();

return 0;
}

int osc_hide_handler(const char*, const char*, lo_arg**, int, lo_message, void*)
{
d_debug("osc_hide_handler()");

if (globalUI != nullptr)
globalUI->dssiui_hide();

return 0;
}

int osc_quit_handler(const char*, const char*, lo_arg**, int, lo_message, void*)
{
d_debug("osc_quit_handler()");

if (globalUI != nullptr)
globalUI->dssiui_quit();

return 0;
}

END_NAMESPACE_DISTRHO

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

int main(int argc, char* argv[])
{
USE_NAMESPACE_DISTRHO

// dummy test mode
if (argc == 1)
{
gUiTitle = "DSSI UI Test";

initUiIfNeeded();
globalUI->dssiui_show();
globalUI->exec();

delete globalUI;
globalUI = nullptr;

return 0;
}

if (argc != 5)
{
fprintf(stderr, "Usage: %s <osc-url> <plugin-dll> <plugin-label> <instance-name>\n", argv[0]);
return 1;
}

const char* oscUrl = argv[1];
const char* uiTitle = argv[4];

char* const oscHost = lo_url_get_hostname(oscUrl);
char* const oscPort = lo_url_get_port(oscUrl);
char* const oscPath = lo_url_get_path(oscUrl);
size_t oscPathSize = strlen(oscPath);
lo_address oscAddr = lo_address_new(oscHost, oscPort);
lo_server oscServer = lo_server_new_with_proto(nullptr, LO_UDP, osc_error_handler);

char* const oscServerPath = lo_server_get_url(oscServer);

char pluginPath[strlen(oscServerPath)+oscPathSize];
strcpy(pluginPath, oscServerPath);
strcat(pluginPath, oscPath+1);

#if DISTRHO_PLUGIN_WANT_STATE
char oscPathConfigure[oscPathSize+11];
strcpy(oscPathConfigure, oscPath);
strcat(oscPathConfigure, "/configure");
lo_server_add_method(oscServer, oscPathConfigure, "ss", osc_configure_handler, nullptr);
#endif

char oscPathControl[oscPathSize+9];
strcpy(oscPathControl, oscPath);
strcat(oscPathControl, "/control");
lo_server_add_method(oscServer, oscPathControl, "if", osc_control_handler, nullptr);

d_stdout("oscServerPath: \"%s\"", oscServerPath);
d_stdout("pluginPath: \"%s\"", pluginPath);
d_stdout("oscPathControl: \"%s\"", oscPathControl);

#if DISTRHO_PLUGIN_WANT_PROGRAMS
char oscPathProgram[oscPathSize+9];
strcpy(oscPathProgram, oscPath);
strcat(oscPathProgram, "/program");
lo_server_add_method(oscServer, oscPathProgram, "ii", osc_program_handler, nullptr);
#endif

char oscPathSampleRate[oscPathSize+13];
strcpy(oscPathSampleRate, oscPath);
strcat(oscPathSampleRate, "/sample-rate");
lo_server_add_method(oscServer, oscPathSampleRate, "i", osc_sample_rate_handler, nullptr);

char oscPathShow[oscPathSize+6];
strcpy(oscPathShow, oscPath);
strcat(oscPathShow, "/show");
lo_server_add_method(oscServer, oscPathShow, "", osc_show_handler, nullptr);

char oscPathHide[oscPathSize+6];
strcpy(oscPathHide, oscPath);
strcat(oscPathHide, "/hide");
lo_server_add_method(oscServer, oscPathHide, "", osc_hide_handler, nullptr);

char oscPathQuit[oscPathSize+6];
strcpy(oscPathQuit, oscPath);
strcat(oscPathQuit, "/quit");
lo_server_add_method(oscServer, oscPathQuit, "", osc_quit_handler, nullptr);

lo_server_add_method(oscServer, nullptr, nullptr, osc_debug_handler, nullptr);

gUiTitle = uiTitle;

gOscData.addr = oscAddr;
gOscData.path = oscPath;
gOscData.server = oscServer;
gOscData.send_update(pluginPath);

// wait for init
for (int i=0; i < 100; ++i)
{
lo_server_recv(oscServer);

if (d_lastUiSampleRate != 0.0 || globalUI != nullptr)
break;

d_msleep(50);
}

int ret = 1;

if (d_lastUiSampleRate != 0.0 || globalUI != nullptr)
{
initUiIfNeeded();

globalUI->exec();

delete globalUI;
globalUI = nullptr;

ret = 0;
}

#if DISTRHO_PLUGIN_WANT_STATE
lo_server_del_method(oscServer, oscPathConfigure, "ss");
#endif
lo_server_del_method(oscServer, oscPathControl, "if");
#if DISTRHO_PLUGIN_WANT_PROGRAMS
lo_server_del_method(oscServer, oscPathProgram, "ii");
#endif
lo_server_del_method(oscServer, oscPathSampleRate, "i");
lo_server_del_method(oscServer, oscPathShow, "");
lo_server_del_method(oscServer, oscPathHide, "");
lo_server_del_method(oscServer, oscPathQuit, "");
lo_server_del_method(oscServer, nullptr, nullptr);

std::free(oscServerPath);
std::free(oscHost);
std::free(oscPort);
std::free(oscPath);

lo_address_free(oscAddr);
lo_server_free(oscServer);

return ret;
}

+ 0
- 393
distrho/src/DistrhoUIInternal.hpp View File

@@ -1,393 +0,0 @@
/*
* 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_UI_INTERNAL_HPP_INCLUDED
#define DISTRHO_UI_INTERNAL_HPP_INCLUDED

#include "../DistrhoUI.hpp"
#include "../../dgl/App.hpp"
#include "../../dgl/Window.hpp"

using DGL::App;
using DGL::IdleCallback;
using DGL::Window;

START_NAMESPACE_DISTRHO

// -----------------------------------------------------------------------
// Static data, see DistrhoUI.cpp

extern double d_lastUiSampleRate;
extern void* d_lastUiDspPtr;
extern Window* d_lastUiWindow;

// -----------------------------------------------------------------------
// UI callbacks

typedef void (*editParamFunc) (void* ptr, uint32_t rindex, bool started);
typedef void (*setParamFunc) (void* ptr, uint32_t rindex, float value);
typedef void (*setStateFunc) (void* ptr, const char* key, const char* value);
typedef void (*sendNoteFunc) (void* ptr, uint8_t channel, uint8_t note, uint8_t velo);
typedef void (*setSizeFunc) (void* ptr, uint width, uint height);

// -----------------------------------------------------------------------
// UI private data

struct UI::PrivateData {
// DSP
double sampleRate;
uint32_t parameterOffset;
#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
void* dspPtr;
#endif

// Callbacks
editParamFunc editParamCallbackFunc;
setParamFunc setParamCallbackFunc;
setStateFunc setStateCallbackFunc;
sendNoteFunc sendNoteCallbackFunc;
setSizeFunc setSizeCallbackFunc;
void* ptr;

PrivateData() noexcept
: sampleRate(d_lastUiSampleRate),
parameterOffset(0),
#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
dspPtr(d_lastUiDspPtr),
#endif
editParamCallbackFunc(nullptr),
setParamCallbackFunc(nullptr),
setStateCallbackFunc(nullptr),
sendNoteCallbackFunc(nullptr),
setSizeCallbackFunc(nullptr),
ptr(nullptr)
{
DISTRHO_SAFE_ASSERT(d_isNotZero(sampleRate));

#if defined(DISTRHO_PLUGIN_TARGET_DSSI) || defined(DISTRHO_PLUGIN_TARGET_LV2)
parameterOffset += DISTRHO_PLUGIN_NUM_INPUTS + DISTRHO_PLUGIN_NUM_OUTPUTS;
# if DISTRHO_PLUGIN_WANT_LATENCY
parameterOffset += 1;
# endif
#endif

#ifdef DISTRHO_PLUGIN_TARGET_LV2
# if (DISTRHO_PLUGIN_IS_SYNTH || DISTRHO_PLUGIN_WANT_TIMEPOS || DISTRHO_PLUGIN_WANT_STATE)
parameterOffset += 1;
# if DISTRHO_PLUGIN_WANT_STATE
parameterOffset += 1;
# endif
# endif
#endif
}

void editParamCallback(const uint32_t rindex, const bool started)
{
if (editParamCallbackFunc != nullptr)
editParamCallbackFunc(ptr, rindex, started);
}

void setParamCallback(const uint32_t rindex, const float value)
{
if (setParamCallbackFunc != nullptr)
setParamCallbackFunc(ptr, rindex, value);
}

void setStateCallback(const char* const key, const char* const value)
{
if (setStateCallbackFunc != nullptr)
setStateCallbackFunc(ptr, key, value);
}

void sendNoteCallback(const uint8_t channel, const uint8_t note, const uint8_t velocity)
{
if (sendNoteCallbackFunc != nullptr)
sendNoteCallbackFunc(ptr, channel, note, velocity);
}

void setSizeCallback(const uint width, const uint height)
{
if (setSizeCallbackFunc != nullptr)
setSizeCallbackFunc(ptr, width, height);
}
};

// -----------------------------------------------------------------------
// Plugin Window, needed to take care of resize properly

static inline
UI* createUiWrapper(void* const dspPtr, Window* const window)
{
d_lastUiDspPtr = dspPtr;
d_lastUiWindow = window;
UI* const ret = createUI();
d_lastUiDspPtr = nullptr;
d_lastUiWindow = nullptr;
return ret;
}

class UIExporterWindow : public Window
{
public:
UIExporterWindow(App& app, const intptr_t winId, void* const dspPtr)
: Window(app, winId),
fUI(createUiWrapper(dspPtr, this)),
fIsReady(false)
{
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,);

// set window size
setResizable(false);
setSize(fUI->getWidth(), fUI->getHeight());
}

~UIExporterWindow()
{
delete fUI;
}

UI* getUI() const noexcept
{
return fUI;
}

bool isReady() const noexcept
{
return fIsReady;
}

protected:
// custom window reshape
void onReshape(uint width, uint height) override
{
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,);

fUI->d_uiReshape(width, height);
fIsReady = true;
}

// custom file-browser selected
void fileBrowserSelected(const char* filename) override
{
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,);

fUI->d_uiFileBrowserSelected(filename);
}

private:
UI* const fUI;
bool fIsReady;
};

// -----------------------------------------------------------------------
// UI exporter class

class UIExporter
{
public:
UIExporter(void* const ptr, const intptr_t winId,
const editParamFunc editParamCall, const setParamFunc setParamCall, const setStateFunc setStateCall, const sendNoteFunc sendNoteCall, const setSizeFunc setSizeCall,
void* const dspPtr = nullptr)
: glApp(),
glWindow(glApp, winId, dspPtr),
fChangingSize(false),
fUI(glWindow.getUI()),
fData((fUI != nullptr) ? fUI->pData : nullptr)
{
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,);
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,);

fData->ptr = ptr;
fData->editParamCallbackFunc = editParamCall;
fData->setParamCallbackFunc = setParamCall;
fData->setStateCallbackFunc = setStateCall;
fData->sendNoteCallbackFunc = sendNoteCall;
fData->setSizeCallbackFunc = setSizeCall;
}

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

uint getWidth() const noexcept
{
return glWindow.getWidth();
}

uint getHeight() const noexcept
{
return glWindow.getHeight();
}

bool isVisible() const noexcept
{
return glWindow.isVisible();
}

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

intptr_t getWindowId() const noexcept
{
return glWindow.getWindowId();
}

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

uint32_t getParameterOffset() const noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0);

return fData->parameterOffset;
}

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

void parameterChanged(const uint32_t index, const float value)
{
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,);

fUI->d_parameterChanged(index, value);
}

#if DISTRHO_PLUGIN_WANT_PROGRAMS
void programChanged(const uint32_t index)
{
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,);

fUI->d_programChanged(index);
}
#endif

#if DISTRHO_PLUGIN_WANT_STATE
void stateChanged(const char* const key, const char* const value)
{
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,);
DISTRHO_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',);
DISTRHO_SAFE_ASSERT_RETURN(value != nullptr,);

fUI->d_stateChanged(key, value);
}
#endif

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

void exec(IdleCallback* const cb)
{
DISTRHO_SAFE_ASSERT_RETURN(cb != nullptr,);
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,);

glWindow.addIdleCallback(cb);
glWindow.setVisible(true);
glApp.exec();
}

void exec_idle()
{
if (glWindow.isReady())
fUI->d_uiIdle();
}

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

glApp.idle();

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

return ! glApp.isQuiting();
}

void quit()
{
glWindow.close();
glApp.quit();
}

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

void setWindowSize(const uint width, const uint height, const bool updateUI = false)
{
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,);
DISTRHO_SAFE_ASSERT_RETURN(! fChangingSize,);

fChangingSize = true;

if (updateUI)
fUI->setSize(width, height);

glWindow.setSize(width, height);

fChangingSize = false;
}

void setWindowTitle(const char* const uiTitle)
{
glWindow.setTitle(uiTitle);
}

void setWindowTransientWinId(const uintptr_t winId)
{
glWindow.setTransientWinId(winId);
}

bool setWindowVisible(const bool yesNo)
{
glWindow.setVisible(yesNo);

return ! glApp.isQuiting();
}

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

void setSampleRate(const double sampleRate, const bool doCallback = false)
{
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,);
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,);
DISTRHO_SAFE_ASSERT(sampleRate > 0.0);

if (d_isEqual(fData->sampleRate, sampleRate))
return;

fData->sampleRate = sampleRate;

if (doCallback)
fUI->d_sampleRateChanged(sampleRate);
}

private:
// -------------------------------------------------------------------
// DGL Application and Window for this widget

App glApp;
UIExporterWindow glWindow;

// prevent recursion
bool fChangingSize;

// -------------------------------------------------------------------
// Widget and DistrhoUI data

UI* const fUI;
UI::PrivateData* const fData;

DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(UIExporter)
};

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

END_NAMESPACE_DISTRHO

#endif // DISTRHO_UI_INTERNAL_HPP_INCLUDED

+ 0
- 536
distrho/src/DistrhoUILV2.cpp View File

@@ -1,536 +0,0 @@
/*
* 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 "DistrhoUIInternal.hpp"

#include "../extra/d_string.hpp"

#include "lv2/atom.h"
#include "lv2/atom-util.h"
#include "lv2/data-access.h"
#include "lv2/instance-access.h"
#include "lv2/options.h"
#include "lv2/ui.h"
#include "lv2/urid.h"
#include "lv2/lv2_kxstudio_properties.h"
#include "lv2/lv2_programs.h"

START_NAMESPACE_DISTRHO

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

class UiLv2
{
public:
UiLv2(const intptr_t winId,
const LV2_Options_Option* options, const LV2_URID_Map* const uridMap, const LV2UI_Resize* const uiResz, const LV2UI_Touch* uiTouch,
const LV2UI_Controller controller, const LV2UI_Write_Function writeFunc,
LV2UI_Widget* const widget, void* const dspPtr)
: fUI(this, winId, editParameterCallback, setParameterCallback, setStateCallback, sendNoteCallback, setSizeCallback, dspPtr),
fUridMap(uridMap),
fUiResize(uiResz),
fUiTouch(uiTouch),
fController(controller),
fWriteFunction(writeFunc),
fEventTransferURID(uridMap->map(uridMap->handle, LV2_ATOM__eventTransfer)),
fKeyValueURID(uridMap->map(uridMap->handle, "urn:distrho:keyValueState")),
fWinIdWasNull(winId == 0)
{
if (fUiResize != nullptr && winId != 0)
fUiResize->ui_resize(fUiResize->handle, fUI.getWidth(), fUI.getHeight());

if (widget != nullptr)
*widget = (LV2UI_Widget*)fUI.getWindowId();

#if DISTRHO_PLUGIN_WANT_STATE
// tell the DSP we're ready to receive msgs
setState("__dpf_ui_data__", "");
#endif

if (winId != 0)
return;

// if winId == 0 then options must not be null
DISTRHO_SAFE_ASSERT_RETURN(options != nullptr,);

const LV2_URID uridWindowTitle(uridMap->map(uridMap->handle, LV2_UI__windowTitle));
const LV2_URID uridTransientWinId(uridMap->map(uridMap->handle, LV2_KXSTUDIO_PROPERTIES__TransientWindowId));

bool hasTitle = false;

for (int i=0; options[i].key != 0; ++i)
{
if (options[i].key == uridTransientWinId)
{
if (options[i].type == uridMap->map(uridMap->handle, LV2_ATOM__Long))
{
if (const int64_t transientWinId = *(const int64_t*)options[i].value)
fUI.setWindowTransientWinId(static_cast<intptr_t>(transientWinId));
}
else
d_stderr("Host provides transientWinId but has wrong value type");
}
else if (options[i].key == uridWindowTitle)
{
if (options[i].type == uridMap->map(uridMap->handle, LV2_ATOM__String))
{
if (const char* const windowTitle = (const char*)options[i].value)
{
hasTitle = true;
fUI.setWindowTitle(windowTitle);
}
}
else
d_stderr("Host provides windowTitle but has wrong value type");
}
}

if (! hasTitle)
fUI.setWindowTitle(DISTRHO_PLUGIN_NAME);
}

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

void lv2ui_port_event(const uint32_t rindex, const uint32_t bufferSize, const uint32_t format, const void* const buffer)
{
if (format == 0)
{
const uint32_t parameterOffset(fUI.getParameterOffset());

DISTRHO_SAFE_ASSERT_RETURN(rindex >= parameterOffset,)
DISTRHO_SAFE_ASSERT_RETURN(bufferSize == sizeof(float),)

const float value(*(const float*)buffer);
fUI.parameterChanged(rindex-parameterOffset, value);
}
#if DISTRHO_PLUGIN_WANT_STATE
else if (format == fEventTransferURID)
{
const LV2_Atom* const atom((const LV2_Atom*)buffer);

DISTRHO_SAFE_ASSERT_RETURN(atom->type == fKeyValueURID,);

const char* const key = (const char*)LV2_ATOM_BODY_CONST(atom);
const char* const value = key+(std::strlen(key)+1);

fUI.stateChanged(key, value);
}
#endif
}

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

int lv2ui_idle()
{
if (fWinIdWasNull)
return (fUI.idle() && fUI.isVisible()) ? 0 : 1;

return fUI.idle() ? 0 : 1;
}

int lv2ui_show()
{
return fUI.setWindowVisible(true) ? 0 : 1;
}

int lv2ui_hide()
{
return fUI.setWindowVisible(false) ? 0 : 1;
}

int lv2ui_resize(uint width, uint height)
{
fUI.setWindowSize(width, height, true);
return 0;
}

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

uint32_t lv2_get_options(LV2_Options_Option* const /*options*/)
{
// currently unused
return LV2_OPTIONS_ERR_UNKNOWN;
}

uint32_t lv2_set_options(const LV2_Options_Option* const options)
{
for (int i=0; options[i].key != 0; ++i)
{
if (options[i].key == fUridMap->map(fUridMap->handle, LV2_CORE__sampleRate))
{
if (options[i].type == fUridMap->map(fUridMap->handle, LV2_ATOM__Double))
{
const double sampleRate(*(const double*)options[i].value);
fUI.setSampleRate(sampleRate);
continue;
}
else
{
d_stderr("Host changed sampleRate but with wrong value type");
continue;
}
}
}

return LV2_OPTIONS_SUCCESS;
}

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

#if DISTRHO_PLUGIN_WANT_PROGRAMS
void lv2ui_select_program(const uint32_t bank, const uint32_t program)
{
const uint32_t realProgram(bank * 128 + program);

fUI.programChanged(realProgram);
}
#endif

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

protected:
void editParameterValue(const uint32_t rindex, const bool started)
{
if (fUiTouch != nullptr && fUiTouch->touch != nullptr)
fUiTouch->touch(fUiTouch->handle, rindex, started);
}

void setParameterValue(const uint32_t rindex, const float value)
{
DISTRHO_SAFE_ASSERT_RETURN(fWriteFunction != nullptr,);

fWriteFunction(fController, rindex, sizeof(float), 0, &value);
}

void setState(const char* const key, const char* const value)
{
DISTRHO_SAFE_ASSERT_RETURN(fWriteFunction != nullptr,);

const uint32_t eventInPortIndex(DISTRHO_PLUGIN_NUM_INPUTS + DISTRHO_PLUGIN_NUM_OUTPUTS);

// join key and value
d_string tmpStr;
tmpStr += key;
tmpStr += "\xff";
tmpStr += value;

tmpStr[std::strlen(key)] = '\0';

// set msg size (key + separator + value + null terminator)
const size_t msgSize(tmpStr.length()+1);

// reserve atom space
const size_t atomSize(lv2_atom_pad_size(sizeof(LV2_Atom) + msgSize));
char atomBuf[atomSize];
std::memset(atomBuf, 0, atomSize);

// set atom info
LV2_Atom* const atom((LV2_Atom*)atomBuf);
atom->size = msgSize;
atom->type = fKeyValueURID;

// set atom data
std::memcpy(atomBuf + sizeof(LV2_Atom), tmpStr.buffer(), msgSize);

// send to DSP side
fWriteFunction(fController, eventInPortIndex, atomSize, fEventTransferURID, atom);
}

void sendNote(const uint8_t /*channel*/, const uint8_t /*note*/, const uint8_t /*velocity*/)
{
}

void setSize(const uint width, const uint height)
{
fUI.setWindowSize(width, height);

if (fUiResize != nullptr && ! fWinIdWasNull)
fUiResize->ui_resize(fUiResize->handle, width, height);
}

private:
UIExporter fUI;

// LV2 features
const LV2_URID_Map* const fUridMap;
const LV2UI_Resize* const fUiResize;
const LV2UI_Touch* const fUiTouch;

// LV2 UI stuff
const LV2UI_Controller fController;
const LV2UI_Write_Function fWriteFunction;

// Need to save this
const LV2_URID fEventTransferURID;
const LV2_URID fKeyValueURID;

// using ui:showInterface if true
bool fWinIdWasNull;

// -------------------------------------------------------------------
// Callbacks

#define uiPtr ((UiLv2*)ptr)

static void editParameterCallback(void* ptr, uint32_t rindex, bool started)
{
uiPtr->editParameterValue(rindex, started);
}

static void setParameterCallback(void* ptr, uint32_t rindex, float value)
{
uiPtr->setParameterValue(rindex, value);
}

static void setStateCallback(void* ptr, const char* key, const char* value)
{
uiPtr->setState(key, value);
}

static void sendNoteCallback(void* ptr, uint8_t channel, uint8_t note, uint8_t velocity)
{
uiPtr->sendNote(channel, note, velocity);
}

static void setSizeCallback(void* ptr, uint width, uint height)
{
uiPtr->setSize(width, height);
}

#undef uiPtr
};

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

static LV2UI_Handle lv2ui_instantiate(const LV2UI_Descriptor*, const char* uri, const char*, LV2UI_Write_Function writeFunction, LV2UI_Controller controller, LV2UI_Widget* widget, const LV2_Feature* const* features)
{
if (uri == nullptr || std::strcmp(uri, DISTRHO_PLUGIN_URI) != 0)
{
d_stderr("Invalid plugin URI");
return nullptr;
}

const LV2_Options_Option* options = nullptr;
const LV2_URID_Map* uridMap = nullptr;
const LV2UI_Resize* uiResize = nullptr;
const LV2UI_Touch* uiTouch = nullptr;
void* parentId = nullptr;
void* instance = nullptr;

#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
# define DISTRHO_DIRECT_ACCESS_URI "urn:distrho:direct-access"

struct LV2_DirectAccess_Interface {
void* (*get_instance_pointer)(LV2_Handle handle);
};
const LV2_Extension_Data_Feature* extData = nullptr;
#endif

for (int i=0; features[i] != nullptr; ++i)
{
if (std::strcmp(features[i]->URI, LV2_OPTIONS__options) == 0)
options = (const LV2_Options_Option*)features[i]->data;
else if (std::strcmp(features[i]->URI, LV2_URID__map) == 0)
uridMap = (const LV2_URID_Map*)features[i]->data;
else if (std::strcmp(features[i]->URI, LV2_UI__resize) == 0)
uiResize = (const LV2UI_Resize*)features[i]->data;
else if (std::strcmp(features[i]->URI, LV2_UI__parent) == 0)
parentId = features[i]->data;
#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
else if (std::strcmp(features[i]->URI, LV2_DATA_ACCESS_URI) == 0)
extData = (const LV2_Extension_Data_Feature*)features[i]->data;
else if (std::strcmp(features[i]->URI, LV2_INSTANCE_ACCESS_URI) == 0)
instance = features[i]->data;
#endif
}

if (options == nullptr && parentId == nullptr)
{
d_stderr("Options feature missing (needed for show-interface), cannot continue!");
return nullptr;
}

if (uridMap == nullptr)
{
d_stderr("URID Map feature missing, cannot continue!");
return nullptr;
}

if (parentId == nullptr)
{
d_stdout("Parent Window Id missing, host should be using ui:showInterface...");
}

#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
if (extData == nullptr || instance == nullptr)
{
d_stderr("Data or instance access missing, cannot continue!");
return nullptr;
}

if (const LV2_DirectAccess_Interface* const directAccess = (const LV2_DirectAccess_Interface*)extData->data_access(DISTRHO_DIRECT_ACCESS_URI))
instance = directAccess->get_instance_pointer(instance);
else
instance = nullptr;

if (instance == nullptr)
{
d_stderr("Failed to get direct access, cannot continue!");
return nullptr;
}
#endif

const intptr_t winId((intptr_t)parentId);

if (options != nullptr)
{
const LV2_URID uridSampleRate(uridMap->map(uridMap->handle, LV2_CORE__sampleRate));

for (int i=0; options[i].key != 0; ++i)
{
if (options[i].key == uridSampleRate)
{
if (options[i].type == uridMap->map(uridMap->handle, LV2_ATOM__Double))
d_lastUiSampleRate = *(const double*)options[i].value;
else
d_stderr("Host provides sampleRate but has wrong value type");

break;
}
}
}

if (d_lastUiSampleRate == 0.0)
{
d_stdout("WARNING: this host does not send sample-rate information for LV2 UIs, using 44100 as fallback (this could be wrong)");
d_lastUiSampleRate = 44100.0;
}

return new UiLv2(winId, options, uridMap, uiResize, uiTouch, controller, writeFunction, widget, instance);
}

#define uiPtr ((UiLv2*)ui)

static void lv2ui_cleanup(LV2UI_Handle ui)
{
delete uiPtr;
}

static void lv2ui_port_event(LV2UI_Handle ui, uint32_t portIndex, uint32_t bufferSize, uint32_t format, const void* buffer)
{
uiPtr->lv2ui_port_event(portIndex, bufferSize, format, buffer);
}

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

static int lv2ui_idle(LV2UI_Handle ui)
{
return uiPtr->lv2ui_idle();
}

static int lv2ui_show(LV2UI_Handle ui)
{
return uiPtr->lv2ui_show();
}

static int lv2ui_hide(LV2UI_Handle ui)
{
return uiPtr->lv2ui_hide();
}

static int lv2ui_resize(LV2UI_Handle ui, int width, int height)
{
DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr, 1);
DISTRHO_SAFE_ASSERT_RETURN(width > 0, 1);
DISTRHO_SAFE_ASSERT_RETURN(height > 0, 1);

return 1; // This needs more testing
//return uiPtr->lv2ui_resize(width, height);
}

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

static uint32_t lv2_get_options(LV2UI_Handle ui, LV2_Options_Option* options)
{
return uiPtr->lv2_get_options(options);
}

static uint32_t lv2_set_options(LV2UI_Handle ui, const LV2_Options_Option* options)
{
return uiPtr->lv2_set_options(options);
}

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

#if DISTRHO_PLUGIN_WANT_PROGRAMS
static void lv2ui_select_program(LV2UI_Handle ui, uint32_t bank, uint32_t program)
{
uiPtr->lv2ui_select_program(bank, program);
}
#endif

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

static const void* lv2ui_extension_data(const char* uri)
{
static const LV2_Options_Interface options = { lv2_get_options, lv2_set_options };
static const LV2UI_Idle_Interface uiIdle = { lv2ui_idle };
static const LV2UI_Show_Interface uiShow = { lv2ui_show, lv2ui_hide };
static const LV2UI_Resize uiResz = { nullptr, lv2ui_resize };

if (std::strcmp(uri, LV2_OPTIONS__interface) == 0)
return &options;
if (std::strcmp(uri, LV2_UI__idleInterface) == 0)
return &uiIdle;
if (std::strcmp(uri, LV2_UI__showInterface) == 0)
return &uiShow;
if (std::strcmp(uri, LV2_UI__resize) == 0)
return &uiResz;

#if DISTRHO_PLUGIN_WANT_PROGRAMS
static const LV2_Programs_UI_Interface uiPrograms = { lv2ui_select_program };

if (std::strcmp(uri, LV2_PROGRAMS__UIInterface) == 0)
return &uiPrograms;
#endif

return nullptr;
}

#undef instancePtr

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

static const LV2UI_Descriptor sLv2UiDescriptor = {
DISTRHO_UI_URI,
lv2ui_instantiate,
lv2ui_cleanup,
lv2ui_port_event,
lv2ui_extension_data
};

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

END_NAMESPACE_DISTRHO

DISTRHO_PLUGIN_EXPORT
const LV2UI_Descriptor* lv2ui_descriptor(uint32_t index)
{
USE_NAMESPACE_DISTRHO
return (index == 0) ? &sLv2UiDescriptor : nullptr;
}

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

+ 0
- 441
distrho/src/dssi/dssi.h View File

@@ -1,441 +0,0 @@
/* -*- c-basic-offset: 4 -*- */

/* dssi.h

DSSI version 1.0
Copyright (c) 2004, 2009 Chris Cannam, Steve Harris and Sean Bolton
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public License
as published by the Free Software Foundation; either version 2.1 of
the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301 USA
*/

#ifndef DSSI_INCLUDED
#define DSSI_INCLUDED

#include "../ladspa/ladspa.h"
#include "seq_event-compat.h"

#define DSSI_VERSION "1.0"
#define DSSI_VERSION_MAJOR 1
#define DSSI_VERSION_MINOR 0

#ifdef __cplusplus
extern "C" {
#endif

/*
There is a need for an API that supports hosted MIDI soft synths
with GUIs in Linux audio applications. In time the GMPI initiative
should comprehensively address this need, but the requirement for
Linux applications to be able to support simple hosted synths is
here now, and GMPI is not. This proposal (the "DSSI Soft Synth
Interface" or DSSI, pronounced "dizzy") aims to provide a simple
solution in a way that we hope will prove complete and compelling
enough to support now, yet not so compelling as to supplant GMPI or
any other comprehensive future proposal.

For simplicity and familiarity, this API is based as far as
possible on existing work -- the LADSPA plugin API for control
values and audio processing, and the ALSA sequencer event types for
MIDI event communication. The GUI part of the proposal is quite
new, but may also be applicable retroactively to LADSPA plugins
that do not otherwise support this synth interface.
*/

typedef struct _DSSI_Program_Descriptor {

/** Bank number for this program. Note that DSSI does not support
MIDI-style separation of bank LSB and MSB values. There is no
restriction on the set of available banks: the numbers do not
need to be contiguous, there does not need to be a bank 0, etc. */
unsigned long Bank;

/** Program number (unique within its bank) for this program.
There is no restriction on the set of available programs: the
numbers do not need to be contiguous, there does not need to
be a program 0, etc. */
unsigned long Program;

/** Name of the program. */
const char * Name;

} DSSI_Program_Descriptor;


typedef struct _DSSI_Descriptor {

/**
* DSSI_API_Version
*
* This member indicates the DSSI API level used by this plugin.
* If we're lucky, this will never be needed. For now all plugins
* must set it to 1.
*/
int DSSI_API_Version;

/**
* LADSPA_Plugin
*
* A DSSI synth plugin consists of a LADSPA plugin plus an
* additional framework for controlling program settings and
* transmitting MIDI events. A plugin must fully implement the
* LADSPA descriptor fields as well as the required LADSPA
* functions including instantiate() and (de)activate(). It
* should also implement run(), with the same behaviour as if
* run_synth() (below) were called with no synth events.
*
* In order to instantiate a synth the host calls the LADSPA
* instantiate function, passing in this LADSPA_Descriptor
* pointer. The returned LADSPA_Handle is used as the argument
* for the DSSI functions below as well as for the LADSPA ones.
*/
const LADSPA_Descriptor *LADSPA_Plugin;

/**
* configure()
*
* This member is a function pointer that sends a piece of
* configuration data to the plugin. The key argument specifies
* some aspect of the synth's configuration that is to be changed,
* and the value argument specifies a new value for it. A plugin
* that does not require this facility at all may set this member
* to NULL.
*
* This call is intended to set some session-scoped aspect of a
* plugin's behaviour, for example to tell the plugin to load
* sample data from a particular file. The plugin should act
* immediately on the request. The call should return NULL on
* success, or an error string that may be shown to the user. The
* host will free the returned value after use if it is non-NULL.
*
* Calls to configure() are not automated as timed events.
* Instead, a host should remember the last value associated with
* each key passed to configure() during a given session for a
* given plugin instance, and should call configure() with the
* correct value for each key the next time it instantiates the
* "same" plugin instance, for example on reloading a project in
* which the plugin was used before. Plugins should note that a
* host may typically instantiate a plugin multiple times with the
* same configuration values, and should share data between
* instances where practical.
*
* Calling configure() completely invalidates the program and bank
* information last obtained from the plugin.
*
* Reserved and special key prefixes
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* The DSSI: prefix
* ----------------
* Configure keys starting with DSSI: are reserved for particular
* purposes documented in the DSSI specification. At the moment,
* there is one such key: DSSI:PROJECT_DIRECTORY. A host may call
* configure() passing this key and a directory path value. This
* indicates to the plugin and its UI that a directory at that
* path exists and may be used for project-local data. Plugins
* may wish to use the project directory as a fallback location
* when looking for other file data, or as a base for relative
* paths in other configuration values.
*
* The GLOBAL: prefix
* ------------------
* Configure keys starting with GLOBAL: may be used by the plugin
* and its UI for any purpose, but are treated specially by the
* host. When one of these keys is used in a configure OSC call
* from the plugin UI, the host makes the corresponding configure
* call (preserving the GLOBAL: prefix) not only to the target
* plugin but also to all other plugins in the same instance
* group, as well as their UIs. Note that if any instance
* returns non-NULL from configure to indicate error, the host
* may stop there (and the set of plugins on which configure has
* been called will thus depend on the host implementation).
* See also the configure OSC call documentation in RFC.txt.
*/
char *(*configure)(LADSPA_Handle Instance,
const char *Key,
const char *Value);

#define DSSI_RESERVED_CONFIGURE_PREFIX "DSSI:"
#define DSSI_GLOBAL_CONFIGURE_PREFIX "GLOBAL:"
#define DSSI_PROJECT_DIRECTORY_KEY \
DSSI_RESERVED_CONFIGURE_PREFIX "PROJECT_DIRECTORY"

/**
* get_program()
*
* This member is a function pointer that provides a description
* of a program (named preset sound) available on this synth. A
* plugin that does not support programs at all should set this
* member to NULL.
*
* The Index argument is an index into the plugin's list of
* programs, not a program number as represented by the Program
* field of the DSSI_Program_Descriptor. (This distinction is
* needed to support synths that use non-contiguous program or
* bank numbers.)
*
* This function returns a DSSI_Program_Descriptor pointer that is
* guaranteed to be valid only until the next call to get_program,
* deactivate, or configure, on the same plugin instance. This
* function must return NULL if passed an Index argument out of
* range, so that the host can use it to query the number of
* programs as well as their properties.
*/
const DSSI_Program_Descriptor *(*get_program)(LADSPA_Handle Instance,
unsigned long Index);
/**
* select_program()
*
* This member is a function pointer that selects a new program
* for this synth. The program change should take effect
* immediately at the start of the next run_synth() call. (This
* means that a host providing the capability of changing programs
* between any two notes on a track must vary the block size so as
* to place the program change at the right place. A host that
* wanted to avoid this would probably just instantiate a plugin
* for each program.)
*
* A plugin that does not support programs at all should set this
* member NULL. Plugins should ignore a select_program() call
* with an invalid bank or program.
*
* A plugin is not required to select any particular default
* program on activate(): it's the host's duty to set a program
* explicitly. The current program is invalidated by any call to
* configure().
*
* A plugin is permitted to re-write the values of its input
* control ports when select_program is called. The host should
* re-read the input control port values and update its own
* records appropriately. (This is the only circumstance in
* which a DSSI plugin is allowed to modify its own input ports.)
*/
void (*select_program)(LADSPA_Handle Instance,
unsigned long Bank,
unsigned long Program);

/**
* get_midi_controller_for_port()
*
* This member is a function pointer that returns the MIDI
* controller number or NRPN that should be mapped to the given
* input control port. If the given port should not have any MIDI
* controller mapped to it, the function should return DSSI_NONE.
* The behaviour of this function is undefined if the given port
* number does not correspond to an input control port. A plugin
* that does not want MIDI controllers mapped to ports at all may
* set this member NULL.
*
* Correct values can be got using the macros DSSI_CC(num) and
* DSSI_NRPN(num) as appropriate, and values can be combined using
* bitwise OR: e.g. DSSI_CC(23) | DSSI_NRPN(1069) means the port
* should respond to CC #23 and NRPN #1069.
*
* The host is responsible for doing proper scaling from MIDI
* controller and NRPN value ranges to port ranges according to
* the plugin's LADSPA port hints. Hosts should not deliver
* through run_synth any MIDI controller events that have already
* been mapped to control port values.
*
* A plugin should not attempt to request mappings from
* controllers 0 or 32 (MIDI Bank Select MSB and LSB).
*/
int (*get_midi_controller_for_port)(LADSPA_Handle Instance,
unsigned long Port);

/**
* run_synth()
*
* This member is a function pointer that runs a synth for a
* block. This is identical in function to the LADSPA run()
* function, except that it also supplies events to the synth.
*
* A plugin may provide this function, run_multiple_synths() (see
* below), both, or neither (if it is not in fact a synth). A
* plugin that does not provide this function must set this member
* to NULL. Authors of synth plugins are encouraged to provide
* this function if at all possible.
*
* The Events pointer points to a block of EventCount ALSA
* sequencer events, which is used to communicate MIDI and related
* events to the synth. Each event is timestamped relative to the
* start of the block, (mis)using the ALSA "tick time" field as a
* frame count. The host is responsible for ensuring that events
* with differing timestamps are already ordered by time.
*
* See also the notes on activation, port connection etc in
* ladpsa.h, in the context of the LADSPA run() function.
*
* Note Events
* ~~~~~~~~~~~
* There are two minor requirements aimed at making the plugin
* writer's life as simple as possible:
*
* 1. A host must never send events of type SND_SEQ_EVENT_NOTE.
* Notes should always be sent as separate SND_SEQ_EVENT_NOTE_ON
* and NOTE_OFF events. A plugin should discard any one-point
* NOTE events it sees.
*
* 2. A host must not attempt to switch notes off by sending
* zero-velocity NOTE_ON events. It should always send true
* NOTE_OFFs. It is the host's responsibility to remap events in
* cases where an external MIDI source has sent it zero-velocity
* NOTE_ONs.
*
* Bank and Program Events
* ~~~~~~~~~~~~~~~~~~~~~~~
* Hosts must map MIDI Bank Select MSB and LSB (0 and 32)
* controllers and MIDI Program Change events onto the banks and
* programs specified by the plugin, using the DSSI select_program
* call. No host should ever deliver a program change or bank
* select controller to a plugin via run_synth.
*/
void (*run_synth)(LADSPA_Handle Instance,
unsigned long SampleCount,
snd_seq_event_t *Events,
unsigned long EventCount);

/**
* run_synth_adding()
*
* This member is a function pointer that runs an instance of a
* synth for a block, adding its outputs to the values already
* present at the output ports. This is provided for symmetry
* with LADSPA run_adding(), and is equally optional. A plugin
* that does not provide it must set this member to NULL.
*/
void (*run_synth_adding)(LADSPA_Handle Instance,
unsigned long SampleCount,
snd_seq_event_t *Events,
unsigned long EventCount);

/**
* run_multiple_synths()
*
* This member is a function pointer that runs multiple synth
* instances for a block. This is very similar to run_synth(),
* except that Instances, Events, and EventCounts each point to
* arrays that hold the LADSPA handles, event buffers, and
* event counts for each of InstanceCount instances. That is,
* Instances points to an array of InstanceCount pointers to
* DSSI plugin instantiations, Events points to an array of
* pointers to each instantiation's respective event list, and
* EventCounts points to an array containing each instantiation's
* respective event count.
*
* A host using this function must guarantee that ALL active
* instances of the plugin are represented in each call to the
* function -- that is, a host may not call run_multiple_synths()
* for some instances of a given plugin and then call run_synth()
* as well for others. 'All .. instances of the plugin' means
* every instance sharing the same LADSPA label and shared object
* (*.so) file (rather than every instance sharing the same *.so).
* 'Active' means any instance for which activate() has been called
* but deactivate() has not.
*
* A plugin may provide this function, run_synths() (see above),
* both, or neither (if it not in fact a synth). A plugin that
* does not provide this function must set this member to NULL.
* Plugin authors implementing run_multiple_synths are strongly
* encouraged to implement run_synth as well if at all possible,
* to aid simplistic hosts, even where it would be less efficient
* to use it.
*/
void (*run_multiple_synths)(unsigned long InstanceCount,
LADSPA_Handle *Instances,
unsigned long SampleCount,
snd_seq_event_t **Events,
unsigned long *EventCounts);

/**
* run_multiple_synths_adding()
*
* This member is a function pointer that runs multiple synth
* instances for a block, adding each synth's outputs to the
* values already present at the output ports. This is provided
* for symmetry with both the DSSI run_multiple_synths() and LADSPA
* run_adding() functions, and is equally optional. A plugin
* that does not provide it must set this member to NULL.
*/
void (*run_multiple_synths_adding)(unsigned long InstanceCount,
LADSPA_Handle *Instances,
unsigned long SampleCount,
snd_seq_event_t **Events,
unsigned long *EventCounts);

/**
* set_custom_data()
*/
int (*set_custom_data)(LADSPA_Handle Instance,
void *Data,
unsigned long DataLength);

/**
* get_custom_data()
*/
int (*get_custom_data)(LADSPA_Handle Instance,
void **Data,
unsigned long *DataLength);

} DSSI_Descriptor;

/**
* DSSI supports a plugin discovery method similar to that of LADSPA:
*
* - DSSI hosts may wish to locate DSSI plugin shared object files by
* searching the paths contained in the DSSI_PATH and LADSPA_PATH
* environment variables, if they are present. Both are expected
* to be colon-separated lists of directories to be searched (in
* order), and DSSI_PATH should be searched first if both variables
* are set.
*
* - Each shared object file containing DSSI plugins must include a
* function dssi_descriptor(), with the following function prototype
* and C-style linkage. Hosts may enumerate the plugin types
* available in the shared object file by repeatedly calling
* this function with successive Index values (beginning from 0),
* until a return value of NULL indicates no more plugin types are
* available. Each non-NULL return is the DSSI_Descriptor
* of a distinct plugin type.
*/

const DSSI_Descriptor *dssi_descriptor(unsigned long Index);
typedef const DSSI_Descriptor *(*DSSI_Descriptor_Function)(unsigned long Index);

/*
* Macros to specify particular MIDI controllers in return values from
* get_midi_controller_for_port()
*/

#define DSSI_CC_BITS 0x20000000
#define DSSI_NRPN_BITS 0x40000000

#define DSSI_NONE -1
#define DSSI_CONTROLLER_IS_SET(n) (DSSI_NONE != (n))

#define DSSI_CC(n) (DSSI_CC_BITS | (n))
#define DSSI_IS_CC(n) (DSSI_CC_BITS & (n))
#define DSSI_CC_NUMBER(n) ((n) & 0x7f)

#define DSSI_NRPN(n) (DSSI_NRPN_BITS | ((n) << 7))
#define DSSI_IS_NRPN(n) (DSSI_NRPN_BITS & (n))
#define DSSI_NRPN_NUMBER(n) (((n) >> 7) & 0x3fff)

#ifdef __cplusplus
}
#endif

#endif /* DSSI_INCLUDED */

+ 0
- 272
distrho/src/dssi/seq_event-compat.h View File

@@ -1,272 +0,0 @@
/*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/

#ifndef __ALSA_SEQ_EVENT_COMPAT_H
#define __ALSA_SEQ_EVENT_COMPAT_H

/**
* Sequencer event data type
*/
typedef unsigned char snd_seq_event_type_t;

/** Sequencer event type */
enum snd_seq_event_type {
/** system status; event data type = #snd_seq_result_t */
SND_SEQ_EVENT_SYSTEM = 0,
/** returned result status; event data type = #snd_seq_result_t */
SND_SEQ_EVENT_RESULT,

/** note on and off with duration; event data type = #snd_seq_ev_note_t */
SND_SEQ_EVENT_NOTE = 5,
/** note on; event data type = #snd_seq_ev_note_t */
SND_SEQ_EVENT_NOTEON,
/** note off; event data type = #snd_seq_ev_note_t */
SND_SEQ_EVENT_NOTEOFF,
/** key pressure change (aftertouch); event data type = #snd_seq_ev_note_t */
SND_SEQ_EVENT_KEYPRESS,

/** controller; event data type = #snd_seq_ev_ctrl_t */
SND_SEQ_EVENT_CONTROLLER = 10,
/** program change; event data type = #snd_seq_ev_ctrl_t */
SND_SEQ_EVENT_PGMCHANGE,
/** channel pressure; event data type = #snd_seq_ev_ctrl_t */
SND_SEQ_EVENT_CHANPRESS,
/** pitchwheel; event data type = #snd_seq_ev_ctrl_t; data is from -8192 to 8191) */
SND_SEQ_EVENT_PITCHBEND,
/** 14 bit controller value; event data type = #snd_seq_ev_ctrl_t */
SND_SEQ_EVENT_CONTROL14,
/** 14 bit NRPN; event data type = #snd_seq_ev_ctrl_t */
SND_SEQ_EVENT_NONREGPARAM,
/** 14 bit RPN; event data type = #snd_seq_ev_ctrl_t */
SND_SEQ_EVENT_REGPARAM,

/** SPP with LSB and MSB values; event data type = #snd_seq_ev_ctrl_t */
SND_SEQ_EVENT_SONGPOS = 20,
/** Song Select with song ID number; event data type = #snd_seq_ev_ctrl_t */
SND_SEQ_EVENT_SONGSEL,
/** midi time code quarter frame; event data type = #snd_seq_ev_ctrl_t */
SND_SEQ_EVENT_QFRAME,
/** SMF Time Signature event; event data type = #snd_seq_ev_ctrl_t */
SND_SEQ_EVENT_TIMESIGN,
/** SMF Key Signature event; event data type = #snd_seq_ev_ctrl_t */
SND_SEQ_EVENT_KEYSIGN,

/** MIDI Real Time Start message; event data type = #snd_seq_ev_queue_control_t */
SND_SEQ_EVENT_START = 30,
/** MIDI Real Time Continue message; event data type = #snd_seq_ev_queue_control_t */
SND_SEQ_EVENT_CONTINUE,
/** MIDI Real Time Stop message; event data type = #snd_seq_ev_queue_control_t */
SND_SEQ_EVENT_STOP,
/** Set tick queue position; event data type = #snd_seq_ev_queue_control_t */
SND_SEQ_EVENT_SETPOS_TICK,
/** Set real-time queue position; event data type = #snd_seq_ev_queue_control_t */
SND_SEQ_EVENT_SETPOS_TIME,
/** (SMF) Tempo event; event data type = #snd_seq_ev_queue_control_t */
SND_SEQ_EVENT_TEMPO,
/** MIDI Real Time Clock message; event data type = #snd_seq_ev_queue_control_t */
SND_SEQ_EVENT_CLOCK,
/** MIDI Real Time Tick message; event data type = #snd_seq_ev_queue_control_t */
SND_SEQ_EVENT_TICK,
/** Queue timer skew; event data type = #snd_seq_ev_queue_control_t */
SND_SEQ_EVENT_QUEUE_SKEW,
/** Sync position changed; event data type = #snd_seq_ev_queue_control_t */
SND_SEQ_EVENT_SYNC_POS,

/** Tune request; event data type = none */
SND_SEQ_EVENT_TUNE_REQUEST = 40,
/** Reset to power-on state; event data type = none */
SND_SEQ_EVENT_RESET,
/** Active sensing event; event data type = none */
SND_SEQ_EVENT_SENSING,

/** Echo-back event; event data type = any type */
SND_SEQ_EVENT_ECHO = 50,
/** OSS emulation raw event; event data type = any type */
SND_SEQ_EVENT_OSS,

/** New client has connected; event data type = #snd_seq_addr_t */
SND_SEQ_EVENT_CLIENT_START = 60,
/** Client has left the system; event data type = #snd_seq_addr_t */
SND_SEQ_EVENT_CLIENT_EXIT,
/** Client status/info has changed; event data type = #snd_seq_addr_t */
SND_SEQ_EVENT_CLIENT_CHANGE,
/** New port was created; event data type = #snd_seq_addr_t */
SND_SEQ_EVENT_PORT_START,
/** Port was deleted from system; event data type = #snd_seq_addr_t */
SND_SEQ_EVENT_PORT_EXIT,
/** Port status/info has changed; event data type = #snd_seq_addr_t */
SND_SEQ_EVENT_PORT_CHANGE,

/** Ports connected; event data type = #snd_seq_connect_t */
SND_SEQ_EVENT_PORT_SUBSCRIBED,
/** Ports disconnected; event data type = #snd_seq_connect_t */
SND_SEQ_EVENT_PORT_UNSUBSCRIBED,

/** user-defined event; event data type = any (fixed size) */
SND_SEQ_EVENT_USR0 = 90,
/** user-defined event; event data type = any (fixed size) */
SND_SEQ_EVENT_USR1,
/** user-defined event; event data type = any (fixed size) */
SND_SEQ_EVENT_USR2,
/** user-defined event; event data type = any (fixed size) */
SND_SEQ_EVENT_USR3,
/** user-defined event; event data type = any (fixed size) */
SND_SEQ_EVENT_USR4,
/** user-defined event; event data type = any (fixed size) */
SND_SEQ_EVENT_USR5,
/** user-defined event; event data type = any (fixed size) */
SND_SEQ_EVENT_USR6,
/** user-defined event; event data type = any (fixed size) */
SND_SEQ_EVENT_USR7,
/** user-defined event; event data type = any (fixed size) */
SND_SEQ_EVENT_USR8,
/** user-defined event; event data type = any (fixed size) */
SND_SEQ_EVENT_USR9,

/** system exclusive data (variable length); event data type = #snd_seq_ev_ext_t */
SND_SEQ_EVENT_SYSEX = 130,
/** error event; event data type = #snd_seq_ev_ext_t */
SND_SEQ_EVENT_BOUNCE,
/** reserved for user apps; event data type = #snd_seq_ev_ext_t */
SND_SEQ_EVENT_USR_VAR0 = 135,
/** reserved for user apps; event data type = #snd_seq_ev_ext_t */
SND_SEQ_EVENT_USR_VAR1,
/** reserved for user apps; event data type = #snd_seq_ev_ext_t */
SND_SEQ_EVENT_USR_VAR2,
/** reserved for user apps; event data type = #snd_seq_ev_ext_t */
SND_SEQ_EVENT_USR_VAR3,
/** reserved for user apps; event data type = #snd_seq_ev_ext_t */
SND_SEQ_EVENT_USR_VAR4,

/** NOP; ignored in any case */
SND_SEQ_EVENT_NONE = 255
};

/** Sequencer event address */
typedef struct snd_seq_addr {
unsigned char client; /**< Client id */
unsigned char port; /**< Port id */
} snd_seq_addr_t;

/** Connection (subscription) between ports */
typedef struct snd_seq_connect {
snd_seq_addr_t sender; /**< sender address */
snd_seq_addr_t dest; /**< destination address */
} snd_seq_connect_t;

/** Real-time data record */
typedef struct snd_seq_real_time {
unsigned int tv_sec; /**< seconds */
unsigned int tv_nsec; /**< nanoseconds */
} snd_seq_real_time_t;

/** (MIDI) Tick-time data record */
typedef unsigned int snd_seq_tick_time_t;

/** unioned time stamp */
typedef union snd_seq_timestamp {
snd_seq_tick_time_t tick; /**< tick-time */
struct snd_seq_real_time time; /**< real-time */
} snd_seq_timestamp_t;

/** Note event */
typedef struct snd_seq_ev_note {
unsigned char channel; /**< channel number */
unsigned char note; /**< note */
unsigned char velocity; /**< velocity */
unsigned char off_velocity; /**< note-off velocity; only for #SND_SEQ_EVENT_NOTE */
unsigned int duration; /**< duration until note-off; only for #SND_SEQ_EVENT_NOTE */
} snd_seq_ev_note_t;

/** Controller event */
typedef struct snd_seq_ev_ctrl {
unsigned char channel; /**< channel number */
unsigned char unused[3]; /**< reserved */
unsigned int param; /**< control parameter */
signed int value; /**< control value */
} snd_seq_ev_ctrl_t;

/** generic set of bytes (12x8 bit) */
typedef struct snd_seq_ev_raw8 {
unsigned char d[12]; /**< 8 bit value */
} snd_seq_ev_raw8_t;

/** generic set of integers (3x32 bit) */
typedef struct snd_seq_ev_raw32 {
unsigned int d[3]; /**< 32 bit value */
} snd_seq_ev_raw32_t;

/** external stored data */
typedef struct snd_seq_ev_ext {
unsigned int len; /**< length of data */
void *ptr; /**< pointer to data (note: can be 64-bit) */
} __attribute__((packed)) snd_seq_ev_ext_t;

/** Result events */
typedef struct snd_seq_result {
int event; /**< processed event type */
int result; /**< status */
} snd_seq_result_t;

/** Queue skew values */
typedef struct snd_seq_queue_skew {
unsigned int value; /**< skew value */
unsigned int base; /**< skew base */
} snd_seq_queue_skew_t;

/** queue timer control */
typedef struct snd_seq_ev_queue_control {
unsigned char queue; /**< affected queue */
unsigned char unused[3]; /**< reserved */
union {
signed int value; /**< affected value (e.g. tempo) */
snd_seq_timestamp_t time; /**< time */
unsigned int position; /**< sync position */
snd_seq_queue_skew_t skew; /**< queue skew */
unsigned int d32[2]; /**< any data */
unsigned char d8[8]; /**< any data */
} param; /**< data value union */
} snd_seq_ev_queue_control_t;

/** Sequencer event */
typedef struct snd_seq_event {
snd_seq_event_type_t type; /**< event type */
unsigned char flags; /**< event flags */
unsigned char tag; /**< tag */

unsigned char queue; /**< schedule queue */
snd_seq_timestamp_t time; /**< schedule time */

snd_seq_addr_t source; /**< source address */
snd_seq_addr_t dest; /**< destination address */

union {
snd_seq_ev_note_t note; /**< note information */
snd_seq_ev_ctrl_t control; /**< MIDI control information */
snd_seq_ev_raw8_t raw8; /**< raw8 data */
snd_seq_ev_raw32_t raw32; /**< raw32 data */
snd_seq_ev_ext_t ext; /**< external data */
snd_seq_ev_queue_control_t queue; /**< queue control */
snd_seq_timestamp_t time; /**< timestamp */
snd_seq_addr_t addr; /**< address */
snd_seq_connect_t connect; /**< connect information */
snd_seq_result_t result; /**< operation result code */
} data; /**< event data... */
} snd_seq_event_t;

#endif /* __ALSA_SEQ_EVENT_COMPAT_H */


+ 0
- 603
distrho/src/ladspa/ladspa.h View File

@@ -1,603 +0,0 @@
/* ladspa.h

Linux Audio Developer's Simple Plugin API Version 1.1[LGPL].
Copyright (C) 2000-2002 Richard W.E. Furse, Paul Barton-Davis,
Stefan Westerfeld.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public License
as published by the Free Software Foundation; either version 2.1 of
the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA. */

#ifndef LADSPA_INCLUDED
#define LADSPA_INCLUDED

#define LADSPA_VERSION "1.1"
#define LADSPA_VERSION_MAJOR 1
#define LADSPA_VERSION_MINOR 1

#ifdef __cplusplus
extern "C" {
#endif

/*****************************************************************************/

/* Overview:

There is a large number of synthesis packages in use or development
on the Linux platform at this time. This API (`The Linux Audio
Developer's Simple Plugin API') attempts to give programmers the
ability to write simple `plugin' audio processors in C/C++ and link
them dynamically (`plug') into a range of these packages (`hosts').
It should be possible for any host and any plugin to communicate
completely through this interface.

This API is deliberately short and simple. To achieve compatibility
with a range of promising Linux sound synthesis packages it
attempts to find the `greatest common divisor' in their logical
behaviour. Having said this, certain limiting decisions are
implicit, notably the use of a fixed type (LADSPA_Data) for all
data transfer and absence of a parameterised `initialisation'
phase. See below for the LADSPA_Data typedef.

Plugins are expected to distinguish between control and audio
data. Plugins have `ports' that are inputs or outputs for audio or
control data and each plugin is `run' for a `block' corresponding
to a short time interval measured in samples. Audio data is
communicated using arrays of LADSPA_Data, allowing a block of audio
to be processed by the plugin in a single pass. Control data is
communicated using single LADSPA_Data values. Control data has a
single value at the start of a call to the `run()' or `run_adding()'
function, and may be considered to remain this value for its
duration. The plugin may assume that all its input and output ports
have been connected to the relevant data location (see the
`connect_port()' function below) before it is asked to run.

Plugins will reside in shared object files suitable for dynamic
linking by dlopen() and family. The file will provide a number of
`plugin types' that can be used to instantiate actual plugins
(sometimes known as `plugin instances') that can be connected
together to perform tasks.

This API contains very limited error-handling. */

/*****************************************************************************/

/* Fundamental data type passed in and out of plugin. This data type
is used to communicate audio samples and control values. It is
assumed that the plugin will work sensibly given any numeric input
value although it may have a preferred range (see hints below).

For audio it is generally assumed that 1.0f is the `0dB' reference
amplitude and is a `normal' signal level. */

typedef float LADSPA_Data;

/*****************************************************************************/

/* Special Plugin Properties:
Optional features of the plugin type are encapsulated in the
LADSPA_Properties type. This is assembled by ORing individual
properties together. */

typedef int LADSPA_Properties;

/* Property LADSPA_PROPERTY_REALTIME indicates that the plugin has a
real-time dependency (e.g. listens to a MIDI device) and so its
output must not be cached or subject to significant latency. */
#define LADSPA_PROPERTY_REALTIME 0x1

/* Property LADSPA_PROPERTY_INPLACE_BROKEN indicates that the plugin
may cease to work correctly if the host elects to use the same data
location for both input and output (see connect_port()). This
should be avoided as enabling this flag makes it impossible for
hosts to use the plugin to process audio `in-place.' */
#define LADSPA_PROPERTY_INPLACE_BROKEN 0x2

/* Property LADSPA_PROPERTY_HARD_RT_CAPABLE indicates that the plugin
is capable of running not only in a conventional host but also in a
`hard real-time' environment. To qualify for this the plugin must
satisfy all of the following:

(1) The plugin must not use malloc(), free() or other heap memory
management within its run() or run_adding() functions. All new
memory used in run() must be managed via the stack. These
restrictions only apply to the run() function.

(2) The plugin will not attempt to make use of any library
functions with the exceptions of functions in the ANSI standard C
and C maths libraries, which the host is expected to provide.

(3) The plugin will not access files, devices, pipes, sockets, IPC
or any other mechanism that might result in process or thread
blocking.
(4) The plugin will take an amount of time to execute a run() or
run_adding() call approximately of form (A+B*SampleCount) where A
and B depend on the machine and host in use. This amount of time
may not depend on input signals or plugin state. The host is left
the responsibility to perform timings to estimate upper bounds for
A and B. */
#define LADSPA_PROPERTY_HARD_RT_CAPABLE 0x4

#define LADSPA_IS_REALTIME(x) ((x) & LADSPA_PROPERTY_REALTIME)
#define LADSPA_IS_INPLACE_BROKEN(x) ((x) & LADSPA_PROPERTY_INPLACE_BROKEN)
#define LADSPA_IS_HARD_RT_CAPABLE(x) ((x) & LADSPA_PROPERTY_HARD_RT_CAPABLE)

/*****************************************************************************/

/* Plugin Ports:

Plugins have `ports' that are inputs or outputs for audio or
data. Ports can communicate arrays of LADSPA_Data (for audio
inputs/outputs) or single LADSPA_Data values (for control
input/outputs). This information is encapsulated in the
LADSPA_PortDescriptor type which is assembled by ORing individual
properties together.

Note that a port must be an input or an output port but not both
and that a port must be a control or audio port but not both. */

typedef int LADSPA_PortDescriptor;

/* Property LADSPA_PORT_INPUT indicates that the port is an input. */
#define LADSPA_PORT_INPUT 0x1

/* Property LADSPA_PORT_OUTPUT indicates that the port is an output. */
#define LADSPA_PORT_OUTPUT 0x2

/* Property LADSPA_PORT_CONTROL indicates that the port is a control
port. */
#define LADSPA_PORT_CONTROL 0x4

/* Property LADSPA_PORT_AUDIO indicates that the port is a audio
port. */
#define LADSPA_PORT_AUDIO 0x8

#define LADSPA_IS_PORT_INPUT(x) ((x) & LADSPA_PORT_INPUT)
#define LADSPA_IS_PORT_OUTPUT(x) ((x) & LADSPA_PORT_OUTPUT)
#define LADSPA_IS_PORT_CONTROL(x) ((x) & LADSPA_PORT_CONTROL)
#define LADSPA_IS_PORT_AUDIO(x) ((x) & LADSPA_PORT_AUDIO)

/*****************************************************************************/

/* Plugin Port Range Hints:

The host may wish to provide a representation of data entering or
leaving a plugin (e.g. to generate a GUI automatically). To make
this more meaningful, the plugin should provide `hints' to the host
describing the usual values taken by the data.
Note that these are only hints. The host may ignore them and the
plugin must not assume that data supplied to it is meaningful. If
the plugin receives invalid input data it is expected to continue
to run without failure and, where possible, produce a sensible
output (e.g. a high-pass filter given a negative cutoff frequency
might switch to an all-pass mode).
Hints are meaningful for all input and output ports but hints for
input control ports are expected to be particularly useful.
More hint information is encapsulated in the
LADSPA_PortRangeHintDescriptor type which is assembled by ORing
individual hint types together. Hints may require further
LowerBound and UpperBound information.

All the hint information for a particular port is aggregated in the
LADSPA_PortRangeHint structure. */

typedef int LADSPA_PortRangeHintDescriptor;

/* Hint LADSPA_HINT_BOUNDED_BELOW indicates that the LowerBound field
of the LADSPA_PortRangeHint should be considered meaningful. The
value in this field should be considered the (inclusive) lower
bound of the valid range. If LADSPA_HINT_SAMPLE_RATE is also
specified then the value of LowerBound should be multiplied by the
sample rate. */
#define LADSPA_HINT_BOUNDED_BELOW 0x1

/* Hint LADSPA_HINT_BOUNDED_ABOVE indicates that the UpperBound field
of the LADSPA_PortRangeHint should be considered meaningful. The
value in this field should be considered the (inclusive) upper
bound of the valid range. If LADSPA_HINT_SAMPLE_RATE is also
specified then the value of UpperBound should be multiplied by the
sample rate. */
#define LADSPA_HINT_BOUNDED_ABOVE 0x2

/* Hint LADSPA_HINT_TOGGLED indicates that the data item should be
considered a Boolean toggle. Data less than or equal to zero should
be considered `off' or `false,' and data above zero should be
considered `on' or `true.' LADSPA_HINT_TOGGLED may not be used in
conjunction with any other hint except LADSPA_HINT_DEFAULT_0 or
LADSPA_HINT_DEFAULT_1. */
#define LADSPA_HINT_TOGGLED 0x4

/* Hint LADSPA_HINT_SAMPLE_RATE indicates that any bounds specified
should be interpreted as multiples of the sample rate. For
instance, a frequency range from 0Hz to the Nyquist frequency (half
the sample rate) could be requested by this hint in conjunction
with LowerBound = 0 and UpperBound = 0.5. Hosts that support bounds
at all must support this hint to retain meaning. */
#define LADSPA_HINT_SAMPLE_RATE 0x8

/* Hint LADSPA_HINT_LOGARITHMIC indicates that it is likely that the
user will find it more intuitive to view values using a logarithmic
scale. This is particularly useful for frequencies and gains. */
#define LADSPA_HINT_LOGARITHMIC 0x10

/* Hint LADSPA_HINT_INTEGER indicates that a user interface would
probably wish to provide a stepped control taking only integer
values. Any bounds set should be slightly wider than the actual
integer range required to avoid floating point rounding errors. For
instance, the integer set {0,1,2,3} might be described as [-0.1,
3.1]. */
#define LADSPA_HINT_INTEGER 0x20

/* The various LADSPA_HINT_HAS_DEFAULT_* hints indicate a `normal'
value for the port that is sensible as a default. For instance,
this value is suitable for use as an initial value in a user
interface or as a value the host might assign to a control port
when the user has not provided one. Defaults are encoded using a
mask so only one default may be specified for a port. Some of the
hints make use of lower and upper bounds, in which case the
relevant bound or bounds must be available and
LADSPA_HINT_SAMPLE_RATE must be applied as usual. The resulting
default must be rounded if LADSPA_HINT_INTEGER is present. Default
values were introduced in LADSPA v1.1. */
#define LADSPA_HINT_DEFAULT_MASK 0x3C0

/* This default values indicates that no default is provided. */
#define LADSPA_HINT_DEFAULT_NONE 0x0

/* This default hint indicates that the suggested lower bound for the
port should be used. */
#define LADSPA_HINT_DEFAULT_MINIMUM 0x40

/* This default hint indicates that a low value between the suggested
lower and upper bounds should be chosen. For ports with
LADSPA_HINT_LOGARITHMIC, this should be exp(log(lower) * 0.75 +
log(upper) * 0.25). Otherwise, this should be (lower * 0.75 + upper
* 0.25). */
#define LADSPA_HINT_DEFAULT_LOW 0x80

/* This default hint indicates that a middle value between the
suggested lower and upper bounds should be chosen. For ports with
LADSPA_HINT_LOGARITHMIC, this should be exp(log(lower) * 0.5 +
log(upper) * 0.5). Otherwise, this should be (lower * 0.5 + upper *
0.5). */
#define LADSPA_HINT_DEFAULT_MIDDLE 0xC0

/* This default hint indicates that a high value between the suggested
lower and upper bounds should be chosen. For ports with
LADSPA_HINT_LOGARITHMIC, this should be exp(log(lower) * 0.25 +
log(upper) * 0.75). Otherwise, this should be (lower * 0.25 + upper
* 0.75). */
#define LADSPA_HINT_DEFAULT_HIGH 0x100

/* This default hint indicates that the suggested upper bound for the
port should be used. */
#define LADSPA_HINT_DEFAULT_MAXIMUM 0x140

/* This default hint indicates that the number 0 should be used. Note
that this default may be used in conjunction with
LADSPA_HINT_TOGGLED. */
#define LADSPA_HINT_DEFAULT_0 0x200

/* This default hint indicates that the number 1 should be used. Note
that this default may be used in conjunction with
LADSPA_HINT_TOGGLED. */
#define LADSPA_HINT_DEFAULT_1 0x240

/* This default hint indicates that the number 100 should be used. */
#define LADSPA_HINT_DEFAULT_100 0x280

/* This default hint indicates that the Hz frequency of `concert A'
should be used. This will be 440 unless the host uses an unusual
tuning convention, in which case it may be within a few Hz. */
#define LADSPA_HINT_DEFAULT_440 0x2C0

#define LADSPA_IS_HINT_BOUNDED_BELOW(x) ((x) & LADSPA_HINT_BOUNDED_BELOW)
#define LADSPA_IS_HINT_BOUNDED_ABOVE(x) ((x) & LADSPA_HINT_BOUNDED_ABOVE)
#define LADSPA_IS_HINT_TOGGLED(x) ((x) & LADSPA_HINT_TOGGLED)
#define LADSPA_IS_HINT_SAMPLE_RATE(x) ((x) & LADSPA_HINT_SAMPLE_RATE)
#define LADSPA_IS_HINT_LOGARITHMIC(x) ((x) & LADSPA_HINT_LOGARITHMIC)
#define LADSPA_IS_HINT_INTEGER(x) ((x) & LADSPA_HINT_INTEGER)

#define LADSPA_IS_HINT_HAS_DEFAULT(x) ((x) & LADSPA_HINT_DEFAULT_MASK)
#define LADSPA_IS_HINT_DEFAULT_MINIMUM(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \
== LADSPA_HINT_DEFAULT_MINIMUM)
#define LADSPA_IS_HINT_DEFAULT_LOW(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \
== LADSPA_HINT_DEFAULT_LOW)
#define LADSPA_IS_HINT_DEFAULT_MIDDLE(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \
== LADSPA_HINT_DEFAULT_MIDDLE)
#define LADSPA_IS_HINT_DEFAULT_HIGH(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \
== LADSPA_HINT_DEFAULT_HIGH)
#define LADSPA_IS_HINT_DEFAULT_MAXIMUM(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \
== LADSPA_HINT_DEFAULT_MAXIMUM)
#define LADSPA_IS_HINT_DEFAULT_0(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \
== LADSPA_HINT_DEFAULT_0)
#define LADSPA_IS_HINT_DEFAULT_1(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \
== LADSPA_HINT_DEFAULT_1)
#define LADSPA_IS_HINT_DEFAULT_100(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \
== LADSPA_HINT_DEFAULT_100)
#define LADSPA_IS_HINT_DEFAULT_440(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \
== LADSPA_HINT_DEFAULT_440)

typedef struct _LADSPA_PortRangeHint {

/* Hints about the port. */
LADSPA_PortRangeHintDescriptor HintDescriptor;

/* Meaningful when hint LADSPA_HINT_BOUNDED_BELOW is active. When
LADSPA_HINT_SAMPLE_RATE is also active then this value should be
multiplied by the relevant sample rate. */
LADSPA_Data LowerBound;

/* Meaningful when hint LADSPA_HINT_BOUNDED_ABOVE is active. When
LADSPA_HINT_SAMPLE_RATE is also active then this value should be
multiplied by the relevant sample rate. */
LADSPA_Data UpperBound;

} LADSPA_PortRangeHint;

/*****************************************************************************/

/* Plugin Handles:

This plugin handle indicates a particular instance of the plugin
concerned. It is valid to compare this to NULL (0 for C++) but
otherwise the host should not attempt to interpret it. The plugin
may use it to reference internal instance data. */

typedef void * LADSPA_Handle;

/*****************************************************************************/

/* Descriptor for a Type of Plugin:

This structure is used to describe a plugin type. It provides a
number of functions to examine the type, instantiate it, link it to
buffers and workspaces and to run it. */

typedef struct _LADSPA_Descriptor {

/* This numeric identifier indicates the plugin type
uniquely. Plugin programmers may reserve ranges of IDs from a
central body to avoid clashes. Hosts may assume that IDs are
below 0x1000000. */
unsigned long UniqueID;

/* This identifier can be used as a unique, case-sensitive
identifier for the plugin type within the plugin file. Plugin
types should be identified by file and label rather than by index
or plugin name, which may be changed in new plugin
versions. Labels must not contain white-space characters. */
const char * Label;

/* This indicates a number of properties of the plugin. */
LADSPA_Properties Properties;

/* This member points to the null-terminated name of the plugin
(e.g. "Sine Oscillator"). */
const char * Name;

/* This member points to the null-terminated string indicating the
maker of the plugin. This can be an empty string but not NULL. */
const char * Maker;

/* This member points to the null-terminated string indicating any
copyright applying to the plugin. If no Copyright applies the
string "None" should be used. */
const char * Copyright;

/* This indicates the number of ports (input AND output) present on
the plugin. */
unsigned long PortCount;

/* This member indicates an array of port descriptors. Valid indices
vary from 0 to PortCount-1. */
const LADSPA_PortDescriptor * PortDescriptors;

/* This member indicates an array of null-terminated strings
describing ports (e.g. "Frequency (Hz)"). Valid indices vary from
0 to PortCount-1. */
const char * const * PortNames;

/* This member indicates an array of range hints for each port (see
above). Valid indices vary from 0 to PortCount-1. */
const LADSPA_PortRangeHint * PortRangeHints;

/* This may be used by the plugin developer to pass any custom
implementation data into an instantiate call. It must not be used
or interpreted by the host. It is expected that most plugin
writers will not use this facility as LADSPA_Handle should be
used to hold instance data. */
void * ImplementationData;

/* This member is a function pointer that instantiates a plugin. A
handle is returned indicating the new plugin instance. The
instantiation function accepts a sample rate as a parameter. The
plugin descriptor from which this instantiate function was found
must also be passed. This function must return NULL if
instantiation fails.

Note that instance initialisation should generally occur in
activate() rather than here. */
LADSPA_Handle (*instantiate)(const struct _LADSPA_Descriptor * Descriptor,
unsigned long SampleRate);

/* This member is a function pointer that connects a port on an
instantiated plugin to a memory location at which a block of data
for the port will be read/written. The data location is expected
to be an array of LADSPA_Data for audio ports or a single
LADSPA_Data value for control ports. Memory issues will be
managed by the host. The plugin must read/write the data at these
locations every time run() or run_adding() is called and the data
present at the time of this connection call should not be
considered meaningful.

connect_port() may be called more than once for a plugin instance
to allow the host to change the buffers that the plugin is
reading or writing. These calls may be made before or after
activate() or deactivate() calls.

connect_port() must be called at least once for each port before
run() or run_adding() is called. When working with blocks of
LADSPA_Data the plugin should pay careful attention to the block
size passed to the run function as the block allocated may only
just be large enough to contain the block of samples.

Plugin writers should be aware that the host may elect to use the
same buffer for more than one port and even use the same buffer
for both input and output (see LADSPA_PROPERTY_INPLACE_BROKEN).
However, overlapped buffers or use of a single buffer for both
audio and control data may result in unexpected behaviour. */
void (*connect_port)(LADSPA_Handle Instance,
unsigned long Port,
LADSPA_Data * DataLocation);

/* This member is a function pointer that initialises a plugin
instance and activates it for use. This is separated from
instantiate() to aid real-time support and so that hosts can
reinitialise a plugin instance by calling deactivate() and then
activate(). In this case the plugin instance must reset all state
information dependent on the history of the plugin instance
except for any data locations provided by connect_port() and any
gain set by set_run_adding_gain(). If there is nothing for
activate() to do then the plugin writer may provide a NULL rather
than an empty function.

When present, hosts must call this function once before run() (or
run_adding()) is called for the first time. This call should be
made as close to the run() call as possible and indicates to
real-time plugins that they are now live. Plugins should not rely
on a prompt call to run() after activate(). activate() may not be
called again unless deactivate() is called first. Note that
connect_port() may be called before or after a call to
activate(). */
void (*activate)(LADSPA_Handle Instance);

/* This method is a function pointer that runs an instance of a
plugin for a block. Two parameters are required: the first is a
handle to the particular instance to be run and the second
indicates the block size (in samples) for which the plugin
instance may run.

Note that if an activate() function exists then it must be called
before run() or run_adding(). If deactivate() is called for a
plugin instance then the plugin instance may not be reused until
activate() has been called again.

If the plugin has the property LADSPA_PROPERTY_HARD_RT_CAPABLE
then there are various things that the plugin should not do
within the run() or run_adding() functions (see above). */
void (*run)(LADSPA_Handle Instance,
unsigned long SampleCount);

/* This method is a function pointer that runs an instance of a
plugin for a block. This has identical behaviour to run() except
in the way data is output from the plugin. When run() is used,
values are written directly to the memory areas associated with
the output ports. However when run_adding() is called, values
must be added to the values already present in the memory
areas. Furthermore, output values written must be scaled by the
current gain set by set_run_adding_gain() (see below) before
addition.

run_adding() is optional. When it is not provided by a plugin,
this function pointer must be set to NULL. When it is provided,
the function set_run_adding_gain() must be provided also. */
void (*run_adding)(LADSPA_Handle Instance,
unsigned long SampleCount);

/* This method is a function pointer that sets the output gain for
use when run_adding() is called (see above). If this function is
never called the gain is assumed to default to 1. Gain
information should be retained when activate() or deactivate()
are called.

This function should be provided by the plugin if and only if the
run_adding() function is provided. When it is absent this
function pointer must be set to NULL. */
void (*set_run_adding_gain)(LADSPA_Handle Instance,
LADSPA_Data Gain);

/* This is the counterpart to activate() (see above). If there is
nothing for deactivate() to do then the plugin writer may provide
a NULL rather than an empty function.

Hosts must deactivate all activated units after they have been
run() (or run_adding()) for the last time. This call should be
made as close to the last run() call as possible and indicates to
real-time plugins that they are no longer live. Plugins should
not rely on prompt deactivation. Note that connect_port() may be
called before or after a call to deactivate().

Deactivation is not similar to pausing as the plugin instance
will be reinitialised when activate() is called to reuse it. */
void (*deactivate)(LADSPA_Handle Instance);

/* Once an instance of a plugin has been finished with it can be
deleted using the following function. The instance handle passed
ceases to be valid after this call.
If activate() was called for a plugin instance then a
corresponding call to deactivate() must be made before cleanup()
is called. */
void (*cleanup)(LADSPA_Handle Instance);

} LADSPA_Descriptor;

/**********************************************************************/

/* Accessing a Plugin: */

/* The exact mechanism by which plugins are loaded is host-dependent,
however all most hosts will need to know is the name of shared
object file containing the plugin types. To allow multiple hosts to
share plugin types, hosts may wish to check for environment
variable LADSPA_PATH. If present, this should contain a
colon-separated path indicating directories that should be searched
(in order) when loading plugin types.

A plugin programmer must include a function called
"ladspa_descriptor" with the following function prototype within
the shared object file. This function will have C-style linkage (if
you are using C++ this is taken care of by the `extern "C"' clause
at the top of the file).

A host will find the plugin shared object file by one means or
another, find the ladspa_descriptor() function, call it, and
proceed from there.

Plugin types are accessed by index (not ID) using values from 0
upwards. Out of range indexes must result in this function
returning NULL, so the plugin count can be determined by checking
for the least index that results in NULL being returned. */

const LADSPA_Descriptor * ladspa_descriptor(unsigned long Index);

/* Datatype corresponding to the ladspa_descriptor() function. */
typedef const LADSPA_Descriptor *
(*LADSPA_Descriptor_Function)(unsigned long Index);

/**********************************************************************/

#ifdef __cplusplus
}
#endif

#endif /* LADSPA_INCLUDED */

/* EOF */

+ 0
- 747
distrho/src/lv2/atom-forge.h View File

@@ -1,747 +0,0 @@
/*
Copyright 2008-2013 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 forge.h An API for constructing LV2 atoms.

This file provides an API for constructing Atoms which makes it relatively
simple to build nested atoms of arbitrary complexity without requiring
dynamic memory allocation.

The API is based on successively appending the appropriate pieces to build a
complete Atom. The size of containers is automatically updated. Functions
that begin a container return (via their frame argument) a stack frame which
must be popped when the container is finished.

All output is written to a user-provided buffer or sink function. This
makes it popssible to create create atoms on the stack, on the heap, in LV2
port buffers, in a ringbuffer, or elsewhere, all using the same API.

This entire API is realtime safe if used with a buffer or a realtime safe
sink, except lv2_atom_forge_init() which is only realtime safe if the URI
map function is.

Note these functions are all static inline, do not take their address.

This header is non-normative, it is provided for convenience.
*/

#ifndef LV2_ATOM_FORGE_H
#define LV2_ATOM_FORGE_H

#include <assert.h>

#include "atom.h"
#include "atom-util.h"
#include "urid.h"

#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
# define LV2_ATOM_FORGE_DEPRECATED __attribute__((__deprecated__))
#else
# define LV2_ATOM_FORGE_DEPRECATED
#endif

#ifdef __cplusplus
extern "C" {
#else
# include <stdbool.h>
#endif

/** Handle for LV2_Atom_Forge_Sink. */
typedef void* LV2_Atom_Forge_Sink_Handle;

/** A reference to a chunk of written output. */
typedef intptr_t LV2_Atom_Forge_Ref;

/** Sink function for writing output. See lv2_atom_forge_set_sink(). */
typedef LV2_Atom_Forge_Ref
(*LV2_Atom_Forge_Sink)(LV2_Atom_Forge_Sink_Handle handle,
const void* buf,
uint32_t size);

/** Function for resolving a reference. See lv2_atom_forge_set_sink(). */
typedef LV2_Atom*
(*LV2_Atom_Forge_Deref_Func)(LV2_Atom_Forge_Sink_Handle handle,
LV2_Atom_Forge_Ref ref);

/** A stack frame used for keeping track of nested Atom containers. */
typedef struct _LV2_Atom_Forge_Frame {
struct _LV2_Atom_Forge_Frame* parent;
LV2_Atom_Forge_Ref ref;
} LV2_Atom_Forge_Frame;

/** A "forge" for creating atoms by appending to a buffer. */
typedef struct {
uint8_t* buf;
uint32_t offset;
uint32_t size;

LV2_Atom_Forge_Sink sink;
LV2_Atom_Forge_Deref_Func deref;
LV2_Atom_Forge_Sink_Handle handle;

LV2_Atom_Forge_Frame* stack;

LV2_URID Blank LV2_ATOM_FORGE_DEPRECATED;
LV2_URID Bool;
LV2_URID Chunk;
LV2_URID Double;
LV2_URID Float;
LV2_URID Int;
LV2_URID Long;
LV2_URID Literal;
LV2_URID Object;
LV2_URID Path;
LV2_URID Property;
LV2_URID Resource LV2_ATOM_FORGE_DEPRECATED;
LV2_URID Sequence;
LV2_URID String;
LV2_URID Tuple;
LV2_URID URI;
LV2_URID URID;
LV2_URID Vector;
} LV2_Atom_Forge;

static inline void
lv2_atom_forge_set_buffer(LV2_Atom_Forge* forge, uint8_t* buf, size_t size);

/**
Initialise @p forge.

URIs will be mapped using @p map and stored, a reference to @p map itself is
not held.
*/
static inline void
lv2_atom_forge_init(LV2_Atom_Forge* forge, LV2_URID_Map* map)
{
#if defined(__clang__)
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wdeprecated-declarations"
#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
lv2_atom_forge_set_buffer(forge, NULL, 0);
forge->Blank = map->map(map->handle, LV2_ATOM__Blank);
forge->Bool = map->map(map->handle, LV2_ATOM__Bool);
forge->Chunk = map->map(map->handle, LV2_ATOM__Chunk);
forge->Double = map->map(map->handle, LV2_ATOM__Double);
forge->Float = map->map(map->handle, LV2_ATOM__Float);
forge->Int = map->map(map->handle, LV2_ATOM__Int);
forge->Long = map->map(map->handle, LV2_ATOM__Long);
forge->Literal = map->map(map->handle, LV2_ATOM__Literal);
forge->Object = map->map(map->handle, LV2_ATOM__Object);
forge->Path = map->map(map->handle, LV2_ATOM__Path);
forge->Property = map->map(map->handle, LV2_ATOM__Property);
forge->Resource = map->map(map->handle, LV2_ATOM__Resource);
forge->Sequence = map->map(map->handle, LV2_ATOM__Sequence);
forge->String = map->map(map->handle, LV2_ATOM__String);
forge->Tuple = map->map(map->handle, LV2_ATOM__Tuple);
forge->URI = map->map(map->handle, LV2_ATOM__URI);
forge->URID = map->map(map->handle, LV2_ATOM__URID);
forge->Vector = map->map(map->handle, LV2_ATOM__Vector);
#if defined(__clang__)
# pragma clang diagnostic pop
#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
# pragma GCC diagnostic pop
#endif
}

static inline LV2_Atom*
lv2_atom_forge_deref(LV2_Atom_Forge* forge, LV2_Atom_Forge_Ref ref)
{
if (forge->buf) {
return (LV2_Atom*)ref;
} else {
return forge->deref(forge->handle, ref);
}
}

/**
@name Object Stack
@{
*/

/**
Push a stack frame.
This is done automatically by container functions (which take a stack frame
pointer), but may be called by the user to push the top level container when
writing to an existing Atom.
*/
static inline LV2_Atom_Forge_Ref
lv2_atom_forge_push(LV2_Atom_Forge* forge,
LV2_Atom_Forge_Frame* frame,
LV2_Atom_Forge_Ref ref)
{
frame->parent = forge->stack;
frame->ref = ref;
forge->stack = frame;
return ref;
}

/** Pop a stack frame. This must be called when a container is finished. */
static inline void
lv2_atom_forge_pop(LV2_Atom_Forge* forge, LV2_Atom_Forge_Frame* frame)
{
assert(frame == forge->stack);
forge->stack = frame->parent;
}

/** Return true iff the top of the stack has the given type. */
static inline bool
lv2_atom_forge_top_is(LV2_Atom_Forge* forge, uint32_t type)
{
return forge->stack && forge->stack->ref &&
(lv2_atom_forge_deref(forge, forge->stack->ref)->type == type);
}

/** Return true iff @p type is an atom:Object. */
static inline bool
lv2_atom_forge_is_object_type(const LV2_Atom_Forge* forge, uint32_t type)
{
#if defined(__clang__)
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wdeprecated-declarations"
#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
return (type == forge->Object ||
type == forge->Blank ||
type == forge->Resource);
#if defined(__clang__)
# pragma clang diagnostic pop
#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
# pragma GCC diagnostic pop
#endif
}

/** Return true iff @p type is an atom:Object with a blank ID. */
static inline bool
lv2_atom_forge_is_blank(const LV2_Atom_Forge* forge,
uint32_t type,
const LV2_Atom_Object_Body* body)
{
#if defined(__clang__)
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wdeprecated-declarations"
#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
return (type == forge->Blank ||
(type == forge->Object && body->id == 0));
#if defined(__clang__)
# pragma clang diagnostic pop
#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
# pragma GCC diagnostic pop
#endif
}

/**
@}
@name Output Configuration
@{
*/

/** Set the output buffer where @p forge will write atoms. */
static inline void
lv2_atom_forge_set_buffer(LV2_Atom_Forge* forge, uint8_t* buf, size_t size)
{
forge->buf = buf;
forge->size = (uint32_t)size;
forge->offset = 0;
forge->deref = NULL;
forge->sink = NULL;
forge->handle = NULL;
forge->stack = NULL;
}

/**
Set the sink function where @p forge will write output.

The return value of forge functions is an LV2_Atom_Forge_Ref which is an
integer type safe to use as a pointer but is otherwise opaque. The sink
function must return a ref that can be dereferenced to access as least
sizeof(LV2_Atom) bytes of the written data, so sizes can be updated. For
ringbuffers, this should be possible as long as the size of the buffer is a
multiple of sizeof(LV2_Atom), since atoms are always aligned.

Note that 0 is an invalid reference, so if you are using a buffer offset be
sure to offset it such that 0 is never a valid reference. You will get
confusing errors otherwise.
*/
static inline void
lv2_atom_forge_set_sink(LV2_Atom_Forge* forge,
LV2_Atom_Forge_Sink sink,
LV2_Atom_Forge_Deref_Func deref,
LV2_Atom_Forge_Sink_Handle handle)
{
forge->buf = NULL;
forge->size = forge->offset = 0;
forge->deref = deref;
forge->sink = sink;
forge->handle = handle;
forge->stack = NULL;
}

/**
@}
@name Low Level Output
@{
*/

/**
Write raw output. This is used internally, but is also useful for writing
atom types not explicitly supported by the forge API. Note the caller is
responsible for ensuring the output is approriately padded.
*/
static inline LV2_Atom_Forge_Ref
lv2_atom_forge_raw(LV2_Atom_Forge* forge, const void* data, uint32_t size)
{
LV2_Atom_Forge_Ref out = 0;
if (forge->sink) {
out = forge->sink(forge->handle, data, size);
} else {
out = (LV2_Atom_Forge_Ref)forge->buf + (LV2_Atom_Forge_Ref)forge->offset;
uint8_t* mem = forge->buf + forge->offset;
if (forge->offset + size > forge->size) {
return 0;
}
forge->offset += size;
memcpy(mem, data, size);
}
for (LV2_Atom_Forge_Frame* f = forge->stack; f; f = f->parent) {
lv2_atom_forge_deref(forge, f->ref)->size += size;
}
return out;
}

/** Pad output accordingly so next write is 64-bit aligned. */
static inline void
lv2_atom_forge_pad(LV2_Atom_Forge* forge, uint32_t written)
{
const uint64_t pad = 0;
const uint32_t pad_size = lv2_atom_pad_size(written) - written;
lv2_atom_forge_raw(forge, &pad, pad_size);
}

/** Write raw output, padding to 64-bits as necessary. */
static inline LV2_Atom_Forge_Ref
lv2_atom_forge_write(LV2_Atom_Forge* forge, const void* data, uint32_t size)
{
LV2_Atom_Forge_Ref out = lv2_atom_forge_raw(forge, data, size);
if (out) {
lv2_atom_forge_pad(forge, size);
}
return out;
}

/** Write a null-terminated string body. */
static inline LV2_Atom_Forge_Ref
lv2_atom_forge_string_body(LV2_Atom_Forge* forge,
const char* str,
uint32_t len)
{
LV2_Atom_Forge_Ref out = lv2_atom_forge_raw(forge, str, len);
if (out && (out = lv2_atom_forge_raw(forge, "", 1))) {
lv2_atom_forge_pad(forge, len + 1);
}
return out;
}

/**
@}
@name Atom Output
@{
*/

/** Write an atom:Atom header. */
static inline LV2_Atom_Forge_Ref
lv2_atom_forge_atom(LV2_Atom_Forge* forge, uint32_t size, uint32_t type)
{
const LV2_Atom a = { size, type };
return lv2_atom_forge_raw(forge, &a, sizeof(a));
}

/** Write a primitive (fixed-size) atom. */
static inline LV2_Atom_Forge_Ref
lv2_atom_forge_primitive(LV2_Atom_Forge* forge, const LV2_Atom* a)
{
if (lv2_atom_forge_top_is(forge, forge->Vector)) {
return lv2_atom_forge_raw(forge, LV2_ATOM_BODY_CONST(a), a->size);
} else {
return lv2_atom_forge_write(
forge, a, (uint32_t)sizeof(LV2_Atom) + a->size);
}
}

/** Write an atom:Int. */
static inline LV2_Atom_Forge_Ref
lv2_atom_forge_int(LV2_Atom_Forge* forge, int32_t val)
{
const LV2_Atom_Int a = { { sizeof(val), forge->Int }, val };
return lv2_atom_forge_primitive(forge, &a.atom);
}

/** Write an atom:Long. */
static inline LV2_Atom_Forge_Ref
lv2_atom_forge_long(LV2_Atom_Forge* forge, int64_t val)
{
const LV2_Atom_Long a = { { sizeof(val), forge->Long }, val };
return lv2_atom_forge_primitive(forge, &a.atom);
}

/** Write an atom:Float. */
static inline LV2_Atom_Forge_Ref
lv2_atom_forge_float(LV2_Atom_Forge* forge, float val)
{
const LV2_Atom_Float a = { { sizeof(val), forge->Float }, val };
return lv2_atom_forge_primitive(forge, &a.atom);
}

/** Write an atom:Double. */
static inline LV2_Atom_Forge_Ref
lv2_atom_forge_double(LV2_Atom_Forge* forge, double val)
{
const LV2_Atom_Double a = { { sizeof(val), forge->Double }, val };
return lv2_atom_forge_primitive(forge, &a.atom);
}

/** Write an atom:Bool. */
static inline LV2_Atom_Forge_Ref
lv2_atom_forge_bool(LV2_Atom_Forge* forge, bool val)
{
const LV2_Atom_Bool a = { { sizeof(int32_t), forge->Bool }, val ? 1 : 0 };
return lv2_atom_forge_primitive(forge, &a.atom);
}

/** Write an atom:URID. */
static inline LV2_Atom_Forge_Ref
lv2_atom_forge_urid(LV2_Atom_Forge* forge, LV2_URID id)
{
const LV2_Atom_URID a = { { sizeof(id), forge->URID }, id };
return lv2_atom_forge_primitive(forge, &a.atom);
}

/** Write an atom compatible with atom:String. Used internally. */
static inline LV2_Atom_Forge_Ref
lv2_atom_forge_typed_string(LV2_Atom_Forge* forge,
uint32_t type,
const char* str,
uint32_t len)
{
const LV2_Atom_String a = { { len + 1, type } };
LV2_Atom_Forge_Ref out = lv2_atom_forge_raw(forge, &a, sizeof(a));
if (out) {
if (!lv2_atom_forge_string_body(forge, str, len)) {
LV2_Atom* atom = lv2_atom_forge_deref(forge, out);
atom->size = atom->type = 0;
out = 0;
}
}
return out;
}

/** Write an atom:String. Note that @p str need not be NULL terminated. */
static inline LV2_Atom_Forge_Ref
lv2_atom_forge_string(LV2_Atom_Forge* forge, const char* str, uint32_t len)
{
return lv2_atom_forge_typed_string(forge, forge->String, str, len);
}

/**
Write an atom:URI. Note that @p uri need not be NULL terminated.
This does not map the URI, but writes the complete URI string. To write
a mapped URI, use lv2_atom_forge_urid().
*/
static inline LV2_Atom_Forge_Ref
lv2_atom_forge_uri(LV2_Atom_Forge* forge, const char* uri, uint32_t len)
{
return lv2_atom_forge_typed_string(forge, forge->URI, uri, len);
}

/** Write an atom:Path. Note that @p path need not be NULL terminated. */
static inline LV2_Atom_Forge_Ref
lv2_atom_forge_path(LV2_Atom_Forge* forge, const char* path, uint32_t len)
{
return lv2_atom_forge_typed_string(forge, forge->Path, path, len);
}

/** Write an atom:Literal. */
static inline LV2_Atom_Forge_Ref
lv2_atom_forge_literal(LV2_Atom_Forge* forge,
const char* str,
uint32_t len,
uint32_t datatype,
uint32_t lang)
{
const LV2_Atom_Literal a = {
{ (uint32_t)(sizeof(LV2_Atom_Literal) - sizeof(LV2_Atom) + len + 1),
forge->Literal },
{ datatype,
lang }
};
LV2_Atom_Forge_Ref out = lv2_atom_forge_raw(forge, &a, sizeof(a));
if (out) {
if (!lv2_atom_forge_string_body(forge, str, len)) {
LV2_Atom* atom = lv2_atom_forge_deref(forge, out);
atom->size = atom->type = 0;
out = 0;
}
}
return out;
}

/** Start an atom:Vector. */
static inline LV2_Atom_Forge_Ref
lv2_atom_forge_vector_head(LV2_Atom_Forge* forge,
LV2_Atom_Forge_Frame* frame,
uint32_t child_size,
uint32_t child_type)
{
const LV2_Atom_Vector a = {
{ sizeof(LV2_Atom_Vector_Body), forge->Vector },
{ child_size, child_type }
};
return lv2_atom_forge_push(
forge, frame, lv2_atom_forge_write(forge, &a, sizeof(a)));
}

/** Write a complete atom:Vector. */
static inline LV2_Atom_Forge_Ref
lv2_atom_forge_vector(LV2_Atom_Forge* forge,
uint32_t child_size,
uint32_t child_type,
uint32_t n_elems,
const void* elems)
{
const LV2_Atom_Vector a = {
{ (uint32_t)(sizeof(LV2_Atom_Vector_Body) + n_elems * child_size),
forge->Vector },
{ child_size, child_type }
};
LV2_Atom_Forge_Ref out = lv2_atom_forge_write(forge, &a, sizeof(a));
if (out) {
lv2_atom_forge_write(forge, elems, child_size * n_elems);
}
return out;
}

/**
Write the header of an atom:Tuple.

The passed frame will be initialised to represent this tuple. To complete
the tuple, write a sequence of atoms, then pop the frame with
lv2_atom_forge_pop().

For example:
@code
// Write tuple (1, 2.0)
LV2_Atom_Forge_Frame frame;
LV2_Atom* tup = (LV2_Atom*)lv2_atom_forge_tuple(forge, &frame);
lv2_atom_forge_int32(forge, 1);
lv2_atom_forge_float(forge, 2.0);
lv2_atom_forge_pop(forge, &frame);
@endcode
*/
static inline LV2_Atom_Forge_Ref
lv2_atom_forge_tuple(LV2_Atom_Forge* forge, LV2_Atom_Forge_Frame* frame)
{
const LV2_Atom_Tuple a = { { 0, forge->Tuple } };
return lv2_atom_forge_push(
forge, frame, lv2_atom_forge_write(forge, &a, sizeof(a)));
}

/**
Write the header of an atom:Object.

The passed frame will be initialised to represent this object. To complete
the object, write a sequence of properties, then pop the frame with
lv2_atom_forge_pop().

For example:
@code
LV2_URID eg_Cat = map("http://example.org/Cat");
LV2_URID eg_name = map("http://example.org/name");

// Start object with type eg_Cat and blank ID
LV2_Atom_Forge_Frame frame;
lv2_atom_forge_object(forge, &frame, 0, eg_Cat);

// Append property eg:name = "Hobbes"
lv2_atom_forge_key(forge, eg_name);
lv2_atom_forge_string(forge, "Hobbes", strlen("Hobbes"));

// Finish object
lv2_atom_forge_pop(forge, &frame);
@endcode
*/
static inline LV2_Atom_Forge_Ref
lv2_atom_forge_object(LV2_Atom_Forge* forge,
LV2_Atom_Forge_Frame* frame,
LV2_URID id,
LV2_URID otype)
{
const LV2_Atom_Object a = {
{ (uint32_t)sizeof(LV2_Atom_Object_Body), forge->Object },
{ id, otype }
};
return lv2_atom_forge_push(
forge, frame, lv2_atom_forge_write(forge, &a, sizeof(a)));
}

/**
The same as lv2_atom_forge_object(), but for object:Resource.

This function is deprecated and should not be used in new code.
Use lv2_atom_forge_object() directly instead.
*/
LV2_ATOM_FORGE_DEPRECATED
static inline LV2_Atom_Forge_Ref
lv2_atom_forge_resource(LV2_Atom_Forge* forge,
LV2_Atom_Forge_Frame* frame,
LV2_URID id,
LV2_URID otype)
{
#if defined(__clang__)
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wdeprecated-declarations"
#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
const LV2_Atom_Object a = {
{ (uint32_t)sizeof(LV2_Atom_Object_Body), forge->Resource },
{ id, otype }
};
return lv2_atom_forge_push(
forge, frame, lv2_atom_forge_write(forge, &a, sizeof(a)));
#if defined(__clang__)
# pragma clang diagnostic pop
#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
# pragma GCC diagnostic pop
#endif
}

/**
The same as lv2_atom_forge_object(), but for object:Blank.

This function is deprecated and should not be used in new code.
Use lv2_atom_forge_object() directly instead.
*/
LV2_ATOM_FORGE_DEPRECATED
static inline LV2_Atom_Forge_Ref
lv2_atom_forge_blank(LV2_Atom_Forge* forge,
LV2_Atom_Forge_Frame* frame,
uint32_t id,
LV2_URID otype)
{
#if defined(__clang__)
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wdeprecated-declarations"
#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
const LV2_Atom_Object a = {
{ (uint32_t)sizeof(LV2_Atom_Object_Body), forge->Blank },
{ id, otype }
};
return lv2_atom_forge_push(
forge, frame, lv2_atom_forge_write(forge, &a, sizeof(a)));
#if defined(__clang__)
# pragma clang diagnostic pop
#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
# pragma GCC diagnostic pop
#endif
}

/**
Write a property key in an Object, to be followed by the value.

See lv2_atom_forge_object() documentation for an example.
*/
static inline LV2_Atom_Forge_Ref
lv2_atom_forge_key(LV2_Atom_Forge* forge,
LV2_URID key)
{
const LV2_Atom_Property_Body a = { key, 0, { 0, 0 } };
return lv2_atom_forge_write(forge, &a, 2 * (uint32_t)sizeof(uint32_t));
}

/**
Write the header for a property body in an object, with context.

If you do not need the context, which is almost certainly the case,
use the simpler lv2_atom_forge_key() instead.
*/
static inline LV2_Atom_Forge_Ref
lv2_atom_forge_property_head(LV2_Atom_Forge* forge,
LV2_URID key,
LV2_URID context)
{
const LV2_Atom_Property_Body a = { key, context, { 0, 0 } };
return lv2_atom_forge_write(forge, &a, 2 * (uint32_t)sizeof(uint32_t));
}

/**
Write the header for a Sequence.
*/
static inline LV2_Atom_Forge_Ref
lv2_atom_forge_sequence_head(LV2_Atom_Forge* forge,
LV2_Atom_Forge_Frame* frame,
uint32_t unit)
{
const LV2_Atom_Sequence a = {
{ (uint32_t)sizeof(LV2_Atom_Sequence_Body), forge->Sequence },
{ unit, 0 }
};
return lv2_atom_forge_push(
forge, frame, lv2_atom_forge_write(forge, &a, sizeof(a)));
}

/**
Write the time stamp header of an Event (in a Sequence) in audio frames.
After this, call the appropriate forge method(s) to write the body. Note
the returned reference is to an LV2_Event which is NOT an Atom.
*/
static inline LV2_Atom_Forge_Ref
lv2_atom_forge_frame_time(LV2_Atom_Forge* forge, int64_t frames)
{
return lv2_atom_forge_write(forge, &frames, sizeof(frames));
}

/**
Write the time stamp header of an Event (in a Sequence) in beats. After
this, call the appropriate forge method(s) to write the body. Note the
returned reference is to an LV2_Event which is NOT an Atom.
*/
static inline LV2_Atom_Forge_Ref
lv2_atom_forge_beat_time(LV2_Atom_Forge* forge, double beats)
{
return lv2_atom_forge_write(forge, &beats, sizeof(beats));
}

/**
@}
*/

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

#endif /* LV2_ATOM_FORGE_H */

+ 0
- 249
distrho/src/lv2/atom-helpers.h View File

@@ -1,249 +0,0 @@
// lv2_atom_helpers.h
//
/****************************************************************************
Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved.

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

*****************************************************************************/

/* Helper functions for LV2 atom:Sequence event buffer.
*
* tentatively adapted from:
*
* - lv2_evbuf.h,c - An abstract/opaque LV2 event buffer implementation.
*
* - event-helpers.h - Helper functions for the LV2 Event extension.
* <http://lv2plug.in/ns/ext/event>
*
* Copyright 2008-2012 David Robillard <http://drobilla.net>
*/

#ifndef LV2_ATOM_HELPERS_H
#define LV2_ATOM_HELPERS_H

#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>

#include "atom-util.h"

#ifdef __cplusplus
extern "C" {
#endif

// An abstract/opaque LV2 atom:Sequence buffer.
//
typedef
struct _LV2_Atom_Buffer
{
uint32_t capacity;
uint32_t chunk_type;
uint32_t sequence_type;
LV2_Atom_Sequence atoms;

} LV2_Atom_Buffer;


// Clear and initialize an existing LV2 atom:Sequenece buffer.
//
static inline
void lv2_atom_buffer_reset ( LV2_Atom_Buffer *buf, bool input )
{
if (input) {
buf->atoms.atom.size = sizeof(LV2_Atom_Sequence_Body);
buf->atoms.atom.type = buf->sequence_type;
} else {
buf->atoms.atom.size = buf->capacity;
buf->atoms.atom.type = buf->chunk_type;
}
}


// Allocate a new, empty LV2 atom:Sequence buffer.
//
static inline
LV2_Atom_Buffer *lv2_atom_buffer_new (
uint32_t capacity, uint32_t chunk_type, uint32_t sequence_type, bool input )
{
LV2_Atom_Buffer *buf = (LV2_Atom_Buffer *)
malloc(sizeof(LV2_Atom_Buffer) + sizeof(LV2_Atom_Sequence) + capacity);

buf->capacity = capacity;
buf->chunk_type = chunk_type;
buf->sequence_type = sequence_type;

lv2_atom_buffer_reset(buf, input);

return buf;
}


// Free an LV2 atom:Sequenece buffer allocated with lv2_atome_buffer_new.
//
static inline
void lv2_atom_buffer_free ( LV2_Atom_Buffer *buf )
{
free(buf);
}


// Return the total padded size of events stored in a LV2 atom:Sequence buffer.
//
static inline
uint32_t lv2_atom_buffer_get_size ( LV2_Atom_Buffer *buf )
{
if (buf->atoms.atom.type == buf->sequence_type)
return buf->atoms.atom.size - uint32_t(sizeof(LV2_Atom_Sequence_Body));
else
return 0;
}


// Return the actual LV2 atom:Sequence implementation.
//
static inline
LV2_Atom_Sequence *lv2_atom_buffer_get_sequence ( LV2_Atom_Buffer *buf )
{
return &buf->atoms;
}


// An iterator over an atom:Sequence buffer.
//
typedef
struct _LV2_Atom_Buffer_Iterator
{
LV2_Atom_Buffer *buf;
uint32_t offset;

} LV2_Atom_Buffer_Iterator;


// Reset an iterator to point to the start of an LV2 atom:Sequence buffer.
//
static inline
bool lv2_atom_buffer_begin (
LV2_Atom_Buffer_Iterator *iter, LV2_Atom_Buffer *buf )
{
iter->buf = buf;
iter->offset = 0;

return (buf->atoms.atom.size > 0);
}


// Reset an iterator to point to the end of an LV2 atom:Sequence buffer.
//
static inline
bool lv2_atom_buffer_end (
LV2_Atom_Buffer_Iterator *iter, LV2_Atom_Buffer *buf )
{
iter->buf = buf;
iter->offset = lv2_atom_pad_size(lv2_atom_buffer_get_size(buf));

return (iter->offset < buf->capacity - sizeof(LV2_Atom_Event));
}


// Check if a LV2 atom:Sequenece buffer iterator is valid.
//
static inline
bool lv2_atom_buffer_is_valid ( LV2_Atom_Buffer_Iterator *iter )
{
return iter->offset < lv2_atom_buffer_get_size(iter->buf);
}


// Advance a LV2 atom:Sequenece buffer iterator forward one event.
//
static inline
bool lv2_atom_buffer_increment ( LV2_Atom_Buffer_Iterator *iter )
{
if (!lv2_atom_buffer_is_valid(iter))
return false;

LV2_Atom_Buffer *buf = iter->buf;
LV2_Atom_Sequence *atoms = &buf->atoms;
uint32_t size = ((LV2_Atom_Event *) ((char *)
LV2_ATOM_CONTENTS(LV2_Atom_Sequence, atoms) + iter->offset))->body.size;
iter->offset += lv2_atom_pad_size(uint32_t(sizeof(LV2_Atom_Event)) + size);

return true;
}


// Get the event currently pointed at a LV2 atom:Sequence buffer iterator.
//
static inline
LV2_Atom_Event *lv2_atom_buffer_get (
LV2_Atom_Buffer_Iterator *iter, uint8_t **data )
{
if (!lv2_atom_buffer_is_valid(iter))
return NULL;

LV2_Atom_Buffer *buf = iter->buf;
LV2_Atom_Sequence *atoms = &buf->atoms;
LV2_Atom_Event *ev = (LV2_Atom_Event *) ((char *)
LV2_ATOM_CONTENTS(LV2_Atom_Sequence, atoms) + iter->offset);

*data = (uint8_t *) LV2_ATOM_BODY(&ev->body);

return ev;
}


// Write an event at a LV2 atom:Sequence buffer iterator.

static inline
bool lv2_atom_buffer_write (
LV2_Atom_Buffer_Iterator *iter,
uint32_t frames,
uint32_t /*subframes*/,
uint32_t type,
uint32_t size,
const uint8_t *data )
{
LV2_Atom_Buffer *buf = iter->buf;
LV2_Atom_Sequence *atoms = &buf->atoms;
if (buf->capacity - sizeof(LV2_Atom) - atoms->atom.size
< sizeof(LV2_Atom_Event) + size)
return false;

LV2_Atom_Event *ev = (LV2_Atom_Event*) ((char *)
LV2_ATOM_CONTENTS(LV2_Atom_Sequence, atoms) + iter->offset);

ev->time.frames = frames;
ev->body.type = type;
ev->body.size = size;

memcpy(LV2_ATOM_BODY(&ev->body), data, size);

size = lv2_atom_pad_size(uint32_t(sizeof(LV2_Atom_Event)) + size);
atoms->atom.size += size;
iter->offset += size;

return true;
}

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

#endif // LV2_ATOM_HELPERS_H

// end of lv2_atom_helpers.h

+ 0
- 446
distrho/src/lv2/atom-util.h View File

@@ -1,446 +0,0 @@
/*
Copyright 2008-2013 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 util.h Helper functions for the LV2 Atom extension.

Note these functions are all static inline, do not take their address.

This header is non-normative, it is provided for convenience.
*/

#ifndef LV2_ATOM_UTIL_H
#define LV2_ATOM_UTIL_H

#include <stdarg.h>
#include <stdint.h>
#include <string.h>

#include "atom.h"

#ifdef __cplusplus
extern "C" {
#else
# include <stdbool.h>
#endif

/** Pad a size to 64 bits. */
static inline uint32_t
lv2_atom_pad_size(uint32_t size)
{
return (size + 7U) & (~7U);
}

/** Return the total size of @p atom, including the header. */
static inline uint32_t
lv2_atom_total_size(const LV2_Atom* atom)
{
return (uint32_t)sizeof(LV2_Atom) + atom->size;
}

/** Return true iff @p atom is null. */
static inline bool
lv2_atom_is_null(const LV2_Atom* atom)
{
return !atom || (atom->type == 0 && atom->size == 0);
}

/** Return true iff @p a is equal to @p b. */
static inline bool
lv2_atom_equals(const LV2_Atom* a, const LV2_Atom* b)
{
return (a == b) || ((a->type == b->type) &&
(a->size == b->size) &&
!memcmp(a + 1, b + 1, a->size));
}

/**
@name Sequence Iterator
@{
*/

/** Get an iterator pointing to the first event in a Sequence body. */
static inline const LV2_Atom_Event*
lv2_atom_sequence_begin(const LV2_Atom_Sequence_Body* body)
{
return (const LV2_Atom_Event*)(body + 1);
}

/** Get an iterator pointing to the end of a Sequence body. */
static inline LV2_Atom_Event*
lv2_atom_sequence_end(LV2_Atom_Sequence_Body* body, uint32_t size)
{
return (LV2_Atom_Event*)((uint8_t*)body + lv2_atom_pad_size(size));
}

/** Return true iff @p i has reached the end of @p body. */
static inline bool
lv2_atom_sequence_is_end(const LV2_Atom_Sequence_Body* body,
uint32_t size,
const LV2_Atom_Event* i)
{
return (const uint8_t*)i >= ((const uint8_t*)body + size);
}

/** Return an iterator to the element following @p i. */
static inline const LV2_Atom_Event*
lv2_atom_sequence_next(const LV2_Atom_Event* i)
{
return (const LV2_Atom_Event*)((const uint8_t*)i
+ sizeof(LV2_Atom_Event)
+ lv2_atom_pad_size(i->body.size));
}

/**
A macro for iterating over all events in a Sequence.
@param seq The sequence to iterate over
@param iter The name of the iterator

This macro is used similarly to a for loop (which it expands to), e.g.:
@code
LV2_ATOM_SEQUENCE_FOREACH(sequence, ev) {
// Do something with ev (an LV2_Atom_Event*) here...
}
@endcode
*/
#define LV2_ATOM_SEQUENCE_FOREACH(seq, iter) \
for (const LV2_Atom_Event* (iter) = lv2_atom_sequence_begin(&(seq)->body); \
!lv2_atom_sequence_is_end(&(seq)->body, (seq)->atom.size, (iter)); \
(iter) = lv2_atom_sequence_next(iter))

/** Like LV2_ATOM_SEQUENCE_FOREACH but for a headerless sequence body. */
#define LV2_ATOM_SEQUENCE_BODY_FOREACH(body, size, iter) \
for (const LV2_Atom_Event* (iter) = lv2_atom_sequence_begin(body); \
!lv2_atom_sequence_is_end(body, size, (iter)); \
(iter) = lv2_atom_sequence_next(iter))

/**
@}
@name Sequence Utilities
@{
*/

/**
Clear all events from @p sequence.

This simply resets the size field, the other fields are left untouched.
*/
static inline void
lv2_atom_sequence_clear(LV2_Atom_Sequence* seq)
{
seq->atom.size = sizeof(LV2_Atom_Sequence_Body);
}

/**
Append an event at the end of @p sequence.

@param seq Sequence to append to.
@param capacity Total capacity of the sequence atom
(e.g. as set by the host for sequence output ports).
@param event Event to write.

@return A pointer to the newly written event in @p seq,
or NULL on failure (insufficient space).
*/
static inline LV2_Atom_Event*
lv2_atom_sequence_append_event(LV2_Atom_Sequence* seq,
uint32_t capacity,
const LV2_Atom_Event* event)
{
const uint32_t total_size = (uint32_t)sizeof(*event) + event->body.size;
if (capacity - seq->atom.size < total_size) {
return NULL;
}

LV2_Atom_Event* e = lv2_atom_sequence_end(&seq->body, seq->atom.size);
memcpy(e, event, total_size);

seq->atom.size += lv2_atom_pad_size(total_size);

return e;
}

/**
@}
@name Tuple Iterator
@{
*/

/** Get an iterator pointing to the first element in @p tup. */
static inline const LV2_Atom*
lv2_atom_tuple_begin(const LV2_Atom_Tuple* tup)
{
return (const LV2_Atom*)(LV2_ATOM_BODY_CONST(tup));
}

/** Return true iff @p i has reached the end of @p body. */
static inline bool
lv2_atom_tuple_is_end(const void* body, uint32_t size, const LV2_Atom* i)
{
return (const uint8_t*)i >= ((const uint8_t*)body + size);
}

/** Return an iterator to the element following @p i. */
static inline const LV2_Atom*
lv2_atom_tuple_next(const LV2_Atom* i)
{
return (const LV2_Atom*)(
(const uint8_t*)i + sizeof(LV2_Atom) + lv2_atom_pad_size(i->size));
}

/**
A macro for iterating over all properties of a Tuple.
@param tuple The tuple to iterate over
@param iter The name of the iterator

This macro is used similarly to a for loop (which it expands to), e.g.:
@code
LV2_ATOMO_TUPLE_FOREACH(tuple, elem) {
// Do something with elem (an LV2_Atom*) here...
}
@endcode
*/
#define LV2_ATOM_TUPLE_FOREACH(tuple, iter) \
for (const LV2_Atom* (iter) = lv2_atom_tuple_begin(tuple); \
!lv2_atom_tuple_is_end(LV2_ATOM_BODY_CONST(tuple), (tuple)->size, (iter)); \
(iter) = lv2_atom_tuple_next(iter))

/** Like LV2_ATOM_TUPLE_FOREACH but for a headerless tuple body. */
#define LV2_ATOM_TUPLE_BODY_FOREACH(body, size, iter) \
for (const LV2_Atom* (iter) = (const LV2_Atom*)body; \
!lv2_atom_tuple_is_end(body, size, (iter)); \
(iter) = lv2_atom_tuple_next(iter))

/**
@}
@name Object Iterator
@{
*/

/** Return a pointer to the first property in @p body. */
static inline const LV2_Atom_Property_Body*
lv2_atom_object_begin(const LV2_Atom_Object_Body* body)
{
return (const LV2_Atom_Property_Body*)(body + 1);
}

/** Return true iff @p i has reached the end of @p obj. */
static inline bool
lv2_atom_object_is_end(const LV2_Atom_Object_Body* body,
uint32_t size,
const LV2_Atom_Property_Body* i)
{
return (const uint8_t*)i >= ((const uint8_t*)body + size);
}

/** Return an iterator to the property following @p i. */
static inline const LV2_Atom_Property_Body*
lv2_atom_object_next(const LV2_Atom_Property_Body* i)
{
const LV2_Atom* const value = (const LV2_Atom*)(
(const uint8_t*)i + 2 * sizeof(uint32_t));
return (const LV2_Atom_Property_Body*)(
(const uint8_t*)i + lv2_atom_pad_size(
(uint32_t)sizeof(LV2_Atom_Property_Body) + value->size));
}

/**
A macro for iterating over all properties of an Object.
@param obj The object to iterate over
@param iter The name of the iterator

This macro is used similarly to a for loop (which it expands to), e.g.:
@code
LV2_ATOM_OBJECT_FOREACH(object, i) {
// Do something with prop (an LV2_Atom_Property_Body*) here...
}
@endcode
*/
#define LV2_ATOM_OBJECT_FOREACH(obj, iter) \
for (const LV2_Atom_Property_Body* (iter) = lv2_atom_object_begin(&(obj)->body); \
!lv2_atom_object_is_end(&(obj)->body, (obj)->atom.size, (iter)); \
(iter) = lv2_atom_object_next(iter))

/** Like LV2_ATOM_OBJECT_FOREACH but for a headerless object body. */
#define LV2_ATOM_OBJECT_BODY_FOREACH(body, size, iter) \
for (const LV2_Atom_Property_Body* (iter) = lv2_atom_object_begin(body); \
!lv2_atom_object_is_end(body, size, (iter)); \
(iter) = lv2_atom_object_next(iter))

/**
@}
@name Object Query
@{
*/

/** A single entry in an Object query. */
typedef struct {
uint32_t key; /**< Key to query (input set by user) */
const LV2_Atom** value; /**< Found value (output set by query function) */
} LV2_Atom_Object_Query;

static const LV2_Atom_Object_Query LV2_ATOM_OBJECT_QUERY_END = { 0, NULL };

/**
Get an object's values for various keys.

The value pointer of each item in @p query will be set to the location of
the corresponding value in @p object. Every value pointer in @p query MUST
be initialised to NULL. This function reads @p object in a single linear
sweep. By allocating @p query on the stack, objects can be "queried"
quickly without allocating any memory. This function is realtime safe.

This function can only do "flat" queries, it is not smart enough to match
variables in nested objects.

For example:
@code
const LV2_Atom* name = NULL;
const LV2_Atom* age = NULL;
LV2_Atom_Object_Query q[] = {
{ urids.eg_name, &name },
{ urids.eg_age, &age },
LV2_ATOM_OBJECT_QUERY_END
};
lv2_atom_object_query(obj, q);
// name and age are now set to the appropriate values in obj, or NULL.
@endcode
*/
static inline int
lv2_atom_object_query(const LV2_Atom_Object* object,
LV2_Atom_Object_Query* query)
{
int matches = 0;
int n_queries = 0;

/* Count number of query keys so we can short-circuit when done */
for (LV2_Atom_Object_Query* q = query; q->key; ++q) {
++n_queries;
}

LV2_ATOM_OBJECT_FOREACH(object, prop) {
for (LV2_Atom_Object_Query* q = query; q->key; ++q) {
if (q->key == prop->key && !*q->value) {
*q->value = &prop->value;
if (++matches == n_queries) {
return matches;
}
break;
}
}
}
return matches;
}

/**
Body only version of lv2_atom_object_get().
*/
static inline int
lv2_atom_object_body_get(uint32_t size, const LV2_Atom_Object_Body* body, ...)
{
int matches = 0;
int n_queries = 0;

/* Count number of keys so we can short-circuit when done */
va_list args;
va_start(args, body);
for (n_queries = 0; va_arg(args, uint32_t); ++n_queries) {
if (!va_arg(args, const LV2_Atom**)) {
return -1;
}
}
va_end(args);

LV2_ATOM_OBJECT_BODY_FOREACH(body, size, prop) {
va_start(args, body);
for (int i = 0; i < n_queries; ++i) {
uint32_t qkey = va_arg(args, uint32_t);
const LV2_Atom** qval = va_arg(args, const LV2_Atom**);
if (qkey == prop->key && !*qval) {
*qval = &prop->value;
if (++matches == n_queries) {
return matches;
}
break;
}
}
va_end(args);
}
return matches;
}

/**
Variable argument version of lv2_atom_object_query().

This is nicer-looking in code, but a bit more error-prone since it is not
type safe and the argument list must be terminated.

The arguments should be a series of uint32_t key and const LV2_Atom** value
pairs, terminated by a zero key. The value pointers MUST be initialized to
NULL. For example:

@code
const LV2_Atom* name = NULL;
const LV2_Atom* age = NULL;
lv2_atom_object_get(obj,
uris.name_key, &name,
uris.age_key, &age,
0);
@endcode
*/
static inline int
lv2_atom_object_get(const LV2_Atom_Object* object, ...)
{
int matches = 0;
int n_queries = 0;

/* Count number of keys so we can short-circuit when done */
va_list args;
va_start(args, object);
for (n_queries = 0; va_arg(args, uint32_t); ++n_queries) {
if (!va_arg(args, const LV2_Atom**)) {
return -1;
}
}
va_end(args);

LV2_ATOM_OBJECT_FOREACH(object, prop) {
va_start(args, object);
for (int i = 0; i < n_queries; ++i) {
uint32_t qkey = va_arg(args, uint32_t);
const LV2_Atom** qval = va_arg(args, const LV2_Atom**);
if (qkey == prop->key && !*qval) {
*qval = &prop->value;
if (++matches == n_queries) {
return matches;
}
break;
}
}
va_end(args);
}
return matches;
}

/**
@}
*/

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

#endif /* LV2_ATOM_UTIL_H */

+ 0
- 246
distrho/src/lv2/atom.h View File

@@ -1,246 +0,0 @@
/*
Copyright 2008-2012 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 atom.h C header for the LV2 Atom extension
<http://lv2plug.in/ns/ext/atom>.
*/

#ifndef LV2_ATOM_H
#define LV2_ATOM_H

#include <stdint.h>
#include <stddef.h>

#define LV2_ATOM_URI "http://lv2plug.in/ns/ext/atom"
#define LV2_ATOM_PREFIX LV2_ATOM_URI "#"

#define LV2_ATOM__Atom LV2_ATOM_PREFIX "Atom"
#define LV2_ATOM__AtomPort LV2_ATOM_PREFIX "AtomPort"
#define LV2_ATOM__Blank LV2_ATOM_PREFIX "Blank"
#define LV2_ATOM__Bool LV2_ATOM_PREFIX "Bool"
#define LV2_ATOM__Chunk LV2_ATOM_PREFIX "Chunk"
#define LV2_ATOM__Double LV2_ATOM_PREFIX "Double"
#define LV2_ATOM__Event LV2_ATOM_PREFIX "Event"
#define LV2_ATOM__Float LV2_ATOM_PREFIX "Float"
#define LV2_ATOM__Int LV2_ATOM_PREFIX "Int"
#define LV2_ATOM__Literal LV2_ATOM_PREFIX "Literal"
#define LV2_ATOM__Long LV2_ATOM_PREFIX "Long"
#define LV2_ATOM__Number LV2_ATOM_PREFIX "Number"
#define LV2_ATOM__Object LV2_ATOM_PREFIX "Object"
#define LV2_ATOM__Path LV2_ATOM_PREFIX "Path"
#define LV2_ATOM__Property LV2_ATOM_PREFIX "Property"
#define LV2_ATOM__Resource LV2_ATOM_PREFIX "Resource"
#define LV2_ATOM__Sequence LV2_ATOM_PREFIX "Sequence"
#define LV2_ATOM__Sound LV2_ATOM_PREFIX "Sound"
#define LV2_ATOM__String LV2_ATOM_PREFIX "String"
#define LV2_ATOM__Tuple LV2_ATOM_PREFIX "Tuple"
#define LV2_ATOM__URI LV2_ATOM_PREFIX "URI"
#define LV2_ATOM__URID LV2_ATOM_PREFIX "URID"
#define LV2_ATOM__Vector LV2_ATOM_PREFIX "Vector"
#define LV2_ATOM__atomTransfer LV2_ATOM_PREFIX "atomTransfer"
#define LV2_ATOM__beatTime LV2_ATOM_PREFIX "beatTime"
#define LV2_ATOM__bufferType LV2_ATOM_PREFIX "bufferType"
#define LV2_ATOM__childType LV2_ATOM_PREFIX "childType"
#define LV2_ATOM__eventTransfer LV2_ATOM_PREFIX "eventTransfer"
#define LV2_ATOM__frameTime LV2_ATOM_PREFIX "frameTime"
#define LV2_ATOM__supports LV2_ATOM_PREFIX "supports"
#define LV2_ATOM__timeUnit LV2_ATOM_PREFIX "timeUnit"

#define LV2_ATOM_REFERENCE_TYPE 0

#ifdef __cplusplus
extern "C" {
#endif

/** This expression will fail to compile if double does not fit in 64 bits. */
typedef char lv2_atom_assert_double_fits_in_64_bits[
((sizeof(double) <= sizeof(uint64_t)) * 2) - 1];

/**
Return a pointer to the contents of an Atom. The "contents" of an atom
is the data past the complete type-specific header.
@param type The type of the atom, e.g. LV2_Atom_String.
@param atom A variable-sized atom.
*/
#define LV2_ATOM_CONTENTS(type, atom) \
((uint8_t*)(atom) + sizeof(type))

/**
Const version of LV2_ATOM_CONTENTS.
*/
#define LV2_ATOM_CONTENTS_CONST(type, atom) \
((const uint8_t*)(atom) + sizeof(type))

/**
Return a pointer to the body of an Atom. The "body" of an atom is the
data just past the LV2_Atom head (i.e. the same offset for all types).
*/
#define LV2_ATOM_BODY(atom) LV2_ATOM_CONTENTS(LV2_Atom, atom)

/**
Const version of LV2_ATOM_BODY.
*/
#define LV2_ATOM_BODY_CONST(atom) LV2_ATOM_CONTENTS_CONST(LV2_Atom, atom)

/** The header of an atom:Atom. */
typedef struct {
uint32_t size; /**< Size in bytes, not including type and size. */
uint32_t type; /**< Type of this atom (mapped URI). */
} LV2_Atom;

/** An atom:Int or atom:Bool. May be cast to LV2_Atom. */
typedef struct {
LV2_Atom atom; /**< Atom header. */
int32_t body; /**< Integer value. */
} LV2_Atom_Int;

/** An atom:Long. May be cast to LV2_Atom. */
typedef struct {
LV2_Atom atom; /**< Atom header. */
int64_t body; /**< Integer value. */
} LV2_Atom_Long;

/** An atom:Float. May be cast to LV2_Atom. */
typedef struct {
LV2_Atom atom; /**< Atom header. */
float body; /**< Floating point value. */
} LV2_Atom_Float;

/** An atom:Double. May be cast to LV2_Atom. */
typedef struct {
LV2_Atom atom; /**< Atom header. */
double body; /**< Floating point value. */
} LV2_Atom_Double;

/** An atom:Bool. May be cast to LV2_Atom. */
typedef LV2_Atom_Int LV2_Atom_Bool;

/** An atom:URID. May be cast to LV2_Atom. */
typedef struct {
LV2_Atom atom; /**< Atom header. */
uint32_t body; /**< URID. */
} LV2_Atom_URID;

/** An atom:String. May be cast to LV2_Atom. */
typedef struct {
LV2_Atom atom; /**< Atom header. */
/* Contents (a null-terminated UTF-8 string) follow here. */
} LV2_Atom_String;

/** The body of an atom:Literal. */
typedef struct {
uint32_t datatype; /**< Datatype URID. */
uint32_t lang; /**< Language URID. */
/* Contents (a null-terminated UTF-8 string) follow here. */
} LV2_Atom_Literal_Body;

/** An atom:Literal. May be cast to LV2_Atom. */
typedef struct {
LV2_Atom atom; /**< Atom header. */
LV2_Atom_Literal_Body body; /**< Body. */
} LV2_Atom_Literal;

/** An atom:Tuple. May be cast to LV2_Atom. */
typedef struct {
LV2_Atom atom; /**< Atom header. */
/* Contents (a series of complete atoms) follow here. */
} LV2_Atom_Tuple;

/** The body of an atom:Vector. */
typedef struct {
uint32_t child_size; /**< The size of each element in the vector. */
uint32_t child_type; /**< The type of each element in the vector. */
/* Contents (a series of packed atom bodies) follow here. */
} LV2_Atom_Vector_Body;

/** An atom:Vector. May be cast to LV2_Atom. */
typedef struct {
LV2_Atom atom; /**< Atom header. */
LV2_Atom_Vector_Body body; /**< Body. */
} LV2_Atom_Vector;

/** The body of an atom:Property (e.g. in an atom:Object). */
typedef struct {
uint32_t key; /**< Key (predicate) (mapped URI). */
uint32_t context; /**< Context URID (may be, and generally is, 0). */
LV2_Atom value; /**< Value atom header. */
/* Value atom body follows here. */
} LV2_Atom_Property_Body;

/** An atom:Property. May be cast to LV2_Atom. */
typedef struct {
LV2_Atom atom; /**< Atom header. */
LV2_Atom_Property_Body body; /**< Body. */
} LV2_Atom_Property;

/** The body of an atom:Object. May be cast to LV2_Atom. */
typedef struct {
uint32_t id; /**< URID, or 0 for blank. */
uint32_t otype; /**< Type URID (same as rdf:type, for fast dispatch). */
/* Contents (a series of property bodies) follow here. */
} LV2_Atom_Object_Body;

/** An atom:Object. May be cast to LV2_Atom. */
typedef struct {
LV2_Atom atom; /**< Atom header. */
LV2_Atom_Object_Body body; /**< Body. */
} LV2_Atom_Object;

/** The header of an atom:Event. Note this type is NOT an LV2_Atom. */
typedef struct {
/** Time stamp. Which type is valid is determined by context. */
union {
int64_t frames; /**< Time in audio frames. */
double beats; /**< Time in beats. */
} time;
LV2_Atom body; /**< Event body atom header. */
/* Body atom contents follow here. */
} LV2_Atom_Event;

/**
The body of an atom:Sequence (a sequence of events).

The unit field is either a URID that described an appropriate time stamp
type, or may be 0 where a default stamp type is known. For
LV2_Descriptor::run(), the default stamp type is audio frames.

The contents of a sequence is a series of LV2_Atom_Event, each aligned
to 64-bits, e.g.:
<pre>
| Event 1 (size 6) | Event 2
| | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|FRAMES |SUBFRMS|TYPE |SIZE |DATADATADATAPAD|FRAMES |SUBFRMS|...
</pre>
*/
typedef struct {
uint32_t unit; /**< URID of unit of event time stamps. */
uint32_t pad; /**< Currently unused. */
/* Contents (a series of events) follow here. */
} LV2_Atom_Sequence_Body;

/** An atom:Sequence. */
typedef struct {
LV2_Atom atom; /**< Atom header. */
LV2_Atom_Sequence_Body body; /**< Body. */
} LV2_Atom_Sequence;

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

#endif /* LV2_ATOM_H */

+ 0
- 30
distrho/src/lv2/buf-size.h View File

@@ -1,30 +0,0 @@
/*
Copyright 2007-2012 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 LV2_BUF_SIZE_H
#define LV2_BUF_SIZE_H

#define LV2_BUF_SIZE_URI "http://lv2plug.in/ns/ext/buf-size"
#define LV2_BUF_SIZE_PREFIX LV2_BUF_SIZE_URI "#"

#define LV2_BUF_SIZE__boundedBlockLength LV2_BUF_SIZE_PREFIX "boundedBlockLength"
#define LV2_BUF_SIZE__fixedBlockLength LV2_BUF_SIZE_PREFIX "fixedBlockLength"
#define LV2_BUF_SIZE__maxBlockLength LV2_BUF_SIZE_PREFIX "maxBlockLength"
#define LV2_BUF_SIZE__minBlockLength LV2_BUF_SIZE_PREFIX "minBlockLength"
#define LV2_BUF_SIZE__powerOf2BlockLength LV2_BUF_SIZE_PREFIX "powerOf2BlockLength"
#define LV2_BUF_SIZE__sequenceSize LV2_BUF_SIZE_PREFIX "sequenceSize"

#endif /* LV2_BUF_SIZE_H */

+ 0
- 63
distrho/src/lv2/data-access.h View File

@@ -1,63 +0,0 @@
/*
LV2 Data Access Extension
Copyright 2008-2011 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 data-access.h
C header for the LV2 Extension Data extension
<http://lv2plug.in/ns/ext/data-access>.

This extension defines a method for (e.g.) plugin UIs to have (possibly
marshalled) access to the extension_data function on a plugin instance.
*/

#ifndef LV2_DATA_ACCESS_H
#define LV2_DATA_ACCESS_H

#define LV2_DATA_ACCESS_URI "http://lv2plug.in/ns/ext/data-access"

#ifdef __cplusplus
extern "C" {
#endif

/**
The data field of the LV2_Feature for this extension.

To support this feature the host must pass an LV2_Feature struct to the
instantiate method with URI "http://lv2plug.in/ns/ext/data-access"
and data pointed to an instance of this struct.
*/
typedef struct {
/**
A pointer to a method the UI can call to get data (of a type specified
by some other extension) from the plugin.

This call never is never guaranteed to return anything, UIs should
degrade gracefully if direct access to the plugin data is not possible
(in which case this function will return NULL).

This is for access to large data that can only possibly work if the UI
and plugin are running in the same process. For all other things, use
the normal LV2 UI communication system.
*/
const void* (*data_access)(const char* uri);
} LV2_Extension_Data_Feature;

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

#endif /* LV2_DATA_ACCESS_H */

+ 0
- 144
distrho/src/lv2/dynmanifest.h View File

@@ -1,144 +0,0 @@
/*
Dynamic manifest specification for LV2
Copyright 2008-2011 Stefano D'Angelo <zanga.mail@gmail.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.

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 dynmanifest.h
C header for the LV2 Dynamic Manifest extension
<http://lv2plug.in/ns/ext/dynmanifest>.
Revision: 1.2
*/

#ifndef LV2_DYN_MANIFEST_H_INCLUDED
#define LV2_DYN_MANIFEST_H_INCLUDED

#include <stdio.h>

#include "lv2.h"

#define LV2_DYN_MANIFEST_URI "http://lv2plug.in/ns/ext/dynmanifest"

#ifdef __cplusplus
extern "C" {
#endif

/**
Dynamic manifest generator handle.

This handle indicates a particular status of a dynamic manifest generator.
The host MUST NOT attempt to interpret it and, unlikely LV2_Handle, it is
NOT even valid to compare this to NULL. The dynamic manifest generator MAY
use it to reference internal data.
*/
typedef void * LV2_Dyn_Manifest_Handle;

/**
Generate the dynamic manifest.

@param handle Pointer to an uninitialized dynamic manifest generator handle.

@param features NULL terminated array of LV2_Feature structs which represent
the features the host supports. The dynamic manifest generator may refuse to
(re)generate the dynamic manifest if required features are not found here
(however hosts SHOULD NOT use this as a discovery mechanism, instead of
reading the static manifest file). This array must always exist; if a host
has no features, it MUST pass a single element array containing NULL.

@return 0 on success, otherwise a non-zero error code. The host SHOULD
evaluate the result of the operation by examining the returned value and
MUST NOT try to interpret the value of handle.
*/
int lv2_dyn_manifest_open(LV2_Dyn_Manifest_Handle * handle,
const LV2_Feature *const * features);

/**
Fetch a "list" of subject URIs described in the dynamic manifest.

The dynamic manifest generator has to fill the resource only with the needed
triples to make the host aware of the "objects" it wants to expose. For
example, if the plugin library exposes a regular LV2 plugin, it should
output only a triple like the following:

<http://www.example.com/plugin/uri> a lv2:Plugin .

The objects that are elegible for exposure are those that would need to be
represented by a subject node in a static manifest.

@param handle Dynamic manifest generator handle.

@param fp FILE * identifying the resource the host has to set up for the
dynamic manifest generator. The host MUST pass a writable, empty resource to
this function, and the dynamic manifest generator MUST ONLY perform write
operations on it at the end of the stream (e.g., using only fprintf(),
fwrite() and similar).

@return 0 on success, otherwise a non-zero error code.
*/
int lv2_dyn_manifest_get_subjects(LV2_Dyn_Manifest_Handle handle,
FILE * fp);

/**
Function that fetches data related to a specific URI.

The dynamic manifest generator has to fill the resource with data related to
object represented by the given URI. For example, if the library exposes a
regular LV2 plugin whose URI, as retrieved by the host using
lv2_dyn_manifest_get_subjects() is http://www.example.com/plugin/uri, it
should output something like:

<pre>
<http://www.example.com/plugin/uri>
a lv2:Plugin ;
doap:name "My Plugin" ;
lv2:binary <mylib.so> ;
etc:etc "..." .
</pre>

@param handle Dynamic manifest generator handle.

@param fp FILE * identifying the resource the host has to set up for the
dynamic manifest generator. The host MUST pass a writable resource to this
function, and the dynamic manifest generator MUST ONLY perform write
operations on it at the current position of the stream (e.g. using only
fprintf(), fwrite() and similar).

@param uri URI to get data about (in the "plain" form, i.e., absolute URI
without Turtle prefixes).

@return 0 on success, otherwise a non-zero error code.
*/
int lv2_dyn_manifest_get_data(LV2_Dyn_Manifest_Handle handle,
FILE * fp,
const char * uri);

/**
Function that ends the operations on the dynamic manifest generator.

This function SHOULD be used by the dynamic manifest generator to perform
cleanup operations, etc.

Once this function is called, referring to handle will cause undefined
behavior.

@param handle Dynamic manifest generator handle.
*/
void lv2_dyn_manifest_close(LV2_Dyn_Manifest_Handle handle);

#ifdef __cplusplus
}
#endif

#endif /* LV2_DYN_MANIFEST_H_INCLUDED */

+ 0
- 266
distrho/src/lv2/event-helpers.h View File

@@ -1,266 +0,0 @@
/*
Copyright 2008-2012 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 event-helpers.h Helper functions for the LV2 Event extension
<http://lv2plug.in/ns/ext/event>.
*/

#ifndef LV2_EVENT_HELPERS_H
#define LV2_EVENT_HELPERS_H

#include <stdint.h>
#include <stdlib.h>
#include <string.h>

#include "event.h"

#ifdef __cplusplus
extern "C" {
#else
# include <stdbool.h>
#endif

/** @file
* Helper functions for the LV2 Event extension
* <http://lv2plug.in/ns/ext/event>.
*
* These functions are provided for convenience only, use of them is not
* required for supporting lv2ev (i.e. the events extension is defined by the
* raw buffer format described in lv2_event.h and NOT by this API).
*
* Note that these functions are all static inline which basically means:
* do not take the address of these functions. */


/** Pad a size to 64 bits (for event sizes) */
static inline uint16_t
lv2_event_pad_size(uint16_t size)
{
return (uint16_t)(size + 7U) & (uint16_t)(~7U);
}


/** Initialize (empty, reset..) an existing event buffer.
* The contents of buf are ignored entirely and overwritten, except capacity
* which is unmodified. */
static inline void
lv2_event_buffer_reset(LV2_Event_Buffer* buf,
uint16_t stamp_type,
uint8_t* data)
{
buf->data = data;
buf->header_size = sizeof(LV2_Event_Buffer);
buf->stamp_type = stamp_type;
buf->event_count = 0;
buf->size = 0;
}


/** Allocate a new, empty event buffer. */
static inline LV2_Event_Buffer*
lv2_event_buffer_new(uint32_t capacity, uint16_t stamp_type)
{
const size_t size = sizeof(LV2_Event_Buffer) + capacity;
LV2_Event_Buffer* buf = (LV2_Event_Buffer*)malloc(size);
if (buf != NULL) {
buf->capacity = capacity;
lv2_event_buffer_reset(buf, stamp_type, (uint8_t *)(buf + 1));
return buf;
} else {
return NULL;
}
}


/** An iterator over an LV2_Event_Buffer.
*
* Multiple simultaneous read iterators over a single buffer is fine,
* but changing the buffer invalidates all iterators (e.g. RW Lock). */
typedef struct {
LV2_Event_Buffer* buf;
uint32_t offset;
} LV2_Event_Iterator;


/** Reset an iterator to point to the start of @a buf.
* @return True if @a iter is valid, otherwise false (buffer is empty) */
static inline bool
lv2_event_begin(LV2_Event_Iterator* iter,
LV2_Event_Buffer* buf)
{
iter->buf = buf;
iter->offset = 0;
return (buf->size > 0);
}


/** Check if @a iter is valid.
* @return True if @a iter is valid, otherwise false (past end of buffer) */
static inline bool
lv2_event_is_valid(LV2_Event_Iterator* iter)
{
return (iter->buf && (iter->offset < iter->buf->size));
}


/** Advance @a iter forward one event.
* @a iter must be valid.
* @return True if @a iter is valid, otherwise false (reached end of buffer) */
static inline bool
lv2_event_increment(LV2_Event_Iterator* iter)
{
if (!lv2_event_is_valid(iter)) {
return false;
}

LV2_Event* const ev = (LV2_Event*)(
(uint8_t*)iter->buf->data + iter->offset);

iter->offset += lv2_event_pad_size(
(uint16_t)((uint16_t)sizeof(LV2_Event) + ev->size));

return true;
}


/** Dereference an event iterator (get the event currently pointed at).
* @a iter must be valid.
* @a data if non-NULL, will be set to point to the contents of the event
* returned.
* @return A Pointer to the event @a iter is currently pointing at, or NULL
* if the end of the buffer is reached (in which case @a data is
* also set to NULL). */
static inline LV2_Event*
lv2_event_get(LV2_Event_Iterator* iter,
uint8_t** data)
{
if (!lv2_event_is_valid(iter)) {
return NULL;
}

LV2_Event* const ev = (LV2_Event*)(
(uint8_t*)iter->buf->data + iter->offset);

if (data)
*data = (uint8_t*)ev + sizeof(LV2_Event);

return ev;
}


/** Write an event at @a iter.
* The event (if any) pointed to by @a iter will be overwritten, and @a iter
* incremented to point to the following event (i.e. several calls to this
* function can be done in sequence without twiddling iter in-between).
* @return True if event was written, otherwise false (buffer is full). */
static inline bool
lv2_event_write(LV2_Event_Iterator* iter,
uint32_t frames,
uint32_t subframes,
uint16_t type,
uint16_t size,
const uint8_t* data)
{
if (!iter->buf)
return false;

if (iter->buf->capacity - iter->buf->size < sizeof(LV2_Event) + size)
return false;

LV2_Event* const ev = (LV2_Event*)(
(uint8_t*)iter->buf->data + iter->offset);

ev->frames = frames;
ev->subframes = subframes;
ev->type = type;
ev->size = size;
memcpy((uint8_t*)ev + sizeof(LV2_Event), data, size);
++iter->buf->event_count;

size = lv2_event_pad_size((uint16_t)(sizeof(LV2_Event) + size));
iter->buf->size += size;
iter->offset += size;

return true;
}


/** Reserve space for an event in the buffer and return a pointer to
the memory where the caller can write the event data, or NULL if there
is not enough room in the buffer. */
static inline uint8_t*
lv2_event_reserve(LV2_Event_Iterator* iter,
uint32_t frames,
uint32_t subframes,
uint16_t type,
uint16_t size)
{
const uint16_t total_size = (uint16_t)(sizeof(LV2_Event) + size);
if (iter->buf->capacity - iter->buf->size < total_size)
return NULL;

LV2_Event* const ev = (LV2_Event*)(
(uint8_t*)iter->buf->data + iter->offset);

ev->frames = frames;
ev->subframes = subframes;
ev->type = type;
ev->size = size;
++iter->buf->event_count;

const uint16_t padded_size = lv2_event_pad_size(total_size);
iter->buf->size += padded_size;
iter->offset += padded_size;

return (uint8_t*)ev + sizeof(LV2_Event);
}


/** Write an event at @a iter.
* The event (if any) pointed to by @a iter will be overwritten, and @a iter
* incremented to point to the following event (i.e. several calls to this
* function can be done in sequence without twiddling iter in-between).
* @return True if event was written, otherwise false (buffer is full). */
static inline bool
lv2_event_write_event(LV2_Event_Iterator* iter,
const LV2_Event* ev,
const uint8_t* data)
{
const uint16_t total_size = (uint16_t)(sizeof(LV2_Event) + ev->size);
if (iter->buf->capacity - iter->buf->size < total_size)
return false;

LV2_Event* const write_ev = (LV2_Event*)(
(uint8_t*)iter->buf->data + iter->offset);

*write_ev = *ev;
memcpy((uint8_t*)write_ev + sizeof(LV2_Event), data, ev->size);
++iter->buf->event_count;

const uint16_t padded_size = lv2_event_pad_size(total_size);
iter->buf->size += padded_size;
iter->offset += padded_size;

return true;
}

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

#endif /* LV2_EVENT_HELPERS_H */


+ 0
- 294
distrho/src/lv2/event.h View File

@@ -1,294 +0,0 @@
/*
Copyright 2008-2011 David Robillard <http://drobilla.net>
Copyright 2006-2007 Lars Luthman <lars.luthman@gmail.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.

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 event.h
C API for the LV2 Event extension <http://lv2plug.in/ns/ext/event>.

This extension is a generic transport mechanism for time stamped events
of any type (e.g. MIDI, OSC, ramps, etc). Each port can transport mixed
events of any type; the type of events and timestamps are defined by a URI
which is mapped to an integer by the host for performance reasons.

This extension requires the host to support the LV2 URI Map extension.
Any host which supports this extension MUST guarantee that any call to
the LV2 URI Map uri_to_id function with the URI of this extension as the
'map' argument returns a value within the range of uint16_t.
*/

#ifndef LV2_EVENT_H
#define LV2_EVENT_H

#define LV2_EVENT_URI "http://lv2plug.in/ns/ext/event"
#define LV2_EVENT_PREFIX LV2_EVENT_URI "#"

#define LV2_EVENT__Event LV2_EVENT_PREFIX "Event"
#define LV2_EVENT__EventPort LV2_EVENT_PREFIX "EventPort"
#define LV2_EVENT__FrameStamp LV2_EVENT_PREFIX "FrameStamp"
#define LV2_EVENT__TimeStamp LV2_EVENT_PREFIX "TimeStamp"
#define LV2_EVENT__generatesTimeStamp LV2_EVENT_PREFIX "generatesTimeStamp"
#define LV2_EVENT__generic LV2_EVENT_PREFIX "generic"
#define LV2_EVENT__inheritsEvent LV2_EVENT_PREFIX "inheritsEvent"
#define LV2_EVENT__inheritsTimeStamp LV2_EVENT_PREFIX "inheritsTimeStamp"
#define LV2_EVENT__supportsEvent LV2_EVENT_PREFIX "supportsEvent"
#define LV2_EVENT__supportsTimeStamp LV2_EVENT_PREFIX "supportsTimeStamp"

#define LV2_EVENT_AUDIO_STAMP 0

#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif

/**
The best Pulses Per Quarter Note for tempo-based uint32_t timestamps.
Equal to 2^12 * 5 * 7 * 9 * 11 * 13 * 17, which is evenly divisble
by all integers from 1 through 18 inclusive, and powers of 2 up to 2^12.
*/
static const uint32_t LV2_EVENT_PPQN = 3136573440U;

/**
An LV2 event (header only).

LV2 events are generic time-stamped containers for any type of event.
The type field defines the format of a given event's contents.

This struct defines the header of an LV2 event. An LV2 event is a single
chunk of POD (plain old data), usually contained in a flat buffer (see
LV2_EventBuffer below). Unless a required feature says otherwise, hosts may
assume a deep copy of an LV2 event can be created safely using a simple:

memcpy(ev_copy, ev, sizeof(LV2_Event) + ev->size); (or equivalent)
*/
typedef struct {
/**
The frames portion of timestamp. The units used here can optionally be
set for a port (with the lv2ev:timeUnits property), otherwise this is
audio frames, corresponding to the sample_count parameter of the LV2 run
method (e.g. frame 0 is the first frame for that call to run).
*/
uint32_t frames;

/**
The sub-frames portion of timestamp. The units used here can optionally
be set for a port (with the lv2ev:timeUnits property), otherwise this is
1/(2^32) of an audio frame.
*/
uint32_t subframes;

/**
The type of this event, as a number which represents some URI
defining an event type. This value MUST be some value previously
returned from a call to the uri_to_id function defined in the LV2
URI map extension (see lv2_uri_map.h).
There are special rules which must be followed depending on the type
of an event. If the plugin recognizes an event type, the definition
of that event type will describe how to interpret the event, and
any required behaviour. Otherwise, if the type is 0, this event is a
non-POD event and lv2_event_unref MUST be called if the event is
'dropped' (see above). Even if the plugin does not understand an event,
it may pass the event through to an output by simply copying (and NOT
calling lv2_event_unref). These rules are designed to allow for generic
event handling plugins and large non-POD events, but with minimal hassle
on simple plugins that "don't care" about these more advanced features.
*/
uint16_t type;

/**
The size of the data portion of this event in bytes, which immediately
follows. The header size (12 bytes) is not included in this value.
*/
uint16_t size;

/* size bytes of data follow here */
} LV2_Event;


/**
A buffer of LV2 events (header only).

Like events (which this contains) an event buffer is a single chunk of POD:
the entire buffer (including contents) can be copied with a single memcpy.
The first contained event begins sizeof(LV2_EventBuffer) bytes after the
start of this struct.

After this header, the buffer contains an event header (defined by struct
LV2_Event), followed by that event's contents (padded to 64 bits), followed
by another header, etc:

| | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | |
|FRAMES |SUBFRMS|TYP|LEN|DATA..DATA..PAD|FRAMES | ...
*/
typedef struct {
/**
The contents of the event buffer. This may or may not reside in the
same block of memory as this header, plugins must not assume either.
The host guarantees this points to at least capacity bytes of allocated
memory (though only size bytes of that are valid events).
*/
uint8_t* data;

/**
The size of this event header in bytes (including everything).

This is to allow for extending this header in the future without
breaking binary compatibility. Whenever this header is copied,
it MUST be done using this field (and NOT the sizeof this struct).
*/
uint16_t header_size;

/**
The type of the time stamps for events in this buffer.
As a special exception, '0' always means audio frames and subframes
(1/UINT32_MAX'th of a frame) in the sample rate passed to instantiate.

INPUTS: The host must set this field to the numeric ID of some URI
defining the meaning of the frames/subframes fields of contained events
(obtained by the LV2 URI Map uri_to_id function with the URI of this
extension as the 'map' argument, see lv2_uri_map.h). The host must
never pass a plugin a buffer which uses a stamp type the plugin does not
'understand'. The value of this field must never change, except when
connect_port is called on the input port, at which time the host MUST
have set the stamp_type field to the value that will be used for all
subsequent run calls.

OUTPUTS: The plugin may set this to any value that has been returned
from uri_to_id with the URI of this extension for a 'map' argument.
When connected to a buffer with connect_port, output ports MUST set this
field to the type of time stamp they will be writing. On any call to
connect_port on an event input port, the plugin may change this field on
any output port, it is the responsibility of the host to check if any of
these values have changed and act accordingly.
*/
uint16_t stamp_type;

/**
The number of events in this buffer.

INPUTS: The host must set this field to the number of events contained
in the data buffer before calling run(). The plugin must not change
this field.

OUTPUTS: The plugin must set this field to the number of events it has
written to the buffer before returning from run(). Any initial value
should be ignored by the plugin.
*/
uint32_t event_count;

/**
The size of the data buffer in bytes.
This is set by the host and must not be changed by the plugin.
The host is allowed to change this between run() calls.
*/
uint32_t capacity;

/**
The size of the initial portion of the data buffer containing data.

INPUTS: The host must set this field to the number of bytes used
by all events it has written to the buffer (including headers)
before calling the plugin's run().
The plugin must not change this field.

OUTPUTS: The plugin must set this field to the number of bytes
used by all events it has written to the buffer (including headers)
before returning from run().
Any initial value should be ignored by the plugin.
*/
uint32_t size;
} LV2_Event_Buffer;


/**
Opaque pointer to host data.
*/
typedef void* LV2_Event_Callback_Data;


/**
Non-POD events feature.

To support this feature the host must pass an LV2_Feature struct to the
plugin's instantiate method with URI "http://lv2plug.in/ns/ext/event"
and data pointed to an instance of this struct. Note this feature
is not mandatory to support the event extension.
*/
typedef struct {
/**
Opaque pointer to host data.

The plugin MUST pass this to any call to functions in this struct.
Otherwise, it must not be interpreted in any way.
*/
LV2_Event_Callback_Data callback_data;

/**
Take a reference to a non-POD event.

If a plugin receives an event with type 0, it means the event is a
pointer to some object in memory and not a flat sequence of bytes
in the buffer. When receiving a non-POD event, the plugin already
has an implicit reference to the event. If the event is stored AND
passed to an output, lv2_event_ref MUST be called on that event.
If the event is only stored OR passed through, this is not necessary
(as the plugin already has 1 implicit reference).

@param event An event received at an input that will not be copied to
an output or stored in any way.

@param context The calling context. Like event types, this is a mapped
URI, see lv2_context.h. Simple plugin with just a run() method should
pass 0 here (the ID of the 'standard' LV2 run context). The host
guarantees that this function is realtime safe iff @a context is
realtime safe.

PLUGINS THAT VIOLATE THESE RULES MAY CAUSE CRASHES AND MEMORY LEAKS.
*/
uint32_t (*lv2_event_ref)(LV2_Event_Callback_Data callback_data,
LV2_Event* event);

/**
Drop a reference to a non-POD event.

If a plugin receives an event with type 0, it means the event is a
pointer to some object in memory and not a flat sequence of bytes
in the buffer. If the plugin does not pass the event through to
an output or store it internally somehow, it MUST call this function
on the event (more information on using non-POD events below).

@param event An event received at an input that will not be copied to an
output or stored in any way.

@param context The calling context. Like event types, this is a mapped
URI, see lv2_context.h. Simple plugin with just a run() method should
pass 0 here (the ID of the 'standard' LV2 run context). The host
guarantees that this function is realtime safe iff @a context is
realtime safe.

PLUGINS THAT VIOLATE THESE RULES MAY CAUSE CRASHES AND MEMORY LEAKS.
*/
uint32_t (*lv2_event_unref)(LV2_Event_Callback_Data callback_data,
LV2_Event* event);
} LV2_Event_Feature;

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

#endif /* LV2_EVENT_H */

+ 0
- 37
distrho/src/lv2/instance-access.h View File

@@ -1,37 +0,0 @@
/*
LV2 Instance Access Extension
Copyright 2008-2012 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 LV2_INSTANCE_ACCESS_H
#define LV2_INSTANCE_ACCESS_H

#define LV2_INSTANCE_ACCESS_URI "http://lv2plug.in/ns/ext/instance-access"

/**
@file instance-access.h
C header for the LV2 Instance Access extension
<http://lv2plug.in/ns/ext/instance-access>.
This extension defines a method for (e.g.) plugin UIs to get a direct
handle to an LV2 plugin instance (LV2_Handle), if possible.
To support this feature the host must pass an LV2_Feature struct to the
UI instantiate method with URI "http://lv2plug.in/ns/ext/instance-access"
and data pointed directly to the LV2_Handle of the plugin instance.
*/

#endif /* LV2_INSTANCE_ACCESS_H */


+ 0
- 99
distrho/src/lv2/log.h View File

@@ -1,99 +0,0 @@
/*
Copyright 2012 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 log.h C header for the LV2 Log extension
<http://lv2plug.in/ns/ext/log>.
*/

#ifndef LV2_LOG_H
#define LV2_LOG_H

#define LV2_LOG_URI "http://lv2plug.in/ns/ext/log"
#define LV2_LOG_PREFIX LV2_LOG_URI "#"

#define LV2_LOG__Entry LV2_LOG_PREFIX "Entry"
#define LV2_LOG__Error LV2_LOG_PREFIX "Error"
#define LV2_LOG__Note LV2_LOG_PREFIX "Note"
#define LV2_LOG__Trace LV2_LOG_PREFIX "Trace"
#define LV2_LOG__Warning LV2_LOG_PREFIX "Warning"
#define LV2_LOG__log LV2_LOG_PREFIX "log"

#include <stdarg.h>

#include "urid.h"

#ifdef __cplusplus
extern "C" {
#endif

#ifdef __GNUC__
/** Allow type checking of printf-like functions. */
# define LV2_LOG_FUNC(fmt, arg1) __attribute__((format(printf, fmt, arg1)))
#else
# define LV2_LOG_FUNC(fmt, arg1)
#endif

/**
Opaque data to host data for LV2_Log_Log.
*/
typedef void* LV2_Log_Handle;

/**
Log feature (LV2_LOG__log)
*/
typedef struct _LV2_Log {
/**
Opaque pointer to host data.

This MUST be passed to methods in this struct whenever they are called.
Otherwise, it must not be interpreted in any way.
*/
LV2_Log_Handle handle;

/**
Log a message, passing format parameters directly.

The API of this function matches that of the standard C printf function,
except for the addition of the first two parameters. This function may
be called from any non-realtime context, or from any context if @p type
is @ref LV2_LOG__Trace.
*/
LV2_LOG_FUNC(3, 4)
int (*printf)(LV2_Log_Handle handle,
LV2_URID type,
const char* fmt, ...);

/**
Log a message, passing format parameters in a va_list.

The API of this function matches that of the standard C vprintf
function, except for the addition of the first two parameters. This
function may be called from any non-realtime context, or from any
context if @p type is @ref LV2_LOG__Trace.
*/
LV2_LOG_FUNC(3, 0)
int (*vprintf)(LV2_Log_Handle handle,
LV2_URID type,
const char* fmt,
va_list ap);
} LV2_Log_Log;

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

#endif /* LV2_LOG_H */

+ 0
- 146
distrho/src/lv2/logger.h View File

@@ -1,146 +0,0 @@
/*
Copyright 2012-2013 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 logger.h Convenience API for easy logging in plugin code.

This file provides simple wrappers for the most common log operations for
use in plugin implementations. If host support for logging is not
available, then these functions will print to stderr instead.

This header is non-normative, it is provided for convenience.
*/

#ifndef LV2_ATOM_LOGGER_H
#define LV2_ATOM_LOGGER_H

#include <stdio.h>
#include <string.h>

#include "log.h"

#ifdef __cplusplus
extern "C" {
#endif

/**
Logger convenience API state.
*/
typedef struct {
LV2_Log_Log* log;

LV2_URID Error;
LV2_URID Note;
LV2_URID Trace;
LV2_URID Warning;
} LV2_Log_Logger;

/**
Initialise @p logger.

URIs will be mapped using @p map and stored, a reference to @p map itself is
not held. Both @p map and @p log may be NULL when unsupported by the host,
in which case the implementation will fall back to printing to stderr.
*/
static inline void
lv2_log_logger_init(LV2_Log_Logger* logger,
LV2_URID_Map* map,
LV2_Log_Log* log)
{
memset(logger, 0, sizeof(LV2_Log_Logger));
logger->log = log;
if (map) {
logger->Error = map->map(map->handle, LV2_LOG__Error);
logger->Note = map->map(map->handle, LV2_LOG__Note);
logger->Trace = map->map(map->handle, LV2_LOG__Trace);
logger->Warning = map->map(map->handle, LV2_LOG__Warning);
}
}

/**
Log a message to the host, or stderr if support is unavailable.
*/
LV2_LOG_FUNC(3, 0)
static inline int
lv2_log_vprintf(LV2_Log_Logger* logger,
LV2_URID type,
const char* fmt,
va_list args)
{
if (logger->log) {
return logger->log->vprintf(logger->log->handle, type, fmt, args);
} else {
return vfprintf(stderr, fmt, args);
}
}

/** Log an error via lv2_log_vprintf(). */
LV2_LOG_FUNC(2, 3)
static inline int
lv2_log_error(LV2_Log_Logger* logger, const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
const int ret = lv2_log_vprintf(logger, logger->Error, fmt, args);
va_end(args);
return ret;
}

/** Log a note via lv2_log_vprintf(). */
LV2_LOG_FUNC(2, 3)
static inline int
lv2_log_note(LV2_Log_Logger* logger, const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
const int ret = lv2_log_vprintf(logger, logger->Note, fmt, args);
va_end(args);
return ret;
}

/** Log a trace via lv2_log_vprintf(). */
LV2_LOG_FUNC(2, 3)
static inline int
lv2_log_trace(LV2_Log_Logger* logger, const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
const int ret = lv2_log_vprintf(logger, logger->Trace, fmt, args);
va_end(args);
return ret;
}

/** Log a warning via lv2_log_vprintf(). */
LV2_LOG_FUNC(2, 3)
static inline int
lv2_log_warning(LV2_Log_Logger* logger, const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
const int ret = lv2_log_vprintf(logger, logger->Warning, fmt, args);
va_end(args);
return ret;
}

/**
@}
*/

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

#endif /* LV2_LOG_LOGGER_H */

+ 0
- 98
distrho/src/lv2/lv2-midifunctions.h View File

@@ -1,98 +0,0 @@
/****************************************************************************
lv2-midifunctions.h - support file for using MIDI in LV2 plugins
Copyright (C) 2006 Lars Luthman <lars.luthman@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 01222-1307 USA

****************************************************************************/

#ifndef LV2_MIDIFUNCTIONS
#define LV2_MIDIFUNCTIONS

#include "lv2-miditype.h"

#ifdef __cplusplus
extern "C" {
#endif

typedef struct {
LV2_MIDI* midi;
uint32_t frame_count;
uint32_t position;
} LV2_MIDIState;


inline double lv2midi_get_event(LV2_MIDIState* state,
double* timestamp,
uint32_t* size,
unsigned char** data) {
if (state->position >= state->midi->size) {
state->position = state->midi->size;
*timestamp = state->frame_count;
*size = 0;
*data = NULL;
return *timestamp;
}
*timestamp = *(double*)(state->midi->data + state->position);
*size = (uint32_t)*(size_t*)(state->midi->data + state->position + sizeof(double));
*data = state->midi->data + state->position +
sizeof(double) + sizeof(size_t);
return *timestamp;
}


inline double lv2midi_step(LV2_MIDIState* state) {

if (state->position >= state->midi->size) {
state->position = state->midi->size;
return state->frame_count;
}
state->position += (uint32_t)sizeof(double);
size_t size = *(size_t*)(state->midi->data + state->position);
state->position += (uint32_t)sizeof(size_t);
state->position += (uint32_t)size;
return *(double*)(state->midi->data + state->position);
}


inline void lv2midi_put_event(LV2_MIDIState* state,
double timestamp,
uint32_t size,
const unsigned char* data) {
if (state->midi->size + sizeof(double) + sizeof(size_t) + size < state->midi->capacity)
{
*((double*)(state->midi->data + state->midi->size)) = timestamp;
state->midi->size += (uint32_t)sizeof(double);
*((size_t*)(state->midi->data + state->midi->size)) = size;
state->midi->size += (uint32_t)sizeof(size_t);
memcpy(state->midi->data + state->midi->size, data, size);

state->midi->size += size;
state->midi->event_count++;
}
}

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

#endif


+ 0
- 175
distrho/src/lv2/lv2-miditype.h View File

@@ -1,175 +0,0 @@
/****************************************************************************
lv2-miditype.h - header file for using MIDI in LV2 plugins
Copyright (C) 2006 Lars Luthman <lars.luthman@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 01222-1307 USA

****************************************************************************/

#ifndef LV2_MIDITYPE_H
#define LV2_MIDITYPE_H

#ifdef __cplusplus
extern "C" {
#endif

/** This data structure is used to contain the MIDI events for one run()
cycle. The port buffer for a LV2 port that has the datatype
<http://ll-plugins.nongnu.org/lv2/ext/miditype> should be a pointer
to an instance of this struct.

To store two Note On events on MIDI channel 0 in a buffer, with timestamps
12 and 35.5, you could use something like this code (assuming that
midi_data is a variable of type LV2_MIDI):
@code
size_t buffer_offset = 0;
*(double*)(midi_data->data + buffer_offset) = 12;
buffer_offset += sizeof(double);
*(size_t*)(midi_data->data + buffer_offset) = 3;
buffer_offset += sizeof(size_t);
midi_data->data[buffer_offset++] = 0x90;
midi_data->data[buffer_offset++] = 0x48;
midi_data->data[buffer_offset++] = 0x64;
++midi_data->event_count;
*(double*)(midi_data->data + buffer_offset) = 35.5;
buffer_offset += sizeof(double);
*(size_t*)(midi_data->data + buffer_offset) = 3;
buffer_offset += sizeof(size_t);
midi_data->data[buffer_offset++] = 0x90;
midi_data->data[buffer_offset++] = 0x55;
midi_data->data[buffer_offset++] = 0x64;
++midi_data->event_count;
midi_data->size = buffer_offset;
@endcode
This would be done by the host in the case of an input port, and by the
plugin in the case of an output port. Whoever is writing events to the
buffer must also take care not to exceed the capacity of the data buffer.
To read events from a buffer, you could do something like this:
@code
size_t buffer_offset = 0;
uint32_t i;
for (i = 0; i < midi_data->event_count; ++i) {
double timestamp = *(double*)(midi_data->data + buffer_offset);
buffer_offset += sizeof(double);
size_t size = *(size_t*)(midi_data->data + buffer_offset);
buffer_offset += sizeof(size_t);
do_something_with_event(timestamp, size,
midi_data->data + buffer_offset);
buffer_offset += size;
}
@endcode
*/
typedef struct {

/** The number of MIDI events in the data buffer.
INPUT PORTS: It's the host's responsibility to set this field to the
number of MIDI events contained in the data buffer before calling the
plugin's run() function. The plugin may not change this field.
OUTPUT PORTS: It's the plugin's responsibility to set this field to the
number of MIDI events it has stored in the data buffer before returning
from the run() function. Any initial value should be ignored by the
plugin.
*/
uint32_t event_count;
/** The size of the data buffer in bytes. It is set by the host and may not
be changed by the plugin. The host is allowed to change this between
run() calls.
*/
uint32_t capacity;
/** The size of the initial part of the data buffer that actually contains
data.
INPUT PORTS: It's the host's responsibility to set this field to the
number of bytes used by all MIDI events it has written to the buffer
(including timestamps and size fields) before calling the plugin's
run() function. The plugin may not change this field.
OUTPUT PORTS: It's the plugin's responsibility to set this field to
the number of bytes used by all MIDI events it has written to the
buffer (including timestamps and size fields) before returning from
the run() function. Any initial value should be ignored by the plugin.
*/
uint32_t size;
/** The data buffer that is used to store MIDI events. The events are packed
after each other, and the format of each event is as follows:
First there is a timestamp, which should have the type "double",
i.e. have the same bit size as a double and the same bit layout as a
double (whatever that is on the current platform). This timestamp gives
the offset from the beginning of the current cycle, in frames, that
the MIDI event occurs on. It must be strictly smaller than the 'nframes'
parameter to the current run() call. The MIDI events in the buffer must
be ordered by their timestamp, e.g. an event with a timestamp of 123.23
must be stored after an event with a timestamp of 65.0.
The second part of the event is a size field, which should have the type
"size_t" (as defined in the standard C header stddef.h). It should
contain the size of the MIDI data for this event, i.e. the number of
bytes used to store the actual MIDI event. The bytes used by the
timestamp and the size field should not be counted.
The third part of the event is the actual MIDI data. There are some
requirements that must be followed:
* Running status is not allowed. Every event must have its own status
byte.
* Note On events with velocity 0 are not allowed. These events are
equivalent to Note Off in standard MIDI streams, but in order to make
plugins and hosts easier to write, as well as more efficient, only
proper Note Off events are allowed as Note Off.
* "Realtime events" (status bytes 0xF8 to 0xFF) are allowed, but may not
occur inside other events like they are allowed to in hardware MIDI
streams.
* All events must be fully contained in a single data buffer, i.e. events
may not "wrap around" by storing the first few bytes in one buffer and
then wait for the next run() call to store the rest of the event. If
there isn't enough space in the current data buffer to store an event,
the event will either have to wait until next run() call, be ignored,
or compensated for in some more clever way.
* All events must be valid MIDI events. This means for example that
only the first byte in each event (the status byte) may have the eighth
bit set, that Note On and Note Off events are always 3 bytes long etc.
The MIDI writer (host or plugin) is responsible for writing valid MIDI
events to the buffer, and the MIDI reader (plugin or host) can assume
that all events are valid.
On a platform where double is 8 bytes and size_t is 4 bytes, the data
buffer layout for a 3-byte event followed by a 4-byte event may look
something like this:
_______________________________________________________________
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | ...
|TIMESTAMP 1 |SIZE 1 |DATA |TIMESTAMP 2 |SIZE 2 |DATA | ...
*/
unsigned char* data;

} LV2_MIDI;

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

#endif

+ 0
- 458
distrho/src/lv2/lv2.h View File

@@ -1,458 +0,0 @@
/*
LV2 - An audio plugin interface specification.
Copyright 2006-2012 Steve Harris, David Robillard.

Based on LADSPA, Copyright 2000-2002 Richard W.E. Furse,
Paul Barton-Davis, Stefan Westerfeld.

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 lv2.h
API for the LV2 specification <http://lv2plug.in/ns/lv2core>.
Revision: 12.0
*/

#ifndef LV2_H_INCLUDED
#define LV2_H_INCLUDED

#include <stdint.h>

#define LV2_CORE_URI "http://lv2plug.in/ns/lv2core"
#define LV2_CORE_PREFIX LV2_CORE_URI "#"

#define LV2_CORE__AllpassPlugin LV2_CORE_PREFIX "AllpassPlugin"
#define LV2_CORE__AmplifierPlugin LV2_CORE_PREFIX "AmplifierPlugin"
#define LV2_CORE__AnalyserPlugin LV2_CORE_PREFIX "AnalyserPlugin"
#define LV2_CORE__AudioPort LV2_CORE_PREFIX "AudioPort"
#define LV2_CORE__BandpassPlugin LV2_CORE_PREFIX "BandpassPlugin"
#define LV2_CORE__CVPort LV2_CORE_PREFIX "CVPort"
#define LV2_CORE__ChorusPlugin LV2_CORE_PREFIX "ChorusPlugin"
#define LV2_CORE__CombPlugin LV2_CORE_PREFIX "CombPlugin"
#define LV2_CORE__CompressorPlugin LV2_CORE_PREFIX "CompressorPlugin"
#define LV2_CORE__ConstantPlugin LV2_CORE_PREFIX "ConstantPlugin"
#define LV2_CORE__ControlPort LV2_CORE_PREFIX "ControlPort"
#define LV2_CORE__ConverterPlugin LV2_CORE_PREFIX "ConverterPlugin"
#define LV2_CORE__DelayPlugin LV2_CORE_PREFIX "DelayPlugin"
#define LV2_CORE__DistortionPlugin LV2_CORE_PREFIX "DistortionPlugin"
#define LV2_CORE__DynamicsPlugin LV2_CORE_PREFIX "DynamicsPlugin"
#define LV2_CORE__EQPlugin LV2_CORE_PREFIX "EQPlugin"
#define LV2_CORE__EnvelopePlugin LV2_CORE_PREFIX "EnvelopePlugin"
#define LV2_CORE__ExpanderPlugin LV2_CORE_PREFIX "ExpanderPlugin"
#define LV2_CORE__ExtensionData LV2_CORE_PREFIX "ExtensionData"
#define LV2_CORE__Feature LV2_CORE_PREFIX "Feature"
#define LV2_CORE__FilterPlugin LV2_CORE_PREFIX "FilterPlugin"
#define LV2_CORE__FlangerPlugin LV2_CORE_PREFIX "FlangerPlugin"
#define LV2_CORE__FunctionPlugin LV2_CORE_PREFIX "FunctionPlugin"
#define LV2_CORE__GatePlugin LV2_CORE_PREFIX "GatePlugin"
#define LV2_CORE__GeneratorPlugin LV2_CORE_PREFIX "GeneratorPlugin"
#define LV2_CORE__HighpassPlugin LV2_CORE_PREFIX "HighpassPlugin"
#define LV2_CORE__InputPort LV2_CORE_PREFIX "InputPort"
#define LV2_CORE__InstrumentPlugin LV2_CORE_PREFIX "InstrumentPlugin"
#define LV2_CORE__LimiterPlugin LV2_CORE_PREFIX "LimiterPlugin"
#define LV2_CORE__LowpassPlugin LV2_CORE_PREFIX "LowpassPlugin"
#define LV2_CORE__MixerPlugin LV2_CORE_PREFIX "MixerPlugin"
#define LV2_CORE__ModulatorPlugin LV2_CORE_PREFIX "ModulatorPlugin"
#define LV2_CORE__MultiEQPlugin LV2_CORE_PREFIX "MultiEQPlugin"
#define LV2_CORE__OscillatorPlugin LV2_CORE_PREFIX "OscillatorPlugin"
#define LV2_CORE__OutputPort LV2_CORE_PREFIX "OutputPort"
#define LV2_CORE__ParaEQPlugin LV2_CORE_PREFIX "ParaEQPlugin"
#define LV2_CORE__PhaserPlugin LV2_CORE_PREFIX "PhaserPlugin"
#define LV2_CORE__PitchPlugin LV2_CORE_PREFIX "PitchPlugin"
#define LV2_CORE__Plugin LV2_CORE_PREFIX "Plugin"
#define LV2_CORE__PluginBase LV2_CORE_PREFIX "PluginBase"
#define LV2_CORE__Point LV2_CORE_PREFIX "Point"
#define LV2_CORE__Port LV2_CORE_PREFIX "Port"
#define LV2_CORE__PortProperty LV2_CORE_PREFIX "PortProperty"
#define LV2_CORE__Resource LV2_CORE_PREFIX "Resource"
#define LV2_CORE__ReverbPlugin LV2_CORE_PREFIX "ReverbPlugin"
#define LV2_CORE__ScalePoint LV2_CORE_PREFIX "ScalePoint"
#define LV2_CORE__SimulatorPlugin LV2_CORE_PREFIX "SimulatorPlugin"
#define LV2_CORE__SpatialPlugin LV2_CORE_PREFIX "SpatialPlugin"
#define LV2_CORE__Specification LV2_CORE_PREFIX "Specification"
#define LV2_CORE__SpectralPlugin LV2_CORE_PREFIX "SpectralPlugin"
#define LV2_CORE__UtilityPlugin LV2_CORE_PREFIX "UtilityPlugin"
#define LV2_CORE__WaveshaperPlugin LV2_CORE_PREFIX "WaveshaperPlugin"
#define LV2_CORE__appliesTo LV2_CORE_PREFIX "appliesTo"
#define LV2_CORE__binary LV2_CORE_PREFIX "binary"
#define LV2_CORE__connectionOptional LV2_CORE_PREFIX "connectionOptional"
#define LV2_CORE__control LV2_CORE_PREFIX "control"
#define LV2_CORE__default LV2_CORE_PREFIX "default"
#define LV2_CORE__designation LV2_CORE_PREFIX "designation"
#define LV2_CORE__documentation LV2_CORE_PREFIX "documentation"
#define LV2_CORE__enumeration LV2_CORE_PREFIX "enumeration"
#define LV2_CORE__extensionData LV2_CORE_PREFIX "extensionData"
#define LV2_CORE__freeWheeling LV2_CORE_PREFIX "freeWheeling"
#define LV2_CORE__hardRTCapable LV2_CORE_PREFIX "hardRTCapable"
#define LV2_CORE__inPlaceBroken LV2_CORE_PREFIX "inPlaceBroken"
#define LV2_CORE__index LV2_CORE_PREFIX "index"
#define LV2_CORE__integer LV2_CORE_PREFIX "integer"
#define LV2_CORE__isLive LV2_CORE_PREFIX "isLive"
#define LV2_CORE__latency LV2_CORE_PREFIX "latency"
#define LV2_CORE__maximum LV2_CORE_PREFIX "maximum"
#define LV2_CORE__microVersion LV2_CORE_PREFIX "microVersion"
#define LV2_CORE__minimum LV2_CORE_PREFIX "minimum"
#define LV2_CORE__minorVersion LV2_CORE_PREFIX "minorVersion"
#define LV2_CORE__name LV2_CORE_PREFIX "name"
#define LV2_CORE__optionalFeature LV2_CORE_PREFIX "optionalFeature"
#define LV2_CORE__port LV2_CORE_PREFIX "port"
#define LV2_CORE__portProperty LV2_CORE_PREFIX "portProperty"
#define LV2_CORE__project LV2_CORE_PREFIX "project"
#define LV2_CORE__prototype LV2_CORE_PREFIX "prototype"
#define LV2_CORE__reportsLatency LV2_CORE_PREFIX "reportsLatency"
#define LV2_CORE__requiredFeature LV2_CORE_PREFIX "requiredFeature"
#define LV2_CORE__sampleRate LV2_CORE_PREFIX "sampleRate"
#define LV2_CORE__scalePoint LV2_CORE_PREFIX "scalePoint"
#define LV2_CORE__symbol LV2_CORE_PREFIX "symbol"
#define LV2_CORE__toggled LV2_CORE_PREFIX "toggled"

#ifdef __cplusplus
extern "C" {
#endif

/**
Plugin Instance Handle.

This is a handle for one particular instance of a plugin. It is valid to
compare to NULL (or 0 for C++) but otherwise the host MUST NOT attempt to
interpret it.
*/
typedef void * LV2_Handle;

/**
Feature.

Features allow hosts to make additional functionality available to plugins
without requiring modification to the LV2 API. Extensions may define new
features and specify the @ref URI and @ref data to be used if necessary.
Some features, such as lv2:isLive, do not require the host to pass data.
*/
typedef struct _LV2_Feature {
/**
A globally unique, case-sensitive identifier (URI) for this feature.

This MUST be a valid URI string as defined by RFC 3986.
*/
const char * URI;

/**
Pointer to arbitrary data.

The format of this data is defined by the extension which describes the
feature with the given @ref URI.
*/
void * data;
} LV2_Feature;

/**
Plugin Descriptor.

This structure provides the core functions necessary to instantiate and use
a plugin.
*/
typedef struct _LV2_Descriptor {
/**
A globally unique, case-sensitive identifier for this plugin.

This MUST be a valid URI string as defined by RFC 3986. All plugins with
the same URI MUST be compatible to some degree, see
http://lv2plug.in/ns/lv2core for details.
*/
const char * URI;

/**
Instantiate the plugin.

Note that instance initialisation should generally occur in activate()
rather than here. If a host calls instantiate(), it MUST call cleanup()
at some point in the future.

@param descriptor Descriptor of the plugin to instantiate.

@param sample_rate Sample rate, in Hz, for the new plugin instance.

@param bundle_path Path to the LV2 bundle which contains this plugin
binary. It MUST include the trailing directory separator (e.g. '/') so
that simply appending a filename will yield the path to that file in the
bundle.

@param features A NULL terminated array of LV2_Feature structs which
represent the features the host supports. Plugins may refuse to
instantiate if required features are not found here. However, hosts MUST
NOT use this as a discovery mechanism: instead, use the RDF data to
determine which features are required and do not attempt to instantiate
unsupported plugins at all. This parameter MUST NOT be NULL, i.e. a host
that supports no features MUST pass a single element array containing
NULL.

@return A handle for the new plugin instance, or NULL if instantiation
has failed.
*/
LV2_Handle (*instantiate)(const struct _LV2_Descriptor * descriptor,
double sample_rate,
const char * bundle_path,
const LV2_Feature *const * features);

/**
Connect a port on a plugin instance to a memory location.

Plugin writers should be aware that the host may elect to use the same
buffer for more than one port and even use the same buffer for both
input and output (see lv2:inPlaceBroken in lv2.ttl).

If the plugin has the feature lv2:hardRTCapable then there are various
things that the plugin MUST NOT do within the connect_port() function;
see lv2core.ttl for details.

connect_port() MUST be called at least once for each port before run()
is called, unless that port is lv2:connectionOptional. The plugin must
pay careful attention to the block size passed to run() since the block
allocated may only just be large enough to contain the data, and is not
guaranteed to remain constant between run() calls.

connect_port() may be called more than once for a plugin instance to
allow the host to change the buffers that the plugin is reading or
writing. These calls may be made before or after activate() or
deactivate() calls.

@param instance Plugin instance containing the port.

@param port Index of the port to connect. The host MUST NOT try to
connect a port index that is not defined in the plugin's RDF data. If
it does, the plugin's behaviour is undefined (a crash is likely).

@param data_location Pointer to data of the type defined by the port
type in the plugin's RDF data (e.g. an array of float for an
lv2:AudioPort). This pointer must be stored by the plugin instance and
used to read/write data when run() is called. Data present at the time
of the connect_port() call MUST NOT be considered meaningful.
*/
void (*connect_port)(LV2_Handle instance,
uint32_t port,
void * data_location);

/**
Initialise a plugin instance and activate it for use.

This is separated from instantiate() to aid real-time support and so
that hosts can reinitialise a plugin instance by calling deactivate()
and then activate(). In this case the plugin instance MUST reset all
state information dependent on the history of the plugin instance except
for any data locations provided by connect_port(). If there is nothing
for activate() to do then this field may be NULL.

When present, hosts MUST call this function once before run() is called
for the first time. This call SHOULD be made as close to the run() call
as possible and indicates to real-time plugins that they are now live,
however plugins MUST NOT rely on a prompt call to run() after
activate().

The host MUST NOT call activate() again until deactivate() has been
called first. If a host calls activate(), it MUST call deactivate() at
some point in the future. Note that connect_port() may be called before
or after activate().
*/
void (*activate)(LV2_Handle instance);

/**
Run a plugin instance for a block.

Note that if an activate() function exists then it must be called before
run(). If deactivate() is called for a plugin instance then run() may
not be called until activate() has been called again.

If the plugin has the feature lv2:hardRTCapable then there are various
things that the plugin MUST NOT do within the run() function (see
lv2core.ttl for details).

As a special case, when @p sample_count == 0, the plugin should update
any output ports that represent a single instant in time (e.g. control
ports, but not audio ports). This is particularly useful for latent
plugins, which should update their latency output port so hosts can
pre-roll plugins to compute latency. Plugins MUST NOT crash when
@p sample_count == 0.

@param instance Instance to be run.

@param sample_count The block size (in samples) for which the plugin
instance must run.
*/
void (*run)(LV2_Handle instance,
uint32_t sample_count);

/**
Deactivate a plugin instance (counterpart to activate()).

Hosts MUST deactivate all activated instances after they have been run()
for the last time. This call SHOULD be made as close to the last run()
call as possible and indicates to real-time plugins that they are no
longer live, however plugins MUST NOT rely on prompt deactivation. If
there is nothing for deactivate() to do then this field may be NULL

Deactivation is not similar to pausing since the plugin instance will be
reinitialised by activate(). However, deactivate() itself MUST NOT fully
reset plugin state. For example, the host may deactivate a plugin, then
store its state (using some extension to do so).

Hosts MUST NOT call deactivate() unless activate() was previously
called. Note that connect_port() may be called before or after
deactivate().
*/
void (*deactivate)(LV2_Handle instance);

/**
Clean up a plugin instance (counterpart to instantiate()).

Once an instance of a plugin has been finished with it must be deleted
using this function. The instance handle passed ceases to be valid after
this call.

If activate() was called for a plugin instance then a corresponding call
to deactivate() MUST be made before cleanup() is called. Hosts MUST NOT
call cleanup() unless instantiate() was previously called.
*/
void (*cleanup)(LV2_Handle instance);

/**
Return additional plugin data defined by some extenion.

A typical use of this facility is to return a struct containing function
pointers to extend the LV2_Descriptor API.

The actual type and meaning of the returned object MUST be specified
precisely by the extension. This function MUST return NULL for any
unsupported URI. If a plugin does not support any extension data, this
field may be NULL.

The host is never responsible for freeing the returned value.
*/
const void * (*extension_data)(const char * uri);
} LV2_Descriptor;

/**
Put this (LV2_SYMBOL_EXPORT) before any functions that are to be loaded
by the host as a symbol from the dynamic library.
*/
#ifdef _WIN32
# define LV2_SYMBOL_EXPORT __declspec(dllexport)
#else
# define LV2_SYMBOL_EXPORT
#endif

/**
Prototype for plugin accessor function.

Plugins are discovered by hosts using RDF data (not by loading libraries).
See http://lv2plug.in for details on the discovery process, though most
hosts should use an existing library to implement this functionality.

This is the simple plugin discovery API, suitable for most statically
defined plugins. Advanced plugins that need access to their bundle during
discovery can use lv2_lib_descriptor() instead. Plugin libraries MUST
include a function called "lv2_descriptor" or "lv2_lib_descriptor" with
C-style linkage, but SHOULD provide "lv2_descriptor" wherever possible.

When it is time to load a plugin (designated by its URI), the host loads the
plugin's library, gets the lv2_descriptor() function from it, and uses this
function to find the LV2_Descriptor for the desired plugin. Plugins are
accessed by index using values from 0 upwards. This function MUST return
NULL for out of range indices, so the host can enumerate plugins by
increasing @p index until NULL is returned.

Note that @p index has no meaning, hosts MUST NOT depend on it remaining
consistent between loads of the plugin library.
*/
LV2_SYMBOL_EXPORT
const LV2_Descriptor * lv2_descriptor(uint32_t index);

/**
Type of the lv2_descriptor() function in a library (old discovery API).
*/
typedef const LV2_Descriptor *
(*LV2_Descriptor_Function)(uint32_t index);

/**
Handle for a library descriptor.
*/
typedef void* LV2_Lib_Handle;

/**
Descriptor for a plugin library.

To access a plugin library, the host creates an LV2_Lib_Descriptor via the
lv2_lib_descriptor() function in the shared object.
*/
typedef struct {
/**
Opaque library data which must be passed as the first parameter to all
the methods of this struct.
*/
LV2_Lib_Handle handle;

/**
The total size of this struct. This allows for this struct to be
expanded in the future if necessary. This MUST be set by the library to
sizeof(LV2_Lib_Descriptor). The host MUST NOT access any fields of this
struct beyond get_plugin() unless this field indicates they are present.
*/
uint32_t size;

/**
Destroy this library descriptor and free all related resources.
*/
void (*cleanup)(LV2_Lib_Handle handle);

/**
Plugin accessor.

Plugins are accessed by index using values from 0 upwards. Out of range
indices MUST result in this function returning NULL, so the host can
enumerate plugins by increasing @a index until NULL is returned.
*/
const LV2_Descriptor * (*get_plugin)(LV2_Lib_Handle handle,
uint32_t index);
} LV2_Lib_Descriptor;

/**
Prototype for library accessor function.

This is the more advanced discovery API, which allows plugin libraries to
access their bundles during discovery, which makes it possible for plugins to
be dynamically defined by files in their bundle. This API also has an
explicit cleanup function, removing any need for non-portable shared library
destructors. Simple plugins that do not require these features may use
lv2_descriptor() instead.

This is the entry point for a plugin library. Hosts load this symbol from
the library and call this function to obtain a library descriptor which can
be used to access all the contained plugins. The returned object must not
be destroyed (using LV2_Lib_Descriptor::cleanup()) until all plugins loaded
from that library have been destroyed.
*/
const LV2_Lib_Descriptor *
lv2_lib_descriptor(const char * bundle_path,
const LV2_Feature *const * features);

/**
Type of the lv2_lib_descriptor() function in an LV2 library.
*/
typedef const LV2_Lib_Descriptor *
(*LV2_Lib_Descriptor_Function)(const char * bundle_path,
const LV2_Feature *const * features);

#ifdef __cplusplus
}
#endif

#endif /* LV2_H_INCLUDED */

+ 0
- 109
distrho/src/lv2/lv2_external_ui.h View File

@@ -1,109 +0,0 @@
/*
LV2 External UI extension
This work is in public domain.

This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

If you have questions, contact Filipe Coelho (aka falkTX) <falktx@falktx.com>
or ask in #lad channel, FreeNode IRC network.
*/

/**
@file lv2_external_ui.h
C header for the LV2 External UI extension <http://kxstudio.sf.net/ns/lv2ext/external-ui>.
*/

#ifndef LV2_EXTERNAL_UI_H
#define LV2_EXTERNAL_UI_H

#include "ui.h"

#define LV2_EXTERNAL_UI_URI "http://kxstudio.sf.net/ns/lv2ext/external-ui"
#define LV2_EXTERNAL_UI_PREFIX LV2_EXTERNAL_UI_URI "#"

#define LV2_EXTERNAL_UI__Host LV2_EXTERNAL_UI_PREFIX "Host"
#define LV2_EXTERNAL_UI__Widget LV2_EXTERNAL_UI_PREFIX "Widget"

/** This extension used to be defined by a lv2plug.in URI */
#define LV2_EXTERNAL_UI_DEPRECATED_URI "http://lv2plug.in/ns/extensions/ui#external"

#ifdef __cplusplus
extern "C" {
#endif

/**
* When LV2_EXTERNAL_UI__Widget UI is instantiated, the returned
* LV2UI_Widget handle must be cast to pointer to LV2_External_UI_Widget.
* UI is created in invisible state.
*/
typedef struct _LV2_External_UI_Widget {
/**
* Host calls this function regulary. UI library implementing the
* callback may do IPC or redraw the UI.
*
* @param _this_ the UI context
*/
void (*run)(struct _LV2_External_UI_Widget * _this_);

/**
* Host calls this function to make the plugin UI visible.
*
* @param _this_ the UI context
*/
void (*show)(struct _LV2_External_UI_Widget * _this_);

/**
* Host calls this function to make the plugin UI invisible again.
*
* @param _this_ the UI context
*/
void (*hide)(struct _LV2_External_UI_Widget * _this_);

} LV2_External_UI_Widget;

#define LV2_EXTERNAL_UI_RUN(ptr) (ptr)->run(ptr)
#define LV2_EXTERNAL_UI_SHOW(ptr) (ptr)->show(ptr)
#define LV2_EXTERNAL_UI_HIDE(ptr) (ptr)->hide(ptr)

/**
* On UI instantiation, host must supply LV2_EXTERNAL_UI__Host feature.
* LV2_Feature::data must be pointer to LV2_External_UI_Host.
*/
typedef struct _LV2_External_UI_Host {
/**
* Callback that plugin UI will call when UI (GUI window) is closed by user.
* This callback will be called during execution of LV2_External_UI_Widget::run()
* (i.e. not from background thread).
*
* After this callback is called, UI is defunct. Host must call LV2UI_Descriptor::cleanup().
* If host wants to make the UI visible again, the UI must be reinstantiated.
*
* @note When using the depreated URI LV2_EXTERNAL_UI_DEPRECATED_URI,
* some hosts will not call LV2UI_Descriptor::cleanup() as they should,
* and may call show() again without re-initialization.
*
* @param controller Host context associated with plugin UI, as
* supplied to LV2UI_Descriptor::instantiate().
*/
void (*ui_closed)(LV2UI_Controller controller);

/**
* Optional (may be NULL) "user friendly" identifier which the UI
* may display to allow a user to easily associate this particular
* UI instance with the correct plugin instance as it is represented
* by the host (e.g. "track 1" or "channel 4").
*
* If supplied by host, the string will be referenced only during
* LV2UI_Descriptor::instantiate()
*/
const char * plugin_human_id;

} LV2_External_UI_Host;

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

#endif /* LV2_EXTERNAL_UI_H */

+ 0
- 33
distrho/src/lv2/lv2_kxstudio_properties.h View File

@@ -1,33 +0,0 @@
/*
LV2 KXStudio Properties Extension
Copyright 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.

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 lv2_kxstudio_properties.h
C header for the LV2 KXStudio Properties extension <http://kxstudio.sf.net/ns/lv2ext/props>.
*/

#ifndef LV2_KXSTUDIO_PROPERTIES_H
#define LV2_KXSTUDIO_PROPERTIES_H

#define LV2_KXSTUDIO_PROPERTIES_URI "http://kxstudio.sf.net/ns/lv2ext/props"
#define LV2_KXSTUDIO_PROPERTIES_PREFIX LV2_KXSTUDIO_PROPERTIES_URI "#"

#define LV2_KXSTUDIO_PROPERTIES__NonAutomable LV2_KXSTUDIO_PROPERTIES_PREFIX "NonAutomable"
#define LV2_KXSTUDIO_PROPERTIES__TimePositionTicksPerBeat LV2_KXSTUDIO_PROPERTIES_PREFIX "TimePositionTicksPerBeat"
#define LV2_KXSTUDIO_PROPERTIES__TransientWindowId LV2_KXSTUDIO_PROPERTIES_PREFIX "TransientWindowId"

#endif /* LV2_KXSTUDIO_PROPERTIES_H */

+ 0
- 174
distrho/src/lv2/lv2_programs.h View File

@@ -1,174 +0,0 @@
/*
LV2 Programs Extension
Copyright 2012 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.

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 lv2_programs.h
C header for the LV2 programs extension <http://kxstudio.sf.net/ns/lv2ext/programs>.
*/

#ifndef LV2_PROGRAMS_H
#define LV2_PROGRAMS_H

#include "lv2.h"
#include "ui.h"

#define LV2_PROGRAMS_URI "http://kxstudio.sf.net/ns/lv2ext/programs"
#define LV2_PROGRAMS_PREFIX LV2_PROGRAMS_URI "#"

#define LV2_PROGRAMS__Host LV2_PROGRAMS_PREFIX "Host"
#define LV2_PROGRAMS__Interface LV2_PROGRAMS_PREFIX "Interface"
#define LV2_PROGRAMS__UIInterface LV2_PROGRAMS_PREFIX "UIInterface"

#ifdef __cplusplus
extern "C" {
#endif

typedef void* LV2_Programs_Handle;

typedef struct _LV2_Program_Descriptor {

/** Bank number for this program. Note that this extension does not
support MIDI-style separation of bank LSB and MSB values. There is
no restriction on the set of available banks: the numbers do not
need to be contiguous, there does not need to be a bank 0, etc. */
uint32_t bank;

/** Program number (unique within its bank) for this program. There is
no restriction on the set of available programs: the numbers do not
need to be contiguous, there does not need to be a program 0, etc. */
uint32_t program;

/** Name of the program. */
const char * name;

} LV2_Program_Descriptor;

/**
Programs extension, plugin data.

When the plugin's extension_data is called with argument LV2_PROGRAMS__Interface,
the plugin MUST return an LV2_Programs_Instance structure, which remains valid
for the lifetime of the plugin.
*/
typedef struct _LV2_Programs_Interface {
/**
* get_program()
*
* This member is a function pointer that provides a description
* of a program (named preset sound) available on this plugin.
*
* The index argument is an index into the plugin's list of
* programs, not a program number as represented by the Program
* field of the LV2_Program_Descriptor. (This distinction is
* needed to support plugins that use non-contiguous program or
* bank numbers.)
*
* This function returns a LV2_Program_Descriptor pointer that is
* guaranteed to be valid only until the next call to get_program
* or deactivate, on the same plugin instance. This function must
* return NULL if passed an index argument out of range, so that
* the host can use it to query the number of programs as well as
* their properties.
*/
const LV2_Program_Descriptor *(*get_program)(LV2_Handle handle,
uint32_t index);

/**
* select_program()
*
* This member is a function pointer that selects a new program
* for this plugin. The program change should take effect
* immediately at the start of the next run() call. (This
* means that a host providing the capability of changing programs
* between any two notes on a track must vary the block size so as
* to place the program change at the right place. A host that
* wanted to avoid this would probably just instantiate a plugin
* for each program.)
*
* Plugins should ignore a select_program() call with an invalid
* bank or program.
*
* A plugin is not required to select any particular default
* program on activate(): it's the host's duty to set a program
* explicitly.
*
* A plugin is permitted to re-write the values of its input
* control ports when select_program is called. The host should
* re-read the input control port values and update its own
* records appropriately. (This is the only circumstance in which
* a LV2 plugin is allowed to modify its own control-input ports.)
*/
void (*select_program)(LV2_Handle handle,
uint32_t bank,
uint32_t program);

} LV2_Programs_Interface;

/**
Programs extension, UI data.

When the UI's extension_data is called with argument LV2_PROGRAMS__UIInterface,
the UI MUST return an LV2_Programs_UI_Interface structure, which remains valid
for the lifetime of the UI.
*/
typedef struct _LV2_Programs_UI_Interface {
/**
* select_program()
*
* This is exactly the same as select_program in LV2_Programs_Instance,
* but this struct relates to the UI instead of the plugin.
*
* When called, UIs should update their state to match the selected program.
*/
void (*select_program)(LV2UI_Handle handle,
uint32_t bank,
uint32_t program);

} LV2_Programs_UI_Interface;

/**
Feature data for LV2_PROGRAMS__Host.
*/
typedef struct _LV2_Programs_Host {
/**
* Opaque host data.
*/
LV2_Programs_Handle handle;

/**
* program_changed()
*
* Tell the host to reload a plugin's program.
* Parameter handle MUST be the 'handle' member of this struct.
* Parameter index is program index to change.
* When index is -1, host should reload all the programs.
*
* The plugin MUST NEVER call this function on a RT context or during run().
*
* NOTE: This call is to inform the host about a program's bank, program or name change.
* It DOES NOT change the current selected program.
*/
void (*program_changed)(LV2_Programs_Handle handle,
int32_t index);

} LV2_Programs_Host;

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

#endif /* LV2_PROGRAMS_H */

+ 0
- 119
distrho/src/lv2/lv2_rtmempool.h View File

@@ -1,119 +0,0 @@
/*
LV2 realtime safe memory pool extension definition
This work is in public domain.

This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

If you have questions, contact Filipe Coelho (aka falkTX) <falktx@falktx.com>
or ask in #lad channel, FreeNode IRC network.
*/

/**
* @file lv2_rtmempool.h
* C header for the LV2 rtmempool extension <http://kxstudio.sf.net/ns/lv2ext/rtmempool>.
*
*/

#ifndef LV2_RTMEMPOOL_H
#define LV2_RTMEMPOOL_H

#define LV2_RTSAFE_MEMORY_POOL_URI "http://kxstudio.sf.net/ns/lv2ext/rtmempool"
#define LV2_RTSAFE_MEMORY_POOL_PREFIX LV2_RTSAFE_MEMORY_POOL_URI "#"

#define LV2_RTSAFE_MEMORY_POOL__Pool LV2_RTSAFE_MEMORY_POOL_URI "Pool"

/** max size of memory pool name, in chars, including terminating zero char */
#define LV2_RTSAFE_MEMORY_POOL_NAME_MAX 128

/** This extension used to be defined by a different URI */
#define LV2_RTSAFE_MEMORY_POOL_DEPRECATED_URI "http://home.gna.org/lv2dynparam/rtmempool/v1"

#ifdef __cplusplus
extern "C" {
#else
#include <stdbool.h>
#endif

/**
* Opaque data to host data for LV2_RtMemPool_Pool.
*/
typedef void* LV2_RtMemPool_Handle;

/**
* On instantiation, host must supply LV2_RTSAFE_MEMORY_POOL__Pool feature.
* LV2_Feature::data must be pointer to LV2_RtMemPool_Pool.
*/
typedef struct _LV2_RtMemPool_Pool {
/**
* This function is called when plugin wants to create memory pool
*
* <b>may/will sleep</b>
*
* @param pool_name pool name, for debug purposes, max RTSAFE_MEMORY_POOL_NAME_MAX chars, including terminating zero char. May be NULL.
* @param data_size memory chunk size
* @param min_preallocated min chunks preallocated
* @param max_preallocated max chunks preallocated
*
* @return Success status, true if successful
*/
bool (*create)(LV2_RtMemPool_Handle * handle_ptr,
const char * pool_name,
size_t data_size,
size_t min_preallocated,
size_t max_preallocated);

/**
* This function is called when plugin wants to destroy previously created memory pool
*
* <b>may/will sleep</b>
*/
void (*destroy)(LV2_RtMemPool_Handle handle);

/**
* This function is called when plugin wants to allocate memory in context where sleeping is not allowed
*
* <b>will not sleep</b>
*
* @return Pointer to allocated memory or NULL if memory no memory is available
*/
void * (*allocate_atomic)(LV2_RtMemPool_Handle handle);

/**
* This function is called when plugin wants to allocate memory in context where sleeping is allowed
*
* <b>may/will sleep</b>
*
* @return Pointer to allocated memory or NULL if memory no memory is available (should not happen under normal conditions)
*/
void * (*allocate_sleepy)(LV2_RtMemPool_Handle handle);

/**
* This function is called when plugin wants to deallocate previously allocated memory
*
* <b>will not sleep</b>
*
* @param memory_ptr pointer to previously allocated memory chunk
*/
void (*deallocate)(LV2_RtMemPool_Handle handle,
void * memory_ptr);

} LV2_RtMemPool_Pool;

/**
* Deprecated feature for backwards compatibility.
*/
typedef struct _LV2_RtMemPool_Pool_Deprecated {
unsigned char (*create)(const char*,size_t,size_t,size_t,LV2_RtMemPool_Handle*);
void (*destroy)(LV2_RtMemPool_Handle);
void* (*allocate_atomic)(LV2_RtMemPool_Handle);
void* (*allocate_sleepy)(LV2_RtMemPool_Handle);
void (*deallocate)(LV2_RtMemPool_Handle,void*);
} LV2_RtMemPool_Pool_Deprecated;

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

#endif /* LV2_RTMEMPOOL_H */

+ 0
- 226
distrho/src/lv2/midi.h View File

@@ -1,226 +0,0 @@
/*
Copyright 2012 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 midi.h
C definitions for the LV2 MIDI extension <http://lv2plug.in/ns/ext/midi>.
*/

#ifndef LV2_MIDI_H
#define LV2_MIDI_H

#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#else
# include <stdbool.h>
#endif

#define LV2_MIDI_URI "http://lv2plug.in/ns/ext/midi"
#define LV2_MIDI_PREFIX LV2_MIDI_URI "#"

#define LV2_MIDI__ActiveSense LV2_MIDI_PREFIX "ActiveSense"
#define LV2_MIDI__Aftertouch LV2_MIDI_PREFIX "Aftertouch"
#define LV2_MIDI__Bender LV2_MIDI_PREFIX "Bender"
#define LV2_MIDI__ChannelPressure LV2_MIDI_PREFIX "ChannelPressure"
#define LV2_MIDI__Chunk LV2_MIDI_PREFIX "Chunk"
#define LV2_MIDI__Clock LV2_MIDI_PREFIX "Clock"
#define LV2_MIDI__Continue LV2_MIDI_PREFIX "Continue"
#define LV2_MIDI__Controller LV2_MIDI_PREFIX "Controller"
#define LV2_MIDI__MidiEvent LV2_MIDI_PREFIX "MidiEvent"
#define LV2_MIDI__NoteOff LV2_MIDI_PREFIX "NoteOff"
#define LV2_MIDI__NoteOn LV2_MIDI_PREFIX "NoteOn"
#define LV2_MIDI__ProgramChange LV2_MIDI_PREFIX "ProgramChange"
#define LV2_MIDI__QuarterFrame LV2_MIDI_PREFIX "QuarterFrame"
#define LV2_MIDI__Reset LV2_MIDI_PREFIX "Reset"
#define LV2_MIDI__SongPosition LV2_MIDI_PREFIX "SongPosition"
#define LV2_MIDI__SongSelect LV2_MIDI_PREFIX "SongSelect"
#define LV2_MIDI__Start LV2_MIDI_PREFIX "Start"
#define LV2_MIDI__Stop LV2_MIDI_PREFIX "Stop"
#define LV2_MIDI__SystemCommon LV2_MIDI_PREFIX "SystemCommon"
#define LV2_MIDI__SystemExclusive LV2_MIDI_PREFIX "SystemExclusive"
#define LV2_MIDI__SystemMessage LV2_MIDI_PREFIX "SystemMessage"
#define LV2_MIDI__SystemRealtime LV2_MIDI_PREFIX "SystemRealtime"
#define LV2_MIDI__Tick LV2_MIDI_PREFIX "Tick"
#define LV2_MIDI__TuneRequest LV2_MIDI_PREFIX "TuneRequest"
#define LV2_MIDI__VoiceMessage LV2_MIDI_PREFIX "VoiceMessage"
#define LV2_MIDI__benderValue LV2_MIDI_PREFIX "benderValue"
#define LV2_MIDI__binding LV2_MIDI_PREFIX "binding"
#define LV2_MIDI__byteNumber LV2_MIDI_PREFIX "byteNumber"
#define LV2_MIDI__channel LV2_MIDI_PREFIX "channel"
#define LV2_MIDI__chunk LV2_MIDI_PREFIX "chunk"
#define LV2_MIDI__controllerNumber LV2_MIDI_PREFIX "controllerNumber"
#define LV2_MIDI__controllerValue LV2_MIDI_PREFIX "controllerValue"
#define LV2_MIDI__noteNumber LV2_MIDI_PREFIX "noteNumber"
#define LV2_MIDI__pressure LV2_MIDI_PREFIX "pressure"
#define LV2_MIDI__programNumber LV2_MIDI_PREFIX "programNumber"
#define LV2_MIDI__property LV2_MIDI_PREFIX "property"
#define LV2_MIDI__songNumber LV2_MIDI_PREFIX "songNumber"
#define LV2_MIDI__songPosition LV2_MIDI_PREFIX "songPosition"
#define LV2_MIDI__status LV2_MIDI_PREFIX "status"
#define LV2_MIDI__statusMask LV2_MIDI_PREFIX "statusMask"
#define LV2_MIDI__velocity LV2_MIDI_PREFIX "velocity"

/**
MIDI Message Type.

This includes both voice messages (which have a channel) and system messages
(which do not), as well as a sentinel value for invalid messages. To get
the type of a message suitable for use in a switch statement, use
lv2_midi_get_type() on the status byte.
*/
typedef enum {
LV2_MIDI_MSG_INVALID = 0, /**< Invalid Message */
LV2_MIDI_MSG_NOTE_OFF = 0x80, /**< Note Off */
LV2_MIDI_MSG_NOTE_ON = 0x90, /**< Note On */
LV2_MIDI_MSG_NOTE_PRESSURE = 0xA0, /**< Note Pressure */
LV2_MIDI_MSG_CONTROLLER = 0xB0, /**< Controller */
LV2_MIDI_MSG_PGM_CHANGE = 0xC0, /**< Program Change */
LV2_MIDI_MSG_CHANNEL_PRESSURE = 0xD0, /**< Channel Pressure */
LV2_MIDI_MSG_BENDER = 0xE0, /**< Pitch Bender */
LV2_MIDI_MSG_SYSTEM_EXCLUSIVE = 0xF0, /**< System Exclusive Begin */
LV2_MIDI_MSG_MTC_QUARTER = 0xF1, /**< MTC Quarter Frame */
LV2_MIDI_MSG_SONG_POS = 0xF2, /**< Song Position */
LV2_MIDI_MSG_SONG_SELECT = 0xF3, /**< Song Select */
LV2_MIDI_MSG_TUNE_REQUEST = 0xF6, /**< Tune Request */
LV2_MIDI_MSG_CLOCK = 0xF8, /**< Clock */
LV2_MIDI_MSG_START = 0xFA, /**< Start */
LV2_MIDI_MSG_CONTINUE = 0xFB, /**< Continue */
LV2_MIDI_MSG_STOP = 0xFC, /**< Stop */
LV2_MIDI_MSG_ACTIVE_SENSE = 0xFE, /**< Active Sensing */
LV2_MIDI_MSG_RESET = 0xFF /**< Reset */
} LV2_Midi_Message_Type;

/**
Standard MIDI Controller Numbers.
*/
typedef enum {
LV2_MIDI_CTL_MSB_BANK = 0x00, /**< Bank Selection */
LV2_MIDI_CTL_MSB_MODWHEEL = 0x01, /**< Modulation */
LV2_MIDI_CTL_MSB_BREATH = 0x02, /**< Breath */
LV2_MIDI_CTL_MSB_FOOT = 0x04, /**< Foot */
LV2_MIDI_CTL_MSB_PORTAMENTO_TIME = 0x05, /**< Portamento Time */
LV2_MIDI_CTL_MSB_DATA_ENTRY = 0x06, /**< Data Entry */
LV2_MIDI_CTL_MSB_MAIN_VOLUME = 0x07, /**< Main Volume */
LV2_MIDI_CTL_MSB_BALANCE = 0x08, /**< Balance */
LV2_MIDI_CTL_MSB_PAN = 0x0A, /**< Panpot */
LV2_MIDI_CTL_MSB_EXPRESSION = 0x0B, /**< Expression */
LV2_MIDI_CTL_MSB_EFFECT1 = 0x0C, /**< Effect1 */
LV2_MIDI_CTL_MSB_EFFECT2 = 0x0D, /**< Effect2 */
LV2_MIDI_CTL_MSB_GENERAL_PURPOSE1 = 0x10, /**< General Purpose 1 */
LV2_MIDI_CTL_MSB_GENERAL_PURPOSE2 = 0x11, /**< General Purpose 2 */
LV2_MIDI_CTL_MSB_GENERAL_PURPOSE3 = 0x12, /**< General Purpose 3 */
LV2_MIDI_CTL_MSB_GENERAL_PURPOSE4 = 0x13, /**< General Purpose 4 */
LV2_MIDI_CTL_LSB_BANK = 0x20, /**< Bank Selection */
LV2_MIDI_CTL_LSB_MODWHEEL = 0x21, /**< Modulation */
LV2_MIDI_CTL_LSB_BREATH = 0x22, /**< Breath */
LV2_MIDI_CTL_LSB_FOOT = 0x24, /**< Foot */
LV2_MIDI_CTL_LSB_PORTAMENTO_TIME = 0x25, /**< Portamento Time */
LV2_MIDI_CTL_LSB_DATA_ENTRY = 0x26, /**< Data Entry */
LV2_MIDI_CTL_LSB_MAIN_VOLUME = 0x27, /**< Main Volume */
LV2_MIDI_CTL_LSB_BALANCE = 0x28, /**< Balance */
LV2_MIDI_CTL_LSB_PAN = 0x2A, /**< Panpot */
LV2_MIDI_CTL_LSB_EXPRESSION = 0x2B, /**< Expression */
LV2_MIDI_CTL_LSB_EFFECT1 = 0x2C, /**< Effect1 */
LV2_MIDI_CTL_LSB_EFFECT2 = 0x2D, /**< Effect2 */
LV2_MIDI_CTL_LSB_GENERAL_PURPOSE1 = 0x30, /**< General Purpose 1 */
LV2_MIDI_CTL_LSB_GENERAL_PURPOSE2 = 0x31, /**< General Purpose 2 */
LV2_MIDI_CTL_LSB_GENERAL_PURPOSE3 = 0x32, /**< General Purpose 3 */
LV2_MIDI_CTL_LSB_GENERAL_PURPOSE4 = 0x33, /**< General Purpose 4 */
LV2_MIDI_CTL_SUSTAIN = 0x40, /**< Sustain Pedal */
LV2_MIDI_CTL_PORTAMENTO = 0x41, /**< Portamento */
LV2_MIDI_CTL_SOSTENUTO = 0x42, /**< Sostenuto */
LV2_MIDI_CTL_SOFT_PEDAL = 0x43, /**< Soft Pedal */
LV2_MIDI_CTL_LEGATO_FOOTSWITCH = 0x44, /**< Legato Foot Switch */
LV2_MIDI_CTL_HOLD2 = 0x45, /**< Hold2 */
LV2_MIDI_CTL_SC1_SOUND_VARIATION = 0x46, /**< SC1 Sound Variation */
LV2_MIDI_CTL_SC2_TIMBRE = 0x47, /**< SC2 Timbre */
LV2_MIDI_CTL_SC3_RELEASE_TIME = 0x48, /**< SC3 Release Time */
LV2_MIDI_CTL_SC4_ATTACK_TIME = 0x49, /**< SC4 Attack Time */
LV2_MIDI_CTL_SC5_BRIGHTNESS = 0x4A, /**< SC5 Brightness */
LV2_MIDI_CTL_SC6 = 0x4B, /**< SC6 */
LV2_MIDI_CTL_SC7 = 0x4C, /**< SC7 */
LV2_MIDI_CTL_SC8 = 0x4D, /**< SC8 */
LV2_MIDI_CTL_SC9 = 0x4E, /**< SC9 */
LV2_MIDI_CTL_SC10 = 0x4F, /**< SC10 */
LV2_MIDI_CTL_GENERAL_PURPOSE5 = 0x50, /**< General Purpose 5 */
LV2_MIDI_CTL_GENERAL_PURPOSE6 = 0x51, /**< General Purpose 6 */
LV2_MIDI_CTL_GENERAL_PURPOSE7 = 0x52, /**< General Purpose 7 */
LV2_MIDI_CTL_GENERAL_PURPOSE8 = 0x53, /**< General Purpose 8 */
LV2_MIDI_CTL_PORTAMENTO_CONTROL = 0x54, /**< Portamento Control */
LV2_MIDI_CTL_E1_REVERB_DEPTH = 0x5B, /**< E1 Reverb Depth */
LV2_MIDI_CTL_E2_TREMOLO_DEPTH = 0x5C, /**< E2 Tremolo Depth */
LV2_MIDI_CTL_E3_CHORUS_DEPTH = 0x5D, /**< E3 Chorus Depth */
LV2_MIDI_CTL_E4_DETUNE_DEPTH = 0x5E, /**< E4 Detune Depth */
LV2_MIDI_CTL_E5_PHASER_DEPTH = 0x5F, /**< E5 Phaser Depth */
LV2_MIDI_CTL_DATA_INCREMENT = 0x60, /**< Data Increment */
LV2_MIDI_CTL_DATA_DECREMENT = 0x61, /**< Data Decrement */
LV2_MIDI_CTL_NRPN_LSB = 0x62, /**< Non-registered Parameter Number */
LV2_MIDI_CTL_NRPN_MSB = 0x63, /**< Non-registered Parameter Number */
LV2_MIDI_CTL_RPN_LSB = 0x64, /**< Registered Parameter Number */
LV2_MIDI_CTL_RPN_MSB = 0x65, /**< Registered Parameter Number */
LV2_MIDI_CTL_ALL_SOUNDS_OFF = 0x78, /**< All Sounds Off */
LV2_MIDI_CTL_RESET_CONTROLLERS = 0x79, /**< Reset Controllers */
LV2_MIDI_CTL_LOCAL_CONTROL_SWITCH = 0x7A, /**< Local Control Switch */
LV2_MIDI_CTL_ALL_NOTES_OFF = 0x7B, /**< All Notes Off */
LV2_MIDI_CTL_OMNI_OFF = 0x7C, /**< Omni Off */
LV2_MIDI_CTL_OMNI_ON = 0x7D, /**< Omni On */
LV2_MIDI_CTL_MONO1 = 0x7E, /**< Mono1 */
LV2_MIDI_CTL_MONO2 = 0x7F /**< Mono2 */
} LV2_Midi_Controller;

/**
Return true iff @p msg is a MIDI voice message (which has a channel).
*/
static inline bool
lv2_midi_is_voice_message(const uint8_t* msg) {
return msg[0] >= 0x80 && msg[0] < 0xF0;
}

/**
Return true iff @p msg is a MIDI system message (which has no channel).
*/
static inline bool
lv2_midi_is_system_message(const uint8_t* msg) {
switch (msg[0]) {
case 0xF4: case 0xF5: case 0xF7: case 0xF9: case 0xFD:
return false;
default:
return (msg[0] & 0xF0) == 0xF0;
}
}

/**
Return the type of a MIDI message.
@param msg Pointer to the start (status byte) of a MIDI message.
*/
static inline LV2_Midi_Message_Type
lv2_midi_message_type(const uint8_t* msg) {
if (lv2_midi_is_voice_message(msg)) {
return (LV2_Midi_Message_Type)(msg[0] & 0xF0);
} else if (lv2_midi_is_system_message(msg)) {
return (LV2_Midi_Message_Type)msg[0];
} else {
return LV2_MIDI_MSG_INVALID;
}
}

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

#endif /* LV2_MIDI_H */

+ 0
- 34
distrho/src/lv2/morph.h View File

@@ -1,34 +0,0 @@
/*
Copyright 2012 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 LV2_MORPH_H
#define LV2_MORPH_H

#include <stdint.h>

#include "lv2.h"
#include "urid.h"

#define LV2_MORPH_URI "http://lv2plug.in/ns/ext/morph"
#define LV2_MORPH_PREFIX LV2_MORPH_URI "#"

#define LV2_MORPH__AutoMorphPort LV2_MORPH_PREFIX "AutoMorphPort"
#define LV2_MORPH__MorphPort LV2_MORPH_PREFIX "MorphPort"
#define LV2_MORPH__interface LV2_MORPH_PREFIX "interface"
#define LV2_MORPH__supportsType LV2_MORPH_PREFIX "supportsType"
#define LV2_MORPH__currentType LV2_MORPH_PREFIX "currentType"

#endif /* LV2_MORPH_H */

+ 0
- 132
distrho/src/lv2/options.h View File

@@ -1,132 +0,0 @@
/*
Copyright 2012 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 LV2_OPTIONS_H
#define LV2_OPTIONS_H

#include <stdint.h>

#include "urid.h"
#include "lv2.h"

#define LV2_OPTIONS_URI "http://lv2plug.in/ns/ext/options"
#define LV2_OPTIONS_PREFIX LV2_OPTIONS_URI "#"

#define LV2_OPTIONS__Option LV2_OPTIONS_PREFIX "Option"
#define LV2_OPTIONS__interface LV2_OPTIONS_PREFIX "interface"
#define LV2_OPTIONS__options LV2_OPTIONS_PREFIX "options"
#define LV2_OPTIONS__requiredOption LV2_OPTIONS_PREFIX "requiredOption"
#define LV2_OPTIONS__supportedOption LV2_OPTIONS_PREFIX "supportedOption"

#ifdef __cplusplus
extern "C" {
#endif

/**
The context of an Option, which defines the subject it applies to.
*/
typedef enum {
/**
This option applies to the instance itself. The subject must be
ignored.
*/
LV2_OPTIONS_INSTANCE,

/**
This option applies to some named resource. The subject is a URI mapped
to an integer (a LV2_URID, like the key)
*/
LV2_OPTIONS_RESOURCE,

/**
This option applies to some blank node. The subject is a blank node
identifier, which is valid only within the current local scope.
*/
LV2_OPTIONS_BLANK,

/**
This option applies to a port on the instance. The subject is the
port's index.
*/
LV2_OPTIONS_PORT
} LV2_Options_Context;

/**
An option.

This is a property with a subject, also known as a triple or statement.

This struct is useful anywhere a statement needs to be passed where no
memory ownership issues are present (since the value is a const pointer).

Options can be passed to an instance via the feature LV2_OPTIONS__options
with data pointed to an array of options terminated by a zeroed option, or
accessed/manipulated using LV2_Options_Interface.
*/
typedef struct _LV2_Options_Option {
LV2_Options_Context context; /**< Context (type of subject). */
uint32_t subject; /**< Subject. */
LV2_URID key; /**< Key (property). */
uint32_t size; /**< Size of value in bytes. */
LV2_URID type; /**< Type of value (datatype). */
const void* value; /**< Pointer to value (object). */
} LV2_Options_Option;

/** A status code for option functions. */
typedef enum {
LV2_OPTIONS_SUCCESS = 0, /**< Completed successfully. */
LV2_OPTIONS_ERR_UNKNOWN = 1, /**< Unknown error. */
LV2_OPTIONS_ERR_BAD_SUBJECT = 1 << 1, /**< Invalid/unsupported subject. */
LV2_OPTIONS_ERR_BAD_KEY = 1 << 2, /**< Invalid/unsupported key. */
LV2_OPTIONS_ERR_BAD_VALUE = 1 << 3 /**< Invalid/unsupported value. */
} LV2_Options_Status;

/**
Interface for dynamically setting options (LV2_OPTIONS__interface).
*/
typedef struct _LV2_Options_Interface {
/**
Get the given options.

Each element of the passed options array MUST have type, subject, and
key set. All other fields (size, type, value) MUST be initialised to
zero, and are set to the option value if such an option is found.

This function is in the "instantiation" LV2 threading class, so no other
instance functions may be called concurrently.

@return Bitwise OR of LV2_Options_Status values.
*/
uint32_t (*get)(LV2_Handle instance,
LV2_Options_Option* options);

/**
Set the given options.

This function is in the "instantiation" LV2 threading class, so no other
instance functions may be called concurrently.

@return Bitwise OR of LV2_Options_Status values.
*/
uint32_t (*set)(LV2_Handle instance,
const LV2_Options_Option* options);
} LV2_Options_Interface;

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

#endif /* LV2_OPTIONS_H */

+ 0
- 49
distrho/src/lv2/parameters.h View File

@@ -1,49 +0,0 @@
/*
Copyright 2012 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 LV2_PARAMETERS_H
#define LV2_PARAMETERS_H

#define LV2_PARAMETERS_URI "http://lv2plug.in/ns/ext/parameters"
#define LV2_PARAMETERS_PREFIX LV2_PARAMETERS_URI "#"

#define LV2_PARAMETERS__CompressorControls LV2_PARAMETERS_PREFIX "CompressorControls"
#define LV2_PARAMETERS__ControlGroup LV2_PARAMETERS_PREFIX "ControlGroup"
#define LV2_PARAMETERS__EnvelopeControls LV2_PARAMETERS_PREFIX "EnvelopeControls"
#define LV2_PARAMETERS__FilterControls LV2_PARAMETERS_PREFIX "FilterControls"
#define LV2_PARAMETERS__OscillatorControls LV2_PARAMETERS_PREFIX "OscillatorControls"
#define LV2_PARAMETERS__amplitude LV2_PARAMETERS_PREFIX "amplitude"
#define LV2_PARAMETERS__attack LV2_PARAMETERS_PREFIX "attack"
#define LV2_PARAMETERS__bypass LV2_PARAMETERS_PREFIX "bypass"
#define LV2_PARAMETERS__cutoffFrequency LV2_PARAMETERS_PREFIX "cutoffFrequency"
#define LV2_PARAMETERS__decay LV2_PARAMETERS_PREFIX "decay"
#define LV2_PARAMETERS__delay LV2_PARAMETERS_PREFIX "delay"
#define LV2_PARAMETERS__dryLevel LV2_PARAMETERS_PREFIX "dryLevel"
#define LV2_PARAMETERS__frequency LV2_PARAMETERS_PREFIX "frequency"
#define LV2_PARAMETERS__gain LV2_PARAMETERS_PREFIX "gain"
#define LV2_PARAMETERS__hold LV2_PARAMETERS_PREFIX "hold"
#define LV2_PARAMETERS__pulseWidth LV2_PARAMETERS_PREFIX "pulseWidth"
#define LV2_PARAMETERS__ratio LV2_PARAMETERS_PREFIX "ratio"
#define LV2_PARAMETERS__release LV2_PARAMETERS_PREFIX "release"
#define LV2_PARAMETERS__resonance LV2_PARAMETERS_PREFIX "resonance"
#define LV2_PARAMETERS__sampleRate LV2_PARAMETERS_PREFIX "sampleRate"
#define LV2_PARAMETERS__sustain LV2_PARAMETERS_PREFIX "sustain"
#define LV2_PARAMETERS__threshold LV2_PARAMETERS_PREFIX "threshold"
#define LV2_PARAMETERS__waveform LV2_PARAMETERS_PREFIX "waveform"
#define LV2_PARAMETERS__wetDryRatio LV2_PARAMETERS_PREFIX "wetDryRatio"
#define LV2_PARAMETERS__wetLevel LV2_PARAMETERS_PREFIX "wetLevel"

#endif /* LV2_PARAMETERS_H */

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save