@@ -1,5 +1,5 @@ | |||||
# ----------------------------------------- | # ----------------------------------------- | ||||
# Compile all the Plugins and Ports | |||||
# Compile all the Ports | |||||
PREFIX = /usr/local | PREFIX = /usr/local | ||||
@@ -12,7 +12,6 @@ all: | |||||
$(MAKE) -C libs/juce | $(MAKE) -C libs/juce | ||||
$(MAKE) -C libs/juced | $(MAKE) -C libs/juced | ||||
$(MAKE) -C libs/lv2-ttl-generator | $(MAKE) -C libs/lv2-ttl-generator | ||||
$(MAKE) -C plugins plugins | |||||
$(MAKE) -C ports plugins | $(MAKE) -C ports plugins | ||||
$(MAKE) gen | $(MAKE) gen | ||||
@@ -21,7 +20,6 @@ all: | |||||
install: | install: | ||||
# make dirs | # make dirs | ||||
install -d $(DESTDIR)$(PREFIX)/lib/dssi/ | |||||
install -d $(DESTDIR)$(PREFIX)/lib/lv2/ | install -d $(DESTDIR)$(PREFIX)/lib/lv2/ | ||||
install -d $(DESTDIR)$(PREFIX)/lib/vst/ | install -d $(DESTDIR)$(PREFIX)/lib/vst/ | ||||
install -d $(DESTDIR)/usr/src/distrho/libs/juce/build-juce/ | install -d $(DESTDIR)/usr/src/distrho/libs/juce/build-juce/ | ||||
@@ -30,7 +28,6 @@ install: | |||||
install -d $(DESTDIR)/usr/src/distrho/scripts/ | install -d $(DESTDIR)/usr/src/distrho/scripts/ | ||||
# install plugins | # install plugins | ||||
cp -r bin/dssi/* $(DESTDIR)$(PREFIX)/lib/dssi/ | |||||
cp -r bin/lv2/*.lv2/ $(DESTDIR)$(PREFIX)/lib/lv2/ | cp -r bin/lv2/*.lv2/ $(DESTDIR)$(PREFIX)/lib/lv2/ | ||||
cp -r bin/vst/* $(DESTDIR)$(PREFIX)/lib/vst/ | cp -r bin/vst/* $(DESTDIR)$(PREFIX)/lib/vst/ | ||||
cp -r static-lv2-ttl/*.lv2/ $(DESTDIR)$(PREFIX)/lib/lv2/ | cp -r static-lv2-ttl/*.lv2/ $(DESTDIR)$(PREFIX)/lib/lv2/ | ||||
@@ -72,7 +69,6 @@ clean: | |||||
$(MAKE) clean -C libs/juce | $(MAKE) clean -C libs/juce | ||||
$(MAKE) clean -C libs/juced | $(MAKE) clean -C libs/juced | ||||
$(MAKE) clean -C libs/lv2-ttl-generator | $(MAKE) clean -C libs/lv2-ttl-generator | ||||
$(MAKE) clean -C plugins | |||||
$(MAKE) clean -C ports | $(MAKE) clean -C ports | ||||
rm -rf bin/lv2/*.lv2/ | rm -rf bin/lv2/*.lv2/ | ||||
rm -rf bin/lv2-extra/ | rm -rf bin/lv2-extra/ | ||||
@@ -83,7 +79,6 @@ distclean: clean | |||||
$(MAKE) distclean -C libs/drowaudio | $(MAKE) distclean -C libs/drowaudio | ||||
$(MAKE) distclean -C libs/juce | $(MAKE) distclean -C libs/juce | ||||
$(MAKE) distclean -C libs/juced | $(MAKE) distclean -C libs/juced | ||||
$(MAKE) distclean -C plugins | |||||
$(MAKE) distclean -C ports | $(MAKE) distclean -C ports | ||||
# ----------------------------------------- | # ----------------------------------------- | ||||
@@ -95,17 +90,12 @@ mingw: | |||||
# ----------------------------------------- | # ----------------------------------------- | ||||
# Custom build types | # Custom build types | ||||
dssi: | |||||
$(MAKE) -C libs/dgl | |||||
$(MAKE) -C plugins dssi | |||||
lv2: | lv2: | ||||
$(MAKE) -C libs/dgl | $(MAKE) -C libs/dgl | ||||
$(MAKE) -C libs/drowaudio | $(MAKE) -C libs/drowaudio | ||||
$(MAKE) -C libs/juce | $(MAKE) -C libs/juce | ||||
$(MAKE) -C libs/juced | $(MAKE) -C libs/juced | ||||
$(MAKE) -C libs/lv2-ttl-generator | $(MAKE) -C libs/lv2-ttl-generator | ||||
$(MAKE) -C plugins lv2 | |||||
$(MAKE) -C ports lv2 | $(MAKE) -C ports lv2 | ||||
$(MAKE) gen_lv2 | $(MAKE) gen_lv2 | ||||
@@ -114,6 +104,5 @@ vst: | |||||
$(MAKE) -C libs/drowaudio | $(MAKE) -C libs/drowaudio | ||||
$(MAKE) -C libs/juce | $(MAKE) -C libs/juce | ||||
$(MAKE) -C libs/juced | $(MAKE) -C libs/juced | ||||
$(MAKE) -C plugins vst | |||||
$(MAKE) -C ports vst | $(MAKE) -C ports vst | ||||
$(MAKE) gen_vst | $(MAKE) gen_vst |
@@ -3,16 +3,8 @@ | |||||
----------------------- | ----------------------- | ||||
DISTRHO is an open source project that has the goal of making cross-platform plugins and Linux ports. | DISTRHO is an open source project that has the goal of making cross-platform plugins and Linux ports. | ||||
The DISTRHO Team currently has 2 members - falkTX (the coder) and nieee (graphics designer). | |||||
The source repository is layered out this way: | |||||
bin/ - directory where all the compiled binaries will be placed | |||||
libs/ - libraries | |||||
plugins/ - plugins developed and/or designed by the DISTRHO Team | |||||
ports/ - plugin ports (plugins not made by us) | |||||
scripts/ - build scripts | |||||
sdks/ - SDKs must be placed here (VST SDK) | |||||
<b>This repository contains the Linux ports</b>. | |||||
----------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- | ||||
---- BUILD DEPENDENCIES | ---- BUILD DEPENDENCIES | ||||
@@ -22,14 +14,13 @@ To build plugins, you first need to install the following dependencies: | |||||
All OSes: | All OSes: | ||||
- csound (version 6) | - csound (version 6) | ||||
- liblo | |||||
- premake (version 3) | - premake (version 3) | ||||
Linux: (development versions of these) | Linux: (development versions of these) | ||||
- ladspa | - ladspa | ||||
- freetype2 | - freetype2 | ||||
- OpenGL | |||||
- OpenGL/Mesa | |||||
- X11 core and extensions (Xinerama, XShm, XRender and XCursor) | - X11 core and extensions (Xinerama, XShm, XRender and XCursor) | ||||
@@ -47,7 +38,7 @@ You are now ready to start building. Run this on the source root folder: | |||||
$ make | $ make | ||||
If you just want to build specific plugin versions, you can use 'make dssi', 'make lv2' or 'make vst'. | |||||
If you just want to build specific plugin versions, you can use 'make lv2' or 'make vst'. | |||||
To build in debug mode, use this: | To build in debug mode, use this: | ||||
@@ -1,66 +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 | |||||
class Window; | |||||
// ----------------------------------------------------------------------- | |||||
class App | |||||
{ | |||||
public: | |||||
class IdleCallback | |||||
{ | |||||
public: | |||||
virtual ~IdleCallback() {} | |||||
virtual void idleCallback() = 0; | |||||
}; | |||||
App(); | |||||
~App(); | |||||
void idle(); | |||||
void exec(); | |||||
void quit(); | |||||
bool isQuiting() const; | |||||
void addIdleCallback(IdleCallback* const callback); | |||||
void removeIdleCallback(IdleCallback* const callback); | |||||
private: | |||||
struct PrivateData; | |||||
PrivateData* const pData; | |||||
friend class Window; | |||||
void _addWindow(Window* const window); | |||||
void _removeWindow(Window* const window); | |||||
void _oneShown(); | |||||
void _oneHidden(); | |||||
DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(App) | |||||
}; | |||||
// ----------------------------------------------------------------------- | |||||
END_NAMESPACE_DGL | |||||
#endif // DGL_APP_HPP_INCLUDED |
@@ -1,111 +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" | |||||
// ----------------------------------------------------------------------- | |||||
/* 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; | |||||
/* GL includes */ | |||||
#ifdef DISTRHO_OS_MAC | |||||
# include <OpenGL/gl.h> | |||||
#else | |||||
# include <GL/gl.h> | |||||
#endif | |||||
/* missing GL 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 | |||||
START_NAMESPACE_DGL | |||||
// ----------------------------------------------------------------------- | |||||
/* | |||||
* Convenience symbols for ASCII control characters. | |||||
*/ | |||||
enum Char { | |||||
CHAR_BACKSPACE = 0x08, | |||||
CHAR_ESCAPE = 0x1B, | |||||
CHAR_DELETE = 0x7F | |||||
}; | |||||
/* | |||||
* 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 | |||||
}; | |||||
/* | |||||
* 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 */ | |||||
}; | |||||
// ----------------------------------------------------------------------- | |||||
END_NAMESPACE_DGL | |||||
#endif // DGL_BASE_HPP_INCLUDED |
@@ -1,208 +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_CAIRO_WIDGET_HPP_INCLUDED | |||||
#define DGL_CAIRO_WIDGET_HPP_INCLUDED | |||||
#include "Widget.hpp" | |||||
#include <cairo.h> | |||||
#include <cstdio> | |||||
START_NAMESPACE_DGL | |||||
// ----------------------------------------------------------------------- | |||||
class CairoWidget : public Widget | |||||
{ | |||||
public: | |||||
CairoWidget(Window& parent) | |||||
: Widget(parent), | |||||
fContext(nullptr), | |||||
fSurface(nullptr), | |||||
fTextureId(0) | |||||
{ | |||||
} | |||||
virtual void setWidth(int width) override | |||||
{ | |||||
if (fArea.getWidth() == width) | |||||
return; | |||||
Widget::setWidth(width); | |||||
_recreateSurface(); | |||||
} | |||||
virtual void setHeight(int height) override | |||||
{ | |||||
if (fArea.getHeight() == height) | |||||
return; | |||||
Widget::setHeight(height); | |||||
_recreateSurface(); | |||||
} | |||||
virtual void setSize(const Size<int>& size) override | |||||
{ | |||||
if (fArea.getSize() == size) | |||||
return; | |||||
Widget::setSize(size); | |||||
_recreateSurface(); | |||||
} | |||||
void setSize(int width, int height) | |||||
{ | |||||
setSize(Size<int>(width, height)); | |||||
} | |||||
protected: | |||||
virtual void cairoDisplay(cairo_t* const context) = 0; | |||||
private: | |||||
void onDisplay() override | |||||
{ | |||||
// wait for sizing | |||||
if (fSurface == nullptr || fContext == nullptr) | |||||
{ | |||||
printf("invalid surface\n"); | |||||
return; | |||||
} | |||||
if (fTextureId == 0) | |||||
glGenTextures(1, &fTextureId); | |||||
if (fTextureId == 0) | |||||
{ | |||||
// TODO: invalidate widget | |||||
printf("invalid texture\n"); | |||||
return; | |||||
} | |||||
#if 1 | |||||
const int x = getX(); | |||||
const int y = getY(); | |||||
const int width = getWidth(); | |||||
const int height = getHeight(); | |||||
// draw cairo stuff | |||||
cairoDisplay(fContext); | |||||
// get cairo surface data (RGB24) | |||||
unsigned char* const surfaceData = cairo_image_surface_get_data(fSurface); | |||||
// enable GL texture | |||||
glEnable(GL_TEXTURE_RECTANGLE_ARB); | |||||
// set texture params | |||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); | |||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); | |||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | |||||
// bind texture to surface data | |||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, fTextureId); | |||||
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, surfaceData); | |||||
// draw the texture | |||||
// glBegin(GL_QUADS); | |||||
// glTexCoord2f(0.0f, 0.0f); | |||||
// glVertex2i(x, y); | |||||
// | |||||
// glTexCoord2f(1.0f, 0.0f); | |||||
// glVertex2i(x+width, y); | |||||
// | |||||
// glTexCoord2f(1.0f, 1.0f); | |||||
// glVertex2i(x+width, y+height); | |||||
// | |||||
// glTexCoord2f(0.0f, 1.0f); | |||||
// glVertex2i(x, y+height); | |||||
// glEnd(); | |||||
glBegin(GL_QUADS); | |||||
//glTexCoord2i(x, y); | |||||
glTexCoord2i(0, 0); | |||||
glVertex2i(x, y); | |||||
//glTexCoord2i(x+width, y); | |||||
glTexCoord2i(width, 0); | |||||
glVertex2i(x+width, y); | |||||
//glTexCoord2i(x+width, y+height); | |||||
glTexCoord2i(width, height); | |||||
glVertex2i(x+width, y+height); | |||||
//glTexCoord2i(x, y+height); | |||||
glTexCoord2i(0, height); | |||||
glVertex2i(x, y+height); | |||||
glEnd(); | |||||
// cleanup | |||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); | |||||
glDisable(GL_TEXTURE_RECTANGLE_ARB); | |||||
#endif | |||||
} | |||||
void onClose() override | |||||
{ | |||||
if (fContext != nullptr) | |||||
{ | |||||
cairo_destroy(fContext); | |||||
fContext = nullptr; | |||||
} | |||||
if (fSurface != nullptr) | |||||
{ | |||||
cairo_surface_destroy(fSurface); | |||||
fSurface = nullptr; | |||||
} | |||||
if (fTextureId != 0) | |||||
{ | |||||
glDeleteTextures(1, &fTextureId); | |||||
fTextureId = 0; | |||||
} | |||||
} | |||||
void _recreateSurface() | |||||
{ | |||||
if (fContext != nullptr) | |||||
cairo_destroy(fContext); | |||||
if (fSurface != nullptr) | |||||
cairo_surface_destroy(fSurface); | |||||
fSurface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, fArea.getWidth(), fArea.getHeight()); | |||||
if (fSurface != nullptr) | |||||
fContext = cairo_create(fSurface); | |||||
else | |||||
fContext = nullptr; | |||||
} | |||||
private: | |||||
cairo_t* fContext; | |||||
cairo_surface_t* fSurface; | |||||
GLuint fTextureId; | |||||
DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CairoWidget) | |||||
}; | |||||
// ----------------------------------------------------------------------- | |||||
END_NAMESPACE_DGL | |||||
#endif // DGL_CAIRO_WIDGET_HPP_INCLUDED |
@@ -1,139 +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 | |||||
// ----------------------------------------------------------------------- | |||||
template<typename T> | |||||
class Point | |||||
{ | |||||
public: | |||||
Point() noexcept; | |||||
Point(T x, T y) noexcept; | |||||
Point(const Point<T>& pos) noexcept; | |||||
T getX() const noexcept; | |||||
T getY() const noexcept; | |||||
void setX(T x) noexcept; | |||||
void setY(T y) noexcept; | |||||
void move(T x, T y) noexcept; | |||||
void move(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 Rectangle; | |||||
DISTRHO_PREVENT_HEAP_ALLOCATION | |||||
}; | |||||
// ----------------------------------------------------------------------- | |||||
template<typename T> | |||||
class Size | |||||
{ | |||||
public: | |||||
Size() noexcept; | |||||
Size(T width, T height) noexcept; | |||||
Size(const Size<T>& size) noexcept; | |||||
T getWidth() const noexcept; | |||||
T getHeight() const noexcept; | |||||
void setWidth(T width) noexcept; | |||||
void setHeight(T height) 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*=(T m) noexcept; | |||||
Size<T>& operator/=(T 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; | |||||
DISTRHO_PREVENT_HEAP_ALLOCATION | |||||
}; | |||||
// ----------------------------------------------------------------------- | |||||
template<typename T> | |||||
class Rectangle | |||||
{ | |||||
public: | |||||
Rectangle() noexcept; | |||||
Rectangle(T x, T y, T width, T height) noexcept; | |||||
Rectangle(T x, T y, const Size<T>& size) noexcept; | |||||
Rectangle(const Point<T>& pos, T width, T height) noexcept; | |||||
Rectangle(const Point<T>& pos, const Size<T>& size) noexcept; | |||||
Rectangle(const Rectangle<T>& rect) noexcept; | |||||
T getX() const noexcept; | |||||
T getY() const noexcept; | |||||
T getWidth() const noexcept; | |||||
T getHeight() const noexcept; | |||||
const Point<T>& getPos() const noexcept; | |||||
const Size<T>& getSize() const noexcept; | |||||
bool contains(T x, T y) const noexcept; | |||||
bool contains(const Point<T>& pos) const noexcept; | |||||
bool containsX(T x) const noexcept; | |||||
bool containsY(T y) const noexcept; | |||||
void setX(T x) noexcept; | |||||
void setY(T y) noexcept; | |||||
void setPos(T x, T y) noexcept; | |||||
void setPos(const Point<T>& pos) noexcept; | |||||
void move(T x, T y) noexcept; | |||||
void move(const Point<T>& pos) noexcept; | |||||
void setWidth(T width) noexcept; | |||||
void setHeight(T height) noexcept; | |||||
void setSize(T width, T height) noexcept; | |||||
void setSize(const Size<T>& size) noexcept; | |||||
Rectangle<T>& operator=(const Rectangle<T>& rect) noexcept; | |||||
private: | |||||
Point<T> fPos; | |||||
Size<T> fSize; | |||||
DISTRHO_PREVENT_HEAP_ALLOCATION | |||||
}; | |||||
// ----------------------------------------------------------------------- | |||||
END_NAMESPACE_DGL | |||||
#endif // DGL_GEOMETRY_HPP_INCLUDED |
@@ -1,70 +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 | |||||
// ----------------------------------------------------------------------- | |||||
class Image | |||||
{ | |||||
public: | |||||
Image() noexcept; | |||||
Image(const char* rawData, int width, int height, GLenum format = GL_BGRA, GLenum type = GL_UNSIGNED_BYTE) noexcept; | |||||
Image(const char* rawData, const Size<int>& size, GLenum format = GL_BGRA, GLenum type = GL_UNSIGNED_BYTE) noexcept; | |||||
Image(const Image& image) noexcept; | |||||
~Image(); | |||||
void loadFromMemory(const char* rawData, int width, int height, GLenum format = GL_BGRA, GLenum type = GL_UNSIGNED_BYTE) noexcept; | |||||
void loadFromMemory(const char* rawData, const Size<int>& size, GLenum format = GL_BGRA, GLenum type = GL_UNSIGNED_BYTE) noexcept; | |||||
bool isValid() const noexcept; | |||||
int getWidth() const noexcept; | |||||
int getHeight() const noexcept; | |||||
const Size<int>& getSize() const noexcept; | |||||
const char* getRawData() const noexcept; | |||||
GLenum getFormat() const noexcept; | |||||
GLenum getType() const noexcept; | |||||
void draw(); | |||||
void draw(int x, int y); | |||||
void draw(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<int> fSize; | |||||
GLenum fFormat; | |||||
GLenum fType; | |||||
GLuint fTextureId; | |||||
DISTRHO_PREVENT_HEAP_ALLOCATION | |||||
}; | |||||
// ----------------------------------------------------------------------- | |||||
END_NAMESPACE_DGL | |||||
#endif // DGL_IMAGE_HPP_INCLUDED |
@@ -1,58 +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" | |||||
#ifdef PROPER_CPP11_SUPPORT | |||||
# include <cstdint> | |||||
#else | |||||
# include <stdint.h> | |||||
#endif | |||||
START_NAMESPACE_DGL | |||||
// ----------------------------------------------------------------------- | |||||
class ImageAboutWindow : public Window, | |||||
public Widget | |||||
{ | |||||
public: | |||||
ImageAboutWindow(App& app, Window& parent, const Image& image = Image()); | |||||
ImageAboutWindow(Widget* widget, const Image& image = Image()); | |||||
void setImage(const Image& image); | |||||
protected: | |||||
void onDisplay() override; | |||||
bool onMouse(int button, bool press, int x, int y) override; | |||||
bool onKeyboard(bool press, uint32_t key) override; | |||||
private: | |||||
Image fImgBackground; | |||||
DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ImageAboutWindow) | |||||
}; | |||||
// ----------------------------------------------------------------------- | |||||
END_NAMESPACE_DGL | |||||
#endif // DGL_IMAGE_ABOUT_WINDOW_HPP_INCLUDED |
@@ -1,66 +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; | |||||
}; | |||||
ImageButton(Window& parent, const Image& image); | |||||
ImageButton(Widget* widget, const Image& image); | |||||
ImageButton(Window& parent, const Image& imageNormal, const Image& imageHover, const Image& imageDown); | |||||
ImageButton(Widget* widget, const Image& imageNormal, const Image& imageHover, const Image& imageDown); | |||||
ImageButton(const ImageButton& imageButton); | |||||
void setCallback(Callback* callback); | |||||
protected: | |||||
void onDisplay() override; | |||||
bool onMouse(int button, bool press, int x, int y) override; | |||||
bool onMotion(int x, int y) 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,94 +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; | |||||
}; | |||||
ImageKnob(Window& parent, const Image& image, Orientation orientation = Vertical); | |||||
ImageKnob(Widget* widget, const Image& image, Orientation orientation = Vertical); | |||||
ImageKnob(const ImageKnob& imageKnob); | |||||
float getValue() const; | |||||
void setOrientation(Orientation orientation); | |||||
void setRange(float min, float max); | |||||
void setStep(float step); | |||||
void setValue(float value, bool sendCallback = false); | |||||
void setRotationAngle(int angle); | |||||
void setCallback(Callback* callback); | |||||
protected: | |||||
void onDisplay() override; | |||||
bool onMouse(int button, bool press, int x, int y) override; | |||||
bool onMotion(int x, int y) override; | |||||
void onReshape(int width, int height) override; | |||||
void onClose() override; | |||||
private: | |||||
Image fImage; | |||||
float fMinimum; | |||||
float fMaximum; | |||||
float fStep; | |||||
float fValue; | |||||
float fValueTmp; | |||||
Orientation fOrientation; | |||||
int fRotationAngle; | |||||
bool fDragging; | |||||
int fLastX; | |||||
int fLastY; | |||||
Callback* fCallback; | |||||
bool fIsImgVertical; | |||||
int fImgLayerSize; | |||||
int fImgLayerCount; | |||||
Rectangle<int> fKnobArea; | |||||
GLuint fTextureId; | |||||
DISTRHO_LEAK_DETECTOR(ImageKnob) | |||||
}; | |||||
// ----------------------------------------------------------------------- | |||||
END_NAMESPACE_DGL | |||||
#endif // DGL_IMAGE_KNOB_HPP_INCLUDED |
@@ -1,90 +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; | |||||
}; | |||||
ImageSlider(Window& parent, const Image& image); | |||||
ImageSlider(Widget* widget, const Image& image); | |||||
ImageSlider(const ImageSlider& imageSlider); | |||||
float getValue() const; | |||||
void setStartPos(const Point<int>& startPos); | |||||
void setStartPos(int x, int y); | |||||
void setEndPos(const Point<int>& endPos); | |||||
void setEndPos(int x, int y); | |||||
void setInverted(bool inverted); | |||||
void setRange(float min, float max); | |||||
void setStep(float step); | |||||
void setValue(float value, bool sendCallback = false); | |||||
void setCallback(Callback* callback); | |||||
protected: | |||||
void onDisplay() override; | |||||
bool onMouse(int button, bool press, int x, int y) override; | |||||
bool onMotion(int x, int y) 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(); | |||||
DISTRHO_LEAK_DETECTOR(ImageSlider) | |||||
}; | |||||
// ----------------------------------------------------------------------- | |||||
END_NAMESPACE_DGL | |||||
#endif // DGL_IMAGE_SLIDER_HPP_INCLUDED |
@@ -1,21 +0,0 @@ | |||||
# Compile the dgl library | |||||
all: build | |||||
build: dgl | |||||
dgl: | |||||
$(MAKE) -C build | |||||
clean: | |||||
$(MAKE) clean -C build | |||||
rm -rf build-*/intermediate | |||||
distclean: clean | |||||
rm -f build-*/Makefile | |||||
rm -f build-*/*.make | |||||
rm -f build-*/*.sln | |||||
rm -f build-*/*.vcproj |
@@ -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 "Window.hpp" | |||||
START_NAMESPACE_DGL | |||||
// ----------------------------------------------------------------------- | |||||
class StandaloneWindow | |||||
{ | |||||
public: | |||||
StandaloneWindow() | |||||
: fApp(), | |||||
fWindow(fApp) | |||||
{ | |||||
} | |||||
App& getApp() noexcept | |||||
{ | |||||
return fApp; | |||||
} | |||||
Window& getWindow() noexcept | |||||
{ | |||||
return fWindow; | |||||
} | |||||
void exec() | |||||
{ | |||||
fWindow.show(); | |||||
fApp.exec(); | |||||
} | |||||
// ------------------------------------------------------------------- | |||||
// helpers | |||||
void setResizable(bool yesNo) | |||||
{ | |||||
fWindow.setResizable(yesNo); | |||||
} | |||||
void setSize(unsigned int width, unsigned int height) | |||||
{ | |||||
fWindow.setSize(width, height); | |||||
} | |||||
void setTitle(const char* title) | |||||
{ | |||||
fWindow.setTitle(title); | |||||
} | |||||
protected: | |||||
App fApp; | |||||
Window fWindow; | |||||
DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(StandaloneWindow) | |||||
}; | |||||
// ----------------------------------------------------------------------- | |||||
END_NAMESPACE_DGL | |||||
#endif // DGL_STANDALONE_WINDOW_HPP_INCLUDED |
@@ -1,108 +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" | |||||
#ifdef PROPER_CPP11_SUPPORT | |||||
# include <cstdint> | |||||
#else | |||||
# include <stdint.h> | |||||
#endif | |||||
START_NAMESPACE_DGL | |||||
// ----------------------------------------------------------------------- | |||||
class App; | |||||
class Window; | |||||
class Widget | |||||
{ | |||||
public: | |||||
Widget(Window& parent); | |||||
virtual ~Widget(); | |||||
bool isVisible() const noexcept; | |||||
void setVisible(bool yesNo); | |||||
void show(); | |||||
void hide(); | |||||
int getX() const noexcept; | |||||
int getY() const noexcept; | |||||
const Point<int>& getPos() const noexcept; | |||||
void setX(int x); | |||||
void setY(int y); | |||||
void setPos(int x, int y); | |||||
void setPos(const Point<int>& pos); | |||||
void move(int x, int y); | |||||
void move(const Point<int>& pos); | |||||
int getWidth() const noexcept; | |||||
int getHeight() const noexcept; | |||||
const Size<int>& getSize() const noexcept; | |||||
// virtual needed by cairo | |||||
virtual void setWidth(int width); | |||||
virtual void setHeight(int height); | |||||
virtual void setSize(const Size<int>& size); | |||||
void setSize(int width, int height) | |||||
{ | |||||
setSize(Size<int>(width, height)); | |||||
} | |||||
const Rectangle<int>& getArea() const noexcept; | |||||
uint32_t getEventTimestamp(); | |||||
int getModifiers(); | |||||
App& getParentApp() const noexcept; | |||||
Window& getParentWindow() const noexcept; | |||||
void repaint(); | |||||
protected: | |||||
virtual void onDisplay() = 0; | |||||
virtual bool onKeyboard(bool press, uint32_t key); | |||||
virtual bool onMouse(int button, bool press, int x, int y); | |||||
virtual bool onMotion(int x, int y); | |||||
virtual bool onScroll(int x, int y, float dx, float dy); | |||||
virtual bool onSpecial(bool press, Key key); | |||||
virtual void onReshape(int width, int height); | |||||
virtual void onClose(); | |||||
private: | |||||
Window& fParent; | |||||
bool fVisible; | |||||
Rectangle<int> fArea; | |||||
friend class CairoWidget; | |||||
friend class Window; | |||||
DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(Widget) | |||||
}; | |||||
// ----------------------------------------------------------------------- | |||||
END_NAMESPACE_DGL | |||||
#endif // DGL_WIDGET_HPP_INCLUDED |
@@ -1,88 +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" | |||||
#ifdef PROPER_CPP11_SUPPORT | |||||
# include <cstdint> | |||||
#else | |||||
# include <stdint.h> | |||||
#endif | |||||
START_NAMESPACE_DGL | |||||
// ----------------------------------------------------------------------- | |||||
class App; | |||||
class Widget; | |||||
class Window | |||||
{ | |||||
public: | |||||
Window(App& app); | |||||
Window(App& app, Window& parent); | |||||
Window(App& app, intptr_t parentId); | |||||
virtual ~Window(); | |||||
void show(); | |||||
void hide(); | |||||
void close(); | |||||
void exec(bool lockWait = false); | |||||
void focus(); | |||||
void repaint(); | |||||
bool isVisible() const noexcept; | |||||
void setVisible(bool yesNo); | |||||
bool isResizable() const noexcept; | |||||
void setResizable(bool yesNo); | |||||
int getWidth() const noexcept; | |||||
int getHeight() const noexcept; | |||||
Size<int> getSize() const noexcept; | |||||
void setSize(unsigned int width, unsigned int height); | |||||
void setTitle(const char* title); | |||||
void setTransientWinId(intptr_t winId); | |||||
App& getApp() const noexcept; | |||||
uint32_t getEventTimestamp() const; | |||||
int getModifiers() const; | |||||
intptr_t getWindowId() const; | |||||
private: | |||||
class PrivateData; | |||||
PrivateData* const pData; | |||||
friend class App; | |||||
friend class Widget; | |||||
void _addWidget(Widget* const widget); | |||||
void _removeWidget(Widget* const widget); | |||||
void _idle(); | |||||
DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(Window) | |||||
}; | |||||
// ----------------------------------------------------------------------- | |||||
END_NAMESPACE_DGL | |||||
#endif // DGL_WINDOW_HPP_INCLUDED |
@@ -1,22 +0,0 @@ | |||||
dofile("../../../scripts/make-project.lua") | |||||
package = make_library_project("dgl") | |||||
package.includepaths = { | |||||
".." | |||||
} | |||||
package.files = { | |||||
matchfiles ( | |||||
"../src/*.cpp" | |||||
) | |||||
} | |||||
if (macosx) then | |||||
package.files = { | |||||
package.files, | |||||
"../src/pugl/pugl_osx.m.c", | |||||
"../src/pugl/pugl_osx_extended.m.c" | |||||
} | |||||
end |
@@ -1,133 +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 "../App.hpp" | |||||
#include "../Window.hpp" | |||||
#include <list> | |||||
START_NAMESPACE_DGL | |||||
// ----------------------------------------------------------------------- | |||||
struct App::PrivateData { | |||||
bool doLoop; | |||||
unsigned visibleWindows; | |||||
std::list<Window*> windows; | |||||
std::list<IdleCallback*> idleCallbacks; | |||||
PrivateData() | |||||
: doLoop(false), | |||||
visibleWindows(0) {} | |||||
}; | |||||
// ----------------------------------------------------------------------- | |||||
App::App() | |||||
: pData(new PrivateData()) | |||||
{ | |||||
} | |||||
App::~App() | |||||
{ | |||||
pData->windows.clear(); | |||||
pData->idleCallbacks.clear(); | |||||
delete pData; | |||||
} | |||||
void App::idle() | |||||
{ | |||||
for (std::list<Window*>::iterator it = pData->windows.begin(); it != pData->windows.end(); ++it) | |||||
{ | |||||
Window* const window(*it); | |||||
window->_idle(); | |||||
} | |||||
for (std::list<IdleCallback*>::iterator it = pData->idleCallbacks.begin(); it != pData->idleCallbacks.end(); ++it) | |||||
{ | |||||
IdleCallback* const idleCallback(*it); | |||||
idleCallback->idleCallback(); | |||||
} | |||||
} | |||||
void App::exec() | |||||
{ | |||||
while (pData->doLoop) | |||||
{ | |||||
idle(); | |||||
d_msleep(10); | |||||
} | |||||
} | |||||
void App::quit() | |||||
{ | |||||
pData->doLoop = false; | |||||
for (std::list<Window*>::reverse_iterator rit = pData->windows.rbegin(); rit != pData->windows.rend(); ++rit) | |||||
{ | |||||
Window* const window(*rit); | |||||
window->close(); | |||||
} | |||||
} | |||||
bool App::isQuiting() const | |||||
{ | |||||
return !pData->doLoop; | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
void App::addIdleCallback(IdleCallback* const callback) | |||||
{ | |||||
if (callback != nullptr) | |||||
pData->idleCallbacks.push_back(callback); | |||||
} | |||||
void App::removeIdleCallback(IdleCallback* const callback) | |||||
{ | |||||
if (callback != nullptr) | |||||
pData->idleCallbacks.remove(callback); | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
void App::_addWindow(Window* const window) | |||||
{ | |||||
if (window != nullptr) | |||||
pData->windows.push_back(window); | |||||
} | |||||
void App::_removeWindow(Window* const window) | |||||
{ | |||||
if (window != nullptr) | |||||
pData->windows.remove(window); | |||||
} | |||||
void App::_oneShown() | |||||
{ | |||||
if (++pData->visibleWindows == 1) | |||||
pData->doLoop = true; | |||||
} | |||||
void App::_oneHidden() | |||||
{ | |||||
if (--pData->visibleWindows == 0) | |||||
pData->doLoop = false; | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
END_NAMESPACE_DGL |
@@ -1,416 +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 "../Geometry.hpp" | |||||
START_NAMESPACE_DGL | |||||
// ----------------------------------------------------------------------- | |||||
// Point | |||||
template<typename T> | |||||
Point<T>::Point() noexcept | |||||
: fX(0), | |||||
fY(0) | |||||
{ | |||||
} | |||||
template<typename T> | |||||
Point<T>::Point(T x, T y) noexcept | |||||
: fX(x), | |||||
fY(y) | |||||
{ | |||||
} | |||||
template<typename T> | |||||
Point<T>::Point(const Point& pos) noexcept | |||||
: fX(pos.fX), | |||||
fY(pos.fY) | |||||
{ | |||||
} | |||||
template<typename T> | |||||
T Point<T>::getX() const noexcept | |||||
{ | |||||
return fX; | |||||
} | |||||
template<typename T> | |||||
T Point<T>::getY() const noexcept | |||||
{ | |||||
return fY; | |||||
} | |||||
template<typename T> | |||||
void Point<T>::setX(T x) noexcept | |||||
{ | |||||
fX = x; | |||||
} | |||||
template<typename T> | |||||
void Point<T>::setY(T y) noexcept | |||||
{ | |||||
fY = y; | |||||
} | |||||
template<typename T> | |||||
void Point<T>::move(T x, T y) noexcept | |||||
{ | |||||
fX += x; | |||||
fY += y; | |||||
} | |||||
template<typename T> | |||||
void Point<T>::move(const Point& pos) noexcept | |||||
{ | |||||
fX += pos.fX; | |||||
fY += pos.fY; | |||||
} | |||||
template<typename T> | |||||
Point<T>& Point<T>::operator=(const Point<T>& pos) noexcept | |||||
{ | |||||
fX = pos.fX; | |||||
fY = pos.fY; | |||||
return *this; | |||||
} | |||||
template<typename T> | |||||
Point<T>& Point<T>::operator+=(const Point<T>& pos) noexcept | |||||
{ | |||||
fX += pos.fX; | |||||
fY += pos.fY; | |||||
return *this; | |||||
} | |||||
template<typename T> | |||||
Point<T>& Point<T>::operator-=(const Point<T>& pos) noexcept | |||||
{ | |||||
fX -= pos.fX; | |||||
fY -= pos.fY; | |||||
return *this; | |||||
} | |||||
template<typename T> | |||||
bool Point<T>::operator==(const Point<T>& pos) const noexcept | |||||
{ | |||||
return (fX == pos.fX && fY== pos.fY); | |||||
} | |||||
template<typename T> | |||||
bool Point<T>::operator!=(const Point<T>& pos) const noexcept | |||||
{ | |||||
return !operator==(pos); | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
// Size | |||||
template<typename T> | |||||
Size<T>::Size() noexcept | |||||
: fWidth(0), | |||||
fHeight(0) | |||||
{ | |||||
} | |||||
template<typename T> | |||||
Size<T>::Size(T width, T height) noexcept | |||||
: fWidth(width), | |||||
fHeight(height) | |||||
{ | |||||
} | |||||
template<typename T> | |||||
Size<T>::Size(const Size<T>& size) noexcept | |||||
: fWidth(size.fWidth), | |||||
fHeight(size.fHeight) | |||||
{ | |||||
} | |||||
template<typename T> | |||||
T Size<T>::getWidth() const noexcept | |||||
{ | |||||
return fWidth; | |||||
} | |||||
template<typename T> | |||||
T Size<T>::getHeight() const noexcept | |||||
{ | |||||
return fHeight; | |||||
} | |||||
template<typename T> | |||||
void Size<T>::setWidth(T width) noexcept | |||||
{ | |||||
fWidth = width; | |||||
} | |||||
template<typename T> | |||||
void Size<T>::setHeight(T height) noexcept | |||||
{ | |||||
fHeight = height; | |||||
} | |||||
template<typename T> | |||||
Size<T>& Size<T>::operator=(const Size<T>& size) noexcept | |||||
{ | |||||
fWidth = size.fWidth; | |||||
fHeight = size.fHeight; | |||||
return *this; | |||||
} | |||||
template<typename T> | |||||
Size<T>& Size<T>::operator+=(const Size<T>& size) noexcept | |||||
{ | |||||
fWidth += size.fWidth; | |||||
fHeight += size.fHeight; | |||||
return *this; | |||||
} | |||||
template<typename T> | |||||
Size<T>& Size<T>::operator-=(const Size<T>& size) noexcept | |||||
{ | |||||
fWidth -= size.fWidth; | |||||
fHeight -= size.fHeight; | |||||
return *this; | |||||
} | |||||
template<typename T> | |||||
Size<T>& Size<T>::operator*=(T m) noexcept | |||||
{ | |||||
fWidth *= m; | |||||
fHeight *= m; | |||||
return *this; | |||||
} | |||||
template<typename T> | |||||
Size<T>& Size<T>::operator/=(T d) noexcept | |||||
{ | |||||
fWidth /= d; | |||||
fHeight /= d; | |||||
return *this; | |||||
} | |||||
template<typename T> | |||||
bool Size<T>::operator==(const Size<T>& size) const noexcept | |||||
{ | |||||
return (fWidth == size.fWidth && fHeight == size.fHeight); | |||||
} | |||||
template<typename T> | |||||
bool Size<T>::operator!=(const Size<T>& size) const noexcept | |||||
{ | |||||
return !operator==(size); | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
// Rectangle | |||||
template<typename T> | |||||
Rectangle<T>::Rectangle() noexcept | |||||
: fPos(0, 0), | |||||
fSize(0, 0) | |||||
{ | |||||
} | |||||
template<typename T> | |||||
Rectangle<T>::Rectangle(T x, T y, T width, T height) noexcept | |||||
: fPos(x, y), | |||||
fSize(width, height) | |||||
{ | |||||
} | |||||
template<typename T> | |||||
Rectangle<T>::Rectangle(T x, T y, const Size<T>& size) noexcept | |||||
: fPos(x, y), | |||||
fSize(size) | |||||
{ | |||||
} | |||||
template<typename T> | |||||
Rectangle<T>::Rectangle(const Point<T>& pos, T width, T height) noexcept | |||||
: fPos(pos), | |||||
fSize(width, height) | |||||
{ | |||||
} | |||||
template<typename T> | |||||
Rectangle<T>::Rectangle(const Point<T>& pos, const Size<T>& size) noexcept | |||||
: fPos(pos), | |||||
fSize(size) | |||||
{ | |||||
} | |||||
template<typename T> | |||||
Rectangle<T>::Rectangle(const Rectangle<T>& rect) noexcept | |||||
: fPos(rect.fPos), | |||||
fSize(rect.fSize) | |||||
{ | |||||
} | |||||
template<typename T> | |||||
T Rectangle<T>::getX() const noexcept | |||||
{ | |||||
return fPos.fX; | |||||
} | |||||
template<typename T> | |||||
T Rectangle<T>::getY() const noexcept | |||||
{ | |||||
return fPos.fY; | |||||
} | |||||
template<typename T> | |||||
T Rectangle<T>::getWidth() const noexcept | |||||
{ | |||||
return fSize.fWidth; | |||||
} | |||||
template<typename T> | |||||
T Rectangle<T>::getHeight() const noexcept | |||||
{ | |||||
return fSize.fHeight; | |||||
} | |||||
template<typename T> | |||||
const Point<T>& Rectangle<T>::getPos() const noexcept | |||||
{ | |||||
return fPos; | |||||
} | |||||
template<typename T> | |||||
const Size<T>& Rectangle<T>::getSize() const noexcept | |||||
{ | |||||
return fSize; | |||||
} | |||||
template<typename T> | |||||
bool Rectangle<T>::contains(T x, T y) const noexcept | |||||
{ | |||||
return (x >= fPos.fX && y >= fPos.fY && x <= fPos.fX+fSize.fWidth && y <= fPos.fY+fSize.fHeight); | |||||
} | |||||
template<typename T> | |||||
bool Rectangle<T>::contains(const Point<T>& pos) const noexcept | |||||
{ | |||||
return contains(pos.fX, pos.fY); | |||||
} | |||||
template<typename T> | |||||
bool Rectangle<T>::containsX(T x) const noexcept | |||||
{ | |||||
return (x >= fPos.fX && x <= fPos.fX + fSize.fWidth); | |||||
} | |||||
template<typename T> | |||||
bool Rectangle<T>::containsY(T y) const noexcept | |||||
{ | |||||
return (y >= fPos.fY && y <= fPos.fY + fSize.fHeight); | |||||
} | |||||
template<typename T> | |||||
void Rectangle<T>::setX(T x) noexcept | |||||
{ | |||||
fPos.fX = x; | |||||
} | |||||
template<typename T> | |||||
void Rectangle<T>::setY(T y) noexcept | |||||
{ | |||||
fPos.fY = y; | |||||
} | |||||
template<typename T> | |||||
void Rectangle<T>::setPos(T x, T y) noexcept | |||||
{ | |||||
fPos.fX = x; | |||||
fPos.fY = y; | |||||
} | |||||
template<typename T> | |||||
void Rectangle<T>::setPos(const Point<T>& pos) noexcept | |||||
{ | |||||
fPos = pos; | |||||
} | |||||
template<typename T> | |||||
void Rectangle<T>::move(T x, T y) noexcept | |||||
{ | |||||
fPos.fX += x; | |||||
fPos.fY += y; | |||||
} | |||||
template<typename T> | |||||
void Rectangle<T>::move(const Point<T>& pos) noexcept | |||||
{ | |||||
fPos += pos; | |||||
} | |||||
template<typename T> | |||||
void Rectangle<T>::setWidth(T width) noexcept | |||||
{ | |||||
fSize.fWidth = width; | |||||
} | |||||
template<typename T> | |||||
void Rectangle<T>::setHeight(T height) noexcept | |||||
{ | |||||
fSize.fHeight = height; | |||||
} | |||||
template<typename T> | |||||
void Rectangle<T>::setSize(T width, T height) noexcept | |||||
{ | |||||
fSize.fWidth = width; | |||||
fSize.fHeight = height; | |||||
} | |||||
template<typename T> | |||||
void Rectangle<T>::setSize(const Size<T>& size) noexcept | |||||
{ | |||||
fSize = size; | |||||
} | |||||
template<typename T> | |||||
Rectangle<T>& Rectangle<T>::operator=(const Rectangle<T>& rect) noexcept | |||||
{ | |||||
fPos = rect.fPos; | |||||
fSize = rect.fSize; | |||||
return *this; | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
// Possible template data types | |||||
template class Point<int>; | |||||
template class Point<long>; | |||||
template class Point<float>; | |||||
template class Point<double>; | |||||
template class Size<int>; | |||||
template class Size<long>; | |||||
template class Size<float>; | |||||
template class Size<double>; | |||||
template class Rectangle<int>; | |||||
template class Rectangle<long>; | |||||
template class Rectangle<float>; | |||||
template class Rectangle<double>; | |||||
// ----------------------------------------------------------------------- | |||||
END_NAMESPACE_DGL | |||||
@@ -1,198 +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() noexcept | |||||
: fRawData(nullptr), | |||||
fSize(0, 0), | |||||
fFormat(0), | |||||
fType(0), | |||||
fTextureId(0) | |||||
{ | |||||
} | |||||
Image::Image(const char* rawData, int width, int height, GLenum format, GLenum type) noexcept | |||||
: fRawData(rawData), | |||||
fSize(width, height), | |||||
fFormat(format), | |||||
fType(type), | |||||
fTextureId(0) | |||||
{ | |||||
} | |||||
Image::Image(const char* rawData, const Size<int>& size, GLenum format, GLenum type) noexcept | |||||
: fRawData(rawData), | |||||
fSize(size), | |||||
fFormat(format), | |||||
fType(type), | |||||
fTextureId(0) | |||||
{ | |||||
} | |||||
Image::Image(const Image& image) noexcept | |||||
: fRawData(image.fRawData), | |||||
fSize(image.fSize), | |||||
fFormat(image.fFormat), | |||||
fType(image.fType), | |||||
fTextureId(0) | |||||
{ | |||||
} | |||||
Image::~Image() | |||||
{ | |||||
if (fTextureId != 0) | |||||
{ | |||||
glDeleteTextures(1, &fTextureId); | |||||
fTextureId = 0; | |||||
} | |||||
} | |||||
void Image::loadFromMemory(const char* rawData, int width, int height, GLenum format, GLenum type) noexcept | |||||
{ | |||||
loadFromMemory(rawData, Size<int>(width, height), format, type); | |||||
} | |||||
void Image::loadFromMemory(const char* rawData, const Size<int>& size, GLenum format, GLenum type) noexcept | |||||
{ | |||||
fRawData = rawData; | |||||
fSize = size; | |||||
fFormat = format; | |||||
fType = type; | |||||
} | |||||
bool Image::isValid() const noexcept | |||||
{ | |||||
return (fRawData != nullptr && getWidth() > 0 && getHeight() > 0); | |||||
} | |||||
int Image::getWidth() const noexcept | |||||
{ | |||||
return fSize.getWidth(); | |||||
} | |||||
int Image::getHeight() const noexcept | |||||
{ | |||||
return fSize.getHeight(); | |||||
} | |||||
const Size<int>& 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() | |||||
{ | |||||
draw(0, 0); | |||||
} | |||||
void Image::draw(int x, int y) | |||||
{ | |||||
if (! isValid()) | |||||
return; | |||||
if (fTextureId == 0) | |||||
glGenTextures(1, &fTextureId); | |||||
if (fTextureId == 0) | |||||
{ | |||||
// invalidate image | |||||
fSize = Size<int>(0, 0); | |||||
return; | |||||
} | |||||
glEnable(GL_TEXTURE_2D); | |||||
glBindTexture(GL_TEXTURE_2D, fTextureId); | |||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); | |||||
glPixelStorei(GL_PACK_ALIGNMENT, 1); | |||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWidth(), getHeight(), 0, fFormat, fType, fRawData); | |||||
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); | |||||
float trans[] = { 0.0f, 0.0f, 0.0f, 0.0f }; | |||||
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, trans); | |||||
const int width = getWidth(); | |||||
const int height = getHeight(); | |||||
glBegin(GL_QUADS); | |||||
glTexCoord2f(0.0f, 0.0f); | |||||
glVertex2i(x, y); | |||||
glTexCoord2f(1.0f, 0.0f); | |||||
glVertex2i(x+width, y); | |||||
glTexCoord2f(1.0f, 1.0f); | |||||
glVertex2i(x+width, y+height); | |||||
glTexCoord2f(0.0f, 1.0f); | |||||
glVertex2i(x, y+height); | |||||
glEnd(); | |||||
glBindTexture(GL_TEXTURE_2D, 0); | |||||
glDisable(GL_TEXTURE_2D); | |||||
} | |||||
void Image::draw(const Point<int>& pos) | |||||
{ | |||||
draw(pos.getX(), pos.getY()); | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
Image& Image::operator=(const Image& image) noexcept | |||||
{ | |||||
fRawData = image.fRawData; | |||||
fSize = image.fSize; | |||||
fFormat = image.fFormat; | |||||
fType = image.fType; | |||||
return *this; | |||||
} | |||||
bool Image::operator==(const Image& image) const noexcept | |||||
{ | |||||
return (fRawData == image.fRawData); | |||||
} | |||||
bool Image::operator!=(const Image& image) const noexcept | |||||
{ | |||||
return (fRawData != image.fRawData); | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
END_NAMESPACE_DGL |
@@ -1,78 +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(App& app, Window& parent, const Image& image) | |||||
: Window(app, parent), | |||||
Widget((Window&)*this), | |||||
fImgBackground(image) | |||||
{ | |||||
Window::setResizable(false); | |||||
Window::setSize(static_cast<unsigned int>(image.getWidth()), static_cast<unsigned int>(image.getHeight())); | |||||
Window::setTitle("About"); | |||||
} | |||||
ImageAboutWindow::ImageAboutWindow(Widget* widget, const Image& image) | |||||
: Window(widget->getParentApp(), widget->getParentWindow()), | |||||
Widget((Window&)*this), | |||||
fImgBackground(image) | |||||
{ | |||||
Window::setResizable(false); | |||||
Window::setSize(static_cast<unsigned int>(image.getWidth()), static_cast<unsigned int>(image.getHeight())); | |||||
Window::setTitle("About"); | |||||
} | |||||
void ImageAboutWindow::setImage(const Image& image) | |||||
{ | |||||
fImgBackground = image; | |||||
Window::setSize(static_cast<unsigned int>(image.getWidth()), static_cast<unsigned int>(image.getHeight())); | |||||
} | |||||
void ImageAboutWindow::onDisplay() | |||||
{ | |||||
fImgBackground.draw(); | |||||
} | |||||
bool ImageAboutWindow::onMouse(int, bool press, int, int) | |||||
{ | |||||
if (press) | |||||
{ | |||||
Window::close(); | |||||
return true; | |||||
} | |||||
return false; | |||||
} | |||||
bool ImageAboutWindow::onKeyboard(bool press, uint32_t key) | |||||
{ | |||||
if (press && key == CHAR_ESCAPE) | |||||
{ | |||||
Window::close(); | |||||
return true; | |||||
} | |||||
return false; | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
END_NAMESPACE_DGL |
@@ -1,173 +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" | |||||
#include <cassert> | |||||
START_NAMESPACE_DGL | |||||
// ----------------------------------------------------------------------- | |||||
ImageButton::ImageButton(Window& parent, const Image& image) | |||||
: Widget(parent), | |||||
fImageNormal(image), | |||||
fImageHover(image), | |||||
fImageDown(image), | |||||
fCurImage(&fImageNormal), | |||||
fCurButton(-1), | |||||
fCallback(nullptr) | |||||
{ | |||||
} | |||||
ImageButton::ImageButton(Widget* widget, const Image& image) | |||||
: Widget(widget->getParentWindow()), | |||||
fImageNormal(image), | |||||
fImageHover(image), | |||||
fImageDown(image), | |||||
fCurImage(&fImageNormal), | |||||
fCurButton(-1), | |||||
fCallback(nullptr) | |||||
{ | |||||
} | |||||
ImageButton::ImageButton(Window& parent, const Image& imageNormal, const Image& imageHover, const Image& imageDown) | |||||
: Widget(parent), | |||||
fImageNormal(imageNormal), | |||||
fImageHover(imageHover), | |||||
fImageDown(imageDown), | |||||
fCurImage(&fImageNormal), | |||||
fCurButton(-1), | |||||
fCallback(nullptr) | |||||
{ | |||||
assert(fImageNormal.getSize() == fImageHover.getSize() && fImageHover.getSize() == fImageDown.getSize()); | |||||
setSize(fCurImage->getSize()); | |||||
} | |||||
ImageButton::ImageButton(Widget* widget, const Image& imageNormal, const Image& imageHover, const Image& imageDown) | |||||
: Widget(widget->getParentWindow()), | |||||
fImageNormal(imageNormal), | |||||
fImageHover(imageHover), | |||||
fImageDown(imageDown), | |||||
fCurImage(&fImageNormal), | |||||
fCurButton(-1), | |||||
fCallback(nullptr) | |||||
{ | |||||
assert(fImageNormal.getSize() == fImageHover.getSize() && fImageHover.getSize() == fImageDown.getSize()); | |||||
setSize(fCurImage->getSize()); | |||||
} | |||||
ImageButton::ImageButton(const ImageButton& imageButton) | |||||
: Widget(imageButton.getParentWindow()), | |||||
fImageNormal(imageButton.fImageNormal), | |||||
fImageHover(imageButton.fImageHover), | |||||
fImageDown(imageButton.fImageDown), | |||||
fCurImage(&fImageNormal), | |||||
fCurButton(-1), | |||||
fCallback(imageButton.fCallback) | |||||
{ | |||||
assert(fImageNormal.getSize() == fImageHover.getSize() && fImageHover.getSize() == fImageDown.getSize()); | |||||
setSize(fCurImage->getSize()); | |||||
} | |||||
void ImageButton::setCallback(Callback* callback) | |||||
{ | |||||
fCallback = callback; | |||||
} | |||||
void ImageButton::onDisplay() | |||||
{ | |||||
fCurImage->draw(getPos()); | |||||
} | |||||
bool ImageButton::onMouse(int button, bool press, int x, int y) | |||||
{ | |||||
if (fCurButton != -1 && ! press) | |||||
{ | |||||
if (fCurImage != &fImageNormal) | |||||
{ | |||||
fCurImage = &fImageNormal; | |||||
repaint(); | |||||
} | |||||
if (! getArea().contains(x, y)) | |||||
{ | |||||
fCurButton = -1; | |||||
return false; | |||||
} | |||||
if (fCallback != nullptr) | |||||
fCallback->imageButtonClicked(this, fCurButton); | |||||
//if (getArea().contains(x, y)) | |||||
//{ | |||||
// fCurImage = &fImageHover; | |||||
// repaint(); | |||||
//} | |||||
fCurButton = -1; | |||||
return true; | |||||
} | |||||
if (press && getArea().contains(x, y)) | |||||
{ | |||||
if (fCurImage != &fImageDown) | |||||
{ | |||||
fCurImage = &fImageDown; | |||||
repaint(); | |||||
} | |||||
fCurButton = button; | |||||
return true; | |||||
} | |||||
return false; | |||||
} | |||||
bool ImageButton::onMotion(int x, int y) | |||||
{ | |||||
if (fCurButton != -1) | |||||
return true; | |||||
if (getArea().contains(x, y)) | |||||
{ | |||||
if (fCurImage != &fImageHover) | |||||
{ | |||||
fCurImage = &fImageHover; | |||||
repaint(); | |||||
} | |||||
return true; | |||||
} | |||||
else | |||||
{ | |||||
if (fCurImage != &fImageNormal) | |||||
{ | |||||
fCurImage = &fImageNormal; | |||||
repaint(); | |||||
} | |||||
return false; | |||||
} | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
END_NAMESPACE_DGL |
@@ -1,364 +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> | |||||
#include <cstdio> | |||||
START_NAMESPACE_DGL | |||||
// ----------------------------------------------------------------------- | |||||
ImageKnob::ImageKnob(Window& parent, const Image& image, Orientation orientation) | |||||
: Widget(parent), | |||||
fImage(image), | |||||
fMinimum(0.0f), | |||||
fMaximum(1.0f), | |||||
fStep(0.0f), | |||||
fValue(0.5f), | |||||
fValueTmp(fValue), | |||||
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), | |||||
fKnobArea(0, 0, fImgLayerSize, fImgLayerSize), | |||||
fTextureId(0) | |||||
{ | |||||
setSize(fImgLayerSize, fImgLayerSize); | |||||
} | |||||
ImageKnob::ImageKnob(Widget* widget, const Image& image, Orientation orientation) | |||||
: Widget(widget->getParentWindow()), | |||||
fImage(image), | |||||
fMinimum(0.0f), | |||||
fMaximum(1.0f), | |||||
fStep(0.0f), | |||||
fValue(0.5f), | |||||
fValueTmp(fValue), | |||||
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), | |||||
fKnobArea(0, 0, fImgLayerSize, fImgLayerSize), | |||||
fTextureId(0) | |||||
{ | |||||
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), | |||||
fValueTmp(fValue), | |||||
fOrientation(imageKnob.fOrientation), | |||||
fRotationAngle(imageKnob.fRotationAngle), | |||||
fDragging(false), | |||||
fLastX(0), | |||||
fLastY(0), | |||||
fCallback(imageKnob.fCallback), | |||||
fIsImgVertical(imageKnob.fIsImgVertical), | |||||
fImgLayerSize(imageKnob.fImgLayerSize), | |||||
fImgLayerCount(imageKnob.fImgLayerCount), | |||||
fKnobArea(imageKnob.fKnobArea), | |||||
fTextureId(0) | |||||
{ | |||||
setSize(fImgLayerSize, fImgLayerSize); | |||||
if (fRotationAngle != 0) | |||||
{ | |||||
// force new texture creation | |||||
fRotationAngle = 0; | |||||
setRotationAngle(imageKnob.fRotationAngle); | |||||
} | |||||
} | |||||
float ImageKnob::getValue() const | |||||
{ | |||||
return fValue; | |||||
} | |||||
void ImageKnob::setOrientation(Orientation orientation) | |||||
{ | |||||
if (fOrientation == orientation) | |||||
return; | |||||
fOrientation = orientation; | |||||
} | |||||
void ImageKnob::setRange(float min, float max) | |||||
{ | |||||
if (fValue < min) | |||||
{ | |||||
fValue = min; | |||||
repaint(); | |||||
if (fCallback != nullptr) | |||||
fCallback->imageKnobValueChanged(this, fValue); | |||||
} | |||||
else if (fValue > max) | |||||
{ | |||||
fValue = max; | |||||
repaint(); | |||||
if (fCallback != nullptr) | |||||
fCallback->imageKnobValueChanged(this, fValue); | |||||
} | |||||
fMinimum = min; | |||||
fMaximum = max; | |||||
} | |||||
void ImageKnob::setStep(float step) | |||||
{ | |||||
fStep = step; | |||||
} | |||||
void ImageKnob::setValue(float value, bool sendCallback) | |||||
{ | |||||
if (fValue == value) | |||||
return; | |||||
fValue = value; | |||||
if (fStep == 0.0f) | |||||
fValueTmp = value; | |||||
repaint(); | |||||
if (sendCallback && fCallback != nullptr) | |||||
fCallback->imageKnobValueChanged(this, fValue); | |||||
} | |||||
void ImageKnob::setRotationAngle(int angle) | |||||
{ | |||||
if (fRotationAngle == angle) | |||||
return; | |||||
if (fRotationAngle != 0) | |||||
{ | |||||
// delete old texture | |||||
glDeleteTextures(1, &fTextureId); | |||||
fTextureId = 0; | |||||
} | |||||
fRotationAngle = angle; | |||||
if (angle != 0) | |||||
{ | |||||
glEnable(GL_TEXTURE_2D); | |||||
glGenTextures(1, &fTextureId); | |||||
glBindTexture(GL_TEXTURE_2D, fTextureId); | |||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); | |||||
glPixelStorei(GL_PACK_ALIGNMENT, 1); | |||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWidth(), getHeight(), 0, fImage.getFormat(), fImage.getType(), fImage.getRawData()); | |||||
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); | |||||
float trans[] = { 0.0f, 0.0f, 0.0f, 0.0f }; | |||||
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, trans); | |||||
glBindTexture(GL_TEXTURE_2D, 0); | |||||
glDisable(GL_TEXTURE_2D); | |||||
} | |||||
} | |||||
void ImageKnob::setCallback(Callback* callback) | |||||
{ | |||||
fCallback = callback; | |||||
} | |||||
void ImageKnob::onDisplay() | |||||
{ | |||||
const float normValue = (fValue - fMinimum) / (fMaximum - fMinimum); | |||||
if (fRotationAngle != 0) | |||||
{ | |||||
glEnable(GL_TEXTURE_2D); | |||||
glBindTexture(GL_TEXTURE_2D, fTextureId); | |||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); | |||||
glPixelStorei(GL_PACK_ALIGNMENT, 1); | |||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWidth(), getHeight(), 0, fImage.getFormat(), fImage.getType(), fImage.getRawData()); | |||||
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); | |||||
float trans[] = { 0.0f, 0.0f, 0.0f, 0.0f }; | |||||
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, trans); | |||||
glPushMatrix(); | |||||
const GLint w2 = getWidth()/2; | |||||
const GLint h2 = getHeight()/2; | |||||
glTranslatef(static_cast<float>(getX()+w2), static_cast<float>(getY()+h2), 0.0f); | |||||
glRotatef(normValue*static_cast<float>(fRotationAngle), 0.0f, 0.0f, 1.0f); | |||||
glBegin(GL_QUADS); | |||||
glTexCoord2f(0.0f, 0.0f); | |||||
glVertex2i(-w2, -h2); | |||||
glTexCoord2f(1.0f, 0.0f); | |||||
glVertex2i(getWidth()-w2, -h2); | |||||
glTexCoord2f(1.0f, 1.0f); | |||||
glVertex2i(getWidth()-w2, getHeight()-h2); | |||||
glTexCoord2f(0.0f, 1.0f); | |||||
glVertex2i(-w2, getHeight()-h2); | |||||
glEnd(); | |||||
glPopMatrix(); | |||||
glBindTexture(GL_TEXTURE_2D, 0); | |||||
glDisable(GL_TEXTURE_2D); | |||||
} | |||||
else | |||||
{ | |||||
const int layerDataSize = fImgLayerSize * fImgLayerSize * ((fImage.getFormat() == GL_BGRA || fImage.getFormat() == GL_RGBA) ? 4 : 3); | |||||
const int imageDataSize = layerDataSize * fImgLayerCount; | |||||
const int imageDataOffset = imageDataSize - layerDataSize - (layerDataSize * int(normValue * float(fImgLayerCount-1))); | |||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); | |||||
glPixelStorei(GL_PACK_ALIGNMENT, 1); | |||||
glRasterPos2i(getX(), getY()+getHeight()); | |||||
glDrawPixels(fImgLayerSize, fImgLayerSize, fImage.getFormat(), fImage.getType(), fImage.getRawData() + imageDataOffset); | |||||
} | |||||
} | |||||
bool ImageKnob::onMouse(int button, bool press, int x, int y) | |||||
{ | |||||
if (button != 1) | |||||
return false; | |||||
if (press) | |||||
{ | |||||
if (! getArea().contains(x, y)) | |||||
return false; | |||||
fDragging = true; | |||||
fLastX = x; | |||||
fLastY = y; | |||||
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(int x, int y) | |||||
{ | |||||
if (! fDragging) | |||||
return false; | |||||
bool doVal = false; | |||||
float d, value; | |||||
if (fOrientation == ImageKnob::Horizontal) | |||||
{ | |||||
if (int movX = x - fLastX) | |||||
{ | |||||
d = (getModifiers() & MODIFIER_SHIFT) ? 2000.0f : 200.0f; | |||||
value = fValueTmp + (float(fMaximum - fMinimum) / d * float(movX)); | |||||
doVal = true; | |||||
} | |||||
} | |||||
else if (fOrientation == ImageKnob::Vertical) | |||||
{ | |||||
if (int movY = fLastY - y) | |||||
{ | |||||
d = (getModifiers() & MODIFIER_SHIFT) ? 2000.0f : 200.0f; | |||||
value = fValueTmp + (float(fMaximum - fMinimum) / d * float(movY)); | |||||
doVal = true; | |||||
} | |||||
} | |||||
if (! doVal) | |||||
return false; | |||||
if (value < fMinimum) | |||||
{ | |||||
value = fMinimum; | |||||
fValueTmp = value; | |||||
} | |||||
else if (value > fMaximum) | |||||
{ | |||||
value = fMaximum; | |||||
fValueTmp = value; | |||||
} | |||||
else if (fStep != 0.0f) | |||||
{ | |||||
fValueTmp = value; | |||||
const float rest = std::fmod(value, fStep); | |||||
value = value - rest + (rest > fStep/2.0f ? fStep : 0.0f); | |||||
} | |||||
setValue(value, true); | |||||
fLastX = x; | |||||
fLastY = y; | |||||
return true; | |||||
} | |||||
void ImageKnob::onReshape(int width, int height) | |||||
{ | |||||
// if (fRotationAngle != 0) | |||||
// glEnable(GL_TEXTURE_2D); | |||||
Widget::onReshape(width, height); | |||||
} | |||||
void ImageKnob::onClose() | |||||
{ | |||||
// delete old texture | |||||
setRotationAngle(0); | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
END_NAMESPACE_DGL |
@@ -1,358 +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) | |||||
: 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) | |||||
{ | |||||
setSize(fImage.getSize()); | |||||
} | |||||
ImageSlider::ImageSlider(Widget* widget, const Image& image) | |||||
: 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) | |||||
{ | |||||
setSize(fImage.getSize()); | |||||
} | |||||
ImageSlider::ImageSlider(const ImageSlider& imageSlider) | |||||
: 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) | |||||
{ | |||||
setSize(fImage.getSize()); | |||||
} | |||||
float ImageSlider::getValue() const | |||||
{ | |||||
return fValue; | |||||
} | |||||
void ImageSlider::setStartPos(const Point<int>& startPos) | |||||
{ | |||||
fStartPos = startPos; | |||||
_recheckArea(); | |||||
} | |||||
void ImageSlider::setStartPos(int x, int y) | |||||
{ | |||||
setStartPos(Point<int>(x, y)); | |||||
} | |||||
void ImageSlider::setEndPos(const Point<int>& endPos) | |||||
{ | |||||
fEndPos = endPos; | |||||
_recheckArea(); | |||||
} | |||||
void ImageSlider::setEndPos(int x, int y) | |||||
{ | |||||
setEndPos(Point<int>(x, y)); | |||||
} | |||||
void ImageSlider::setInverted(bool inverted) | |||||
{ | |||||
if (fInverted == inverted) | |||||
return; | |||||
fInverted = inverted; | |||||
repaint(); | |||||
} | |||||
void ImageSlider::setRange(float min, float max) | |||||
{ | |||||
if (fValue < min) | |||||
{ | |||||
fValue = min; | |||||
repaint(); | |||||
if (fCallback != nullptr) | |||||
fCallback->imageSliderValueChanged(this, fValue); | |||||
} | |||||
else if (fValue > max) | |||||
{ | |||||
fValue = max; | |||||
repaint(); | |||||
if (fCallback != nullptr) | |||||
fCallback->imageSliderValueChanged(this, fValue); | |||||
} | |||||
fMinimum = min; | |||||
fMaximum = max; | |||||
} | |||||
void ImageSlider::setStep(float step) | |||||
{ | |||||
fStep = step; | |||||
} | |||||
void ImageSlider::setValue(float value, bool sendCallback) | |||||
{ | |||||
if (fValue == value) | |||||
return; | |||||
fValue = value; | |||||
if (fStep == 0.0f) | |||||
fValueTmp = value; | |||||
repaint(); | |||||
if (sendCallback && fCallback != nullptr) | |||||
fCallback->imageSliderValueChanged(this, fValue); | |||||
} | |||||
void ImageSlider::setCallback(Callback* callback) | |||||
{ | |||||
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 | |||||
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.draw(x, y); | |||||
} | |||||
bool ImageSlider::onMouse(int button, bool press, int x, int y) | |||||
{ | |||||
if (button != 1) | |||||
return false; | |||||
if (press) | |||||
{ | |||||
if (! fSliderArea.contains(x, y)) | |||||
return false; | |||||
float vper; | |||||
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) | |||||
{ | |||||
value = fMinimum; | |||||
fValueTmp = value; | |||||
} | |||||
else if (value > fMaximum) | |||||
{ | |||||
value = fMaximum; | |||||
fValueTmp = value; | |||||
} | |||||
else if (fStep != 0.0f) | |||||
{ | |||||
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(int x, int y) | |||||
{ | |||||
if (! fDragging) | |||||
return false; | |||||
const bool horizontal = fStartPos.getY() == fEndPos.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) | |||||
{ | |||||
value = fMinimum; | |||||
fValueTmp = value; | |||||
} | |||||
else if (value > fMaximum) | |||||
{ | |||||
value = fMaximum; | |||||
fValueTmp = value; | |||||
} | |||||
else if (fStep != 0.0f) | |||||
{ | |||||
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() | |||||
{ | |||||
if (fStartPos.getY() == fEndPos.getY()) | |||||
{ | |||||
// horizontal | |||||
fSliderArea = Rectangle<int>(fStartPos.getX(), | |||||
fStartPos.getY(), | |||||
fEndPos.getX() + fImage.getWidth() - fStartPos.getX(), | |||||
fImage.getHeight()); | |||||
} | |||||
else | |||||
{ | |||||
// vertical | |||||
fSliderArea = Rectangle<int>(fStartPos.getX(), | |||||
fStartPos.getY(), | |||||
fImage.getWidth(), | |||||
fEndPos.getY() + fImage.getHeight() - fStartPos.getY()); | |||||
} | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
END_NAMESPACE_DGL |
@@ -1,238 +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 "../App.hpp" | |||||
#include "../Widget.hpp" | |||||
#include "../Window.hpp" | |||||
#include <cassert> | |||||
START_NAMESPACE_DGL | |||||
// ----------------------------------------------------------------------- | |||||
// Widget | |||||
Widget::Widget(Window& parent) | |||||
: fParent(parent), | |||||
fVisible(true) | |||||
{ | |||||
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); | |||||
} | |||||
int Widget::getX() const noexcept | |||||
{ | |||||
return fArea.getX(); | |||||
} | |||||
int Widget::getY() const noexcept | |||||
{ | |||||
return fArea.getY(); | |||||
} | |||||
const Point<int>& Widget::getPos() const noexcept | |||||
{ | |||||
return fArea.getPos(); | |||||
} | |||||
void Widget::setX(int x) | |||||
{ | |||||
if (fArea.getX() == x) | |||||
return; | |||||
fArea.setX(x); | |||||
fParent.repaint(); | |||||
} | |||||
void Widget::setY(int y) | |||||
{ | |||||
if (fArea.getY() == y) | |||||
return; | |||||
fArea.setY(y); | |||||
fParent.repaint(); | |||||
} | |||||
void Widget::setPos(int x, int y) | |||||
{ | |||||
setPos(Point<int>(x, y)); | |||||
} | |||||
void Widget::setPos(const Point<int>& pos) | |||||
{ | |||||
if (fArea.getPos() == pos) | |||||
return; | |||||
fArea.setPos(pos); | |||||
fParent.repaint(); | |||||
} | |||||
void Widget::move(int x, int y) | |||||
{ | |||||
fArea.move(x, y); | |||||
fParent.repaint(); | |||||
} | |||||
void Widget::move(const Point<int>& pos) | |||||
{ | |||||
fArea.move(pos); | |||||
fParent.repaint(); | |||||
} | |||||
int Widget::getWidth() const noexcept | |||||
{ | |||||
return fArea.getWidth(); | |||||
} | |||||
int Widget::getHeight() const noexcept | |||||
{ | |||||
return fArea.getHeight(); | |||||
} | |||||
const Size<int>& Widget::getSize() const noexcept | |||||
{ | |||||
return fArea.getSize(); | |||||
} | |||||
void Widget::setWidth(int width) | |||||
{ | |||||
if (fArea.getWidth() == width) | |||||
return; | |||||
fArea.setWidth(width); | |||||
fParent.repaint(); | |||||
} | |||||
void Widget::setHeight(int height) | |||||
{ | |||||
if (fArea.getHeight() == height) | |||||
return; | |||||
fArea.setHeight(height); | |||||
fParent.repaint(); | |||||
} | |||||
void Widget::setSize(const Size<int>& size) | |||||
{ | |||||
if (fArea.getSize() == size) | |||||
return; | |||||
fArea.setSize(size); | |||||
fParent.repaint(); | |||||
} | |||||
const Rectangle<int>& Widget::getArea() const noexcept | |||||
{ | |||||
return fArea; | |||||
} | |||||
uint32_t Widget::getEventTimestamp() | |||||
{ | |||||
return fParent.getEventTimestamp(); | |||||
} | |||||
int Widget::getModifiers() | |||||
{ | |||||
return fParent.getModifiers(); | |||||
} | |||||
App& Widget::getParentApp() const noexcept | |||||
{ | |||||
return fParent.getApp(); | |||||
} | |||||
Window& Widget::getParentWindow() const noexcept | |||||
{ | |||||
return fParent; | |||||
} | |||||
void Widget::repaint() | |||||
{ | |||||
fParent.repaint(); | |||||
} | |||||
bool Widget::onKeyboard(bool, uint32_t) | |||||
{ | |||||
return false; | |||||
} | |||||
bool Widget::onMouse(int, bool, int, int) | |||||
{ | |||||
return false; | |||||
} | |||||
bool Widget::onMotion(int, int) | |||||
{ | |||||
return false; | |||||
} | |||||
bool Widget::onScroll(int, int, float, float) | |||||
{ | |||||
return false; | |||||
} | |||||
bool Widget::onSpecial(bool, Key) | |||||
{ | |||||
return false; | |||||
} | |||||
void Widget::onReshape(int width, int height) | |||||
{ | |||||
glEnable(GL_BLEND); | |||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | |||||
glMatrixMode(GL_PROJECTION); | |||||
glLoadIdentity(); | |||||
glOrtho(0, width, height, 0, 0.0f, 1.0f); | |||||
glViewport(0, 0, width, height); | |||||
glMatrixMode(GL_MODELVIEW); | |||||
glLoadIdentity(); | |||||
} | |||||
void Widget::onClose() | |||||
{ | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
END_NAMESPACE_DGL |
@@ -1,949 +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. | |||||
*/ | |||||
// we need this for now | |||||
#define XKEYFOCUSGRAB 1 | |||||
#include "../App.hpp" | |||||
#include "../Widget.hpp" | |||||
#include "../Window.hpp" | |||||
#include <cassert> | |||||
#include <cstdio> | |||||
#include <list> | |||||
#include "pugl/pugl.h" | |||||
#if defined(DISTRHO_OS_WINDOWS) | |||||
# include "pugl/pugl_win.cpp" | |||||
#elif defined(DISTRHO_OS_MAC) | |||||
# include "pugl/pugl_osx_extended.h" | |||||
extern "C" { | |||||
struct PuglViewImpl { | |||||
int width; | |||||
int height; | |||||
};} | |||||
#elif defined(DISTRHO_OS_LINUX) | |||||
# include <sys/types.h> | |||||
# include <unistd.h> | |||||
extern "C" { | |||||
# include "pugl/pugl_x11.c" | |||||
} | |||||
#else | |||||
# error Unsupported platform | |||||
#endif | |||||
#define FOR_EACH_WIDGET(it) \ | |||||
for (std::list<Widget*>::iterator it = fWidgets.begin(); it != fWidgets.end(); ++it) | |||||
#define FOR_EACH_WIDGET_INV(rit) \ | |||||
for (std::list<Widget*>::reverse_iterator rit = fWidgets.rbegin(); rit != fWidgets.rend(); ++rit) | |||||
#ifdef DEBUG | |||||
# define DBG(msg) std::fprintf(stderr, "%s", msg); | |||||
# define DBGp(...) std::fprintf(stderr, __VA_ARGS__); | |||||
# define DBGF std::fflush(stderr); | |||||
#else | |||||
# define DBG(msg) | |||||
# define DBGp(...) | |||||
# define DBGF | |||||
#endif | |||||
START_NAMESPACE_DGL | |||||
Window* dgl_lastUiParent = nullptr; | |||||
// ----------------------------------------------------------------------- | |||||
// Window Private | |||||
class Window::PrivateData | |||||
{ | |||||
public: | |||||
PrivateData(App& app, Window* const self) | |||||
: fApp(app), | |||||
fSelf(self), | |||||
fView(puglCreate(0, "Window", 100, 100, true, false)), | |||||
fFirstInit(true), | |||||
fVisible(false), | |||||
fResizable(true), | |||||
fUsingEmbed(false), | |||||
#if defined(DISTRHO_OS_WINDOWS) | |||||
hwnd(0) | |||||
#elif defined(DISTRHO_OS_LINUX) | |||||
xDisplay(nullptr), | |||||
xWindow(0) | |||||
#elif defined(DISTRHO_OS_MAC) | |||||
fNeedsIdle(true) | |||||
#else | |||||
_dummy('\0') | |||||
#endif | |||||
{ | |||||
DBG("Creating window without parent..."); DBGF; | |||||
init(); | |||||
} | |||||
PrivateData(App& app, Window* const self, Window& parent) | |||||
: fApp(app), | |||||
fSelf(self), | |||||
fView(puglCreate(0, "Window", 100, 100, true, false)), | |||||
fFirstInit(true), | |||||
fVisible(false), | |||||
fResizable(true), | |||||
fUsingEmbed(false), | |||||
fModal(parent.pData), | |||||
#if defined(DISTRHO_OS_WINDOWS) | |||||
hwnd(0) | |||||
#elif defined(DISTRHO_OS_LINUX) | |||||
xDisplay(nullptr), | |||||
xWindow(0) | |||||
#elif defined(DISTRHO_OS_MAC) | |||||
fNeedsIdle(false) | |||||
#else | |||||
_dummy('\0') | |||||
#endif | |||||
{ | |||||
DBG("Creating window with parent..."); DBGF; | |||||
init(); | |||||
#ifdef DISTRHO_OS_LINUX | |||||
const PuglInternals* const parentImpl(parent.pData->fView->impl); | |||||
XSetTransientForHint(xDisplay, xWindow, parentImpl->win); | |||||
#endif | |||||
} | |||||
PrivateData(App& app, Window* const self, const intptr_t parentId) | |||||
: fApp(app), | |||||
fSelf(self), | |||||
fView(puglCreate(parentId, "Window", 100, 100, (parentId == 0), (parentId != 0))), | |||||
fFirstInit(true), | |||||
fVisible(parentId != 0), | |||||
fResizable(parentId == 0), | |||||
fUsingEmbed(parentId != 0), | |||||
#if defined(DISTRHO_OS_WINDOWS) | |||||
hwnd(0) | |||||
#elif defined(DISTRHO_OS_LINUX) | |||||
xDisplay(nullptr), | |||||
xWindow(0) | |||||
#elif defined(DISTRHO_OS_MAC) | |||||
fNeedsIdle(false) | |||||
#else | |||||
_dummy('\0') | |||||
#endif | |||||
{ | |||||
if (parentId != 0) { | |||||
DBG("Creating embedded window..."); DBGF; | |||||
} else { | |||||
DBG("Creating window without parent..."); DBGF; | |||||
} | |||||
init(); | |||||
if (parentId != 0) | |||||
{ | |||||
DBG("NOTE: Embed window is always visible and non-resizable\n"); | |||||
fApp._oneShown(); | |||||
fFirstInit = false; | |||||
} | |||||
} | |||||
void init() | |||||
{ | |||||
if (fSelf == nullptr || fView == nullptr) | |||||
{ | |||||
DBG("Failed!\n"); | |||||
dgl_lastUiParent = nullptr; | |||||
return; | |||||
} | |||||
dgl_lastUiParent = fSelf; | |||||
puglSetHandle(fView, this); | |||||
puglSetDisplayFunc(fView, onDisplayCallback); | |||||
puglSetKeyboardFunc(fView, onKeyboardCallback); | |||||
puglSetMotionFunc(fView, onMotionCallback); | |||||
puglSetMouseFunc(fView, onMouseCallback); | |||||
puglSetScrollFunc(fView, onScrollCallback); | |||||
puglSetSpecialFunc(fView, onSpecialCallback); | |||||
puglSetReshapeFunc(fView, onReshapeCallback); | |||||
puglSetCloseFunc(fView, onCloseCallback); | |||||
#if defined(DISTRHO_OS_WINDOWS) | |||||
PuglInternals* impl = fView->impl; | |||||
hwnd = impl->hwnd; | |||||
assert(hwnd != 0); | |||||
#elif defined(DISTRHO_OS_LINUX) | |||||
PuglInternals* impl = fView->impl; | |||||
xDisplay = impl->display; | |||||
xWindow = impl->win; | |||||
assert(xWindow != 0); | |||||
if (! fUsingEmbed) | |||||
{ | |||||
pid_t pid = getpid(); | |||||
Atom _nwp = XInternAtom(xDisplay, "_NET_WM_PID", True); | |||||
XChangeProperty(xDisplay, xWindow, _nwp, XA_CARDINAL, 32, PropModeReplace, (const unsigned char*)&pid, 1); | |||||
} | |||||
#endif | |||||
DBG("Success!\n"); | |||||
#if 0 | |||||
// process any initial events | |||||
puglProcessEvents(fView); | |||||
#endif | |||||
fApp._addWindow(fSelf); | |||||
} | |||||
~PrivateData() | |||||
{ | |||||
DBG("Destroying window..."); DBGF; | |||||
//fOnModal = false; | |||||
fWidgets.clear(); | |||||
if (fSelf != nullptr) | |||||
{ | |||||
fApp._removeWindow(fSelf); | |||||
fSelf = nullptr; | |||||
} | |||||
if (fView != nullptr) | |||||
{ | |||||
puglDestroy(fView); | |||||
fView = nullptr; | |||||
} | |||||
#if defined(DISTRHO_OS_WINDOWS) | |||||
hwnd = 0; | |||||
#elif defined(DISTRHO_OS_LINUX) | |||||
xDisplay = nullptr; | |||||
xWindow = 0; | |||||
#endif | |||||
DBG("Success!\n"); | |||||
} | |||||
// ------------------------------------------------------------------- | |||||
void close() | |||||
{ | |||||
DBG("Window close\n"); | |||||
setVisible(false); | |||||
if (! fFirstInit) | |||||
{ | |||||
fApp._oneHidden(); | |||||
fFirstInit = true; | |||||
} | |||||
} | |||||
void exec(const bool lockWait) | |||||
{ | |||||
DBG("Window exec\n"); | |||||
exec_init(); | |||||
if (lockWait) | |||||
{ | |||||
for (; fVisible && fModal.enabled;) | |||||
{ | |||||
idle(); | |||||
d_msleep(10); | |||||
} | |||||
exec_fini(); | |||||
} | |||||
else | |||||
{ | |||||
idle(); | |||||
} | |||||
} | |||||
// ------------------------------------------------------------------- | |||||
void focus() | |||||
{ | |||||
DBG("Window focus\n"); | |||||
#if defined(DISTRHO_OS_WINDOWS) | |||||
SetForegroundWindow(hwnd); | |||||
SetActiveWindow(hwnd); | |||||
SetFocus(hwnd); | |||||
#elif defined(DISTRHO_OS_MAC) | |||||
puglImplFocus(fView); | |||||
#elif defined(DISTRHO_OS_LINUX) | |||||
XRaiseWindow(xDisplay, xWindow); | |||||
XSetInputFocus(xDisplay, xWindow, RevertToPointerRoot, CurrentTime); | |||||
XFlush(xDisplay); | |||||
#endif | |||||
} | |||||
void repaint() | |||||
{ | |||||
//DBG("Window repaint\n"); | |||||
puglPostRedisplay(fView); | |||||
} | |||||
// ------------------------------------------------------------------- | |||||
bool isVisible() const noexcept | |||||
{ | |||||
return fVisible; | |||||
} | |||||
void setVisible(const bool yesNo) | |||||
{ | |||||
if (fVisible == yesNo) | |||||
{ | |||||
DBG("Window setVisible matches current state, ignoring request\n"); | |||||
return; | |||||
} | |||||
if (fUsingEmbed) | |||||
{ | |||||
DBG("Window setVisible cannot be called when embedded\n"); | |||||
return; | |||||
} | |||||
DBG("Window setVisible called\n"); | |||||
fVisible = yesNo; | |||||
if (yesNo && fFirstInit) | |||||
setSize(static_cast<unsigned int>(fView->width), static_cast<unsigned int>(fView->height), true); | |||||
#if defined(DISTRHO_OS_WINDOWS) | |||||
if (yesNo) | |||||
ShowWindow(hwnd, fFirstInit ? SW_SHOWNORMAL : SW_RESTORE); | |||||
else | |||||
ShowWindow(hwnd, SW_HIDE); | |||||
UpdateWindow(hwnd); | |||||
#elif defined(DISTRHO_OS_MAC) | |||||
puglImplSetVisible(fView, yesNo); | |||||
#elif defined(DISTRHO_OS_LINUX) | |||||
if (yesNo) | |||||
XMapRaised(xDisplay, xWindow); | |||||
else | |||||
XUnmapWindow(xDisplay, xWindow); | |||||
XFlush(xDisplay); | |||||
#endif | |||||
if (yesNo) | |||||
{ | |||||
if (fFirstInit) | |||||
{ | |||||
fApp._oneShown(); | |||||
fFirstInit = false; | |||||
} | |||||
} | |||||
else if (fModal.enabled) | |||||
exec_fini(); | |||||
} | |||||
// ------------------------------------------------------------------- | |||||
bool isResizable() const noexcept | |||||
{ | |||||
return fResizable; | |||||
} | |||||
void setResizable(const bool yesNo) | |||||
{ | |||||
if (fResizable == yesNo) | |||||
{ | |||||
DBG("Window setResizable matches current state, ignoring request\n"); | |||||
return; | |||||
} | |||||
if (fUsingEmbed) | |||||
{ | |||||
DBG("Window setResizable cannot be called when embedded\n"); | |||||
return; | |||||
} | |||||
DBG("Window setResizable called\n"); | |||||
fResizable = yesNo; | |||||
setSize(static_cast<unsigned int>(fView->width), static_cast<unsigned int>(fView->height), true); | |||||
} | |||||
// ------------------------------------------------------------------- | |||||
int getWidth() const noexcept | |||||
{ | |||||
return fView->width; | |||||
} | |||||
int getHeight() const noexcept | |||||
{ | |||||
return fView->height; | |||||
} | |||||
Size<int> getSize() const noexcept | |||||
{ | |||||
return Size<int>(fView->width, fView->height); | |||||
} | |||||
void setSize(unsigned int width, unsigned int height, const bool forced = false) | |||||
{ | |||||
if (width == 0 || height == 0) | |||||
{ | |||||
DBGp("Window setSize called with invalid value(s) %i %i, ignoring request\n", width, height); | |||||
return; | |||||
} | |||||
if (fView->width == static_cast<int>(width) && fView->height == static_cast<int>(height) && ! forced) | |||||
{ | |||||
DBGp("Window setSize matches current size, ignoring request (%i %i)\n", width, height); | |||||
return; | |||||
} | |||||
fView->width = static_cast<int>(width); | |||||
fView->height = static_cast<int>(height); | |||||
DBGp("Window setSize called %s, size %i %i\n", forced ? "(forced)" : "(not forced)", width, height); | |||||
#if defined(DISTRHO_OS_WINDOWS) | |||||
int winFlags = WS_POPUPWINDOW | WS_CAPTION; | |||||
if (fResizable) | |||||
winFlags |= WS_SIZEBOX; | |||||
RECT wr = { 0, 0, static_cast<long>(width), static_cast<long>(height) }; | |||||
AdjustWindowRectEx(&wr, winFlags, FALSE, WS_EX_TOPMOST); | |||||
SetWindowPos(hwnd, 0, 0, 0, wr.right-wr.left, wr.bottom-wr.top, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOZORDER); | |||||
if (! forced) | |||||
UpdateWindow(hwnd); | |||||
#elif defined(DISTRHO_OS_MAC) | |||||
puglImplSetSize(fView, width, height, forced); | |||||
#elif defined(DISTRHO_OS_LINUX) | |||||
XResizeWindow(xDisplay, xWindow, width, height); | |||||
if (! fResizable) | |||||
{ | |||||
XSizeHints sizeHints; | |||||
memset(&sizeHints, 0, sizeof(sizeHints)); | |||||
sizeHints.flags = PSize|PMinSize|PMaxSize; | |||||
sizeHints.width = static_cast<int>(width); | |||||
sizeHints.height = static_cast<int>(height); | |||||
sizeHints.min_width = static_cast<int>(width); | |||||
sizeHints.min_height = static_cast<int>(height); | |||||
sizeHints.max_width = static_cast<int>(width); | |||||
sizeHints.max_height = static_cast<int>(height); | |||||
XSetNormalHints(xDisplay, xWindow, &sizeHints); | |||||
} | |||||
if (! forced) | |||||
XFlush(xDisplay); | |||||
#endif | |||||
repaint(); | |||||
} | |||||
// ------------------------------------------------------------------- | |||||
void setTitle(const char* const title) | |||||
{ | |||||
DBGp("Window setTitle \"%s\"\n", title); | |||||
#if defined(DISTRHO_OS_WINDOWS) | |||||
SetWindowTextA(hwnd, title); | |||||
#elif defined(DISTRHO_OS_MAC) | |||||
puglImplSetTitle(fView, title); | |||||
#elif defined(DISTRHO_OS_LINUX) | |||||
XStoreName(xDisplay, xWindow, title); | |||||
#endif | |||||
} | |||||
void setTransientWinId(const intptr_t winId) | |||||
{ | |||||
#if defined(DISTRHO_OS_LINUX) | |||||
XSetTransientForHint(xDisplay, xWindow, static_cast< ::Window>(winId)); | |||||
#else | |||||
return; | |||||
// unused | |||||
(void)winId; | |||||
#endif | |||||
} | |||||
// ------------------------------------------------------------------- | |||||
App& getApp() const noexcept | |||||
{ | |||||
return fApp; | |||||
} | |||||
int getModifiers() const | |||||
{ | |||||
return puglGetModifiers(fView); | |||||
} | |||||
uint32_t getEventTimestamp() const | |||||
{ | |||||
return puglGetEventTimestamp(fView); | |||||
} | |||||
intptr_t getWindowId() const | |||||
{ | |||||
return puglGetNativeWindow(fView); | |||||
} | |||||
// ------------------------------------------------------------------- | |||||
void addWidget(Widget* const widget) | |||||
{ | |||||
fWidgets.push_back(widget); | |||||
} | |||||
void removeWidget(Widget* const widget) | |||||
{ | |||||
fWidgets.remove(widget); | |||||
} | |||||
void idle() | |||||
{ | |||||
puglProcessEvents(fView); | |||||
#ifdef DISTRHO_OS_MAC | |||||
if (fNeedsIdle) | |||||
puglImplIdle(fView); | |||||
#endif | |||||
if (fModal.enabled && fModal.parent != nullptr) | |||||
fModal.parent->idle(); | |||||
} | |||||
// ------------------------------------------------------------------- | |||||
void exec_init() | |||||
{ | |||||
DBG("Window modal loop starting..."); DBGF; | |||||
assert(fModal.parent != nullptr); | |||||
if (fModal.parent == nullptr) | |||||
{ | |||||
DBG("Failed, there's no modal parent!\n"); | |||||
return setVisible(true); | |||||
} | |||||
fModal.enabled = true; | |||||
fModal.parent->fModal.childFocus = this; | |||||
#ifdef DISTRHO_OS_WINDOWS | |||||
// Center this window | |||||
PuglInternals* const parentImpl = fModal.parent->fView->impl; | |||||
RECT curRect; | |||||
RECT parentRect; | |||||
GetWindowRect(hwnd, &curRect); | |||||
GetWindowRect(parentImpl->hwnd, &parentRect); | |||||
int x = parentRect.left+(parentRect.right-curRect.right)/2; | |||||
int y = parentRect.top +(parentRect.bottom-curRect.bottom)/2; | |||||
SetWindowPos(hwnd, 0, x, y, 0, 0, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER); | |||||
UpdateWindow(hwnd); | |||||
#endif | |||||
fModal.parent->setVisible(true); | |||||
setVisible(true); | |||||
DBG("Ok\n"); | |||||
} | |||||
void exec_fini() | |||||
{ | |||||
DBG("Window modal loop stopping..."); DBGF; | |||||
fModal.enabled = false; | |||||
if (fModal.parent != nullptr) | |||||
fModal.parent->fModal.childFocus = nullptr; | |||||
DBG("Ok\n"); | |||||
} | |||||
// ------------------------------------------------------------------- | |||||
protected: | |||||
void onDisplay() | |||||
{ | |||||
//DBG("PUGL: onDisplay\n"); | |||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | |||||
glLoadIdentity(); | |||||
FOR_EACH_WIDGET(it) | |||||
{ | |||||
Widget* const widget(*it); | |||||
if (widget->isVisible()) | |||||
widget->onDisplay(); | |||||
} | |||||
} | |||||
void onKeyboard(const bool press, const uint32_t key) | |||||
{ | |||||
DBGp("PUGL: onKeyboard : %i %i\n", press, key); | |||||
if (fModal.childFocus != nullptr) | |||||
return fModal.childFocus->focus(); | |||||
FOR_EACH_WIDGET_INV(rit) | |||||
{ | |||||
Widget* const widget(*rit); | |||||
if (widget->isVisible() && widget->onKeyboard(press, key)) | |||||
break; | |||||
} | |||||
} | |||||
void onMouse(const int button, const bool press, const int x, const int y) | |||||
{ | |||||
DBGp("PUGL: onMouse : %i %i %i %i\n", button, press, x, y); | |||||
if (fModal.childFocus != nullptr) | |||||
return fModal.childFocus->focus(); | |||||
FOR_EACH_WIDGET_INV(rit) | |||||
{ | |||||
Widget* const widget(*rit); | |||||
if (widget->isVisible() && widget->onMouse(button, press, x, y)) | |||||
break; | |||||
} | |||||
} | |||||
void onMotion(const int x, const int y) | |||||
{ | |||||
DBGp("PUGL: onMotion : %i %i\n", x, y); | |||||
if (fModal.childFocus != nullptr) | |||||
return; | |||||
FOR_EACH_WIDGET_INV(rit) | |||||
{ | |||||
Widget* const widget(*rit); | |||||
if (widget->isVisible() && widget->onMotion(x, y)) | |||||
break; | |||||
} | |||||
} | |||||
void onScroll(const int x, const int y, const float dx, const float dy) | |||||
{ | |||||
DBGp("PUGL: onScroll : %i %i %f %f\n", x, y, dx, dy); | |||||
if (fModal.childFocus != nullptr) | |||||
return; | |||||
FOR_EACH_WIDGET_INV(rit) | |||||
{ | |||||
Widget* const widget(*rit); | |||||
if (widget->isVisible() && widget->onScroll(x, y, dx, dy)) | |||||
break; | |||||
} | |||||
} | |||||
void onSpecial(const bool press, const Key key) | |||||
{ | |||||
DBGp("PUGL: onSpecial : %i %i\n", press, key); | |||||
if (fModal.childFocus != nullptr) | |||||
return; | |||||
FOR_EACH_WIDGET_INV(rit) | |||||
{ | |||||
Widget* const widget(*rit); | |||||
if (widget->isVisible() && widget->onSpecial(press, key)) | |||||
break; | |||||
} | |||||
} | |||||
void onReshape(const int width, const int height) | |||||
{ | |||||
DBGp("PUGL: onReshape : %i %i\n", width, height); | |||||
FOR_EACH_WIDGET(it) | |||||
{ | |||||
Widget* const widget(*it); | |||||
widget->onReshape(width, height); | |||||
} | |||||
} | |||||
void onClose() | |||||
{ | |||||
DBG("PUGL: onClose\n"); | |||||
if (fModal.enabled && fModal.parent != nullptr) | |||||
exec_fini(); | |||||
if (fModal.childFocus != nullptr) | |||||
fModal.childFocus->onClose(); | |||||
FOR_EACH_WIDGET(it) | |||||
{ | |||||
Widget* const widget(*it); | |||||
widget->onClose(); | |||||
} | |||||
close(); | |||||
} | |||||
// ------------------------------------------------------------------- | |||||
private: | |||||
App& fApp; | |||||
Window* fSelf; | |||||
PuglView* fView; | |||||
bool fFirstInit; | |||||
bool fVisible; | |||||
bool fResizable; | |||||
bool fUsingEmbed; | |||||
std::list<Widget*> fWidgets; | |||||
struct Modal { | |||||
bool enabled; | |||||
PrivateData* parent; | |||||
PrivateData* childFocus; | |||||
Modal() | |||||
: enabled(false), | |||||
parent(nullptr), | |||||
childFocus(nullptr) {} | |||||
Modal(PrivateData* const p) | |||||
: enabled(false), | |||||
parent(p), | |||||
childFocus(nullptr) {} | |||||
~Modal() | |||||
{ | |||||
assert(! enabled); | |||||
assert(childFocus == nullptr); | |||||
} | |||||
} fModal; | |||||
#if defined(DISTRHO_OS_WINDOWS) | |||||
HWND hwnd; | |||||
#elif defined(DISTRHO_OS_LINUX) | |||||
Display* xDisplay; | |||||
::Window xWindow; | |||||
#elif defined(DISTRHO_OS_MAC) | |||||
bool fNeedsIdle; | |||||
#else | |||||
char _dummy; | |||||
#endif | |||||
// ------------------------------------------------------------------- | |||||
// Callbacks | |||||
#define handlePtr ((PrivateData*)puglGetHandle(view)) | |||||
static void onDisplayCallback(PuglView* view) | |||||
{ | |||||
handlePtr->onDisplay(); | |||||
} | |||||
static void onKeyboardCallback(PuglView* view, bool press, uint32_t key) | |||||
{ | |||||
handlePtr->onKeyboard(press, key); | |||||
} | |||||
static void onMouseCallback(PuglView* view, int button, bool press, int x, int y) | |||||
{ | |||||
handlePtr->onMouse(button, press, x, y); | |||||
} | |||||
static void onMotionCallback(PuglView* view, int x, int y) | |||||
{ | |||||
handlePtr->onMotion(x, y); | |||||
} | |||||
static void onScrollCallback(PuglView* view, int x, int y, float dx, float dy) | |||||
{ | |||||
handlePtr->onScroll(x, y, dx, dy); | |||||
} | |||||
static void onSpecialCallback(PuglView* view, bool press, PuglKey key) | |||||
{ | |||||
handlePtr->onSpecial(press, static_cast<Key>(key)); | |||||
} | |||||
static void onReshapeCallback(PuglView* view, int width, int height) | |||||
{ | |||||
handlePtr->onReshape(width, height); | |||||
} | |||||
static void onCloseCallback(PuglView* view) | |||||
{ | |||||
handlePtr->onClose(); | |||||
} | |||||
#undef handlePtr | |||||
}; | |||||
// ----------------------------------------------------------------------- | |||||
// Window | |||||
Window::Window(App& app) | |||||
: pData(new PrivateData(app, this)) | |||||
{ | |||||
} | |||||
Window::Window(App& app, Window& parent) | |||||
: pData(new PrivateData(app, this, parent)) | |||||
{ | |||||
} | |||||
Window::Window(App& app, intptr_t parentId) | |||||
: pData(new PrivateData(app, this, parentId)) | |||||
{ | |||||
} | |||||
Window::~Window() | |||||
{ | |||||
delete pData; | |||||
} | |||||
void Window::show() | |||||
{ | |||||
pData->setVisible(true); | |||||
} | |||||
void Window::hide() | |||||
{ | |||||
pData->setVisible(false); | |||||
} | |||||
void Window::close() | |||||
{ | |||||
pData->close(); | |||||
} | |||||
void Window::exec(bool lockWait) | |||||
{ | |||||
pData->exec(lockWait); | |||||
} | |||||
void Window::focus() | |||||
{ | |||||
pData->focus(); | |||||
} | |||||
void Window::repaint() | |||||
{ | |||||
pData->repaint(); | |||||
} | |||||
bool Window::isVisible() const noexcept | |||||
{ | |||||
return pData->isVisible(); | |||||
} | |||||
void Window::setVisible(bool yesNo) | |||||
{ | |||||
pData->setVisible(yesNo); | |||||
} | |||||
bool Window::isResizable() const noexcept | |||||
{ | |||||
return pData->isResizable(); | |||||
} | |||||
void Window::setResizable(bool yesNo) | |||||
{ | |||||
pData->setResizable(yesNo); | |||||
} | |||||
int Window::getWidth() const noexcept | |||||
{ | |||||
return pData->getWidth(); | |||||
} | |||||
int Window::getHeight() const noexcept | |||||
{ | |||||
return pData->getHeight(); | |||||
} | |||||
Size<int> Window::getSize() const noexcept | |||||
{ | |||||
return pData->getSize(); | |||||
} | |||||
void Window::setSize(unsigned int width, unsigned int height) | |||||
{ | |||||
pData->setSize(width, height); | |||||
} | |||||
void Window::setTitle(const char* title) | |||||
{ | |||||
pData->setTitle(title); | |||||
} | |||||
void Window::setTransientWinId(intptr_t winId) | |||||
{ | |||||
pData->setTransientWinId(winId); | |||||
} | |||||
App& Window::getApp() const noexcept | |||||
{ | |||||
return pData->getApp(); | |||||
} | |||||
int Window::getModifiers() const | |||||
{ | |||||
return pData->getModifiers(); | |||||
} | |||||
uint32_t Window::getEventTimestamp() const | |||||
{ | |||||
return pData->getEventTimestamp(); | |||||
} | |||||
intptr_t Window::getWindowId() const | |||||
{ | |||||
return pData->getWindowId(); | |||||
} | |||||
void Window::_addWidget(Widget* const widget) | |||||
{ | |||||
pData->addWidget(widget); | |||||
} | |||||
void Window::_removeWidget(Widget* const widget) | |||||
{ | |||||
pData->removeWidget(widget); | |||||
} | |||||
void Window::_idle() | |||||
{ | |||||
pData->idle(); | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
END_NAMESPACE_DGL | |||||
#undef DBG | |||||
#undef DBGF |
@@ -1,357 +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.h API for Pugl, a minimal portable API for OpenGL. | |||||
*/ | |||||
#ifndef PUGL_H_INCLUDED | |||||
#define PUGL_H_INCLUDED | |||||
#include <stdint.h> | |||||
/* | |||||
This API is pure portable C and contains no platform specific elements, or | |||||
even a GL dependency. However, unfortunately GL includes vary across | |||||
platforms so they are included here to allow for pure portable programs. | |||||
*/ | |||||
#ifdef __APPLE__ | |||||
# include "OpenGL/gl.h" | |||||
#else | |||||
# ifdef _WIN32 | |||||
# include <windows.h> /* Broken Windows GL headers require this */ | |||||
# endif | |||||
# include "GL/gl.h" | |||||
#endif | |||||
#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 | |||||
# define PUGL_API | |||||
#endif | |||||
#ifdef __cplusplus | |||||
extern "C" { | |||||
#else | |||||
# include <stdbool.h> | |||||
#endif | |||||
/** | |||||
@defgroup pugl Pugl | |||||
A minimal portable API for OpenGL. | |||||
@{ | |||||
*/ | |||||
/** | |||||
An OpenGL view. | |||||
*/ | |||||
typedef struct PuglViewImpl PuglView; | |||||
/** | |||||
A native window handle. | |||||
On X11, this is a Window. | |||||
On OSX, this is an NSView*. | |||||
On Windows, this is a HWND. | |||||
*/ | |||||
typedef intptr_t PuglNativeWindow; | |||||
/** | |||||
Return status code. | |||||
*/ | |||||
typedef enum { | |||||
PUGL_SUCCESS = 0 | |||||
} PuglStatus; | |||||
/** | |||||
Convenience symbols for ASCII control characters. | |||||
*/ | |||||
typedef enum { | |||||
PUGL_CHAR_BACKSPACE = 0x08, | |||||
PUGL_CHAR_ESCAPE = 0x1B, | |||||
PUGL_CHAR_DELETE = 0x7F | |||||
} PuglChar; | |||||
/** | |||||
Special (non-Unicode) keyboard keys. | |||||
*/ | |||||
typedef enum { | |||||
PUGL_KEY_F1 = 1, | |||||
PUGL_KEY_F2, | |||||
PUGL_KEY_F3, | |||||
PUGL_KEY_F4, | |||||
PUGL_KEY_F5, | |||||
PUGL_KEY_F6, | |||||
PUGL_KEY_F7, | |||||
PUGL_KEY_F8, | |||||
PUGL_KEY_F9, | |||||
PUGL_KEY_F10, | |||||
PUGL_KEY_F11, | |||||
PUGL_KEY_F12, | |||||
PUGL_KEY_LEFT, | |||||
PUGL_KEY_UP, | |||||
PUGL_KEY_RIGHT, | |||||
PUGL_KEY_DOWN, | |||||
PUGL_KEY_PAGE_UP, | |||||
PUGL_KEY_PAGE_DOWN, | |||||
PUGL_KEY_HOME, | |||||
PUGL_KEY_END, | |||||
PUGL_KEY_INSERT, | |||||
PUGL_KEY_SHIFT, | |||||
PUGL_KEY_CTRL, | |||||
PUGL_KEY_ALT, | |||||
PUGL_KEY_SUPER | |||||
} PuglKey; | |||||
/** | |||||
Keyboard modifier flags. | |||||
*/ | |||||
typedef enum { | |||||
PUGL_MOD_SHIFT = 1, /**< Shift key */ | |||||
PUGL_MOD_CTRL = 1 << 1, /**< Control key */ | |||||
PUGL_MOD_ALT = 1 << 2, /**< Alt/Option key */ | |||||
PUGL_MOD_SUPER = 1 << 3 /**< Mod4/Command/Windows key */ | |||||
} PuglMod; | |||||
/** | |||||
Handle for opaque user data. | |||||
*/ | |||||
typedef void* PuglHandle; | |||||
/** | |||||
A function called when the window is closed. | |||||
*/ | |||||
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 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. | |||||
@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); | |||||
/** | |||||
Create a new GL window. | |||||
@param parent Parent window, or 0 for top level. | |||||
@param title Window title, or NULL. | |||||
@param width Window width in pixels. | |||||
@param height Window height in pixels. | |||||
@param resizable Whether window should be user resizable. | |||||
@param visible Whether window should be initially visible. | |||||
*/ | |||||
PUGL_API PuglView* | |||||
puglCreate(PuglNativeWindow parent, | |||||
const char* title, | |||||
int width, | |||||
int height, | |||||
bool resizable, | |||||
bool visible); | |||||
/** | |||||
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); | |||||
/** | |||||
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); | |||||
/** | |||||
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); | |||||
/** | |||||
Return the native window handle. | |||||
*/ | |||||
PUGL_API PuglNativeWindow | |||||
puglGetNativeWindow(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,161 +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_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_GRAB_FOCUS: Work around reparent keyboard issues by grabbing focus. | |||||
PUGL_VERBOSE: Print GL information to console. | |||||
*/ | |||||
#include "pugl.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 | |||||
void puglDefaultReshape(PuglView* view, int width, int height); | |||||
typedef struct PuglInternalsImpl PuglInternals; | |||||
struct PuglViewImpl { | |||||
int width; | |||||
int height; | |||||
PuglHandle handle; | |||||
PuglCloseFunc closeFunc; | |||||
PuglDisplayFunc displayFunc; | |||||
PuglKeyboardFunc keyboardFunc; | |||||
PuglMotionFunc motionFunc; | |||||
PuglMouseFunc mouseFunc; | |||||
PuglReshapeFunc reshapeFunc; | |||||
PuglScrollFunc scrollFunc; | |||||
PuglSpecialFunc specialFunc; | |||||
PuglInternals* impl; | |||||
int mods; | |||||
bool mouse_in_view; | |||||
bool ignoreKeyRepeat; | |||||
bool redisplay; | |||||
uint32_t event_timestamp_ms; | |||||
}; | |||||
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 | |||||
puglDefaultReshape(PuglView* view, int width, int height) | |||||
{ | |||||
glMatrixMode(GL_PROJECTION); | |||||
glLoadIdentity(); | |||||
glOrtho(0, width, height, 0, 0, 1); | |||||
glViewport(0, 0, width, height); | |||||
glMatrixMode(GL_MODELVIEW); | |||||
glLoadIdentity(); | |||||
return; | |||||
// unused | |||||
(void)view; | |||||
} | |||||
void | |||||
puglIgnoreKeyRepeat(PuglView* view, bool ignore) | |||||
{ | |||||
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; | |||||
} |
@@ -1,434 +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) 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 result; | |||||
// unused | |||||
(void)aStyle; (void)bufferingType; (void)flag; | |||||
} | |||||
- (void)setPuglview:(PuglView*)view | |||||
{ | |||||
puglview = view; | |||||
[self setContentSize:NSMakeSize(view->width, view->height)]; | |||||
} | |||||
- (BOOL)windowShouldClose:(id)sender | |||||
{ | |||||
if (puglview->closeFunc) | |||||
puglview->closeFunc(puglview); | |||||
return YES; | |||||
// unused | |||||
(void)sender; | |||||
} | |||||
@end | |||||
static void | |||||
puglDisplay(PuglView* view) | |||||
{ | |||||
if (view->displayFunc) { | |||||
view->displayFunc(view); | |||||
} | |||||
} | |||||
@interface PuglOpenGLView : NSOpenGLView | |||||
{ | |||||
int colorBits; | |||||
int depthBits; | |||||
@public | |||||
PuglView* puglview; | |||||
NSTrackingArea* trackingArea; | |||||
} | |||||
- (id) initWithFrame:(NSRect)frame | |||||
colorBits:(int)numColorBits | |||||
depthBits:(int)numDepthBits; | |||||
- (void) reshape; | |||||
- (void) drawRect:(NSRect)rect; | |||||
- (void) mouseEntered:(NSEvent*)event; | |||||
- (void) mouseExited:(NSEvent*)event; | |||||
- (void) mouseMoved:(NSEvent*)event; | |||||
- (void) mouseDragged:(NSEvent*)event; | |||||
- (void) rightMouseDragged:(NSEvent*)event; | |||||
- (void) mouseDown:(NSEvent*)event; | |||||
- (void) mouseUp:(NSEvent*)event; | |||||
- (void) rightMouseDown:(NSEvent*)event; | |||||
- (void) rightMouseUp:(NSEvent*)event; | |||||
- (void) scrollWheel:(NSEvent*)event; | |||||
- (void) keyDown:(NSEvent*)event; | |||||
- (void) keyUp:(NSEvent*)event; | |||||
- (void) flagsChanged:(NSEvent*)event; | |||||
@end | |||||
@implementation PuglOpenGLView | |||||
- (id) initWithFrame:(NSRect)frame | |||||
colorBits:(int)numColorBits | |||||
depthBits:(int)numDepthBits | |||||
{ | |||||
colorBits = numColorBits; | |||||
depthBits = numDepthBits; | |||||
NSOpenGLPixelFormatAttribute pixelAttribs[16] = { | |||||
NSOpenGLPFADoubleBuffer, | |||||
NSOpenGLPFAAccelerated, | |||||
NSOpenGLPFAColorSize, | |||||
colorBits, | |||||
NSOpenGLPFADepthSize, | |||||
depthBits, | |||||
0 | |||||
}; | |||||
NSOpenGLPixelFormat* pixelFormat = [[NSOpenGLPixelFormat alloc] | |||||
initWithAttributes:pixelAttribs]; | |||||
if (pixelFormat) { | |||||
self = [super initWithFrame:frame pixelFormat:pixelFormat]; | |||||
[pixelFormat release]; | |||||
if (self) { | |||||
[[self openGLContext] makeCurrentContext]; | |||||
[self reshape]; | |||||
} | |||||
} else { | |||||
self = nil; | |||||
} | |||||
return self; | |||||
} | |||||
- (void) reshape | |||||
{ | |||||
[[self openGLContext] update]; | |||||
NSRect bounds = [self bounds]; | |||||
int width = bounds.size.width; | |||||
int height = bounds.size.height; | |||||
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. | |||||
*/ | |||||
if (puglview->reshapeFunc) { | |||||
puglview->reshapeFunc(puglview, width, height); | |||||
} else { | |||||
puglDefaultReshape(puglview, width, height); | |||||
} | |||||
puglview->width = width; | |||||
puglview->height = height; | |||||
} | |||||
} | |||||
- (void) drawRect:(NSRect)rect | |||||
{ | |||||
puglDisplay(puglview); | |||||
glFlush(); | |||||
glSwapAPPLE(); | |||||
// unused | |||||
return; (void)rect; | |||||
} | |||||
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; | |||||
} | |||||
-(void)updateTrackingAreas | |||||
{ | |||||
if (trackingArea != nil) { | |||||
[self removeTrackingArea:trackingArea]; | |||||
[trackingArea release]; | |||||
} | |||||
const int opts = (NSTrackingMouseEnteredAndExited | | |||||
NSTrackingMouseMoved | | |||||
NSTrackingActiveAlways); | |||||
trackingArea = [ [NSTrackingArea alloc] initWithRect:[self bounds] | |||||
options:opts | |||||
owner:self | |||||
userInfo:nil]; | |||||
[self addTrackingArea:trackingArea]; | |||||
} | |||||
- (void)mouseEntered:(NSEvent*)theEvent | |||||
{ | |||||
[self updateTrackingAreas]; | |||||
// unused | |||||
return; (void)theEvent; | |||||
} | |||||
- (void)mouseExited:(NSEvent*)theEvent | |||||
{ | |||||
// unused | |||||
return; (void)theEvent; | |||||
} | |||||
- (void) mouseMoved:(NSEvent*)event | |||||
{ | |||||
if (puglview->motionFunc) { | |||||
NSPoint loc = [event locationInWindow]; | |||||
puglview->mods = getModifiers(puglview, event); | |||||
puglview->motionFunc(puglview, loc.x, puglview->height - loc.y); | |||||
} | |||||
} | |||||
- (void) mouseDragged:(NSEvent*)event | |||||
{ | |||||
if (puglview->motionFunc) { | |||||
NSPoint loc = [event locationInWindow]; | |||||
puglview->mods = getModifiers(puglview, event); | |||||
puglview->motionFunc(puglview, loc.x, puglview->height - loc.y); | |||||
} | |||||
} | |||||
- (void) rightMouseDragged:(NSEvent*)event | |||||
{ | |||||
if (puglview->motionFunc) { | |||||
NSPoint loc = [event locationInWindow]; | |||||
puglview->mods = getModifiers(puglview, event); | |||||
puglview->motionFunc(puglview, loc.x, puglview->height - loc.y); | |||||
} | |||||
} | |||||
- (void) mouseDown:(NSEvent*)event | |||||
{ | |||||
if (puglview->mouseFunc) { | |||||
NSPoint loc = [event locationInWindow]; | |||||
puglview->mods = getModifiers(puglview, event); | |||||
puglview->mouseFunc(puglview, 1, true, loc.x, puglview->height - loc.y); | |||||
} | |||||
} | |||||
- (void) mouseUp:(NSEvent*)event | |||||
{ | |||||
if (puglview->mouseFunc) { | |||||
NSPoint loc = [event locationInWindow]; | |||||
puglview->mods = getModifiers(puglview, event); | |||||
puglview->mouseFunc(puglview, 1, false, loc.x, puglview->height - loc.y); | |||||
} | |||||
[self updateTrackingAreas]; | |||||
} | |||||
- (void) rightMouseDown:(NSEvent*)event | |||||
{ | |||||
if (puglview->mouseFunc) { | |||||
NSPoint loc = [event locationInWindow]; | |||||
puglview->mods = getModifiers(puglview, event); | |||||
puglview->mouseFunc(puglview, 3, true, loc.x, puglview->height - loc.y); | |||||
} | |||||
} | |||||
- (void) rightMouseUp:(NSEvent*)event | |||||
{ | |||||
if (puglview->mouseFunc) { | |||||
NSPoint loc = [event locationInWindow]; | |||||
puglview->mods = getModifiers(puglview, event); | |||||
puglview->mouseFunc(puglview, 3, false, loc.x, puglview->height - loc.y); | |||||
} | |||||
} | |||||
- (void) scrollWheel:(NSEvent*)event | |||||
{ | |||||
if (puglview->scrollFunc) { | |||||
NSPoint loc = [event locationInWindow]; | |||||
puglview->mods = getModifiers(puglview, event); | |||||
puglview->scrollFunc(puglview, | |||||
loc.x, puglview->height - loc.y, | |||||
[event deltaX], [event deltaY]); | |||||
} | |||||
[self updateTrackingAreas]; | |||||
} | |||||
- (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; | |||||
}; | |||||
PuglView* | |||||
puglCreate(PuglNativeWindow parent, | |||||
const char* title, | |||||
int width, | |||||
int height, | |||||
bool resizable, | |||||
bool visible) | |||||
{ | |||||
PuglView* view = (PuglView*)calloc(1, sizeof(PuglView)); | |||||
PuglInternals* impl = (PuglInternals*)calloc(1, sizeof(PuglInternals)); | |||||
if (!view || !impl) { | |||||
return NULL; | |||||
} | |||||
view->impl = impl; | |||||
view->width = width; | |||||
view->height = height; | |||||
[NSAutoreleasePool new]; | |||||
[NSApplication sharedApplication]; | |||||
NSString* titleString = [[NSString alloc] | |||||
initWithBytes:title | |||||
length:strlen(title) | |||||
encoding:NSUTF8StringEncoding]; | |||||
id window = [[PuglWindow new]retain]; | |||||
[window setPuglview:view]; | |||||
[window setTitle:titleString]; | |||||
impl->glview = [PuglOpenGLView new]; | |||||
impl->window = window; | |||||
impl->glview->puglview = view; | |||||
[window setContentView:impl->glview]; | |||||
[NSApp activateIgnoringOtherApps:YES]; | |||||
[window makeFirstResponder:impl->glview]; | |||||
[window makeKeyAndOrderFront:window]; | |||||
if (! visible) { | |||||
[window setIsVisible:NO]; | |||||
} | |||||
return view; | |||||
// unused | |||||
(void)parent; (void)resizable; | |||||
} | |||||
void | |||||
puglDestroy(PuglView* view) | |||||
{ | |||||
view->impl->glview->puglview = NULL; | |||||
[view->impl->window close]; | |||||
[view->impl->glview release]; | |||||
[view->impl->window release]; | |||||
free(view->impl); | |||||
free(view); | |||||
} | |||||
PuglStatus | |||||
puglProcessEvents(PuglView* view) | |||||
{ | |||||
[view->impl->glview setNeedsDisplay: YES]; | |||||
return PUGL_SUCCESS; | |||||
} | |||||
void | |||||
puglPostRedisplay(PuglView* view) | |||||
{ | |||||
view->redisplay = true; | |||||
} | |||||
PuglNativeWindow | |||||
puglGetNativeWindow(PuglView* view) | |||||
{ | |||||
return (PuglNativeWindow)view->impl->glview; | |||||
} |
@@ -1 +0,0 @@ | |||||
pugl_osx.m |
@@ -1,38 +0,0 @@ | |||||
/* | |||||
Copyright 2012 David Robillard <http://drobilla.net> | |||||
Copyright 2013 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 pugl_osx_extended.h Extended OSX/Cocoa Pugl Implementation. | |||||
*/ | |||||
#include <stdbool.h> | |||||
#include "pugl.h" | |||||
#ifdef __cplusplus | |||||
extern "C" { | |||||
#endif | |||||
void puglImplIdle(PuglView* view); | |||||
void puglImplFocus(PuglView* view); | |||||
void puglImplSetSize(PuglView* view, unsigned int width, unsigned int height, bool forced); | |||||
void puglImplSetTitle(PuglView* view, const char* title); | |||||
void puglImplSetVisible(PuglView* view, bool yesNo); | |||||
#ifdef __cplusplus | |||||
} /* extern "C" */ | |||||
#endif |
@@ -1,104 +0,0 @@ | |||||
/* | |||||
Copyright 2012 David Robillard <http://drobilla.net> | |||||
Copyright 2013 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 pugl_osx_extended.m Extended OSX/Cocoa Pugl Implementation. | |||||
*/ | |||||
#import "pugl_osx.m" | |||||
#include "pugl_osx_extended.h" | |||||
void puglImplIdle(PuglView* view) | |||||
{ | |||||
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; | |||||
NSEvent* event; | |||||
static const NSUInteger eventMask = (NSLeftMouseDownMask | NSLeftMouseUpMask | | |||||
NSRightMouseDownMask | NSRightMouseUpMask | | |||||
NSMouseMovedMask | | |||||
NSLeftMouseDraggedMask | NSRightMouseDraggedMask | | |||||
NSMouseEnteredMask | NSMouseExitedMask | | |||||
NSKeyDownMask | NSKeyUpMask | | |||||
NSFlagsChangedMask | | |||||
NSCursorUpdateMask | NSScrollWheelMask); | |||||
for (;;) { | |||||
event = [view->impl->window | |||||
nextEventMatchingMask:eventMask | |||||
untilDate:[NSDate distantPast] | |||||
inMode:NSEventTrackingRunLoopMode | |||||
dequeue:YES]; | |||||
if (event == nil) | |||||
break; | |||||
[view->impl->window sendEvent: event]; | |||||
} | |||||
[pool release]; | |||||
} | |||||
void puglImplFocus(PuglView* view) | |||||
{ | |||||
id window = view->impl->window; | |||||
// TODO | |||||
[NSApp activateIgnoringOtherApps:YES]; | |||||
[window makeKeyAndOrderFront:window]; | |||||
} | |||||
void puglImplSetSize(PuglView* view, unsigned int width, unsigned int height, bool forced) | |||||
{ | |||||
id window = view->impl->window; | |||||
NSRect frame = [window frame]; | |||||
frame.origin.y -= height - frame.size.height; | |||||
frame.size.width = width; | |||||
frame.size.height = height+20; | |||||
// if (forced) { | |||||
// [window setFrame:frame]; | |||||
// } else { | |||||
[window setFrame:frame display:YES animate:NO]; | |||||
// } | |||||
// unused | |||||
return; (void)forced; | |||||
} | |||||
void puglImplSetTitle(PuglView* view, const char* title) | |||||
{ | |||||
id window = view->impl->window; | |||||
NSString* titleString = [[NSString alloc] | |||||
initWithBytes:title | |||||
length:strlen(title) | |||||
encoding:NSUTF8StringEncoding]; | |||||
[window setTitle:titleString]; | |||||
} | |||||
void puglImplSetVisible(PuglView* view, bool yesNo) | |||||
{ | |||||
id window = view->impl->window; | |||||
if (yesNo) | |||||
[window setIsVisible:YES]; | |||||
else | |||||
[window setIsVisible:NO]; | |||||
} |
@@ -1 +0,0 @@ | |||||
pugl_osx_extended.m |
@@ -1,385 +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_win.cpp Windows/WGL Pugl Implementation. | |||||
*/ | |||||
#include <windows.h> | |||||
#include <windowsx.h> | |||||
#include <GL/gl.h> | |||||
#include <stdio.h> | |||||
#include <stdlib.h> | |||||
#include "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 | |||||
const int LOCAL_CLOSE_MSG = WM_USER + 50; | |||||
struct PuglInternalsImpl { | |||||
HWND hwnd; | |||||
HDC hdc; | |||||
HGLRC hglrc; | |||||
WNDCLASS wc; | |||||
}; | |||||
LRESULT CALLBACK | |||||
wndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); | |||||
PuglView* | |||||
puglCreate(PuglNativeWindow parent, | |||||
const char* title, | |||||
int width, | |||||
int height, | |||||
bool resizable, | |||||
bool visible) | |||||
{ | |||||
PuglView* view = (PuglView*)calloc(1, sizeof(PuglView)); | |||||
PuglInternals* impl = (PuglInternals*)calloc(1, sizeof(PuglInternals)); | |||||
if (!view || !impl) { | |||||
return NULL; | |||||
} | |||||
view->impl = impl; | |||||
view->width = width; | |||||
view->height = height; | |||||
// 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]; | |||||
_snprintf(classNameBuf, sizeof(classNameBuf), "%s_%d\n", title, wc_count++); | |||||
impl->wc.style = CS_OWNDC; | |||||
impl->wc.lpfnWndProc = wndProc; | |||||
impl->wc.cbClsExtra = 0; | |||||
impl->wc.cbWndExtra = 0; | |||||
impl->wc.hInstance = 0; | |||||
impl->wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); | |||||
impl->wc.hCursor = LoadCursor(NULL, IDC_ARROW); | |||||
impl->wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); | |||||
impl->wc.lpszMenuName = NULL; | |||||
impl->wc.lpszClassName = classNameBuf; | |||||
RegisterClass(&impl->wc); | |||||
int winFlags = WS_POPUPWINDOW | WS_CAPTION; | |||||
if (resizable) { | |||||
winFlags |= WS_SIZEBOX; | |||||
} | |||||
// Adjust the overall window size to accomodate our requested client size | |||||
RECT wr = { 0, 0, width, height }; | |||||
AdjustWindowRectEx(&wr, winFlags, FALSE, WS_EX_TOPMOST); | |||||
impl->hwnd = CreateWindowEx( | |||||
WS_EX_TOPMOST, | |||||
classNameBuf, title, | |||||
(visible ? WS_VISIBLE : 0) | (parent ? WS_CHILD : winFlags), | |||||
0, 0, wr.right-wr.left, wr.bottom-wr.top, | |||||
(HWND)parent, NULL, NULL, NULL); | |||||
if (!impl->hwnd) { | |||||
free(impl); | |||||
free(view); | |||||
return NULL; | |||||
} | |||||
#ifdef _WIN64 | |||||
SetWindowLongPtr(impl->hwnd, GWLP_USERDATA, (LONG_PTR)view); | |||||
#else | |||||
SetWindowLongPtr(impl->hwnd, GWL_USERDATA, (LONG)view); | |||||
#endif | |||||
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); | |||||
wglMakeCurrent(impl->hdc, impl->hglrc); | |||||
view->width = width; | |||||
view->height = height; | |||||
return view; | |||||
} | |||||
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(view->impl); | |||||
free(view); | |||||
} | |||||
void | |||||
puglReshape(PuglView* view, int width, int height) | |||||
{ | |||||
wglMakeCurrent(view->impl->hdc, view->impl->hglrc); | |||||
if (view->reshapeFunc) { | |||||
view->reshapeFunc(view, width, height); | |||||
} else { | |||||
puglDefaultReshape(view, width, height); | |||||
} | |||||
view->width = width; | |||||
view->height = height; | |||||
} | |||||
void | |||||
puglDisplay(PuglView* view) | |||||
{ | |||||
wglMakeCurrent(view->impl->hdc, view->impl->hglrc); | |||||
if (view->displayFunc) { | |||||
view->displayFunc(view); | |||||
} | |||||
glFlush(); | |||||
SwapBuffers(view->impl->hdc); | |||||
view->redisplay = false; | |||||
} | |||||
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; | |||||
setModifiers(view); | |||||
switch (message) { | |||||
case WM_CREATE: | |||||
case WM_SHOWWINDOW: | |||||
case WM_SIZE: | |||||
RECT rect; | |||||
GetClientRect(view->impl->hwnd, &rect); | |||||
puglReshape(view, rect.right, rect.bottom); | |||||
view->width = rect.right; | |||||
view->height = rect.bottom; | |||||
break; | |||||
case WM_PAINT: | |||||
BeginPaint(view->impl->hwnd, &ps); | |||||
puglDisplay(view); | |||||
EndPaint(view->impl->hwnd, &ps); | |||||
break; | |||||
case WM_MOUSEMOVE: | |||||
if (view->motionFunc) { | |||||
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(); | |||||
view->scrollFunc( | |||||
view, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), | |||||
0.0f, (int16_t)HIWORD(wParam) / (float)WHEEL_DELTA); | |||||
} | |||||
break; | |||||
case WM_MOUSEHWHEEL: | |||||
if (view->scrollFunc) { | |||||
view->event_timestamp_ms = GetMessageTime(); | |||||
view->scrollFunc( | |||||
view, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), | |||||
(int16_t)HIWORD(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) { | |||||
view->keyboardFunc(view, message == WM_KEYDOWN, wParam); | |||||
} | |||||
break; | |||||
case WM_QUIT: | |||||
case LOCAL_CLOSE_MSG: | |||||
if (view->closeFunc) { | |||||
view->closeFunc(view); | |||||
} | |||||
break; | |||||
default: | |||||
return DefWindowProc( | |||||
view->impl->hwnd, message, wParam, lParam); | |||||
} | |||||
return 0; | |||||
} | |||||
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) | |||||
{ | |||||
#ifdef _WIN64 | |||||
PuglView* view = (PuglView*)GetWindowLongPtr(hwnd, GWLP_USERDATA); | |||||
#else | |||||
PuglView* view = (PuglView*)GetWindowLongPtr(hwnd, GWL_USERDATA); | |||||
#endif | |||||
switch (message) { | |||||
case WM_CREATE: | |||||
PostMessage(hwnd, WM_SHOWWINDOW, TRUE, 0); | |||||
return 0; | |||||
case WM_CLOSE: | |||||
PostMessage(hwnd, LOCAL_CLOSE_MSG, wParam, lParam); | |||||
return 0; | |||||
case WM_DESTROY: | |||||
return 0; | |||||
default: | |||||
if (view) { | |||||
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; | |||||
} |
@@ -1,395 +0,0 @@ | |||||
/* | |||||
Copyright 2012-2014 David Robillard <http://drobilla.net> | |||||
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 <GL/gl.h> | |||||
#include <GL/glx.h> | |||||
#include <X11/Xatom.h> | |||||
#include <X11/Xlib.h> | |||||
#include <X11/keysym.h> | |||||
#include "pugl_internal.h" | |||||
struct PuglInternalsImpl { | |||||
Display* display; | |||||
int screen; | |||||
Window win; | |||||
GLXContext ctx; | |||||
Bool doubleBuffered; | |||||
}; | |||||
/** | |||||
Attributes for single-buffered RGBA with at least | |||||
4 bits per color and a 16 bit depth buffer. | |||||
*/ | |||||
static int attrListSgl[] = { | |||||
GLX_RGBA, | |||||
GLX_RED_SIZE, 4, | |||||
GLX_GREEN_SIZE, 4, | |||||
GLX_BLUE_SIZE, 4, | |||||
GLX_DEPTH_SIZE, 16, | |||||
None | |||||
}; | |||||
/** | |||||
Attributes for double-buffered RGBA with at least | |||||
4 bits per color and a 16 bit depth buffer. | |||||
*/ | |||||
static int attrListDbl[] = { | |||||
GLX_RGBA, GLX_DOUBLEBUFFER, | |||||
GLX_RED_SIZE, 4, | |||||
GLX_GREEN_SIZE, 4, | |||||
GLX_BLUE_SIZE, 4, | |||||
GLX_DEPTH_SIZE, 16, | |||||
None | |||||
}; | |||||
PuglView* | |||||
puglCreate(PuglNativeWindow parent, | |||||
const char* title, | |||||
int width, | |||||
int height, | |||||
bool resizable, | |||||
bool visible) | |||||
{ | |||||
PuglView* view = (PuglView*)calloc(1, sizeof(PuglView)); | |||||
PuglInternals* impl = (PuglInternals*)calloc(1, sizeof(PuglInternals)); | |||||
if (!view || !impl) { | |||||
return NULL; | |||||
} | |||||
view->impl = impl; | |||||
view->width = width; | |||||
view->height = height; | |||||
impl->display = XOpenDisplay(0); | |||||
impl->screen = DefaultScreen(impl->display); | |||||
XVisualInfo* vi = glXChooseVisual(impl->display, impl->screen, attrListDbl); | |||||
if (!vi) { | |||||
vi = glXChooseVisual(impl->display, impl->screen, attrListSgl); | |||||
impl->doubleBuffered = False; | |||||
PUGL_LOG("No double buffering available\n"); | |||||
} else { | |||||
impl->doubleBuffered = True; | |||||
PUGL_LOG("Double buffered rendering enabled\n"); | |||||
} | |||||
int glxMajor, glxMinor; | |||||
glXQueryVersion(impl->display, &glxMajor, &glxMinor); | |||||
PUGL_LOGF("GLX Version %d.%d\n", glxMajor, glxMinor); | |||||
impl->ctx = glXCreateContext(impl->display, vi, 0, GL_TRUE); | |||||
Window xParent = parent | |||||
? (Window)parent | |||||
: RootWindow(impl->display, impl->screen); | |||||
Colormap cmap = XCreateColormap( | |||||
impl->display, xParent, vi->visual, AllocNone); | |||||
XSetWindowAttributes attr; | |||||
memset(&attr, 0, sizeof(XSetWindowAttributes)); | |||||
attr.colormap = cmap; | |||||
attr.border_pixel = 0; | |||||
attr.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask | |||||
| ButtonPressMask | ButtonReleaseMask | |||||
#ifdef XKEYFOCUSGRAB | |||||
| EnterWindowMask | |||||
#endif | |||||
| PointerMotionMask | StructureNotifyMask; | |||||
impl->win = XCreateWindow( | |||||
impl->display, xParent, | |||||
0, 0, (unsigned int)view->width, (unsigned int)view->height, 0, vi->depth, InputOutput, vi->visual, | |||||
CWBorderPixel | CWColormap | CWEventMask, &attr); | |||||
XSizeHints sizeHints; | |||||
memset(&sizeHints, 0, sizeof(sizeHints)); | |||||
if (!resizable) { | |||||
sizeHints.flags = PMinSize|PMaxSize; | |||||
sizeHints.min_width = width; | |||||
sizeHints.min_height = height; | |||||
sizeHints.max_width = width; | |||||
sizeHints.max_height = height; | |||||
XSetNormalHints(impl->display, impl->win, &sizeHints); | |||||
} | |||||
if (title) { | |||||
XStoreName(impl->display, impl->win, title); | |||||
} | |||||
if (!parent) { | |||||
Atom wmDelete = XInternAtom(impl->display, "WM_DELETE_WINDOW", True); | |||||
XSetWMProtocols(impl->display, impl->win, &wmDelete, 1); | |||||
} | |||||
if (visible) { | |||||
XMapRaised(impl->display, impl->win); | |||||
} | |||||
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 view; | |||||
} | |||||
void | |||||
puglDestroy(PuglView* view) | |||||
{ | |||||
if (!view) { | |||||
return; | |||||
} | |||||
glXDestroyContext(view->impl->display, view->impl->ctx); | |||||
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) | |||||
{ | |||||
glXMakeCurrent(view->impl->display, view->impl->win, view->impl->ctx); | |||||
if (view->reshapeFunc) { | |||||
view->reshapeFunc(view, width, height); | |||||
} else { | |||||
puglDefaultReshape(view, width, height); | |||||
} | |||||
view->width = width; | |||||
view->height = height; | |||||
} | |||||
static void | |||||
puglDisplay(PuglView* view) | |||||
{ | |||||
glXMakeCurrent(view->impl->display, view->impl->win, view->impl->ctx); | |||||
if (view->displayFunc) { | |||||
view->displayFunc(view); | |||||
} | |||||
glFlush(); | |||||
if (view->impl->doubleBuffered) { | |||||
glXSwapBuffers(view->impl->display, view->impl->win); | |||||
} | |||||
view->redisplay = false; | |||||
} | |||||
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 long xtime) | |||||
{ | |||||
view->event_timestamp_ms = (uint32_t)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 (n == 0) { | |||||
return; | |||||
} else 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, (uint32_t)str[0]); | |||||
} | |||||
} | |||||
PuglStatus | |||||
puglProcessEvents(PuglView* view) | |||||
{ | |||||
XEvent event; | |||||
while (XPending(view->impl->display) > 0) { | |||||
XNextEvent(view->impl->display, &event); | |||||
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, | |||||
(int)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); | |||||
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); | |||||
break; | |||||
} | |||||
} | |||||
dispatchKey(view, &event, false); | |||||
break; | |||||
case ClientMessage: | |||||
if (!strcmp(XGetAtomName(view->impl->display, | |||||
event.xclient.message_type), | |||||
"WM_PROTOCOLS")) { | |||||
if (view->closeFunc) { | |||||
view->closeFunc(view); | |||||
} | |||||
} | |||||
break; | |||||
#ifdef XKEYFOCUSGRAB | |||||
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 (PuglNativeWindow)view->impl->win; | |||||
} |
@@ -1,318 +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_PLUGIN_HPP_INCLUDED | |||||
#define DISTRHO_PLUGIN_HPP_INCLUDED | |||||
#include "extra/d_string.hpp" | |||||
#include "src/DistrhoPluginChecks.h" | |||||
#include <cmath> | |||||
#ifdef PROPER_CPP11_SUPPORT | |||||
# include <cstdint> | |||||
#else | |||||
# include <stdint.h> | |||||
#endif | |||||
#ifndef M_PI | |||||
# define M_PI 3.14159265358979323846 | |||||
#endif | |||||
START_NAMESPACE_DISTRHO | |||||
// ----------------------------------------------------------------------- | |||||
// Parameter Hints | |||||
const uint32_t PARAMETER_IS_AUTOMABLE = 1 << 0; | |||||
const uint32_t PARAMETER_IS_BOOLEAN = 1 << 1; | |||||
const uint32_t PARAMETER_IS_INTEGER = 1 << 2; | |||||
const uint32_t PARAMETER_IS_LOGARITHMIC = 1 << 3; | |||||
const uint32_t PARAMETER_IS_OUTPUT = 1 << 4; | |||||
// ----------------------------------------------------------------------- | |||||
// Parameter Ranges | |||||
struct ParameterRanges { | |||||
float def; | |||||
float min; | |||||
float max; | |||||
ParameterRanges() noexcept | |||||
: def(0.0f), | |||||
min(0.0f), | |||||
max(1.0f) {} | |||||
ParameterRanges(float def, float min, float max) noexcept | |||||
{ | |||||
this->def = def; | |||||
this->min = min; | |||||
this->max = max; | |||||
} | |||||
void clear() noexcept | |||||
{ | |||||
def = 0.0f; | |||||
min = 0.0f; | |||||
max = 1.0f; | |||||
} | |||||
/*! | |||||
* Fix 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. | |||||
*/ | |||||
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 | |||||
{ | |||||
return value * (max - min) + min; | |||||
} | |||||
}; | |||||
// ----------------------------------------------------------------------- | |||||
// Parameter | |||||
struct Parameter { | |||||
uint32_t hints; | |||||
d_string name; | |||||
d_string symbol; | |||||
d_string unit; | |||||
ParameterRanges ranges; | |||||
Parameter() noexcept | |||||
: hints(0x0) {} | |||||
void clear() noexcept | |||||
{ | |||||
hints = 0x0; | |||||
name = ""; | |||||
symbol = ""; | |||||
unit = ""; | |||||
ranges.clear(); | |||||
} | |||||
}; | |||||
// ----------------------------------------------------------------------- | |||||
// MidiEvent | |||||
struct MidiEvent { | |||||
uint32_t frame; | |||||
uint8_t size; | |||||
uint8_t buf[4]; | |||||
void clear() noexcept | |||||
{ | |||||
frame = 0; | |||||
size = 0; | |||||
buf[0] = 0; | |||||
buf[1] = 0; | |||||
buf[2] = 0; | |||||
buf[3] = 0; | |||||
} | |||||
}; | |||||
// ----------------------------------------------------------------------- | |||||
// TimePos | |||||
struct TimePos { | |||||
bool playing; | |||||
uint64_t frame; | |||||
struct BeatBarTick { | |||||
bool valid; | |||||
int32_t bar; /*!< current bar */ | |||||
int32_t beat; /*!< current beat-within-bar */ | |||||
int32_t tick; /*!< current tick-within-beat */ | |||||
double barStartTick; | |||||
float beatsPerBar; /*!< time signature "numerator" */ | |||||
float beatType; /*!< time signature "denominator" */ | |||||
double ticksPerBeat; | |||||
double beatsPerMinute; | |||||
BeatBarTick() 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; | |||||
TimePos() noexcept | |||||
: playing(false), | |||||
frame(0) {} | |||||
}; | |||||
// ----------------------------------------------------------------------- | |||||
// Plugin | |||||
class Plugin | |||||
{ | |||||
public: | |||||
Plugin(uint32_t parameterCount, uint32_t programCount, uint32_t stateCount); | |||||
virtual ~Plugin(); | |||||
// ------------------------------------------------------------------- | |||||
// Host state | |||||
uint32_t d_getBufferSize() const noexcept; | |||||
double d_getSampleRate() const noexcept; | |||||
#if DISTRHO_PLUGIN_WANT_TIMEPOS | |||||
const TimePos& d_getTimePos() const noexcept; | |||||
#endif | |||||
#if DISTRHO_PLUGIN_WANT_LATENCY | |||||
void d_setLatency(uint32_t frames) noexcept; | |||||
#endif | |||||
protected: | |||||
// ------------------------------------------------------------------- | |||||
// Information | |||||
virtual const char* d_getName() const noexcept { return DISTRHO_PLUGIN_NAME; } | |||||
virtual const char* d_getLabel() const noexcept = 0; | |||||
virtual const char* d_getMaker() const noexcept = 0; | |||||
virtual const char* d_getLicense() const noexcept = 0; | |||||
virtual uint32_t d_getVersion() const noexcept = 0; | |||||
virtual long d_getUniqueId() const noexcept = 0; | |||||
// ------------------------------------------------------------------- | |||||
// Init | |||||
virtual void d_initParameter(uint32_t index, Parameter& parameter) = 0; | |||||
#if DISTRHO_PLUGIN_WANT_PROGRAMS | |||||
virtual void d_initProgramName(uint32_t index, d_string& programName) = 0; | |||||
#endif | |||||
#if DISTRHO_PLUGIN_WANT_STATE | |||||
virtual void d_initStateKey(uint32_t index, d_string& stateKey) = 0; | |||||
#endif | |||||
// ------------------------------------------------------------------- | |||||
// Internal data | |||||
virtual float d_getParameterValue(uint32_t index) const = 0; | |||||
virtual void d_setParameterValue(uint32_t index, float value) = 0; | |||||
#if DISTRHO_PLUGIN_WANT_PROGRAMS | |||||
virtual void d_setProgram(uint32_t index) = 0; | |||||
#endif | |||||
#if DISTRHO_PLUGIN_WANT_STATE | |||||
virtual void d_setState(const char* key, const char* value) = 0; | |||||
#endif | |||||
// ------------------------------------------------------------------- | |||||
// Process | |||||
virtual void d_activate() {} | |||||
virtual void d_deactivate() {} | |||||
#if DISTRHO_PLUGIN_IS_SYNTH | |||||
virtual void d_run(float** inputs, float** outputs, uint32_t frames, const MidiEvent* midiEvents, uint32_t midiEventCount) = 0; | |||||
#else | |||||
virtual void d_run(float** inputs, float** outputs, uint32_t frames) = 0; | |||||
#endif | |||||
// ------------------------------------------------------------------- | |||||
// Callbacks (optional) | |||||
virtual void d_bufferSizeChanged(uint32_t newBufferSize); | |||||
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 | |||||
extern Plugin* createPlugin(); | |||||
// ----------------------------------------------------------------------- | |||||
END_NAMESPACE_DISTRHO | |||||
#endif // DISTRHO_PLUGIN_HPP_INCLUDED |
@@ -1,28 +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 "src/DistrhoPlugin.cpp" | |||||
#if defined(DISTRHO_PLUGIN_TARGET_CARLA) | |||||
# include "src/DistrhoPluginCarla.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,104 +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_UI_HPP_INCLUDED | |||||
#define DISTRHO_UI_HPP_INCLUDED | |||||
#include "extra/d_leakdetector.hpp" | |||||
#include "src/DistrhoPluginChecks.h" | |||||
#include "../dgl/Widget.hpp" | |||||
START_NAMESPACE_DISTRHO | |||||
// ----------------------------------------------------------------------- | |||||
// UI | |||||
class UI : public DGL::Widget | |||||
{ | |||||
public: | |||||
UI(); | |||||
virtual ~UI(); | |||||
// ------------------------------------------------------------------- | |||||
// Host DSP State | |||||
double d_getSampleRate() const noexcept; | |||||
void d_editParameter(uint32_t index, bool started); | |||||
void d_setParameterValue(uint32_t index, float value); | |||||
#if DISTRHO_PLUGIN_WANT_STATE | |||||
void d_setState(const char* key, const char* value); | |||||
#endif | |||||
#if DISTRHO_PLUGIN_IS_SYNTH | |||||
void d_sendNote(uint8_t channel, uint8_t note, uint8_t velocity); | |||||
#endif | |||||
// ------------------------------------------------------------------- | |||||
// Host UI State | |||||
void d_uiResize(uint width, uint height); | |||||
protected: | |||||
// ------------------------------------------------------------------- | |||||
// Basic Information | |||||
virtual const char* d_getName() const noexcept { return DISTRHO_PLUGIN_NAME; } | |||||
virtual uint d_getWidth() const noexcept = 0; | |||||
virtual uint d_getHeight() const noexcept = 0; | |||||
// ------------------------------------------------------------------- | |||||
// DSP Callbacks | |||||
virtual void d_parameterChanged(uint32_t index, float value) = 0; | |||||
#if DISTRHO_PLUGIN_WANT_PROGRAMS | |||||
virtual void d_programChanged(uint32_t index) = 0; | |||||
#endif | |||||
#if DISTRHO_PLUGIN_WANT_STATE | |||||
virtual void d_stateChanged(const char* key, const char* value) = 0; | |||||
#endif | |||||
// ------------------------------------------------------------------- | |||||
// UI Callbacks (optional) | |||||
virtual void d_uiIdle() {} | |||||
#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS | |||||
// ------------------------------------------------------------------- | |||||
// Direct DSP access - DO NOT USE THIS UNLESS STRICTLY NECESSARY!! | |||||
void* d_getPluginInstancePointer() const noexcept; | |||||
#endif | |||||
// ------------------------------------------------------------------- | |||||
private: | |||||
struct PrivateData; | |||||
PrivateData* const pData; | |||||
friend class UIExporter; | |||||
DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(UI) | |||||
}; | |||||
// ----------------------------------------------------------------------- | |||||
// Create UI, entry point | |||||
extern UI* createUI(); | |||||
// ----------------------------------------------------------------------- | |||||
END_NAMESPACE_DISTRHO | |||||
#endif // DISTRHO_UI_HPP_INCLUDED |
@@ -1,27 +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 "src/DistrhoUI.cpp" | |||||
#if defined(DISTRHO_PLUGIN_TARGET_CARLA) | |||||
// 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,171 +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_UTILS_HPP_INCLUDED | |||||
#define DISTRHO_UTILS_HPP_INCLUDED | |||||
#include "src/DistrhoDefines.h" | |||||
#include <cstdarg> | |||||
#include <cstdio> | |||||
#include <cstdlib> | |||||
#include <cstring> | |||||
#ifdef PROPER_CPP11_SUPPORT | |||||
# include <cstdint> | |||||
#else | |||||
# include <stdint.h> | |||||
#endif | |||||
#ifdef DISTRHO_OS_WINDOWS | |||||
# include <winsock2.h> | |||||
# include <windows.h> | |||||
#else | |||||
# include <unistd.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 | |||||
static inline | |||||
long d_cconst(const int a, const int b, const int c, const int d) noexcept | |||||
{ | |||||
return (a << 24) | (b << 16) | (c << 8) | (d << 0); | |||||
} | |||||
static inline | |||||
void d_pass() noexcept {} | |||||
// ----------------------------------------------------------------------- | |||||
// string print functions | |||||
#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 | |||||
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 (...) {} | |||||
} | |||||
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 (...) {} | |||||
} | |||||
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 (...) {} | |||||
} | |||||
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); | |||||
} | |||||
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); | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
// d_*sleep | |||||
static inline | |||||
void d_sleep(const uint secs) | |||||
{ | |||||
DISTRHO_SAFE_ASSERT_RETURN(secs > 0,); | |||||
try { | |||||
#ifdef DISTRHO_OS_WINDOWS | |||||
::Sleep(secs * 1000); | |||||
#else | |||||
::sleep(secs); | |||||
#endif | |||||
} DISTRHO_SAFE_EXCEPTION("carla_sleep"); | |||||
} | |||||
static inline | |||||
void d_msleep(const uint msecs) | |||||
{ | |||||
DISTRHO_SAFE_ASSERT_RETURN(msecs > 0,); | |||||
try { | |||||
#ifdef DISTRHO_OS_WINDOWS | |||||
::Sleep(msecs); | |||||
#else | |||||
::usleep(msecs * 1000); | |||||
#endif | |||||
} DISTRHO_SAFE_EXCEPTION("carla_msleep"); | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
#endif // DISTRHO_UTILS_HPP_INCLUDED |
@@ -1,139 +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" | |||||
// ----------------------------------------------------------------------- | |||||
// 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 ::DistrhoLeakedObjectDetector<ClassName>; \ | |||||
static const char* getLeakedObjectClassName() noexcept { return #ClassName; } \ | |||||
::DistrhoLeakedObjectDetector<ClassName> DISTRHO_JOIN_MACRO(leakDetector, __LINE__); | |||||
#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 DistrhoLeakedObjectDetector | |||||
{ | |||||
public: | |||||
//============================================================================== | |||||
DistrhoLeakedObjectDetector() noexcept { ++(getCounter().numObjects); } | |||||
DistrhoLeakedObjectDetector(const DistrhoLeakedObjectDetector&) noexcept { ++(getCounter().numObjects); } | |||||
~DistrhoLeakedObjectDetector() 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; | |||||
} | |||||
}; | |||||
// ----------------------------------------------------------------------- | |||||
#endif // DISTRHO_LEAK_DETECTOR_HPP_INCLUDED |
@@ -1,746 +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" | |||||
// ----------------------------------------------------------------------- | |||||
// 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); | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
#endif // DISTRHO_STRING_HPP_INCLUDED |
@@ -1,142 +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_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 | |||||
# define DISTRHO_DLL_EXTENSION "so" | |||||
# elif defined(__linux__) | |||||
# define DISTRHO_OS_LINUX 1 | |||||
# define DISTRHO_DLL_EXTENSION "so" | |||||
# endif | |||||
#endif | |||||
#ifndef DISTRHO_DLL_EXTENSION | |||||
# define DISTRHO_DLL_EXTENSION "so" | |||||
#endif | |||||
/* Check for C++11 support */ | |||||
#if defined(HAVE_CPP11_SUPPORT) | |||||
# define PROPER_CPP11_SUPPORT | |||||
#elif __cplusplus >= 201103L || (defined(__GNUC__) && defined(__GXX_EXPERIMENTAL_CXX0X__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 405) || __has_extension(cxx_noexcept) | |||||
# define PROPER_CPP11_SUPPORT | |||||
# if (defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) < 407) || ! __has_extension(cxx_override_control) | |||||
# define override // gcc4.7+ only | |||||
# define final // gcc4.7+ only | |||||
# endif | |||||
#endif | |||||
#ifndef PROPER_CPP11_SUPPORT | |||||
# define noexcept throw() | |||||
# define override | |||||
# define final | |||||
# define nullptr (0) | |||||
#endif | |||||
/* Define DISTRHO_SAFE_ASSERT* */ | |||||
#define DISTRHO_SAFE_ASSERT(cond) if (cond) d_pass(); else d_safe_assert(#cond, __FILE__, __LINE__); | |||||
#define DISTRHO_SAFE_ASSERT_BREAK(cond) if (cond) d_pass(); else { d_safe_assert(#cond, __FILE__, __LINE__); break; } | |||||
#define DISTRHO_SAFE_ASSERT_CONTINUE(cond) if (cond) d_pass(); else { d_safe_assert(#cond, __FILE__, __LINE__); continue; } | |||||
#define DISTRHO_SAFE_ASSERT_RETURN(cond, ret) if (cond) d_pass(); else { 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_NO_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; | |||||
#else | |||||
# define START_NAMESPACE_DISTRHO | |||||
# define END_NAMESPACE_DISTRHO | |||||
# define USE_NAMESPACE_DISTRHO | |||||
#endif | |||||
/* Useful typedefs */ | |||||
typedef unsigned char uchar; | |||||
typedef unsigned long int ulong; | |||||
typedef unsigned short int ushort; | |||||
typedef unsigned int uint; | |||||
#endif // DISTRHO_DEFINES_H_INCLUDED |
@@ -1,107 +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 "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(uint32_t parameterCount, uint32_t programCount, uint32_t stateCount) | |||||
: pData(new PrivateData()) | |||||
{ | |||||
if (parameterCount > 0) | |||||
{ | |||||
pData->parameterCount = parameterCount; | |||||
pData->parameters = new Parameter[parameterCount]; | |||||
} | |||||
if (programCount > 0) | |||||
{ | |||||
#if DISTRHO_PLUGIN_WANT_PROGRAMS | |||||
pData->programCount = programCount; | |||||
pData->programNames = new d_string[programCount]; | |||||
#endif | |||||
} | |||||
if (stateCount > 0) | |||||
{ | |||||
#if DISTRHO_PLUGIN_WANT_STATE | |||||
pData->stateCount = stateCount; | |||||
pData->stateKeys = new d_string[stateCount]; | |||||
#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 TimePos& Plugin::d_getTimePos() const noexcept | |||||
{ | |||||
return pData->timePos; | |||||
} | |||||
#endif | |||||
#if DISTRHO_PLUGIN_WANT_LATENCY | |||||
void Plugin::d_setLatency(uint32_t frames) noexcept | |||||
{ | |||||
pData->latency = frames; | |||||
} | |||||
#endif | |||||
// ----------------------------------------------------------------------- | |||||
// Callbacks (optional) | |||||
void Plugin::d_bufferSizeChanged(uint32_t) | |||||
{ | |||||
} | |||||
void Plugin::d_sampleRateChanged(double) | |||||
{ | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
END_NAMESPACE_DISTRHO |
@@ -1,458 +0,0 @@ | |||||
/* | |||||
* DISTRHO Plugin Framework (DPF) | |||||
* Copyright (C) 2012-2014 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, uiResizeCallback, plugin->getInstancePointer()) | |||||
{ | |||||
fUI.setTitle(host->uiName); | |||||
if (host->uiParentId != 0) | |||||
fUI.setTransientWinId(host->uiParentId); | |||||
} | |||||
// --------------------------------------------- | |||||
void carla_show(const bool yesNo) | |||||
{ | |||||
fUI.setVisible(yesNo); | |||||
} | |||||
void carla_idle() | |||||
{ | |||||
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.setTitle(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 handleUiResize(const uint width, const uint height) | |||||
{ | |||||
fUI.setSize(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 uiResizeCallback(void* ptr, uint width, uint height) | |||||
{ | |||||
handlePtr->handleUiResize(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; | |||||
// reset | |||||
param.hints = ::PARAMETER_IS_ENABLED; | |||||
param.scalePointCount = 0; | |||||
param.scalePoints = nullptr; | |||||
{ | |||||
int nativeParamHints = ::PARAMETER_IS_ENABLED; | |||||
const uint32_t paramHints = fPlugin.getParameterHints(index); | |||||
if (paramHints & PARAMETER_IS_AUTOMABLE) | |||||
nativeParamHints |= ::PARAMETER_IS_AUTOMABLE; | |||||
if (paramHints & PARAMETER_IS_BOOLEAN) | |||||
nativeParamHints |= ::PARAMETER_IS_BOOLEAN; | |||||
if (paramHints & PARAMETER_IS_INTEGER) | |||||
nativeParamHints |= ::PARAMETER_IS_INTEGER; | |||||
if (paramHints & PARAMETER_IS_LOGARITHMIC) | |||||
nativeParamHints |= ::PARAMETER_IS_LOGARITHMIC; | |||||
if (paramHints & PARAMETER_IS_OUTPUT) | |||||
nativeParamHints |= ::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; | |||||
carla_copy<uint8_t>(realMidiEvent.buf, midiEvent.data, midiEvent.size); | |||||
} | |||||
fPlugin.run(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(inBuffer, outBuffer, frames); | |||||
} | |||||
#endif | |||||
// ------------------------------------------------------------------- | |||||
// Plugin UI calls | |||||
#if DISTRHO_PLUGIN_HAS_UI | |||||
void uiShow(const bool show) override | |||||
{ | |||||
if (show) | |||||
createUiIfNeeded(); | |||||
if (fUiPtr != nullptr) | |||||
fUiPtr->carla_show(show); | |||||
} | |||||
void uiIdle() override | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(fUiPtr != nullptr,); | |||||
fUiPtr->carla_idle(); | |||||
} | |||||
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,64 +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_PLUGIN_CHECKS_H_INCLUDED | |||||
#define DISTRHO_PLUGIN_CHECKS_H_INCLUDED | |||||
#include "DistrhoPluginInfo.h" | |||||
#ifndef DISTRHO_PLUGIN_NAME | |||||
# error DISTRHO_PLUGIN_NAME undefined! | |||||
#endif | |||||
#ifndef DISTRHO_PLUGIN_HAS_UI | |||||
# error DISTRHO_PLUGIN_HAS_UI undefined! | |||||
#endif | |||||
#ifndef DISTRHO_PLUGIN_IS_SYNTH | |||||
# error DISTRHO_PLUGIN_IS_SYNTH undefined! | |||||
#endif | |||||
#ifndef DISTRHO_PLUGIN_NUM_INPUTS | |||||
# error DISTRHO_PLUGIN_NUM_INPUTS undefined! | |||||
#endif | |||||
#ifndef DISTRHO_PLUGIN_NUM_OUTPUTS | |||||
# error DISTRHO_PLUGIN_NUM_OUTPUTS undefined! | |||||
#endif | |||||
#ifndef DISTRHO_PLUGIN_WANT_LATENCY | |||||
# error DISTRHO_PLUGIN_WANT_LATENCY undefined! | |||||
#endif | |||||
#ifndef DISTRHO_PLUGIN_WANT_PROGRAMS | |||||
# error DISTRHO_PLUGIN_WANT_PROGRAMS undefined! | |||||
#endif | |||||
#ifndef DISTRHO_PLUGIN_WANT_STATE | |||||
# error DISTRHO_PLUGIN_WANT_STATE undefined! | |||||
#endif | |||||
#ifndef DISTRHO_PLUGIN_WANT_TIMEPOS | |||||
# error DISTRHO_PLUGIN_WANT_TIMEPOS undefined! | |||||
#endif | |||||
#ifndef DISTRHO_PLUGIN_WANT_DIRECT_ACCESS | |||||
# define DISTRHO_PLUGIN_WANT_DIRECT_ACCESS 0 | |||||
#endif | |||||
#define DISTRHO_UI_URI DISTRHO_PLUGIN_URI "#UI" | |||||
#endif // DISTRHO_PLUGIN_CHECKS_H_INCLUDED |
@@ -1,429 +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_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 { | |||||
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; | |||||
#endif | |||||
#if DISTRHO_PLUGIN_WANT_LATENCY | |||||
uint32_t latency; | |||||
#endif | |||||
#if DISTRHO_PLUGIN_WANT_TIMEPOS | |||||
TimePos timePos; | |||||
#endif | |||||
uint32_t bufferSize; | |||||
double sampleRate; | |||||
PrivateData() noexcept | |||||
: parameterCount(0), | |||||
parameters(nullptr), | |||||
#if DISTRHO_PLUGIN_WANT_PROGRAMS | |||||
programCount(0), | |||||
programNames(nullptr), | |||||
#endif | |||||
#if DISTRHO_PLUGIN_WANT_STATE | |||||
stateCount(0), | |||||
stateKeys(nullptr), | |||||
#endif | |||||
#if DISTRHO_PLUGIN_WANT_LATENCY | |||||
latency(0), | |||||
#endif | |||||
bufferSize(d_lastBufferSize), | |||||
sampleRate(d_lastSampleRate) | |||||
{ | |||||
DISTRHO_SAFE_ASSERT(bufferSize != 0); | |||||
DISTRHO_SAFE_ASSERT(sampleRate != 0.0); | |||||
} | |||||
~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; | |||||
} | |||||
#endif | |||||
} | |||||
}; | |||||
// ----------------------------------------------------------------------- | |||||
// Plugin exporter class | |||||
class PluginExporter | |||||
{ | |||||
public: | |||||
PluginExporter() | |||||
: fPlugin(createPlugin()), | |||||
fData((fPlugin != nullptr) ? fPlugin->pData : nullptr) | |||||
{ | |||||
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_initStateKey(i, fData->stateKeys[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) & PARAMETER_IS_OUTPUT); | |||||
} | |||||
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]; | |||||
} | |||||
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 setTimePos(const TimePos& timePos) noexcept | |||||
{ | |||||
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,); | |||||
std::memcpy(&fData->timePos, &timePos, sizeof(TimePos)); | |||||
} | |||||
#endif | |||||
// ------------------------------------------------------------------- | |||||
void activate() | |||||
{ | |||||
DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,); | |||||
fPlugin->d_activate(); | |||||
} | |||||
void deactivate() | |||||
{ | |||||
DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,); | |||||
fPlugin->d_deactivate(); | |||||
} | |||||
#if DISTRHO_PLUGIN_IS_SYNTH | |||||
void run(float** const inputs, float** const outputs, const uint32_t frames, const MidiEvent* const midiEvents, const uint32_t midiEventCount) | |||||
{ | |||||
DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,); | |||||
fPlugin->d_run(inputs, outputs, frames, midiEvents, midiEventCount); | |||||
} | |||||
#else | |||||
void run(float** const inputs, float** const outputs, const uint32_t frames) | |||||
{ | |||||
DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,); | |||||
fPlugin->d_run(inputs, outputs, frames); | |||||
} | |||||
#endif | |||||
// ------------------------------------------------------------------- | |||||
void setBufferSize(const uint32_t bufferSize, 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) | |||||
{ | |||||
fPlugin->d_deactivate(); | |||||
fPlugin->d_bufferSizeChanged(bufferSize); | |||||
fPlugin->d_activate(); | |||||
} | |||||
} | |||||
void setSampleRate(const double sampleRate, bool doCallback = false) | |||||
{ | |||||
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,); | |||||
DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,); | |||||
DISTRHO_SAFE_ASSERT(sampleRate > 0.0); | |||||
if (fData->sampleRate == sampleRate) | |||||
return; | |||||
fData->sampleRate = sampleRate; | |||||
if (doCallback) | |||||
{ | |||||
fPlugin->d_deactivate(); | |||||
fPlugin->d_sampleRateChanged(sampleRate); | |||||
fPlugin->d_activate(); | |||||
} | |||||
} | |||||
private: | |||||
// ------------------------------------------------------------------- | |||||
// private members accessed by DistrhoPlugin classes | |||||
Plugin* const fPlugin; | |||||
Plugin::PrivateData* const fData; | |||||
// ------------------------------------------------------------------- | |||||
// 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,705 +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 "DistrhoPluginInternal.hpp" | |||||
#ifdef DISTRHO_PLUGIN_TARGET_DSSI | |||||
# include "dssi/dssi.h" | |||||
#else | |||||
# include "ladspa/ladspa.h" | |||||
# if DISTRHO_PLUGIN_IS_SYNTH | |||||
# error Cannot build synth plugin 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_IS_SYNTH | |||||
// 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].buf[0] = 0x80 + seqEvent.data.note.channel; | |||||
midiEvents[j].buf[1] = seqEvent.data.note.note; | |||||
midiEvents[j].buf[2] = 0; | |||||
midiEvents[j].buf[3] = 0; | |||||
break; | |||||
case SND_SEQ_EVENT_NOTEON: | |||||
j = midiEventCount++; | |||||
midiEvents[j].frame = seqEvent.time.tick; | |||||
midiEvents[j].size = 3; | |||||
midiEvents[j].buf[0] = 0x90 + seqEvent.data.note.channel; | |||||
midiEvents[j].buf[1] = seqEvent.data.note.note; | |||||
midiEvents[j].buf[2] = seqEvent.data.note.velocity; | |||||
midiEvents[j].buf[3] = 0; | |||||
break; | |||||
case SND_SEQ_EVENT_KEYPRESS: | |||||
j = midiEventCount++; | |||||
midiEvents[j].frame = seqEvent.time.tick; | |||||
midiEvents[j].size = 3; | |||||
midiEvents[j].buf[0] = 0xA0 + seqEvent.data.note.channel; | |||||
midiEvents[j].buf[1] = seqEvent.data.note.note; | |||||
midiEvents[j].buf[2] = seqEvent.data.note.velocity; | |||||
midiEvents[j].buf[3] = 0; | |||||
break; | |||||
case SND_SEQ_EVENT_CONTROLLER: | |||||
j = midiEventCount++; | |||||
midiEvents[j].frame = seqEvent.time.tick; | |||||
midiEvents[j].size = 3; | |||||
midiEvents[j].buf[0] = 0xB0 + seqEvent.data.control.channel; | |||||
midiEvents[j].buf[1] = seqEvent.data.control.param; | |||||
midiEvents[j].buf[2] = seqEvent.data.control.value; | |||||
midiEvents[j].buf[3] = 0; | |||||
break; | |||||
case SND_SEQ_EVENT_CHANPRESS: | |||||
j = midiEventCount++; | |||||
midiEvents[j].frame = seqEvent.time.tick; | |||||
midiEvents[j].size = 2; | |||||
midiEvents[j].buf[0] = 0xD0 + seqEvent.data.control.channel; | |||||
midiEvents[j].buf[1] = seqEvent.data.control.value; | |||||
midiEvents[j].buf[2] = 0; | |||||
midiEvents[j].buf[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].buf[0] = 0xE0 + seqEvent.data.control.channel; | |||||
midiEvents[j].buf[1] = 0; | |||||
midiEvents[j].buf[2] = 0; | |||||
midiEvents[j].buf[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_IS_SYNTH | |||||
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 | |||||
LADSPA_Data* fPortAudioIns[DISTRHO_PLUGIN_NUM_INPUTS]; | |||||
#else | |||||
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_IS_SYNTH | |||||
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, | |||||
/* Properties */ LADSPA_PROPERTY_HARD_RT_CAPABLE, | |||||
/* 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_IS_SYNTH | |||||
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; | |||||
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 & PARAMETER_IS_BOOLEAN) | |||||
portRangeHints[port].HintDescriptor |= LADSPA_HINT_TOGGLED; | |||||
if (hints & PARAMETER_IS_INTEGER) | |||||
portRangeHints[port].HintDescriptor |= LADSPA_HINT_INTEGER; | |||||
if (hints & PARAMETER_IS_LOGARITHMIC) | |||||
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,388 +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 "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/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_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 | |||||
#define DISTRHO_LV2_USE_EVENTS_IN (DISTRHO_PLUGIN_IS_SYNTH || DISTRHO_PLUGIN_WANT_TIMEPOS || (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI)) | |||||
#define DISTRHO_LV2_USE_EVENTS_OUT (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 pluginLabel(basename); | |||||
d_string pluginTTL(pluginLabel + ".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 <" + pluginLabel + "." 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_MACOS | |||||
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 | |||||
manifestString += " ui:binary <" + pluginLabel + "_ui." DISTRHO_DLL_EXTENSION "> ;\n"; | |||||
# else | |||||
manifestString += " ui:binary <" + pluginLabel + "." 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 | |||||
pluginString += " lv2:optionalFeature <" LV2_CORE__hardRTCapable "> ,\n"; | |||||
pluginString += " <" LV2_BUF_SIZE__boundedBlockLength "> ;\n"; | |||||
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_TIMEPOS | |||||
pluginString += " atom:supports <" LV2_TIME__Position "> ;\n"; | |||||
# endif | |||||
# if DISTRHO_PLUGIN_IS_SYNTH | |||||
pluginString += " atom:supports <" LV2_MIDI__MidiEvent "> ;\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"; | |||||
pluginString += " atom:supports <" LV2_ATOM__String "> ;\n"; | |||||
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 ;\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) & PARAMETER_IS_INTEGER) | |||||
{ | |||||
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 & PARAMETER_IS_BOOLEAN) | |||||
pluginString += " lv2:portProperty lv2:toggled ;\n"; | |||||
if (hints & PARAMETER_IS_INTEGER) | |||||
pluginString += " lv2:portProperty lv2:integer ;\n"; | |||||
if (hints & PARAMETER_IS_LOGARITHMIC) | |||||
pluginString += " lv2:portProperty <http://lv2plug.in/ns/ext/port-props#logarithmic> ;\n"; | |||||
if ((hints & PARAMETER_IS_AUTOMABLE) == 0 && ! plugin.isParameterOutput(i)) | |||||
pluginString += " lv2:portProperty <http://lv2plug.in/ns/ext/port-props#expensive> ;\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,99 +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 "DistrhoUIInternal.hpp" | |||||
START_NAMESPACE_DGL | |||||
extern Window* dgl_lastUiParent; | |||||
END_NAMESPACE_DGL | |||||
START_NAMESPACE_DISTRHO | |||||
// ----------------------------------------------------------------------- | |||||
// Static data, see DistrhoUIInternal.hpp | |||||
double d_lastUiSampleRate = 0.0; | |||||
// ----------------------------------------------------------------------- | |||||
// UI | |||||
UI::UI() | |||||
: DGL::Widget(*DGL::dgl_lastUiParent), | |||||
pData(new PrivateData()) | |||||
{ | |||||
DISTRHO_SAFE_ASSERT(DGL::dgl_lastUiParent != nullptr); | |||||
DGL::dgl_lastUiParent = nullptr; | |||||
} | |||||
UI::~UI() | |||||
{ | |||||
delete pData; | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
// Host DSP State | |||||
double UI::d_getSampleRate() const noexcept | |||||
{ | |||||
return pData->sampleRate; | |||||
} | |||||
void UI::d_editParameter(uint32_t index, bool started) | |||||
{ | |||||
pData->editParamCallback(index + pData->parameterOffset, started); | |||||
} | |||||
void UI::d_setParameterValue(uint32_t index, float value) | |||||
{ | |||||
pData->setParamCallback(index + pData->parameterOffset, value); | |||||
} | |||||
#if DISTRHO_PLUGIN_WANT_STATE | |||||
void UI::d_setState(const char* key, const char* value) | |||||
{ | |||||
pData->setStateCallback(key, value); | |||||
} | |||||
#endif | |||||
#if DISTRHO_PLUGIN_IS_SYNTH | |||||
void UI::d_sendNote(uint8_t channel, uint8_t note, uint8_t velocity) | |||||
{ | |||||
pData->sendNoteCallback(channel, note, velocity); | |||||
} | |||||
#endif | |||||
// ----------------------------------------------------------------------- | |||||
// Host UI State | |||||
void UI::d_uiResize(uint width, uint height) | |||||
{ | |||||
pData->uiResizeCallback(width, height); | |||||
} | |||||
#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS | |||||
// ----------------------------------------------------------------------- | |||||
// Direct DSP access | |||||
void* UI::d_getPluginInstancePointer() const noexcept | |||||
{ | |||||
return pData->dspPtr; | |||||
} | |||||
#endif | |||||
// ----------------------------------------------------------------------- | |||||
END_NAMESPACE_DISTRHO |
@@ -1,498 +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 "DistrhoUIInternal.hpp" | |||||
#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS | |||||
# error DSSI UIs do not support direct access! | |||||
#endif | |||||
#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, uiResizeCallback), | |||||
fHostClosed(false), | |||||
fOscData(oscData) | |||||
{ | |||||
fUI.setTitle(uiTitle); | |||||
} | |||||
~UIDssi() | |||||
{ | |||||
if (fOscData.server != nullptr && ! fHostClosed) | |||||
fOscData.send_exiting(); | |||||
} | |||||
void exec() | |||||
{ | |||||
for (;;) | |||||
{ | |||||
fOscData.idle(); | |||||
if (! fUI.idle()) | |||||
break; | |||||
d_msleep(50); | |||||
} | |||||
} | |||||
// ------------------------------------------------------------------- | |||||
#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_show() | |||||
{ | |||||
fUI.setVisible(true); | |||||
} | |||||
void dssiui_hide() | |||||
{ | |||||
fUI.setVisible(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 uiResize(const uint width, const uint height) | |||||
{ | |||||
fUI.setSize(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 uiResizeCallback(void* ptr, uint width, uint height) | |||||
{ | |||||
uiPtr->uiResize(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; | |||||
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(); | |||||
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,290 +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_UI_INTERNAL_HPP_INCLUDED | |||||
#define DISTRHO_UI_INTERNAL_HPP_INCLUDED | |||||
#include "../DistrhoUI.hpp" | |||||
#include "../../dgl/App.hpp" | |||||
#include "../../dgl/Window.hpp" | |||||
START_NAMESPACE_DISTRHO | |||||
// ----------------------------------------------------------------------- | |||||
// Static data, see DistrhoUI.cpp | |||||
extern double d_lastUiSampleRate; | |||||
// ----------------------------------------------------------------------- | |||||
// 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 (*uiResizeFunc) (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; | |||||
uiResizeFunc uiResizeCallbackFunc; | |||||
void* ptr; | |||||
PrivateData() noexcept | |||||
: sampleRate(d_lastUiSampleRate), | |||||
parameterOffset(0), | |||||
#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS | |||||
dspPtr(nullptr), | |||||
#endif | |||||
editParamCallbackFunc(nullptr), | |||||
setParamCallbackFunc(nullptr), | |||||
setStateCallbackFunc(nullptr), | |||||
sendNoteCallbackFunc(nullptr), | |||||
uiResizeCallbackFunc(nullptr), | |||||
ptr(nullptr) | |||||
{ | |||||
DISTRHO_SAFE_ASSERT(sampleRate != 0.0); | |||||
#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 uiResizeCallback(const uint width, const uint height) | |||||
{ | |||||
if (uiResizeCallbackFunc != nullptr) | |||||
uiResizeCallbackFunc(ptr, width, height); | |||||
} | |||||
}; | |||||
// ----------------------------------------------------------------------- | |||||
// 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 uiResizeFunc uiResizeCall, | |||||
void* const dspPtr = nullptr) | |||||
: glApp(), | |||||
glWindow(glApp, winId), | |||||
fUi(createUI()), | |||||
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->uiResizeCallbackFunc = uiResizeCall; | |||||
glWindow.setSize(fUi->d_getWidth(), fUi->d_getHeight()); | |||||
glWindow.setResizable(false); | |||||
#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS | |||||
fData->dspPtr = dspPtr; | |||||
#else | |||||
return; // unused | |||||
(void)dspPtr; | |||||
#endif | |||||
} | |||||
~UIExporter() | |||||
{ | |||||
delete fUi; | |||||
} | |||||
// ------------------------------------------------------------------- | |||||
const char* getName() const noexcept | |||||
{ | |||||
DISTRHO_SAFE_ASSERT_RETURN(fUi != nullptr, ""); | |||||
return fUi->d_getName(); | |||||
} | |||||
uint getWidth() const noexcept | |||||
{ | |||||
DISTRHO_SAFE_ASSERT_RETURN(fUi != nullptr, 0); | |||||
return fUi->d_getWidth(); | |||||
} | |||||
uint getHeight() const noexcept | |||||
{ | |||||
DISTRHO_SAFE_ASSERT_RETURN(fUi != nullptr, 0); | |||||
return fUi->d_getHeight(); | |||||
} | |||||
// ------------------------------------------------------------------- | |||||
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 | |||||
// ------------------------------------------------------------------- | |||||
bool idle() | |||||
{ | |||||
DISTRHO_SAFE_ASSERT_RETURN(fUi != nullptr, false); | |||||
fUi->d_uiIdle(); | |||||
glApp.idle(); | |||||
return ! glApp.isQuiting(); | |||||
} | |||||
bool isVisible() const noexcept | |||||
{ | |||||
return glWindow.isVisible(); | |||||
} | |||||
void quit() | |||||
{ | |||||
glWindow.close(); | |||||
glApp.quit(); | |||||
} | |||||
void setSize(const uint width, const uint height) | |||||
{ | |||||
glWindow.setSize(width, height); | |||||
} | |||||
void setTitle(const char* const uiTitle) | |||||
{ | |||||
glWindow.setTitle(uiTitle); | |||||
} | |||||
void setTransientWinId(const intptr_t winId) | |||||
{ | |||||
glWindow.setTransientWinId(winId); | |||||
} | |||||
bool setVisible(const bool yesNo) | |||||
{ | |||||
glWindow.setVisible(yesNo); | |||||
return ! glApp.isQuiting(); | |||||
} | |||||
private: | |||||
// ------------------------------------------------------------------- | |||||
// DGL Application and Window for this plugin | |||||
DGL::App glApp; | |||||
DGL::Window glWindow; | |||||
// ------------------------------------------------------------------- | |||||
// private members accessed by DistrhoUI classes | |||||
UI* const fUi; | |||||
UI::PrivateData* const fData; | |||||
DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(UIExporter) | |||||
DISTRHO_PREVENT_HEAP_ALLOCATION | |||||
}; | |||||
// ----------------------------------------------------------------------- | |||||
END_NAMESPACE_DISTRHO | |||||
#endif // DISTRHO_UI_INTERNAL_HPP_INCLUDED |
@@ -1,441 +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 "DistrhoUIInternal.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_programs.h" | |||||
#include <string> | |||||
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, void* const dspPtr) | |||||
: fUI(this, winId, editParameterCallback, setParameterCallback, setStateCallback, sendNoteCallback, uiResizeCallback, 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 (winId == 0) | |||||
fUI.setTitle(fUI.getName()); | |||||
else if (fUiResize != nullptr) | |||||
fUiResize->ui_resize(fUiResize->handle, fUI.getWidth(), fUI.getHeight()); | |||||
#if DISTRHO_PLUGIN_WANT_STATE | |||||
// tell the DSP we're ready to receive msgs | |||||
setState("__dpf_ui_data__", ""); | |||||
#endif | |||||
if (winId != 0) | |||||
return; | |||||
const LV2_URID uridFrontendWinId(uridMap->map(uridMap->handle, "http://kxstudio.sf.net/ns/carla/frontendWinId")); | |||||
for (int i=0; options[i].key != 0; ++i) | |||||
{ | |||||
if (options[i].key == uridFrontendWinId) | |||||
{ | |||||
if (options[i].type == uridMap->map(uridMap->handle, LV2_ATOM__Long)) | |||||
{ | |||||
if (const int64_t frontendWinId = *(const int64_t*)options[i].value) | |||||
fUI.setTransientWinId(static_cast<intptr_t>(frontendWinId)); | |||||
} | |||||
else | |||||
d_stderr("Host provides frontendWinId but has wrong value type"); | |||||
break; | |||||
} | |||||
} | |||||
} | |||||
// ------------------------------------------------------------------- | |||||
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()); | |||||
if (rindex < parameterOffset) | |||||
return; | |||||
if (bufferSize != sizeof(float)) | |||||
return; | |||||
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); | |||||
// TODO - check atom type | |||||
const char* const stateKey((const char*)LV2_ATOM_BODY_CONST(atom)); | |||||
const char* const stateValue(stateKey+std::strlen(stateKey)+1); | |||||
d_stdout("Got MSG in UI from DSP ==> %s | %s", stateKey, stateValue); | |||||
fUI.stateChanged(stateKey, stateValue); | |||||
} | |||||
#endif | |||||
} | |||||
// ------------------------------------------------------------------- | |||||
int lv2ui_idle() | |||||
{ | |||||
if (fWinIdWasNull) | |||||
return (fUI.idle() && fUI.isVisible()) ? 0 : 1; | |||||
return fUI.idle() ? 0 : 1; | |||||
} | |||||
int lv2ui_show() | |||||
{ | |||||
return fUI.setVisible(true) ? 0 : 1; | |||||
} | |||||
int lv2ui_hide() | |||||
{ | |||||
return fUI.setVisible(false) ? 0 : 1; | |||||
} | |||||
// ------------------------------------------------------------------- | |||||
#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) | |||||
{ | |||||
if (fWriteFunction != nullptr) | |||||
fWriteFunction(fController, rindex, sizeof(float), 0, &value); | |||||
} | |||||
void setState(const char* const key, const char* const value) | |||||
{ | |||||
if (fWriteFunction == nullptr) | |||||
return; | |||||
const uint32_t eventInPortIndex(DISTRHO_PLUGIN_NUM_INPUTS + DISTRHO_PLUGIN_NUM_OUTPUTS); | |||||
// join key and value | |||||
std::string tmpStr; | |||||
tmpStr += std::string(key); | |||||
tmpStr += std::string("\0", 1); | |||||
tmpStr += std::string(value); | |||||
// get msg size | |||||
const size_t msgSize(tmpStr.size()+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.data(), msgSize-1); | |||||
// 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 uiResize(const uint width, const uint height) | |||||
{ | |||||
fUI.setSize(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 uiResizeCallback(void* ptr, uint width, uint height) | |||||
{ | |||||
uiPtr->uiResize(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) | |||||
{ | |||||
d_stderr("Options feature missing, 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 | |||||
{ | |||||
d_stderr("Failed to get direct access, cannot continue!"); | |||||
return nullptr; | |||||
} | |||||
#endif | |||||
*widget = parentId; | |||||
const intptr_t winId((intptr_t)parentId); | |||||
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_lastUiSampleRate = 44100.0; | |||||
return new UiLv2(winId, options, uridMap, uiResize, uiTouch, controller, writeFunction, 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(); | |||||
} | |||||
#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 LV2UI_Idle_Interface uiIdle = { lv2ui_idle }; | |||||
static const LV2UI_Show_Interface uiShow = { lv2ui_show, lv2ui_hide }; | |||||
if (std::strcmp(uri, LV2_UI__idleInterface) == 0) | |||||
return &uiIdle; | |||||
if (std::strcmp(uri, LV2_UI__showInterface) == 0) | |||||
return &uiShow; | |||||
#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,455 +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. | |||||
This is part of the old discovery API, which has been replaced due to being | |||||
inadequate for some plugins. It is limited because the bundle path is not | |||||
available during discovery, and it relies on non-portable shared library | |||||
constructors/destructors. However, this API is still supported and plugins | |||||
are not required to migrate. | |||||
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. | |||||
A plugin library MUST include a function called "lv2_descriptor" with this | |||||
prototype. This function MUST have C-style linkage (if you are using C++ | |||||
this is taken care of by the 'extern "C"' clause at the top of this file). | |||||
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 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,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 */ |
@@ -1,56 +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 patch.h C header for the LV2 Patch extension | |||||
<http://lv2plug.in/ns/ext/patch>. | |||||
The patch extension is purely data, this header merely defines URIs | |||||
for convenience. | |||||
*/ | |||||
#ifndef LV2_PATCH_H | |||||
#define LV2_PATCH_H | |||||
#define LV2_PATCH_URI "http://lv2plug.in/ns/ext/patch" | |||||
#define LV2_PATCH_PREFIX LV2_PATCH_URI "#" | |||||
#define LV2_PATCH__Ack LV2_PATCH_PREFIX "Ack" | |||||
#define LV2_PATCH__Delete LV2_PATCH_PREFIX "Delete" | |||||
#define LV2_PATCH__Error LV2_PATCH_PREFIX "Error" | |||||
#define LV2_PATCH__Get LV2_PATCH_PREFIX "Get" | |||||
#define LV2_PATCH__Message LV2_PATCH_PREFIX "Message" | |||||
#define LV2_PATCH__Move LV2_PATCH_PREFIX "Move" | |||||
#define LV2_PATCH__Patch LV2_PATCH_PREFIX "Patch" | |||||
#define LV2_PATCH__Post LV2_PATCH_PREFIX "Post" | |||||
#define LV2_PATCH__Put LV2_PATCH_PREFIX "Put" | |||||
#define LV2_PATCH__Request LV2_PATCH_PREFIX "Request" | |||||
#define LV2_PATCH__Response LV2_PATCH_PREFIX "Response" | |||||
#define LV2_PATCH__Set LV2_PATCH_PREFIX "Set" | |||||
#define LV2_PATCH__add LV2_PATCH_PREFIX "add" | |||||
#define LV2_PATCH__body LV2_PATCH_PREFIX "body" | |||||
#define LV2_PATCH__destination LV2_PATCH_PREFIX "destination" | |||||
#define LV2_PATCH__property LV2_PATCH_PREFIX "property" | |||||
#define LV2_PATCH__readable LV2_PATCH_PREFIX "readable" | |||||
#define LV2_PATCH__remove LV2_PATCH_PREFIX "remove" | |||||
#define LV2_PATCH__request LV2_PATCH_PREFIX "request" | |||||
#define LV2_PATCH__subject LV2_PATCH_PREFIX "subject" | |||||
#define LV2_PATCH__sequenceNumber LV2_PATCH_PREFIX "sequenceNumber" | |||||
#define LV2_PATCH__value LV2_PATCH_PREFIX "value" | |||||
#define LV2_PATCH__wildcard LV2_PATCH_PREFIX "wildcard" | |||||
#define LV2_PATCH__writable LV2_PATCH_PREFIX "writable" | |||||
#endif /* LV2_PATCH_H */ |
@@ -1,64 +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 port-groups.h | |||||
C definitions for the LV2 Port Groups extension | |||||
<http://lv2plug.in/ns/ext/port-groups>. | |||||
*/ | |||||
#ifndef LV2_PORT_GROUPS_H | |||||
#define LV2_PORT_GROUPS_H | |||||
#define LV2_PORT_GROUPS_URI "http://lv2plug.in/ns/ext/port-groups" | |||||
#define LV2_PORT_GROUPS_PREFIX LV2_PORT_GROUPS_URI "#" | |||||
#define LV2_PORT_GROUPS__DiscreteGroup LV2_PORT_GROUPS_PREFIX "DiscreteGroup" | |||||
#define LV2_PORT_GROUPS__Element LV2_PORT_GROUPS_PREFIX "Element" | |||||
#define LV2_PORT_GROUPS__FivePointOneGroup LV2_PORT_GROUPS_PREFIX "FivePointOneGroup" | |||||
#define LV2_PORT_GROUPS__FivePointZeroGroup LV2_PORT_GROUPS_PREFIX "FivePointZeroGroup" | |||||
#define LV2_PORT_GROUPS__FourPointZeroGroup LV2_PORT_GROUPS_PREFIX "FourPointZeroGroup" | |||||
#define LV2_PORT_GROUPS__Group LV2_PORT_GROUPS_PREFIX "Group" | |||||
#define LV2_PORT_GROUPS__InputGroup LV2_PORT_GROUPS_PREFIX "InputGroup" | |||||
#define LV2_PORT_GROUPS__MidSideGroup LV2_PORT_GROUPS_PREFIX "MidSideGroup" | |||||
#define LV2_PORT_GROUPS__MonoGroup LV2_PORT_GROUPS_PREFIX "MonoGroup" | |||||
#define LV2_PORT_GROUPS__OutputGroup LV2_PORT_GROUPS_PREFIX "OutputGroup" | |||||
#define LV2_PORT_GROUPS__SevenPointOneGroup LV2_PORT_GROUPS_PREFIX "SevenPointOneGroup" | |||||
#define LV2_PORT_GROUPS__SevenPointOneWideGroup LV2_PORT_GROUPS_PREFIX "SevenPointOneWideGroup" | |||||
#define LV2_PORT_GROUPS__SixPointOneGroup LV2_PORT_GROUPS_PREFIX "SixPointOneGroup" | |||||
#define LV2_PORT_GROUPS__StereoGroup LV2_PORT_GROUPS_PREFIX "StereoGroup" | |||||
#define LV2_PORT_GROUPS__ThreePointZeroGroup LV2_PORT_GROUPS_PREFIX "ThreePointZeroGroup" | |||||
#define LV2_PORT_GROUPS__center LV2_PORT_GROUPS_PREFIX "center" | |||||
#define LV2_PORT_GROUPS__centerLeft LV2_PORT_GROUPS_PREFIX "centerLeft" | |||||
#define LV2_PORT_GROUPS__centerRight LV2_PORT_GROUPS_PREFIX "centerRight" | |||||
#define LV2_PORT_GROUPS__element LV2_PORT_GROUPS_PREFIX "element" | |||||
#define LV2_PORT_GROUPS__group LV2_PORT_GROUPS_PREFIX "group" | |||||
#define LV2_PORT_GROUPS__left LV2_PORT_GROUPS_PREFIX "left" | |||||
#define LV2_PORT_GROUPS__lowFrequencyEffects LV2_PORT_GROUPS_PREFIX "lowFrequencyEffects" | |||||
#define LV2_PORT_GROUPS__mainInput LV2_PORT_GROUPS_PREFIX "mainInput" | |||||
#define LV2_PORT_GROUPS__mainOutput LV2_PORT_GROUPS_PREFIX "mainOutput" | |||||
#define LV2_PORT_GROUPS__rearCenter LV2_PORT_GROUPS_PREFIX "rearCenter" | |||||
#define LV2_PORT_GROUPS__rearLeft LV2_PORT_GROUPS_PREFIX "rearLeft" | |||||
#define LV2_PORT_GROUPS__rearRight LV2_PORT_GROUPS_PREFIX "rearRight" | |||||
#define LV2_PORT_GROUPS__right LV2_PORT_GROUPS_PREFIX "right" | |||||
#define LV2_PORT_GROUPS__side LV2_PORT_GROUPS_PREFIX "side" | |||||
#define LV2_PORT_GROUPS__sideChainOf LV2_PORT_GROUPS_PREFIX "sideChainOf" | |||||
#define LV2_PORT_GROUPS__sideLeft LV2_PORT_GROUPS_PREFIX "sideLeft" | |||||
#define LV2_PORT_GROUPS__sideRight LV2_PORT_GROUPS_PREFIX "sideRight" | |||||
#define LV2_PORT_GROUPS__source LV2_PORT_GROUPS_PREFIX "source" | |||||
#define LV2_PORT_GROUPS__subGroupOf LV2_PORT_GROUPS_PREFIX "subGroupOf" | |||||
#endif /* LV2_PORT_GROUPS_H */ |
@@ -1,42 +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 port-props.h | |||||
C definitions for the LV2 Port Props extension | |||||
<http://lv2plug.in/ns/ext/port-props>. | |||||
*/ | |||||
#ifndef LV2_PORT_PROPS_H | |||||
#define LV2_PORT_PROPS_H | |||||
#define LV2_PORT_PROPS_URI "http://lv2plug.in/ns/ext/port-props" | |||||
#define LV2_PORT_PROPS_PREFIX LV2_PORT_PROPS_URI "#" | |||||
#define LV2_PORT_PROPS__causesArtifacts LV2_PORT_PROPS_PREFIX "causesArtifacts" | |||||
#define LV2_PORT_PROPS__continuousCV LV2_PORT_PROPS_PREFIX "continuousCV" | |||||
#define LV2_PORT_PROPS__discreteCV LV2_PORT_PROPS_PREFIX "discreteCV" | |||||
#define LV2_PORT_PROPS__displayPriority LV2_PORT_PROPS_PREFIX "displayPriority" | |||||
#define LV2_PORT_PROPS__expensive LV2_PORT_PROPS_PREFIX "expensive" | |||||
#define LV2_PORT_PROPS__hasStrictBounds LV2_PORT_PROPS_PREFIX "hasStrictBounds" | |||||
#define LV2_PORT_PROPS__logarithmic LV2_PORT_PROPS_PREFIX "logarithmic" | |||||
#define LV2_PORT_PROPS__notAutomatic LV2_PORT_PROPS_PREFIX "notAutomatic" | |||||
#define LV2_PORT_PROPS__notOnGUI LV2_PORT_PROPS_PREFIX "notOnGUI" | |||||
#define LV2_PORT_PROPS__rangeSteps LV2_PORT_PROPS_PREFIX "rangeSteps" | |||||
#define LV2_PORT_PROPS__supportsStrictBounds LV2_PORT_PROPS_PREFIX "supportsStrictBounds" | |||||
#define LV2_PORT_PROPS__trigger LV2_PORT_PROPS_PREFIX "trigger" | |||||
#endif /* LV2_PORT_PROPS_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. | |||||
*/ | |||||
/** | |||||
@file presets.h | |||||
C definitions for the LV2 Presets extension | |||||
<http://lv2plug.in/ns/ext/presets>. | |||||
*/ | |||||
#ifndef LV2_PRESETS_H | |||||
#define LV2_PRESETS_H | |||||
#define LV2_PRESETS_URI "http://lv2plug.in/ns/ext/presets" | |||||
#define LV2_PRESETS_PREFIX LV2_PRESETS_URI "#" | |||||
#define LV2_PRESETS__Preset LV2_PRESETS_PREFIX "Preset" | |||||
#define LV2_PRESETS__preset LV2_PRESETS_PREFIX "preset" | |||||
#define LV2_PRESETS__value LV2_PRESETS_PREFIX "value" | |||||
#endif /* LV2_PRESETS_H */ |
@@ -1,72 +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_RESIZE_PORT_H | |||||
#define LV2_RESIZE_PORT_H | |||||
#include <stddef.h> | |||||
#include <stdint.h> | |||||
#define LV2_RESIZE_PORT_URI "http://lv2plug.in/ns/ext/resize-port" | |||||
#define LV2_RESIZE_PORT_PREFIX LV2_RESIZE_PORT_URI "#" | |||||
#define LV2_RESIZE_PORT__asLargeAs LV2_RESIZE_PORT_PREFIX "asLargeAs" | |||||
#define LV2_RESIZE_PORT__minimumSize LV2_RESIZE_PORT_PREFIX "minimumSize" | |||||
#define LV2_RESIZE_PORT__resize LV2_RESIZE_PORT_PREFIX "resize" | |||||
#ifdef __cplusplus | |||||
extern "C" { | |||||
#else | |||||
# include <stdbool.h> | |||||
#endif | |||||
/** A status code for state functions. */ | |||||
typedef enum { | |||||
LV2_RESIZE_PORT_SUCCESS = 0, /**< Completed successfully. */ | |||||
LV2_RESIZE_PORT_ERR_UNKNOWN = 1, /**< Unknown error. */ | |||||
LV2_RESIZE_PORT_ERR_NO_SPACE = 2 /**< Insufficient space. */ | |||||
} LV2_Resize_Port_Status; | |||||
typedef void* LV2_Resize_Port_Feature_Data; | |||||
typedef struct { | |||||
LV2_Resize_Port_Feature_Data data; | |||||
/** | |||||
Resize a port buffer to at least @a size bytes. | |||||
This function MAY return an error, in which case the port buffer was not | |||||
resized and the port is still connected to the same location. Plugins | |||||
MUST gracefully handle this situation. | |||||
This function is in the audio threading class. | |||||
The host MUST preserve the contents of the port buffer when resizing. | |||||
Plugins MAY resize a port many times in a single run callback. Hosts | |||||
SHOULD make this as inexpensive as possible. | |||||
*/ | |||||
LV2_Resize_Port_Status (*resize)(LV2_Resize_Port_Feature_Data data, | |||||
uint32_t index, | |||||
size_t size); | |||||
} LV2_Resize_Port_Resize; | |||||
#ifdef __cplusplus | |||||
} /* extern "C" */ | |||||
#endif | |||||
#endif /* LV2_RESIZE_PORT_H */ | |||||
@@ -1,352 +0,0 @@ | |||||
/* | |||||
Copyright 2010-2012 David Robillard <http://drobilla.net> | |||||
Copyright 2010 Leonard Ritter <paniq@paniq.org> | |||||
Permission to use, copy, modify, and/or distribute this software for any | |||||
purpose with or without fee is hereby granted, provided that the above | |||||
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 state.h | |||||
C API for the LV2 State extension <http://lv2plug.in/ns/ext/state>. | |||||
*/ | |||||
#ifndef LV2_STATE_H | |||||
#define LV2_STATE_H | |||||
#include <stddef.h> | |||||
#include <stdint.h> | |||||
#include "lv2.h" | |||||
#define LV2_STATE_URI "http://lv2plug.in/ns/ext/state" | |||||
#define LV2_STATE_PREFIX LV2_STATE_URI "#" | |||||
#define LV2_STATE__State LV2_STATE_PREFIX "State" | |||||
#define LV2_STATE__interface LV2_STATE_PREFIX "interface" | |||||
#define LV2_STATE__loadDefaultState LV2_STATE_PREFIX "loadDefaultState" | |||||
#define LV2_STATE__makePath LV2_STATE_PREFIX "makePath" | |||||
#define LV2_STATE__mapPath LV2_STATE_PREFIX "mapPath" | |||||
#define LV2_STATE__state LV2_STATE_PREFIX "state" | |||||
#ifdef __cplusplus | |||||
extern "C" { | |||||
#else | |||||
# include <stdbool.h> | |||||
#endif | |||||
typedef void* LV2_State_Handle; | |||||
typedef void* LV2_State_Map_Path_Handle; | |||||
typedef void* LV2_State_Make_Path_Handle; | |||||
/** | |||||
Flags describing value characteristics. | |||||
These flags are used along with the value's type URI to determine how to | |||||
(de-)serialise the value data, or whether it is even possible to do so. | |||||
*/ | |||||
typedef enum { | |||||
/** | |||||
Plain Old Data. | |||||
Values with this flag contain no pointers or references to other areas | |||||
of memory. It is safe to copy POD values with a simple memcpy and store | |||||
them for the duration of the process. A POD value is not necessarily | |||||
safe to trasmit between processes or machines (e.g. filenames are POD), | |||||
see LV2_STATE_IS_PORTABLE for details. | |||||
Implementations MUST NOT attempt to copy or serialise a non-POD value if | |||||
they do not understand its type (and thus know how to correctly do so). | |||||
*/ | |||||
LV2_STATE_IS_POD = 1, | |||||
/** | |||||
Portable (architecture independent) data. | |||||
Values with this flag are in a format that is usable on any | |||||
architecture. A portable value saved on one machine can be restored on | |||||
another machine regardless of architecture. The format of portable | |||||
values MUST NOT depend on architecture-specific properties like | |||||
endianness or alignment. Portable values MUST NOT contain filenames. | |||||
*/ | |||||
LV2_STATE_IS_PORTABLE = 1 << 1, | |||||
/** | |||||
Native data. | |||||
This flag is used by the host to indicate that the saved data is only | |||||
going to be used locally in the currently running process (e.g. for | |||||
instance duplication or snapshots), so the plugin should use the most | |||||
efficient representation possible and not worry about serialisation | |||||
and portability. | |||||
*/ | |||||
LV2_STATE_IS_NATIVE = 1 << 2 | |||||
} LV2_State_Flags; | |||||
/** A status code for state functions. */ | |||||
typedef enum { | |||||
LV2_STATE_SUCCESS = 0, /**< Completed successfully. */ | |||||
LV2_STATE_ERR_UNKNOWN = 1, /**< Unknown error. */ | |||||
LV2_STATE_ERR_BAD_TYPE = 2, /**< Failed due to unsupported type. */ | |||||
LV2_STATE_ERR_BAD_FLAGS = 3, /**< Failed due to unsupported flags. */ | |||||
LV2_STATE_ERR_NO_FEATURE = 4, /**< Failed due to missing features. */ | |||||
LV2_STATE_ERR_NO_PROPERTY = 5 /**< Failed due to missing property. */ | |||||
} LV2_State_Status; | |||||
/** | |||||
A host-provided function to store a property. | |||||
@param handle Must be the handle passed to LV2_State_Interface.save(). | |||||
@param key The key to store @p value under (URID). | |||||
@param value Pointer to the value to be stored. | |||||
@param size The size of @p value in bytes. | |||||
@param type The type of @p value (URID). | |||||
@param flags LV2_State_Flags for @p value. | |||||
@return 0 on success, otherwise a non-zero error code. | |||||
The host passes a callback of this type to LV2_State_Interface.save(). This | |||||
callback is called repeatedly by the plugin to store all the properties that | |||||
describe its current state. | |||||
DO NOT INVENT NONSENSE URI SCHEMES FOR THE KEY. Best is to use keys from | |||||
existing vocabularies. If nothing appropriate is available, use http URIs | |||||
that point to somewhere you can host documents so documentation can be made | |||||
resolvable (e.g. a child of the plugin or project URI). If this is not | |||||
possible, invent a URN scheme, e.g. urn:myproj:whatever. The plugin MUST | |||||
NOT pass an invalid URI key. | |||||
The host MAY fail to store a property for whatever reason, but SHOULD | |||||
store any property that is LV2_STATE_IS_POD and LV2_STATE_IS_PORTABLE. | |||||
Implementations SHOULD use the types from the LV2 Atom extension | |||||
(http://lv2plug.in/ns/ext/atom) wherever possible. The plugin SHOULD | |||||
attempt to fall-back and avoid the error if possible. | |||||
Note that @p size MUST be > 0, and @p value MUST point to a valid region of | |||||
memory @p size bytes long (this is required to make restore unambiguous). | |||||
The plugin MUST NOT attempt to use this function outside of the | |||||
LV2_State_Interface.restore() context. | |||||
*/ | |||||
typedef LV2_State_Status (*LV2_State_Store_Function)( | |||||
LV2_State_Handle handle, | |||||
uint32_t key, | |||||
const void* value, | |||||
size_t size, | |||||
uint32_t type, | |||||
uint32_t flags); | |||||
/** | |||||
A host-provided function to retrieve a property. | |||||
@param handle Must be the handle passed to LV2_State_Interface.restore(). | |||||
@param key The key of the property to retrieve (URID). | |||||
@param size (Output) If non-NULL, set to the size of the restored value. | |||||
@param type (Output) If non-NULL, set to the type of the restored value. | |||||
@param flags (Output) If non-NULL, set to the flags for the restored value. | |||||
@return A pointer to the restored value (object), or NULL if no value | |||||
has been stored under @p key. | |||||
A callback of this type is passed by the host to | |||||
LV2_State_Interface.restore(). This callback is called repeatedly by the | |||||
plugin to retrieve any properties it requires to restore its state. | |||||
The returned value MUST remain valid until LV2_State_Interface.restore() | |||||
returns. The plugin MUST NOT attempt to use this function, or any value | |||||
returned from it, outside of the LV2_State_Interface.restore() context. | |||||
*/ | |||||
typedef const void* (*LV2_State_Retrieve_Function)( | |||||
LV2_State_Handle handle, | |||||
uint32_t key, | |||||
size_t* size, | |||||
uint32_t* type, | |||||
uint32_t* flags); | |||||
/** | |||||
LV2 Plugin State Interface. | |||||
When the plugin's extension_data is called with argument | |||||
LV2_STATE__interface, the plugin MUST return an LV2_State_Interface | |||||
structure, which remains valid for the lifetime of the plugin. | |||||
The host can use the contained function pointers to save and restore the | |||||
state of a plugin instance at any time, provided the threading restrictions | |||||
of the functions are met. | |||||
Stored data is only guaranteed to be compatible between instances of plugins | |||||
with the same URI (i.e. if a change to a plugin would cause a fatal error | |||||
when restoring state saved by a previous version of that plugin, the plugin | |||||
URI MUST change just as it must when ports change incompatibly). Plugin | |||||
authors should consider this possibility, and always store sensible data | |||||
with meaningful types to avoid such problems in the future. | |||||
*/ | |||||
typedef struct _LV2_State_Interface { | |||||
/** | |||||
Save plugin state using a host-provided @p store callback. | |||||
@param instance The instance handle of the plugin. | |||||
@param store The host-provided store callback. | |||||
@param handle An opaque pointer to host data which MUST be passed as the | |||||
handle parameter to @p store if it is called. | |||||
@param flags Flags describing desired properties of this save. These | |||||
flags may be used to determine the most appropriate values to store. | |||||
@param features Extensible parameter for passing any additional | |||||
features to be used for this save. | |||||
The plugin is expected to store everything necessary to completely | |||||
restore its state later. Plugins SHOULD store simple POD data whenever | |||||
possible, and consider the possibility of state being restored much | |||||
later on a different machine. | |||||
The @p handle pointer and @p store function MUST NOT be used | |||||
beyond the scope of save(). | |||||
This function has its own special threading class: it may not be called | |||||
concurrently with any "Instantiation" function, but it may be called | |||||
concurrently with functions in any other class, unless the definition of | |||||
that class prohibits it (e.g. it may not be called concurrently with a | |||||
"Discovery" function, but it may be called concurrently with an "Audio" | |||||
function. The plugin is responsible for any locking or lock-free | |||||
techniques necessary to make this possible. | |||||
Note that in the simple case where state is only modified by restore(), | |||||
there are no synchronization issues since save() is never called | |||||
concurrently with restore() (though run() may read it during a save). | |||||
Plugins that dynamically modify state while running, however, must take | |||||
care to do so in such a way that a concurrent call to save() will save a | |||||
consistent representation of plugin state for a single instant in time. | |||||
*/ | |||||
LV2_State_Status (*save)(LV2_Handle instance, | |||||
LV2_State_Store_Function store, | |||||
LV2_State_Handle handle, | |||||
uint32_t flags, | |||||
const LV2_Feature *const * features); | |||||
/** | |||||
Restore plugin state using a host-provided @p retrieve callback. | |||||
@param instance The instance handle of the plugin. | |||||
@param retrieve The host-provided retrieve callback. | |||||
@param handle An opaque pointer to host data which MUST be passed as the | |||||
handle parameter to @p retrieve if it is called. | |||||
@param flags Currently unused. | |||||
@param features Extensible parameter for passing any additional | |||||
features to be used for this restore. | |||||
The plugin MAY assume a restored value was set by a previous call to | |||||
LV2_State_Interface.save() by a plugin with the same URI. | |||||
The plugin MUST gracefully fall back to a default value when a value can | |||||
not be retrieved. This allows the host to reset the plugin state with | |||||
an empty map. | |||||
The @p handle pointer and @p store function MUST NOT be used | |||||
beyond the scope of restore(). | |||||
This function is in the "Instantiation" threading class as defined by | |||||
LV2. This means it MUST NOT be called concurrently with any other | |||||
function on the same plugin instance. | |||||
*/ | |||||
LV2_State_Status (*restore)(LV2_Handle instance, | |||||
LV2_State_Retrieve_Function retrieve, | |||||
LV2_State_Handle handle, | |||||
uint32_t flags, | |||||
const LV2_Feature *const * features); | |||||
} LV2_State_Interface; | |||||
/** | |||||
Feature data for state:mapPath (LV2_STATE__mapPath). | |||||
*/ | |||||
typedef struct { | |||||
/** | |||||
Opaque host data. | |||||
*/ | |||||
LV2_State_Map_Path_Handle handle; | |||||
/** | |||||
Map an absolute path to an abstract path for use in plugin state. | |||||
@param handle MUST be the @p handle member of this struct. | |||||
@param absolute_path The absolute path of a file. | |||||
@return An abstract path suitable for use in plugin state. | |||||
The plugin MUST use this function to map any paths that will be stored | |||||
in plugin state. The returned value is an abstract path which MAY not | |||||
be an actual file system path; @ref absolute_path() MUST be used to map | |||||
it to an actual path in order to use the file. | |||||
Plugins MUST NOT make any assumptions about abstract paths except that | |||||
they can be mapped back to the absolute path of the "same" file (though | |||||
not necessarily the same original path) using @ref absolute_path(). | |||||
This function may only be called within the context of | |||||
LV2_State_Interface methods. The caller is responsible for freeing the | |||||
returned value with free(). | |||||
*/ | |||||
char* (*abstract_path)(LV2_State_Map_Path_Handle handle, | |||||
const char* absolute_path); | |||||
/** | |||||
Map an abstract path from plugin state to an absolute path. | |||||
@param handle MUST be the @p handle member of this struct. | |||||
@param abstract_path An abstract path (e.g. a path from plugin state). | |||||
@return An absolute file system path. | |||||
The plugin MUST use this function in order to actually open or otherwise | |||||
use any paths loaded from plugin state. | |||||
This function may only be called within the context of | |||||
LV2_State_Interface methods. The caller is responsible for freeing the | |||||
returned value with free(). | |||||
*/ | |||||
char* (*absolute_path)(LV2_State_Map_Path_Handle handle, | |||||
const char* abstract_path); | |||||
} LV2_State_Map_Path; | |||||
/** | |||||
Feature data for state:makePath (@ref LV2_STATE__makePath). | |||||
*/ | |||||
typedef struct { | |||||
/** | |||||
Opaque host data. | |||||
*/ | |||||
LV2_State_Make_Path_Handle handle; | |||||
/** | |||||
Return a path the plugin may use to create a new file. | |||||
@param handle MUST be the @p handle member of this struct. | |||||
@param path The path of the new file within a namespace unique to this | |||||
plugin instance. | |||||
@return The absolute path to use for the new file. | |||||
This function can be used by plugins to create files and directories, | |||||
either at state saving time (if this feature is passed to | |||||
LV2_State_Interface.save()) or any time (if this feature is passed to | |||||
LV2_Descriptor.instantiate()). | |||||
The host MUST do whatever is necessary for the plugin to be able to | |||||
create a file at the returned path (e.g. using fopen), including | |||||
creating any leading directories. | |||||
If this function is passed to LV2_Descriptor.instantiate(), it may be | |||||
called from any non-realtime context. If it is passed to | |||||
LV2_State_Interface.save(), it may only be called within the dynamic | |||||
scope of that function call. | |||||
The caller is responsible for freeing the returned value with free(). | |||||
*/ | |||||
char* (*path)(LV2_State_Make_Path_Handle handle, | |||||
const char* path); | |||||
} LV2_State_Make_Path; | |||||
#ifdef __cplusplus | |||||
} /* extern "C" */ | |||||
#endif | |||||
#endif /* LV2_STATE_H */ |
@@ -1,49 +0,0 @@ | |||||
/* | |||||
Copyright 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 time.h C header for the LV2 Time extension | |||||
<http://lv2plug.in/ns/ext/time>. | |||||
*/ | |||||
#ifndef LV2_TIME_H | |||||
#define LV2_TIME_H | |||||
#ifdef __cplusplus | |||||
extern "C" { | |||||
#endif | |||||
#define LV2_TIME_URI "http://lv2plug.in/ns/ext/time" | |||||
#define LV2_TIME__Time LV2_TIME_URI "#Time" | |||||
#define LV2_TIME__Position LV2_TIME_URI "#Position" | |||||
#define LV2_TIME__Rate LV2_TIME_URI "#Rate" | |||||
#define LV2_TIME__position LV2_TIME_URI "#position" | |||||
#define LV2_TIME__barBeat LV2_TIME_URI "#barBeat" | |||||
#define LV2_TIME__bar LV2_TIME_URI "#bar" | |||||
#define LV2_TIME__beat LV2_TIME_URI "#beat" | |||||
#define LV2_TIME__beatUnit LV2_TIME_URI "#beatUnit" | |||||
#define LV2_TIME__beatsPerBar LV2_TIME_URI "#beatsPerBar" | |||||
#define LV2_TIME__beatsPerMinute LV2_TIME_URI "#beatsPerMinute" | |||||
#define LV2_TIME__frame LV2_TIME_URI "#frame" | |||||
#define LV2_TIME__framesPerSecond LV2_TIME_URI "#framesPerSecond" | |||||
#define LV2_TIME__speed LV2_TIME_URI "#speed" | |||||
#ifdef __cplusplus | |||||
} /* extern "C" */ | |||||
#endif | |||||
#endif /* LV2_TIME_H */ |
@@ -1,434 +0,0 @@ | |||||
/* | |||||
LV2 UI Extension | |||||
Copyright 2009-2013 David Robillard <d@drobilla.net> | |||||
Copyright 2006-2011 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 ui.h | |||||
C header for the LV2 UI extension <http://lv2plug.in/ns/extensions/ui>. | |||||
*/ | |||||
#ifndef LV2_UI_H | |||||
#define LV2_UI_H | |||||
#include <stdint.h> | |||||
#include "lv2.h" | |||||
#define LV2_UI_URI "http://lv2plug.in/ns/extensions/ui" | |||||
#define LV2_UI_PREFIX LV2_UI_URI "#" | |||||
#define LV2_UI__CocoaUI LV2_UI_PREFIX "CocoaUI" | |||||
#define LV2_UI__Gtk3UI LV2_UI_PREFIX "Gtk3UI" | |||||
#define LV2_UI__GtkUI LV2_UI_PREFIX "GtkUI" | |||||
#define LV2_UI__PortNotification LV2_UI_PREFIX "PortNotification" | |||||
#define LV2_UI__Qt4UI LV2_UI_PREFIX "Qt4UI" | |||||
#define LV2_UI__UI LV2_UI_PREFIX "UI" | |||||
#define LV2_UI__WindowsUI LV2_UI_PREFIX "WindowsUI" | |||||
#define LV2_UI__X11UI LV2_UI_PREFIX "X11UI" | |||||
#define LV2_UI__binary LV2_UI_PREFIX "binary" | |||||
#define LV2_UI__fixedSize LV2_UI_PREFIX "fixedSize" | |||||
#define LV2_UI__idleInterface LV2_UI_PREFIX "idleInterface" | |||||
#define LV2_UI__noUserResize LV2_UI_PREFIX "noUserResize" | |||||
#define LV2_UI__notifyType LV2_UI_PREFIX "notifyType" | |||||
#define LV2_UI__parent LV2_UI_PREFIX "parent" | |||||
#define LV2_UI__plugin LV2_UI_PREFIX "plugin" | |||||
#define LV2_UI__portIndex LV2_UI_PREFIX "portIndex" | |||||
#define LV2_UI__portMap LV2_UI_PREFIX "portMap" | |||||
#define LV2_UI__portNotification LV2_UI_PREFIX "portNotification" | |||||
#define LV2_UI__portSubscribe LV2_UI_PREFIX "portSubscribe" | |||||
#define LV2_UI__resize LV2_UI_PREFIX "resize" | |||||
#define LV2_UI__showInterface LV2_UI_PREFIX "showInterface" | |||||
#define LV2_UI__touch LV2_UI_PREFIX "touch" | |||||
#define LV2_UI__ui LV2_UI_PREFIX "ui" | |||||
#define LV2_UI__updateRate LV2_UI_PREFIX "updateRate" | |||||
/** | |||||
The index returned by LV2_UI_Port_Port::port_index() for unknown ports. | |||||
*/ | |||||
#define LV2UI_INVALID_PORT_INDEX ((uint32_t)-1) | |||||
#ifdef __cplusplus | |||||
extern "C" { | |||||
#else | |||||
# include <stdbool.h> | |||||
#endif | |||||
/** | |||||
A pointer to some widget or other type of UI handle. | |||||
The actual type is defined by the type of the UI. | |||||
*/ | |||||
typedef void* LV2UI_Widget; | |||||
/** | |||||
A pointer to an instance of a UI. | |||||
It is valid to compare this to NULL (0 for C++) but otherwise the host MUST | |||||
not attempt to interpret it. The UI plugin may use it to reference internal | |||||
instance data. | |||||
*/ | |||||
typedef void* LV2UI_Handle; | |||||
/** | |||||
A pointer to a controller provided by the host. | |||||
It is valid to compare this to NULL (0 for C++) but otherwise the UI plugin | |||||
MUST NOT attempt to interpret it. The host may use it to reference internal | |||||
instance data. | |||||
*/ | |||||
typedef void* LV2UI_Controller; | |||||
/** | |||||
A pointer to opaque data for a feature. | |||||
*/ | |||||
typedef void* LV2UI_Feature_Handle; | |||||
/** | |||||
The type of the host-provided function that the UI can use to | |||||
send data to a plugin's input ports. | |||||
The @p buffer parameter must point to a block of data, @c buffer_size bytes | |||||
large. The format of this data and how the host should use it is defined by | |||||
the @p port_protocol. This buffer is owned by the UI and is only valid for | |||||
the duration of this call. | |||||
The @p port_protocol parameter should either be 0 or the URID for a | |||||
ui:PortProtocol. If it is 0, the protocol is implicitly ui:floatProtocol, | |||||
the port must be an lv2:ControlPort input, @c buffer must point to a single | |||||
float value, and @c buffer_size must be sizeof(float). | |||||
The UI SHOULD NOT use a PortProtocol not supported by the host (i.e. one not | |||||
passed by the host as a feature), but the host MUST gracefully ignore any | |||||
port_protocol it does not understand. | |||||
*/ | |||||
typedef void (*LV2UI_Write_Function)(LV2UI_Controller controller, | |||||
uint32_t port_index, | |||||
uint32_t buffer_size, | |||||
uint32_t port_protocol, | |||||
const void* buffer); | |||||
/** | |||||
The implementation of a UI. | |||||
A pointer to an object of this type is returned by the lv2ui_descriptor() | |||||
function. | |||||
*/ | |||||
typedef struct _LV2UI_Descriptor { | |||||
/** | |||||
The URI for this UI (not for the plugin it controls). | |||||
*/ | |||||
const char* URI; | |||||
/** | |||||
Create a new UI object and return a handle to it. This function works | |||||
similarly to the instantiate() member in LV2_Descriptor. | |||||
@param descriptor The descriptor for the UI that you want to instantiate. | |||||
@param plugin_uri The URI of the plugin that this UI will control. | |||||
@param bundle_path The path to the bundle containing the RDF data file | |||||
that references this shared object file, including the trailing '/'. | |||||
@param write_function A function provided by the host that the UI can use | |||||
to send data to the plugin's input ports. | |||||
@param controller A handle for the plugin instance that should be passed | |||||
as the first parameter of @p write_function. | |||||
@param widget A pointer to an LV2UI_Widget. The UI will write a widget | |||||
pointer to this location (what type of widget depends on the RDF class of | |||||
the UI) that will be the main UI widget. | |||||
@param features An array of LV2_Feature pointers. The host must pass all | |||||
feature URIs that it and the UI supports and any additional data, just | |||||
like in the LV2 plugin instantiate() function. Note that UI features and | |||||
plugin features are NOT necessarily the same, they just share the same | |||||
data structure - this will probably not be the same array as the one the | |||||
plugin host passes to a plugin. | |||||
*/ | |||||
LV2UI_Handle (*instantiate)(const struct _LV2UI_Descriptor* descriptor, | |||||
const char* plugin_uri, | |||||
const char* bundle_path, | |||||
LV2UI_Write_Function write_function, | |||||
LV2UI_Controller controller, | |||||
LV2UI_Widget* widget, | |||||
const LV2_Feature* const* features); | |||||
/** | |||||
Destroy the UI object and the associated widget. The host must not try | |||||
to access the widget after calling this function. | |||||
*/ | |||||
void (*cleanup)(LV2UI_Handle ui); | |||||
/** | |||||
Tell the UI that something interesting has happened at a plugin port. | |||||
What is interesting and how it is written to the buffer passed to this | |||||
function is defined by the @p format parameter, which has the same | |||||
meaning as in LV2UI_Write_Function. The only exception is ports of the | |||||
class lv2:ControlPort, for which this function should be called when the | |||||
port value changes (it does not have to be called for every single change | |||||
if the host's UI thread has problems keeping up with the thread the | |||||
plugin is running in), @p buffer_size should be 4, the buffer should | |||||
contain a single IEEE-754 float, and @p format should be 0. | |||||
By default, the host should only call this function for input ports of | |||||
the lv2:ControlPort class. However, this can be modified by using | |||||
ui:portNotification in the UI data, or the ui:portSubscribe feature. | |||||
The @p buffer is only valid during the time of this function call, so if | |||||
the UI wants to keep it for later use it has to copy the contents to an | |||||
internal buffer. | |||||
This member may be set to NULL if the UI is not interested in any | |||||
port events. | |||||
*/ | |||||
void (*port_event)(LV2UI_Handle ui, | |||||
uint32_t port_index, | |||||
uint32_t buffer_size, | |||||
uint32_t format, | |||||
const void* buffer); | |||||
/** | |||||
Return a data structure associated with an extension URI, for example | |||||
a struct containing additional function pointers. | |||||
Avoid returning function pointers directly since standard C/C++ has no | |||||
valid way of casting a void* to a function pointer. This member may be set | |||||
to NULL if the UI is not interested in supporting any extensions. This is | |||||
similar to the extension_data() member in LV2_Descriptor. | |||||
*/ | |||||
const void* (*extension_data)(const char* uri); | |||||
} LV2UI_Descriptor; | |||||
/** | |||||
UI Resize Feature (LV2_UI__resize) | |||||
This structure may be used in two ways: as a feature passed by the host via | |||||
LV2UI_Descriptor::instantiate(), or as extension data provided by a UI via | |||||
LV2UI_Descriptor::extension_data()). | |||||
*/ | |||||
typedef struct _LV2UI_Resize { | |||||
/** | |||||
Pointer to opaque data which must be passed to ui_resize(). | |||||
*/ | |||||
LV2UI_Feature_Handle handle; | |||||
/** | |||||
Request or advertise a size change. | |||||
When this struct is provided by the host, the UI may call this | |||||
function to inform the host about the size of the UI. | |||||
When this struct is provided by the UI, the host may call this | |||||
function to notify the UI that it should change its size accordingly. | |||||
@return 0 on success. | |||||
*/ | |||||
int (*ui_resize)(LV2UI_Feature_Handle handle, int width, int height); | |||||
} LV2UI_Resize; | |||||
/** | |||||
Port Map Feature (LV2_UI__portMap). | |||||
This feature can be used by the UI to get the index for a port with the | |||||
given symbol. This makes it possible to implement and distribute a UI | |||||
separately from the plugin (since symbol is a guaranteed stable port | |||||
identifier while index is not). | |||||
*/ | |||||
typedef struct _LV2UI_Port_Map { | |||||
/** | |||||
Pointer to opaque data which must be passed to ui_resize(). | |||||
*/ | |||||
LV2UI_Feature_Handle handle; | |||||
/** | |||||
Get the index for the port with the given @p symbol. | |||||
@return The index of the port, or LV2UI_INVALID_PORT_INDEX if no such | |||||
port is found. | |||||
*/ | |||||
uint32_t (*port_index)(LV2UI_Feature_Handle handle, const char* symbol); | |||||
} LV2UI_Port_Map; | |||||
/** | |||||
Port subscription feature (LV2_UI__portSubscribe); | |||||
*/ | |||||
typedef struct _LV2UI_Port_Subscribe { | |||||
/** | |||||
Pointer to opaque data which must be passed to ui_resize(). | |||||
*/ | |||||
LV2UI_Feature_Handle handle; | |||||
/** | |||||
Subscribe to updates for a port. | |||||
This means that the host will call the UI's port_event() function when | |||||
the port value changes (as defined by protocol). | |||||
Calling this function with the same @p port_index and @p port_protocol | |||||
as an already active subscription has no effect. | |||||
@param handle The handle field of this struct. | |||||
@param port_index The index of the port. | |||||
@param port_protocol The URID of the ui:PortProtocol. | |||||
@param features Features for this subscription. | |||||
@return 0 on success. | |||||
*/ | |||||
uint32_t (*subscribe)(LV2UI_Feature_Handle handle, | |||||
uint32_t port_index, | |||||
uint32_t port_protocol, | |||||
const LV2_Feature* const* features); | |||||
/** | |||||
Unsubscribe from updates for a port. | |||||
This means that the host will cease calling calling port_event() when | |||||
the port value changes. | |||||
Calling this function with a @p port_index and @p port_protocol that | |||||
does not refer to an active port subscription has no effect. | |||||
@param handle The handle field of this struct. | |||||
@param port_index The index of the port. | |||||
@param port_protocol The URID of the ui:PortProtocol. | |||||
@param features Features for this subscription. | |||||
@return 0 on success. | |||||
*/ | |||||
uint32_t (*unsubscribe)(LV2UI_Feature_Handle handle, | |||||
uint32_t port_index, | |||||
uint32_t port_protocol, | |||||
const LV2_Feature* const* features); | |||||
} LV2UI_Port_Subscribe; | |||||
/** | |||||
A feature to notify the host the user has grabbed a UI control. | |||||
*/ | |||||
typedef struct _LV2UI_Touch { | |||||
/** | |||||
Pointer to opaque data which must be passed to ui_resize(). | |||||
*/ | |||||
LV2UI_Feature_Handle handle; | |||||
/** | |||||
Notify the host that a control has been grabbed or released. | |||||
@param handle The handle field of this struct. | |||||
@param port_index The index of the port associated with the control. | |||||
@param grabbed If true, the control has been grabbed, otherwise the | |||||
control has been released. | |||||
*/ | |||||
void (*touch)(LV2UI_Feature_Handle handle, | |||||
uint32_t port_index, | |||||
bool grabbed); | |||||
} LV2UI_Touch; | |||||
/** | |||||
UI Idle Feature (LV2_UI__idleInterface) | |||||
This feature is an addition to the UI API that provides a callback for the | |||||
host to call rapidly, e.g. to drive the idle callback of a toolkit. | |||||
*/ | |||||
typedef struct _LV2UI_Idle_Interface { | |||||
/** | |||||
Run a single iteration of the UI's idle loop. | |||||
This will be called "frequently" in the UI thread at a rate appropriate | |||||
for a toolkit main loop. There are no precise timing guarantees. | |||||
@return 0 on success, or anything else to stop being called. | |||||
*/ | |||||
int (*idle)(LV2UI_Handle ui); | |||||
} LV2UI_Idle_Interface; | |||||
/** | |||||
UI Show Interface (LV2_UI__showInterface) | |||||
UIs can use this interface to provide show/hide methods to pop up a window, | |||||
which allows them to function in hosts unable to embed their widget type. | |||||
If used, LV2UI_Idle_Interface should also be used to drive the UI. The UI | |||||
should return non-zero from idle() when the window has been closed. | |||||
*/ | |||||
typedef struct _LV2UI_Show_Interface { | |||||
/** | |||||
Show a window for this UI. | |||||
@return 0 on success, or anything else to stop being called. | |||||
*/ | |||||
int (*show)(LV2UI_Handle ui); | |||||
/** | |||||
Hide the window for this UI. | |||||
@return 0 on success, or anything else to stop being called. | |||||
*/ | |||||
int (*hide)(LV2UI_Handle ui); | |||||
} LV2UI_Show_Interface; | |||||
/** | |||||
Peak data for a slice of time, the update format for ui:peakProtocol. | |||||
*/ | |||||
typedef struct _LV2UI_Peak_Data { | |||||
/** | |||||
The start of the measurement period. This is just a running counter | |||||
that is only meaningful in comparison to previous values and must not be | |||||
interpreted as an absolute time. | |||||
*/ | |||||
uint32_t period_start; | |||||
/** | |||||
The size of the measurement period, in the same units as period_start. | |||||
*/ | |||||
uint32_t period_size; | |||||
/** | |||||
The peak value for the measurement period. This should be the maximal | |||||
value for abs(sample) over all the samples in the period. | |||||
*/ | |||||
float peak; | |||||
} LV2UI_Peak_Data; | |||||
/** | |||||
A plugin UI programmer must include a function called "lv2ui_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). This function is | |||||
loaded from the library by the UI host and called to get a | |||||
LV2UI_Descriptor for the wanted plugin. | |||||
Just like lv2_descriptor(), this function takes an index parameter. The | |||||
index should only be used for enumeration and not as any sort of ID number - | |||||
the host should just iterate from 0 and upwards until the function returns | |||||
NULL or a descriptor with an URI matching the one the host is looking for. | |||||
*/ | |||||
LV2_SYMBOL_EXPORT | |||||
const LV2UI_Descriptor* lv2ui_descriptor(uint32_t index); | |||||
/** | |||||
The type of the lv2ui_descriptor() function. | |||||
*/ | |||||
typedef const LV2UI_Descriptor* (*LV2UI_DescriptorFunction)(uint32_t index); | |||||
#ifdef __cplusplus | |||||
} | |||||
#endif | |||||
#endif /* LV2_UI_H */ |
@@ -1,62 +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 units.h | |||||
C definitions for the LV2 Units extension | |||||
<http://lv2plug.in/ns/extensions/units>. | |||||
*/ | |||||
#ifndef LV2_UNITS_H | |||||
#define LV2_UNITS_H | |||||
#define LV2_UNITS_URI "http://lv2plug.in/ns/extensions/units" | |||||
#define LV2_UNITS_PREFIX LV2_UNITS_URI "#" | |||||
#define LV2_UNITS__Conversion LV2_UNITS_PREFIX "Conversion" | |||||
#define LV2_UNITS__Unit LV2_UNITS_PREFIX "Unit" | |||||
#define LV2_UNITS__bar LV2_UNITS_PREFIX "bar" | |||||
#define LV2_UNITS__beat LV2_UNITS_PREFIX "beat" | |||||
#define LV2_UNITS__bpm LV2_UNITS_PREFIX "bpm" | |||||
#define LV2_UNITS__cent LV2_UNITS_PREFIX "cent" | |||||
#define LV2_UNITS__cm LV2_UNITS_PREFIX "cm" | |||||
#define LV2_UNITS__coef LV2_UNITS_PREFIX "coef" | |||||
#define LV2_UNITS__conversion LV2_UNITS_PREFIX "conversion" | |||||
#define LV2_UNITS__db LV2_UNITS_PREFIX "db" | |||||
#define LV2_UNITS__degree LV2_UNITS_PREFIX "degree" | |||||
#define LV2_UNITS__frame LV2_UNITS_PREFIX "frame" | |||||
#define LV2_UNITS__hz LV2_UNITS_PREFIX "hz" | |||||
#define LV2_UNITS__inch LV2_UNITS_PREFIX "inch" | |||||
#define LV2_UNITS__khz LV2_UNITS_PREFIX "khz" | |||||
#define LV2_UNITS__km LV2_UNITS_PREFIX "km" | |||||
#define LV2_UNITS__m LV2_UNITS_PREFIX "m" | |||||
#define LV2_UNITS__mhz LV2_UNITS_PREFIX "mhz" | |||||
#define LV2_UNITS__midiNote LV2_UNITS_PREFIX "midiNote" | |||||
#define LV2_UNITS__mile LV2_UNITS_PREFIX "mile" | |||||
#define LV2_UNITS__min LV2_UNITS_PREFIX "min" | |||||
#define LV2_UNITS__mm LV2_UNITS_PREFIX "mm" | |||||
#define LV2_UNITS__ms LV2_UNITS_PREFIX "ms" | |||||
#define LV2_UNITS__name LV2_UNITS_PREFIX "name" | |||||
#define LV2_UNITS__oct LV2_UNITS_PREFIX "oct" | |||||
#define LV2_UNITS__pc LV2_UNITS_PREFIX "pc" | |||||
#define LV2_UNITS__prefixConversion LV2_UNITS_PREFIX "prefixConversion" | |||||
#define LV2_UNITS__render LV2_UNITS_PREFIX "render" | |||||
#define LV2_UNITS__s LV2_UNITS_PREFIX "s" | |||||
#define LV2_UNITS__semitone12TET LV2_UNITS_PREFIX "semitone12TET" | |||||
#define LV2_UNITS__symbol LV2_UNITS_PREFIX "symbol" | |||||
#define LV2_UNITS__unit LV2_UNITS_PREFIX "unit" | |||||
#endif /* LV2_UNITS_H */ |
@@ -1,98 +0,0 @@ | |||||
/* | |||||
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 | |||||
C header for the LV2 URI Map extension <http://lv2plug.in/ns/ext/uri-map>. | |||||
This extension defines a simple mechanism for plugins to map URIs to | |||||
integers, usually for performance reasons (e.g. processing events typed by | |||||
URIs in real time). The expected use case is for plugins to map URIs to | |||||
integers for things they 'understand' at instantiation time, and store those | |||||
values for use in the audio thread without doing any string comparison. | |||||
This allows the extensibility of RDF with the performance of integers (or | |||||
centrally defined enumerations). | |||||
*/ | |||||
#ifndef LV2_URI_MAP_H | |||||
#define LV2_URI_MAP_H | |||||
#define LV2_URI_MAP_URI "http://lv2plug.in/ns/ext/uri-map" | |||||
#include <stdint.h> | |||||
#ifdef __cplusplus | |||||
extern "C" { | |||||
#endif | |||||
/** | |||||
Opaque pointer to host data. | |||||
*/ | |||||
typedef void* LV2_URI_Map_Callback_Data; | |||||
/** | |||||
URI Map 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/uri-map" | |||||
and data pointed to an instance of this struct. | |||||
*/ | |||||
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_URI_Map_Callback_Data callback_data; | |||||
/** | |||||
Get the numeric ID of a URI from the host. | |||||
@param callback_data Must be the callback_data member of this struct. | |||||
@param map The 'context' of this URI. Certain extensions may define a | |||||
URI that must be passed here with certain restrictions on the return | |||||
value (e.g. limited range). This value may be NULL if the plugin needs | |||||
an ID for a URI in general. Extensions SHOULD NOT define a context | |||||
unless there is a specific need to do so, e.g. to restrict the range of | |||||
the returned value. | |||||
@param uri The URI to be mapped to an integer ID. | |||||
This function is referentially transparent; any number of calls with the | |||||
same arguments is guaranteed to return the same value over the life of a | |||||
plugin instance (though the same URI may return different values with a | |||||
different map parameter). However, this function is not necessarily very | |||||
fast: plugins SHOULD cache any IDs they might need in performance | |||||
critical situations. | |||||
The return value 0 is reserved and indicates that an ID for that URI | |||||
could not be created for whatever reason. Extensions MAY define more | |||||
precisely what this means in a certain context, but in general plugins | |||||
SHOULD handle this situation as gracefully as possible. However, hosts | |||||
SHOULD NOT return 0 from this function in non-exceptional circumstances | |||||
(e.g. the URI map SHOULD be dynamic). Hosts that statically support only | |||||
a fixed set of URIs should not expect plugins to function correctly. | |||||
*/ | |||||
uint32_t (*uri_to_id)(LV2_URI_Map_Callback_Data callback_data, | |||||
const char* map, | |||||
const char* uri); | |||||
} LV2_URI_Map_Feature; | |||||
#ifdef __cplusplus | |||||
} /* extern "C" */ | |||||
#endif | |||||
#endif /* LV2_URI_MAP_H */ |
@@ -1,129 +0,0 @@ | |||||
/* | |||||
Copyright 2008-2012 David Robillard <http://drobilla.net> | |||||
Copyright 2011 Gabriel M. Beddingfield <gabrbedd@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 urid.h | |||||
C header for the LV2 URID extension <http://lv2plug.in/ns/ext/urid> | |||||
*/ | |||||
#ifndef LV2_URID_H | |||||
#define LV2_URID_H | |||||
#define LV2_URID_URI "http://lv2plug.in/ns/ext/urid" | |||||
#define LV2_URID_PREFIX LV2_URID_URI "#" | |||||
#define LV2_URID__map LV2_URID_PREFIX "map" | |||||
#define LV2_URID__unmap LV2_URID_PREFIX "unmap" | |||||
/* Legacy defines */ | |||||
#define LV2_URID_MAP_URI LV2_URID__map | |||||
#define LV2_URID_UNMAP_URI LV2_URID__unmap | |||||
#include <stdint.h> | |||||
#ifdef __cplusplus | |||||
extern "C" { | |||||
#endif | |||||
/** | |||||
Opaque pointer to host data for LV2_URID_Map. | |||||
*/ | |||||
typedef void* LV2_URID_Map_Handle; | |||||
/** | |||||
Opaque pointer to host data for LV2_URID_Unmap. | |||||
*/ | |||||
typedef void* LV2_URID_Unmap_Handle; | |||||
/** | |||||
URI mapped to an integer. | |||||
*/ | |||||
typedef uint32_t LV2_URID; | |||||
/** | |||||
URID Map Feature (LV2_URID__map) | |||||
*/ | |||||
typedef struct _LV2_URID_Map { | |||||
/** | |||||
Opaque pointer to host data. | |||||
This MUST be passed to map_uri() whenever it is called. | |||||
Otherwise, it must not be interpreted in any way. | |||||
*/ | |||||
LV2_URID_Map_Handle handle; | |||||
/** | |||||
Get the numeric ID of a URI. | |||||
If the ID does not already exist, it will be created. | |||||
This function is referentially transparent; any number of calls with the | |||||
same arguments is guaranteed to return the same value over the life of a | |||||
plugin instance. Note, however, that several URIs MAY resolve to the | |||||
same ID if the host considers those URIs equivalent. | |||||
This function is not necessarily very fast or RT-safe: plugins SHOULD | |||||
cache any IDs they might need in performance critical situations. | |||||
The return value 0 is reserved and indicates that an ID for that URI | |||||
could not be created for whatever reason. However, hosts SHOULD NOT | |||||
return 0 from this function in non-exceptional circumstances (i.e. the | |||||
URI map SHOULD be dynamic). | |||||
@param handle Must be the callback_data member of this struct. | |||||
@param uri The URI to be mapped to an integer ID. | |||||
*/ | |||||
LV2_URID (*map)(LV2_URID_Map_Handle handle, | |||||
const char* uri); | |||||
} LV2_URID_Map; | |||||
/** | |||||
URI Unmap Feature (LV2_URID__unmap) | |||||
*/ | |||||
typedef struct _LV2_URID_Unmap { | |||||
/** | |||||
Opaque pointer to host data. | |||||
This MUST be passed to unmap() whenever it is called. | |||||
Otherwise, it must not be interpreted in any way. | |||||
*/ | |||||
LV2_URID_Unmap_Handle handle; | |||||
/** | |||||
Get the URI for a previously mapped numeric ID. | |||||
Returns NULL if @p urid is not yet mapped. Otherwise, the corresponding | |||||
URI is returned in a canonical form. This MAY not be the exact same | |||||
string that was originally passed to LV2_URID_Map::map(), but it MUST be | |||||
an identical URI according to the URI syntax specification (RFC3986). A | |||||
non-NULL return for a given @p urid will always be the same for the life | |||||
of the plugin. Plugins that intend to perform string comparison on | |||||
unmapped URIs SHOULD first canonicalise URI strings with a call to | |||||
map_uri() followed by a call to unmap_uri(). | |||||
@param handle Must be the callback_data member of this struct. | |||||
@param urid The ID to be mapped back to the URI string. | |||||
*/ | |||||
const char* (*unmap)(LV2_URID_Unmap_Handle handle, | |||||
LV2_URID urid); | |||||
} LV2_URID_Unmap; | |||||
#ifdef __cplusplus | |||||
} /* extern "C" */ | |||||
#endif | |||||
#endif /* LV2_URID_H */ |
@@ -1,158 +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 worker.h C header for the LV2 Worker extension | |||||
<http://lv2plug.in/ns/ext/worker>. | |||||
*/ | |||||
#ifndef LV2_WORKER_H | |||||
#define LV2_WORKER_H | |||||
#include <stdint.h> | |||||
#include "lv2.h" | |||||
#define LV2_WORKER_URI "http://lv2plug.in/ns/ext/worker" | |||||
#define LV2_WORKER_PREFIX LV2_WORKER_URI "#" | |||||
#define LV2_WORKER__interface LV2_WORKER_PREFIX "interface" | |||||
#define LV2_WORKER__schedule LV2_WORKER_PREFIX "schedule" | |||||
#ifdef __cplusplus | |||||
extern "C" { | |||||
#endif | |||||
/** | |||||
A status code for worker functions. | |||||
*/ | |||||
typedef enum { | |||||
LV2_WORKER_SUCCESS = 0, /**< Completed successfully. */ | |||||
LV2_WORKER_ERR_UNKNOWN = 1, /**< Unknown error. */ | |||||
LV2_WORKER_ERR_NO_SPACE = 2 /**< Failed due to lack of space. */ | |||||
} LV2_Worker_Status; | |||||
typedef void* LV2_Worker_Respond_Handle; | |||||
/** | |||||
A function to respond to run() from the worker method. | |||||
The @p data MUST be safe for the host to copy and later pass to | |||||
work_response(), and the host MUST guarantee that it will be eventually | |||||
passed to work_response() if this function returns LV2_WORKER_SUCCESS. | |||||
*/ | |||||
typedef LV2_Worker_Status (*LV2_Worker_Respond_Function)( | |||||
LV2_Worker_Respond_Handle handle, | |||||
uint32_t size, | |||||
const void* data); | |||||
/** | |||||
LV2 Plugin Worker Interface. | |||||
This is the interface provided by the plugin to implement a worker method. | |||||
The plugin's extension_data() method should return an LV2_Worker_Interface | |||||
when called with LV2_WORKER__interface as its argument. | |||||
*/ | |||||
typedef struct _LV2_Worker_Interface { | |||||
/** | |||||
The worker method. This is called by the host in a non-realtime context | |||||
as requested, possibly with an arbitrary message to handle. | |||||
A response can be sent to run() using @p respond. The plugin MUST NOT | |||||
make any assumptions about which thread calls this method, other than | |||||
the fact that there are no real-time requirements. | |||||
@param instance The LV2 instance this is a method on. | |||||
@param respond A function for sending a response to run(). | |||||
@param handle Must be passed to @p respond if it is called. | |||||
@param size The size of @p data. | |||||
@param data Data from run(), or NULL. | |||||
*/ | |||||
LV2_Worker_Status (*work)(LV2_Handle instance, | |||||
LV2_Worker_Respond_Function respond, | |||||
LV2_Worker_Respond_Handle handle, | |||||
uint32_t size, | |||||
const void* data); | |||||
/** | |||||
Handle a response from the worker. This is called by the host in the | |||||
run() context when a response from the worker is ready. | |||||
@param instance The LV2 instance this is a method on. | |||||
@param size The size of @p body. | |||||
@param body Message body, or NULL. | |||||
*/ | |||||
LV2_Worker_Status (*work_response)(LV2_Handle instance, | |||||
uint32_t size, | |||||
const void* body); | |||||
/** | |||||
Called when all responses for this cycle have been delivered. | |||||
Since work_response() may be called after run() finished, this provides | |||||
a hook for code that must run after the cycle is completed. | |||||
This field may be NULL if the plugin has no use for it. Otherwise, the | |||||
host MUST call it after every run(), regardless of whether or not any | |||||
responses were sent that cycle. | |||||
*/ | |||||
LV2_Worker_Status (*end_run)(LV2_Handle instance); | |||||
} LV2_Worker_Interface; | |||||
typedef void* LV2_Worker_Schedule_Handle; | |||||
typedef struct _LV2_Worker_Schedule { | |||||
/** | |||||
Opaque host data. | |||||
*/ | |||||
LV2_Worker_Schedule_Handle handle; | |||||
/** | |||||
Request from run() that the host call the worker. | |||||
This function is in the audio threading class. It should be called from | |||||
run() to request that the host call the work() method in a non-realtime | |||||
context with the given arguments. | |||||
This function is always safe to call from run(), but it is not | |||||
guaranteed that the worker is actually called from a different thread. | |||||
In particular, when free-wheeling (e.g. for offline rendering), the | |||||
worker may be executed immediately. This allows single-threaded | |||||
processing with sample accuracy and avoids timing problems when run() is | |||||
executing much faster or slower than real-time. | |||||
Plugins SHOULD be written in such a way that if the worker runs | |||||
immediately, and responses from the worker are delivered immediately, | |||||
the effect of the work takes place immediately with sample accuracy. | |||||
The @p data MUST be safe for the host to copy and later pass to work(), | |||||
and the host MUST guarantee that it will be eventually passed to work() | |||||
if this function returns LV2_WORKER_SUCCESS. | |||||
@param handle The handle field of this struct. | |||||
@param size The size of @p data. | |||||
@param data Message to pass to work(), or NULL. | |||||
*/ | |||||
LV2_Worker_Status (*schedule_work)(LV2_Worker_Schedule_Handle handle, | |||||
uint32_t size, | |||||
const void* data); | |||||
} LV2_Worker_Schedule; | |||||
#ifdef __cplusplus | |||||
} /* extern "C" */ | |||||
#endif | |||||
#endif /* LV2_WORKER_H */ |
@@ -1,279 +0,0 @@ | |||||
/* | |||||
* aeffectx.h - simple header to allow VeSTige compilation and eventually work | |||||
* | |||||
* Copyright (c) 2006 Javier Serrano Polo <jasp00/at/users.sourceforge.net> | |||||
* | |||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net | |||||
* | |||||
* 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 (see COPYING); if not, write to the | |||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | |||||
* Boston, MA 02110-1301 USA. | |||||
* | |||||
*/ | |||||
#include <stdint.h> | |||||
#ifndef _AEFFECTX_H | |||||
#define _AEFFECTX_H | |||||
#define CCONST(a, b, c, d)( ( ( (int) a ) << 24 ) | \ | |||||
( ( (int) b ) << 16 ) | \ | |||||
( ( (int) c ) << 8 ) | \ | |||||
( ( (int) d ) << 0 ) ) | |||||
#define audioMasterAutomate 0 | |||||
#define audioMasterVersion 1 | |||||
#define audioMasterCurrentId 2 | |||||
#define audioMasterIdle 3 | |||||
#define audioMasterPinConnected 4 | |||||
// unsupported? 5 | |||||
#define audioMasterWantMidi 6 | |||||
#define audioMasterGetTime 7 | |||||
#define audioMasterProcessEvents 8 | |||||
#define audioMasterSetTime 9 | |||||
#define audioMasterTempoAt 10 | |||||
#define audioMasterGetNumAutomatableParameters 11 | |||||
#define audioMasterGetParameterQuantization 12 | |||||
#define audioMasterIOChanged 13 | |||||
#define audioMasterNeedIdle 14 | |||||
#define audioMasterSizeWindow 15 | |||||
#define audioMasterGetSampleRate 16 | |||||
#define audioMasterGetBlockSize 17 | |||||
#define audioMasterGetInputLatency 18 | |||||
#define audioMasterGetOutputLatency 19 | |||||
#define audioMasterGetPreviousPlug 20 | |||||
#define audioMasterGetNextPlug 21 | |||||
#define audioMasterWillReplaceOrAccumulate 22 | |||||
#define audioMasterGetCurrentProcessLevel 23 | |||||
#define audioMasterGetAutomationState 24 | |||||
#define audioMasterOfflineStart 25 | |||||
#define audioMasterOfflineRead 26 | |||||
#define audioMasterOfflineWrite 27 | |||||
#define audioMasterOfflineGetCurrentPass 28 | |||||
#define audioMasterOfflineGetCurrentMetaPass 29 | |||||
#define audioMasterSetOutputSampleRate 30 | |||||
// unsupported? 31 | |||||
#define audioMasterGetSpeakerArrangement 31 // deprecated in 2.4? | |||||
#define audioMasterGetVendorString 32 | |||||
#define audioMasterGetProductString 33 | |||||
#define audioMasterGetVendorVersion 34 | |||||
#define audioMasterVendorSpecific 35 | |||||
#define audioMasterSetIcon 36 | |||||
#define audioMasterCanDo 37 | |||||
#define audioMasterGetLanguage 38 | |||||
#define audioMasterOpenWindow 39 | |||||
#define audioMasterCloseWindow 40 | |||||
#define audioMasterGetDirectory 41 | |||||
#define audioMasterUpdateDisplay 42 | |||||
#define audioMasterBeginEdit 43 | |||||
#define audioMasterEndEdit 44 | |||||
#define audioMasterOpenFileSelector 45 | |||||
#define audioMasterCloseFileSelector 46 // currently unused | |||||
#define audioMasterEditFile 47 // currently unused | |||||
#define audioMasterGetChunkFile 48 // currently unused | |||||
#define audioMasterGetInputSpeakerArrangement 49 // currently unused | |||||
#define effFlagsHasEditor 1 | |||||
#define effFlagsCanReplacing (1 << 4) // very likely | |||||
#define effFlagsIsSynth (1 << 8) // currently unused | |||||
#define effOpen 0 | |||||
#define effClose 1 // currently unused | |||||
#define effSetProgram 2 // currently unused | |||||
#define effGetProgram 3 // currently unused | |||||
#define effGetProgramName 5 // currently unused | |||||
#define effGetParamName 8 // currently unused | |||||
#define effSetSampleRate 10 | |||||
#define effSetBlockSize 11 | |||||
#define effMainsChanged 12 | |||||
#define effEditGetRect 13 | |||||
#define effEditOpen 14 | |||||
#define effEditClose 15 | |||||
#define effEditIdle 19 | |||||
#define effEditTop 20 | |||||
#define effProcessEvents 25 | |||||
#define effGetEffectName 45 | |||||
#define effGetVendorString 47 | |||||
#define effGetProductString 48 | |||||
#define effGetVendorVersion 49 | |||||
#define effCanDo 51 // currently unused | |||||
/* from http://asseca.com/vst-24-specs/efGetParameterProperties.html */ | |||||
#define effGetParameterProperties 56 | |||||
#define effGetVstVersion 58 // currently unused | |||||
#define kEffectMagic (CCONST( 'V', 's', 't', 'P' )) | |||||
#define kVstLangEnglish 1 | |||||
#define kVstMidiType 1 | |||||
#define kVstTempoValid (1 << 10) | |||||
#define kVstTransportPlaying (1 << 1) | |||||
struct RemoteVstPlugin; | |||||
#define kVstNanosValid (1 << 8) | |||||
#define kVstPpqPosValid (1 << 9) | |||||
#define kVstTempoValid (1 << 10) | |||||
#define kVstBarsValid (1 << 11) | |||||
#define kVstCyclePosValid (1 << 12) | |||||
#define kVstTimeSigValid (1 << 13) | |||||
#define kVstSmpteValid (1 << 14) | |||||
#define kVstClockValid (1 << 15) | |||||
struct _VstMidiEvent | |||||
{ | |||||
// 00 | |||||
int type; | |||||
// 04 | |||||
int byteSize; | |||||
// 08 | |||||
int deltaFrames; | |||||
// 0c? | |||||
int flags; | |||||
// 10? | |||||
int noteLength; | |||||
// 14? | |||||
int noteOffset; | |||||
// 18 | |||||
char midiData[4]; | |||||
// 1c? | |||||
char detune; | |||||
// 1d? | |||||
char noteOffVelocity; | |||||
// 1e? | |||||
char reserved1; | |||||
// 1f? | |||||
char reserved2; | |||||
}; | |||||
typedef struct _VstMidiEvent VstMidiEvent; | |||||
struct _VstEvent | |||||
{ | |||||
char dump[sizeof (VstMidiEvent)]; | |||||
}; | |||||
typedef struct _VstEvent VstEvent; | |||||
struct _VstEvents | |||||
{ | |||||
// 00 | |||||
int numEvents; | |||||
// 04 | |||||
void *reserved; | |||||
// 08 | |||||
VstEvent * events[2]; | |||||
}; | |||||
typedef struct _VstEvents VstEvents; | |||||
/* this struct taken from http://asseca.com/vst-24-specs/efGetParameterProperties.html */ | |||||
struct _VstParameterProperties | |||||
{ | |||||
float stepFloat; | |||||
float smallStepFloat; | |||||
float largeStepFloat; | |||||
char label[64]; | |||||
int32_t flags; | |||||
int32_t minInteger; | |||||
int32_t maxInteger; | |||||
int32_t stepInteger; | |||||
int32_t largeStepInteger; | |||||
char shortLabel[8]; | |||||
}; | |||||
typedef struct _VstParameterProperties VstParameterProperties; | |||||
/* this enum taken from http://asseca.com/vst-24-specs/efGetParameterProperties.html */ | |||||
enum VstParameterFlags | |||||
{ | |||||
kVstParameterIsSwitch = 1 << 0, /* parameter is a switch (on/off) */ | |||||
kVstParameterUsesIntegerMinMax = 1 << 1, /* minInteger, maxInteger valid */ | |||||
kVstParameterUsesFloatStep = 1 << 2, /* stepFloat, smallStepFloat, largeStepFloat valid */ | |||||
kVstParameterUsesIntStep = 1 << 3, /* stepInteger, largeStepInteger valid */ | |||||
kVstParameterSupportsDisplayIndex = 1 << 4, /* displayIndex valid */ | |||||
kVstParameterSupportsDisplayCategory = 1 << 5, /* category, etc. valid */ | |||||
kVstParameterCanRamp = 1 << 6 /* set if parameter value can ramp up/down */ | |||||
}; | |||||
struct _AEffect | |||||
{ | |||||
// Never use virtual functions!!! | |||||
// 00-03 | |||||
int magic; | |||||
// dispatcher 04-07 | |||||
intptr_t (* dispatcher) (struct _AEffect *, int, int, intptr_t, void *, float); | |||||
// process, quite sure 08-0b | |||||
void (* process) (struct _AEffect *, float **, float **, int); | |||||
// setParameter 0c-0f | |||||
void (* setParameter) (struct _AEffect *, int, float); | |||||
// getParameter 10-13 | |||||
float (* getParameter) (struct _AEffect *, int); | |||||
// programs 14-17 | |||||
int numPrograms; | |||||
// Params 18-1b | |||||
int numParams; | |||||
// Input 1c-1f | |||||
int numInputs; | |||||
// Output 20-23 | |||||
int numOutputs; | |||||
// flags 24-27 | |||||
int flags; | |||||
// Fill somewhere 28-2b | |||||
void *ptr1; | |||||
void *ptr2; | |||||
// Zeroes 2c-2f 30-33 34-37 38-3b | |||||
char empty3[4 + 4 + 4]; | |||||
// 1.0f 3c-3f | |||||
float unkown_float; | |||||
// An object? pointer 40-43 | |||||
void *ptr3; | |||||
// Zeroes 44-47 | |||||
void *user; | |||||
// Id 48-4b | |||||
int32_t uniqueID; | |||||
// Don't know 4c-4f | |||||
char unknown1[4]; | |||||
// processReplacing 50-53 | |||||
void (* processReplacing) (struct _AEffect *, float **, float **, int); | |||||
}; | |||||
typedef struct _AEffect AEffect; | |||||
struct _VstTimeInfo | |||||
{ | |||||
// 00 | |||||
double samplePos; | |||||
// 08 | |||||
double sampleRate; | |||||
// unconfirmed 10 18 | |||||
char empty1[8 + 8]; | |||||
// 20? | |||||
double tempo; | |||||
// unconfirmed 28 30 38 | |||||
char empty2[8 + 8 + 8]; | |||||
// 40? | |||||
int timeSigNumerator; | |||||
// 44? | |||||
int timeSigDenominator; | |||||
// unconfirmed 48 4c 50 | |||||
char empty3[4 + 4 + 4]; | |||||
// 54 | |||||
int flags; | |||||
}; | |||||
typedef struct _VstTimeInfo VstTimeInfo; | |||||
typedef intptr_t (* audioMasterCallback) (AEffect *, int32_t, int32_t, intptr_t, void *, float); | |||||
#endif |
@@ -1,12 +0,0 @@ | |||||
dofile("../../../scripts/make-project.lua") | |||||
package = make_distrho_lv2_ui_project("GrooveJuice") | |||||
package.files = { | |||||
matchfiles ( | |||||
"../source/GrooveJuiceArtwork.cpp", | |||||
"../source/GrooveJuiceUI.cpp", | |||||
"../../../libs/distrho/DistrhoUIMain.cpp" | |||||
) | |||||
} |
@@ -1,11 +0,0 @@ | |||||
dofile("../../../scripts/make-project.lua") | |||||
package = make_distrho_lv2_project("GrooveJuice") | |||||
package.files = { | |||||
matchfiles ( | |||||
"../source/GrooveJuicePlugin.cpp", | |||||
"../../../libs/distrho/DistrhoPluginMain.cpp" | |||||
) | |||||
} |
@@ -1,14 +0,0 @@ | |||||
dofile("../../../scripts/make-project.lua") | |||||
package = make_distrho_vst_project("GrooveJuice") | |||||
package.files = { | |||||
matchfiles ( | |||||
"../source/GrooveJuiceArtwork.cpp", | |||||
"../source/GrooveJuicePlugin.cpp", | |||||
"../source/GrooveJuiceUI.cpp", | |||||
"../../../libs/distrho/DistrhoPluginMain.cpp", | |||||
"../../../libs/distrho/DistrhoUIMain.cpp" | |||||
) | |||||
} |
@@ -1,16 +0,0 @@ | |||||
cd ./LV2/ | |||||
make | |||||
cd .. | |||||
cd ./LV2-UI/ | |||||
make | |||||
cd .. | |||||
#sudo cp ../../bin/vst/PowerJuice.so /usr/lib/vst/ | |||||
#sudo cp -r ../../bin/lv2/GrooveJuice.lv2 /usr/lib/lv2 | |||||
export LV2_PATH="/home/andre/Documents/DISTRHO/bin/lv2" | |||||
exec jalv.gtk urn:distrho:GrooveJuice& | |||||
#sleep 1 | |||||
#jack_connect "PulseAudio JACK Sink:front-left" "PowerJuice:lv2_audio_in_1" | |||||
#jack_connect "PowerJuice:lv2_audio_out_1" "system:playback_1" | |||||
#jack_connect "PowerJuice:lv2_audio_out_1" "system:playback_2" | |||||
@@ -1,36 +0,0 @@ | |||||
/* | |||||
* Vector Juice Plugin | |||||
* Copyright (C) 2014 Andre Sklenar <andre.sklenar@gmail.com>, www.juicelab.cz | |||||
* | |||||
* 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 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. | |||||
* | |||||
* For a full copy of the GNU General Public License see the doc/GPL.txt file. | |||||
*/ | |||||
#ifndef DISTRHO_PLUGIN_INFO_H_INCLUDED | |||||
#define DISTRHO_PLUGIN_INFO_H_INCLUDED | |||||
#define DISTRHO_PLUGIN_NAME "GrooveJuice" | |||||
#define DISTRHO_PLUGIN_HAS_UI 1 | |||||
#define DISTRHO_PLUGIN_IS_SYNTH 1 | |||||
#define DISTRHO_PLUGIN_NUM_INPUTS 0 | |||||
#define DISTRHO_PLUGIN_NUM_OUTPUTS 2 | |||||
#define DISTRHO_PLUGIN_WANT_LATENCY 0 | |||||
#define DISTRHO_PLUGIN_WANT_PROGRAMS 1 | |||||
#define DISTRHO_PLUGIN_WANT_STATE 0 | |||||
#define DISTRHO_PLUGIN_WANT_TIMEPOS 1 | |||||
#define DISTRHO_PLUGIN_URI "urn:distrho:GrooveJuice" | |||||
#endif // DISTRHO_PLUGIN_INFO_H_INCLUDED |
@@ -1,80 +0,0 @@ | |||||
/* (Auto-generated binary data file). */ | |||||
#ifndef BINARY_GROOVEJUICEARTWORK_HPP | |||||
#define BINARY_GROOVEJUICEARTWORK_HPP | |||||
namespace GrooveJuiceArtwork | |||||
{ | |||||
extern const char* aboutData; | |||||
const unsigned int aboutDataSize = 180000; | |||||
const unsigned int aboutWidth = 300; | |||||
const unsigned int aboutHeight = 200; | |||||
extern const char* aboutButtonHoverData; | |||||
const unsigned int aboutButtonHoverDataSize = 5888; | |||||
const unsigned int aboutButtonHoverWidth = 92; | |||||
const unsigned int aboutButtonHoverHeight = 16; | |||||
extern const char* aboutButtonNormalData; | |||||
const unsigned int aboutButtonNormalDataSize = 5888; | |||||
const unsigned int aboutButtonNormalWidth = 92; | |||||
const unsigned int aboutButtonNormalHeight = 16; | |||||
extern const char* backgroundData; | |||||
const unsigned int backgroundDataSize = 1328592; | |||||
const unsigned int backgroundWidth = 712; | |||||
const unsigned int backgroundHeight = 622; | |||||
extern const char* knobData; | |||||
const unsigned int knobDataSize = 10404; | |||||
const unsigned int knobWidth = 51; | |||||
const unsigned int knobHeight = 51; | |||||
extern const char* knob2Data; | |||||
const unsigned int knob2DataSize = 14400; | |||||
const unsigned int knob2Width = 60; | |||||
const unsigned int knob2Height = 60; | |||||
extern const char* orbitData; | |||||
const unsigned int orbitDataSize = 4096; | |||||
const unsigned int orbitWidth = 32; | |||||
const unsigned int orbitHeight = 32; | |||||
extern const char* pageButtonHoverData; | |||||
const unsigned int pageButtonHoverDataSize = 5460; | |||||
const unsigned int pageButtonHoverWidth = 65; | |||||
const unsigned int pageButtonHoverHeight = 21; | |||||
extern const char* pageButtonNormalData; | |||||
const unsigned int pageButtonNormalDataSize = 5460; | |||||
const unsigned int pageButtonNormalWidth = 65; | |||||
const unsigned int pageButtonNormalHeight = 21; | |||||
extern const char* randomizeButtonHoverData; | |||||
const unsigned int randomizeButtonHoverDataSize = 7224; | |||||
const unsigned int randomizeButtonHoverWidth = 86; | |||||
const unsigned int randomizeButtonHoverHeight = 21; | |||||
extern const char* randomizeButtonNormalData; | |||||
const unsigned int randomizeButtonNormalDataSize = 7224; | |||||
const unsigned int randomizeButtonNormalWidth = 86; | |||||
const unsigned int randomizeButtonNormalHeight = 21; | |||||
extern const char* roundletData; | |||||
const unsigned int roundletDataSize = 2500; | |||||
const unsigned int roundletWidth = 25; | |||||
const unsigned int roundletHeight = 25; | |||||
extern const char* sliderData; | |||||
const unsigned int sliderDataSize = 2600; | |||||
const unsigned int sliderWidth = 26; | |||||
const unsigned int sliderHeight = 25; | |||||
extern const char* subOrbitData; | |||||
const unsigned int subOrbitDataSize = 3364; | |||||
const unsigned int subOrbitWidth = 29; | |||||
const unsigned int subOrbitHeight = 29; | |||||
} | |||||
#endif // BINARY_GROOVEJUICEARTWORK_HPP | |||||
@@ -1,621 +0,0 @@ | |||||
/* | |||||
* Vector Juice Plugin | |||||
* Copyright (C) 2014 Andre Sklenar <andre.sklenar@gmail.com>, www.juicelab.cz | |||||
* | |||||
* 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 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. | |||||
* | |||||
* For a full copy of the GNU General Public License see the doc/GPL.txt file. | |||||
*/ | |||||
#include "GrooveJuicePlugin.hpp" | |||||
START_NAMESPACE_DISTRHO | |||||
// ----------------------------------------------------------------------- | |||||
GrooveJuicePlugin::GrooveJuicePlugin() | |||||
: Plugin(paramCount, 1, 0) // 1 program, 0 states | |||||
{ | |||||
// set default values | |||||
d_setProgram(0); | |||||
// reset | |||||
d_deactivate(); | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
// Init | |||||
void GrooveJuicePlugin::d_initParameter(uint32_t index, Parameter& parameter) | |||||
{ | |||||
switch (index) | |||||
{ | |||||
case paramX: | |||||
parameter.hints = PARAMETER_IS_AUTOMABLE; | |||||
parameter.name = "X"; | |||||
parameter.symbol = "x"; | |||||
parameter.unit = ""; | |||||
parameter.ranges.def = 0.5f; | |||||
parameter.ranges.min = 0.0f; | |||||
parameter.ranges.max = 1.0f; | |||||
break; | |||||
case paramY: | |||||
parameter.hints = PARAMETER_IS_AUTOMABLE; | |||||
parameter.name = "Y"; | |||||
parameter.symbol = "y"; | |||||
parameter.unit = ""; | |||||
parameter.ranges.def = 0.5f; | |||||
parameter.ranges.min = 0.0f; | |||||
parameter.ranges.max = 1.0f; | |||||
break; | |||||
case paramOrbitSpeedX: | |||||
parameter.hints = PARAMETER_IS_AUTOMABLE; | |||||
parameter.name = "Orbit Speed X"; | |||||
parameter.symbol = ""; | |||||
parameter.unit = ""; | |||||
parameter.ranges.def = 4.0f; | |||||
parameter.ranges.min = 1.0f; | |||||
parameter.ranges.max = 128.0f; | |||||
break; | |||||
case paramOrbitSpeedY: | |||||
parameter.hints = PARAMETER_IS_AUTOMABLE; | |||||
parameter.name = "Orbit Speed Y"; | |||||
parameter.symbol = ""; | |||||
parameter.unit = ""; | |||||
parameter.ranges.def = 4.0f; | |||||
parameter.ranges.min = 1.0f; | |||||
parameter.ranges.max = 128.0f; | |||||
break; | |||||
case paramOrbitSizeX: | |||||
parameter.hints = PARAMETER_IS_AUTOMABLE; | |||||
parameter.name = "Orbit Size X"; | |||||
parameter.symbol = "osl"; | |||||
parameter.unit = ""; | |||||
parameter.ranges.def = 0.5f; | |||||
parameter.ranges.min = 0.0f; | |||||
parameter.ranges.max = 1.0f; | |||||
break; | |||||
case paramOrbitSizeY: | |||||
parameter.hints = PARAMETER_IS_AUTOMABLE; | |||||
parameter.name = "Orbit Size Y"; | |||||
parameter.symbol = "osr"; | |||||
parameter.unit = ""; | |||||
parameter.ranges.def = 0.5f; | |||||
parameter.ranges.min = 0.0f; | |||||
parameter.ranges.max = 1.0f; | |||||
break; | |||||
case paramSubOrbitSpeed: | |||||
parameter.hints = PARAMETER_IS_AUTOMABLE; | |||||
parameter.name = "SubOrbit Speed"; | |||||
parameter.symbol = ""; | |||||
parameter.unit = ""; | |||||
parameter.ranges.def = 32.0f; | |||||
parameter.ranges.min = 1.0f; | |||||
parameter.ranges.max = 128.0f; | |||||
break; | |||||
case paramSubOrbitSize: | |||||
parameter.hints = PARAMETER_IS_AUTOMABLE; | |||||
parameter.name = "SubOrbit Size"; | |||||
parameter.symbol = ""; | |||||
parameter.unit = ""; | |||||
parameter.ranges.def = 0.5f; | |||||
parameter.ranges.min = 0.0f; | |||||
parameter.ranges.max = 1.0f; | |||||
break; | |||||
case paramSubOrbitSmooth: | |||||
parameter.hints = PARAMETER_IS_AUTOMABLE; | |||||
parameter.name = "SubOrbit Wave"; | |||||
parameter.symbol = ""; | |||||
parameter.unit = ""; | |||||
parameter.ranges.def = 0.5f; | |||||
parameter.ranges.min = 0.0f; | |||||
parameter.ranges.max = 1.0f; | |||||
break; | |||||
case paramOrbitWaveX: | |||||
parameter.hints = PARAMETER_IS_AUTOMABLE; | |||||
parameter.name = "Orbit Wave X"; | |||||
parameter.symbol = ""; | |||||
parameter.unit = ""; | |||||
parameter.ranges.def = 3.0f; | |||||
parameter.ranges.min = 1.0f; | |||||
parameter.ranges.max = 4.0f; | |||||
break; | |||||
case paramOrbitPhaseX: | |||||
parameter.hints = PARAMETER_IS_AUTOMABLE; | |||||
parameter.name = "Orbit Phase X"; | |||||
parameter.symbol = ""; | |||||
parameter.unit = ""; | |||||
parameter.ranges.def = 0.0f; | |||||
parameter.ranges.min = 0.0f; | |||||
parameter.ranges.max = 1.0f; | |||||
break; | |||||
case paramOrbitPhaseY: | |||||
parameter.hints = PARAMETER_IS_AUTOMABLE; | |||||
parameter.name = "Orbit Phase Y"; | |||||
parameter.symbol = ""; | |||||
parameter.unit = ""; | |||||
parameter.ranges.def = 0.0f; | |||||
parameter.ranges.min = 0.0f; | |||||
parameter.ranges.max = 1.0f; | |||||
break; | |||||
case paramOrbitWaveY: | |||||
parameter.hints = PARAMETER_IS_AUTOMABLE; | |||||
parameter.name = "Orbit Wave Y"; | |||||
parameter.symbol = ""; | |||||
parameter.unit = ""; | |||||
parameter.ranges.def = 3.0f; | |||||
parameter.ranges.min = 1.0f; | |||||
parameter.ranges.max = 4.0f; | |||||
break; | |||||
case paramOrbitOutX: | |||||
parameter.hints = PARAMETER_IS_OUTPUT; | |||||
parameter.name = "Orbit X"; | |||||
parameter.symbol = "orx"; | |||||
parameter.unit = ""; | |||||
parameter.ranges.def = 0.5f; | |||||
parameter.ranges.min = 0.0f; | |||||
parameter.ranges.max = 1.0f; | |||||
break; | |||||
case paramOrbitOutY: | |||||
parameter.hints = PARAMETER_IS_OUTPUT; | |||||
parameter.name = "Orbit Y"; | |||||
parameter.symbol = "ory"; | |||||
parameter.unit = ""; | |||||
parameter.ranges.def = 0.5f; | |||||
parameter.ranges.min = 0.0f; | |||||
parameter.ranges.max = 1.0f; | |||||
break; | |||||
case paramSubOrbitOutX: | |||||
parameter.hints = PARAMETER_IS_OUTPUT; | |||||
parameter.name = "SubOrbit X"; | |||||
parameter.symbol = "sorx"; | |||||
parameter.unit = ""; | |||||
parameter.ranges.def = 0.5f; | |||||
parameter.ranges.min = 0.0f; | |||||
parameter.ranges.max = 1.0f; | |||||
break; | |||||
case paramSubOrbitOutY: | |||||
parameter.hints = PARAMETER_IS_OUTPUT; | |||||
parameter.name = "SubOrbit Y"; | |||||
parameter.symbol = "sory"; | |||||
parameter.unit = ""; | |||||
parameter.ranges.def = 0.5f; | |||||
parameter.ranges.min = 0.0f; | |||||
parameter.ranges.max = 1.0f; | |||||
break; | |||||
case paramW1Out: | |||||
parameter.hints = PARAMETER_IS_OUTPUT; | |||||
parameter.name = ""; | |||||
parameter.symbol = ""; | |||||
parameter.unit = ""; | |||||
parameter.ranges.def = 0.5f; | |||||
parameter.ranges.min = 0.0f; | |||||
parameter.ranges.max = 1.0f; | |||||
break; | |||||
case paramW2Out: | |||||
parameter.hints = PARAMETER_IS_OUTPUT; | |||||
parameter.name = ""; | |||||
parameter.symbol = ""; | |||||
parameter.unit = ""; | |||||
parameter.ranges.def = 0.5f; | |||||
parameter.ranges.min = 0.0f; | |||||
parameter.ranges.max = 1.0f; | |||||
break; | |||||
case paramMOut: | |||||
parameter.hints = PARAMETER_IS_OUTPUT; | |||||
parameter.name = ""; | |||||
parameter.symbol = ""; | |||||
parameter.unit = ""; | |||||
parameter.ranges.def = 0.5f; | |||||
parameter.ranges.min = 0.0f; | |||||
parameter.ranges.max = 1.0f; | |||||
break; | |||||
case paramCOut: | |||||
parameter.hints = PARAMETER_IS_OUTPUT; | |||||
parameter.name = ""; | |||||
parameter.symbol = ""; | |||||
parameter.unit = ""; | |||||
parameter.ranges.def = 0.5f; | |||||
parameter.ranges.min = 0.0f; | |||||
parameter.ranges.max = 1.0f; | |||||
break; | |||||
case paramROut: | |||||
parameter.hints = PARAMETER_IS_OUTPUT; | |||||
parameter.name = ""; | |||||
parameter.symbol = ""; | |||||
parameter.unit = ""; | |||||
parameter.ranges.def = 0.5f; | |||||
parameter.ranges.min = 0.0f; | |||||
parameter.ranges.max = 1.0f; | |||||
break; | |||||
case paramSOut: | |||||
parameter.hints = PARAMETER_IS_OUTPUT; | |||||
parameter.name = ""; | |||||
parameter.symbol = ""; | |||||
parameter.unit = ""; | |||||
parameter.ranges.def = 0.5f; | |||||
parameter.ranges.min = 0.0f; | |||||
parameter.ranges.max = 1.0f; | |||||
break; | |||||
case paramReOut: | |||||
parameter.hints = PARAMETER_IS_OUTPUT; | |||||
parameter.name = ""; | |||||
parameter.symbol = ""; | |||||
parameter.unit = ""; | |||||
parameter.ranges.def = 0.5f; | |||||
parameter.ranges.min = 0.0f; | |||||
parameter.ranges.max = 1.0f; | |||||
break; | |||||
case paramShOut: | |||||
parameter.hints = PARAMETER_IS_OUTPUT; | |||||
parameter.name = ""; | |||||
parameter.symbol = ""; | |||||
parameter.unit = ""; | |||||
parameter.ranges.def = 0.5f; | |||||
parameter.ranges.min = 0.0f; | |||||
parameter.ranges.max = 1.0f; | |||||
break; | |||||
} | |||||
if (index>=17 && index<17+64) { | |||||
//int x = (index-17)%8; | |||||
//int y = (x+1)/(index-17) | |||||
parameter.hints = PARAMETER_IS_AUTOMABLE; | |||||
parameter.name = "synth"; | |||||
parameter.symbol = ""; | |||||
parameter.unit = ""; | |||||
parameter.ranges.def = 0.5f; | |||||
parameter.ranges.min = 0.0f; | |||||
parameter.ranges.max = 1.0f; | |||||
} | |||||
} | |||||
void GrooveJuicePlugin::d_initProgramName(uint32_t index, d_string& programName) | |||||
{ | |||||
if (index != 0) | |||||
return; | |||||
programName = "Default"; | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
// Internal data | |||||
float GrooveJuicePlugin::d_getParameterValue(uint32_t index) const | |||||
{ | |||||
if (index<17 || index>=17+64) { | |||||
switch (index) | |||||
{ | |||||
case paramX: | |||||
return x; | |||||
case paramY: | |||||
return y; | |||||
case paramOrbitSizeX: | |||||
return orbitSizeX; | |||||
case paramOrbitSizeY: | |||||
return orbitSizeY; | |||||
case paramOrbitSpeedX: | |||||
return orbitSpeedX; | |||||
case paramOrbitSpeedY: | |||||
return orbitSpeedY; | |||||
case paramSubOrbitSpeed: | |||||
return subOrbitSpeed; | |||||
case paramSubOrbitSize: | |||||
return subOrbitSize; | |||||
case paramOrbitOutX: | |||||
return orbitX; | |||||
case paramOrbitOutY: | |||||
return orbitY; | |||||
case paramSubOrbitOutX: | |||||
return subOrbitX; | |||||
case paramSubOrbitOutY: | |||||
return subOrbitY; | |||||
case paramSubOrbitSmooth: | |||||
return subOrbitSmooth; | |||||
case paramOrbitWaveX: | |||||
return orbitWaveX; | |||||
case paramOrbitWaveY: | |||||
return orbitWaveY; | |||||
case paramOrbitPhaseX: | |||||
return orbitPhaseY; | |||||
case paramOrbitPhaseY: | |||||
return orbitPhaseY; | |||||
case paramW1Out: | |||||
return synthSound[0]; | |||||
case paramW2Out: | |||||
return synthSound[1]; | |||||
case paramMOut: | |||||
return synthSound[2]; | |||||
case paramCOut: | |||||
return synthSound[3]; | |||||
case paramROut: | |||||
return synthSound[4]; | |||||
case paramSOut: | |||||
return synthSound[5]; | |||||
case paramReOut: | |||||
return synthSound[6]; | |||||
case paramShOut: | |||||
return synthSound[7]; | |||||
default: | |||||
return 0.0f; | |||||
} | |||||
} else { | |||||
int num = (index-17); //synth params begin on #17 | |||||
int x = num%8; //synth param | |||||
//synth page | |||||
int y = (num-(num%8))/8; | |||||
return synthData[x][y]; | |||||
} | |||||
} | |||||
void GrooveJuicePlugin::d_setParameterValue(uint32_t index, float value) | |||||
{ | |||||
if (index<17) { | |||||
switch (index) | |||||
{ | |||||
case paramX: | |||||
x = value; | |||||
break; | |||||
case paramY: | |||||
y = value; | |||||
break; | |||||
case paramOrbitSpeedX: | |||||
orbitSpeedX = value; | |||||
resetPhase(); | |||||
break; | |||||
case paramOrbitSpeedY: | |||||
orbitSpeedY = value; | |||||
resetPhase(); | |||||
break; | |||||
case paramOrbitSizeX: | |||||
orbitSizeX = value; | |||||
break; | |||||
case paramOrbitSizeY: | |||||
orbitSizeY = value; | |||||
break; | |||||
case paramSubOrbitSpeed: | |||||
subOrbitSpeed = value; | |||||
resetPhase(); | |||||
break; | |||||
case paramSubOrbitSize: | |||||
subOrbitSize = value; | |||||
break; | |||||
case paramSubOrbitSmooth: | |||||
subOrbitSmooth = value; | |||||
break; | |||||
case paramOrbitWaveX: | |||||
orbitWaveX = value; | |||||
break; | |||||
case paramOrbitWaveY: | |||||
orbitWaveY = value; | |||||
break; | |||||
case paramOrbitPhaseX: | |||||
orbitPhaseX = value; | |||||
resetPhase(); | |||||
break; | |||||
case paramOrbitPhaseY: | |||||
orbitPhaseY = value; | |||||
resetPhase(); | |||||
break; | |||||
} | |||||
} else { | |||||
int num = (index-17); //synth params begin on #17 | |||||
int x = num%8; //synth param | |||||
//synth page | |||||
int y = (num-(num%8))/8; | |||||
synthData[x][y] = value; | |||||
} | |||||
} | |||||
void GrooveJuicePlugin::d_setProgram(uint32_t index) | |||||
{ | |||||
if (index != 0) | |||||
return; | |||||
/* Default parameter values */ | |||||
x = 0.5f; | |||||
y = 0.5f; | |||||
orbitSpeedX = 4.0f; | |||||
orbitSpeedY = 4.0f; | |||||
orbitSizeX = 0.5f; | |||||
orbitSizeY = 0.5f; | |||||
subOrbitSize = 0.5f; | |||||
subOrbitSpeed = 32.0f; | |||||
orbitWaveX = 3.0f; | |||||
orbitWaveY = 3.0f; | |||||
subOrbitSmooth = 0.5f; | |||||
orbitPhaseX = 0.0f; | |||||
orbitPhaseY = 0.0f; | |||||
/* Default variable values */ | |||||
orbitX=orbitY=orbitTX=orbitTY=0.5; | |||||
subOrbitX=subOrbitY=subOrbitTX=subOrbitTY=0; | |||||
interpolationDivider=200; | |||||
bar=tickX=tickY=percentageX=percentageY=tickOffsetX=0; | |||||
tickOffsetY=sinePosX=sinePosY=tick=percentage=tickOffset=sinePos=0; | |||||
waveBlend=0; | |||||
synthL.setSampleRate(d_getSampleRate()); | |||||
synthR.setSampleRate(d_getSampleRate()); | |||||
//parameter smoothing | |||||
for (int i=0; i<2; i++) { | |||||
sA[i] = 0.99f; | |||||
sB[i] = 1.f - sA[i]; | |||||
sZ[i] = 0; | |||||
} | |||||
for (int x=0; x<8; x++) | |||||
for (int y=0; y<8; y++) | |||||
synthData[x][y] = 0.5; | |||||
/* reset filter values */ | |||||
d_activate(); | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
// Process | |||||
void GrooveJuicePlugin::d_activate() | |||||
{ | |||||
//sinePos = 0; | |||||
} | |||||
void GrooveJuicePlugin::d_deactivate() | |||||
{ | |||||
// all values to zero | |||||
} | |||||
void GrooveJuicePlugin::d_run(float**, float** outputs, uint32_t frames, const MidiEvent* midiEvents, uint32_t midiEventCount) | |||||
{ | |||||
float out1, out2, tX, tY; | |||||
/* | |||||
out1 = inputs[0][i]*tN(1-std::sqrt((tX*tX)+(tY*tY))); | |||||
out2 = inputs[1][i]*tN(1-std::sqrt((tX*tX)+(tY*tY))); | |||||
out1 += inputs[2][i]*tN(1-std::sqrt(((1-tX)*(1-tX))+(tY*tY))); | |||||
out2 += inputs[3][i]*tN(1-std::sqrt(((1-tX)*(1-tX))+(tY*tY))); | |||||
out1 += inputs[4][i]*tN(1-std::sqrt(((1-tX)*(1-tX))+((1-tY)*(1-tY)))); | |||||
out2 += inputs[5][i]*tN(1-std::sqrt(((1-tX)*(1-tX))+((1-tY)*(1-tY)))); | |||||
out1 += inputs[6][i]*tN(1-std::sqrt((tX*tX)+((1-tY)*(1-tY)))); | |||||
out2 += inputs[7][i]*tN(1-std::sqrt((tX*tX)+((1-tY)*(1-tY)))); | |||||
*/ | |||||
for (uint32_t i = 0; i<frames; i++) { | |||||
animate(); | |||||
tX = subOrbitX; | |||||
tY = subOrbitY; | |||||
//sum values | |||||
float c = 0.41421f; //mid segment | |||||
float d = c/1.41f; //side segments | |||||
float distances[8]; | |||||
distances[0] = distance(d, 0, tX, tY); | |||||
distances[1] = distance(c+d, 0, tX, tY); | |||||
distances[2] = distance(1, d, tX, tY); | |||||
distances[3] = distance(1, c+d, tX, tY); | |||||
distances[4] = distance(d, 1, tX, tY); | |||||
distances[5] = distance(c+d, 1, tX, tY); | |||||
distances[6] = distance(0, d, tX, tY); | |||||
distances[7] = distance(0, c+d, tX, tY); | |||||
//std::cout << distances[0] << " "; | |||||
//std::cout << tX << std::endl; | |||||
for (int x=0; x<8; x++) { | |||||
float targetValue = 0; | |||||
for (int y=0; y<8; y++) { | |||||
targetValue += synthData[x][y]*(distances[y]); | |||||
} | |||||
synthSound[x] = tN(targetValue); | |||||
} | |||||
//printf("wave1: %f\n", synthSound[0]); | |||||
//std::cout << synthSound[0] << std::endl; | |||||
synthL.setWave(0, synthSound[0]); | |||||
synthR.setWave(0, synthSound[0]); | |||||
synthL.setWave(1, synthSound[1]); | |||||
synthR.setWave(1, synthSound[1]); | |||||
synthL.setMix(synthSound[2]); | |||||
synthR.setMix(synthSound[2]); | |||||
//synthL.setCut(synthSound[3]); | |||||
//synthR.setCut(synthSound[3]); | |||||
//synthL.setReso(synthSound[4]); | |||||
//synthR.setReso(synthSound[4]); | |||||
//synthL.setDecay(synthSound[5]); | |||||
//synthR.setDecay(synthSound[5]); | |||||
synthL.setSustain(synthSound[5]); | |||||
synthR.setSustain(synthSound[5]); | |||||
synthL.setRelease(synthSound[6]); | |||||
synthR.setRelease(synthSound[6]); | |||||
synthL.setStereo(-0.5); | |||||
synthR.setStereo(0.5); | |||||
synthL.setShape(synthSound[7]); | |||||
synthR.setShape(synthSound[7]); | |||||
float cutoff = std::exp((std::log(16000)-std::log(500))*synthSound[3]+std::log(500)); | |||||
filterL.recalc(cutoff, synthSound[4]*0.8, d_getSampleRate(), synthSound[7]); | |||||
filterR.recalc(cutoff, synthSound[4]*0.8, d_getSampleRate(), synthSound[7]); | |||||
outputs[0][i] = filterL.process(synthL.run()); | |||||
outputs[1][i] = filterR.process(synthL.run()); | |||||
} | |||||
//outputs = buffer; | |||||
for (uint32_t i = 0; i<midiEventCount; i++) { | |||||
int mType = midiEvents[i].buf[0] & 0xF0; | |||||
//int mChan = midiEvents[i].buf[0] & 0x0F; | |||||
int mNum = midiEvents[i].buf[1]; | |||||
if (mType == 0x90) { | |||||
//note on | |||||
synthL.play(mNum); | |||||
synthR.play(mNum); | |||||
} else if (mType == 0x80) { | |||||
//note off | |||||
synthL.stop(mNum); | |||||
synthR.stop(mNum); | |||||
} | |||||
} | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
Plugin* createPlugin() | |||||
{ | |||||
return new GrooveJuicePlugin(); | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
END_NAMESPACE_DISTRHO |