@@ -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. |
@@ -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). |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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) | |||
# -------------------------------------------------------------- |
@@ -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 | |||
# -------------------------------------------------------------- |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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" | |||
} | |||
// ----------------------------------------------------------------------- |
@@ -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 |
@@ -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. | |||
@@ -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 |
@@ -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 */ |
@@ -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 */ |
@@ -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 | |||
@@ -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 | |||
@@ -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 */ |
@@ -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 |
@@ -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; | |||
} |
@@ -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; | |||
} |
@@ -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; | |||
} |
@@ -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); |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 ¶m; | |||
} | |||
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 | |||
// ----------------------------------------------------------------------- |
@@ -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 |
@@ -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 |
@@ -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; | |||
} | |||
// ----------------------------------------------------------------------- |
@@ -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 | |||
// ----------------------------------------------------------------------- |
@@ -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; | |||
} | |||
} |
@@ -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 |
@@ -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; | |||
} |
@@ -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 |
@@ -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; | |||
} | |||
// ----------------------------------------------------------------------- |
@@ -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 */ |
@@ -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 */ | |||
@@ -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 */ |
@@ -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 */ |
@@ -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 |
@@ -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 */ |
@@ -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 */ |
@@ -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 */ |
@@ -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 */ |
@@ -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 */ |
@@ -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 */ | |||
@@ -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 */ |
@@ -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 */ | |||
@@ -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 */ |
@@ -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 */ |
@@ -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 | |||
@@ -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 |
@@ -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 */ |
@@ -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 */ |
@@ -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 */ |
@@ -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 */ |
@@ -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 */ |
@@ -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 */ |
@@ -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 */ |
@@ -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 */ |
@@ -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 */ |