Browse Source

Update DISRHO libs

tags/1.9.4
falkTX 10 years ago
parent
commit
03ecf76874
84 changed files with 9936 additions and 650 deletions
  1. +14
    -4
      source/modules/dgl/App.hpp
  2. +3
    -1
      source/modules/dgl/Base.hpp
  3. +105
    -41
      source/modules/dgl/CairoWidget.hpp
  4. +0
    -0
      source/modules/dgl/Geometry.hpp
  5. +5
    -3
      source/modules/dgl/Image.hpp
  6. +0
    -0
      source/modules/dgl/ImageAboutWindow.hpp
  7. +0
    -0
      source/modules/dgl/ImageButton.hpp
  8. +0
    -0
      source/modules/dgl/ImageKnob.hpp
  9. +0
    -0
      source/modules/dgl/ImageSlider.hpp
  10. +16
    -16
      source/modules/dgl/Makefile
  11. +0
    -0
      source/modules/dgl/StandaloneWindow.hpp
  12. +11
    -5
      source/modules/dgl/Widget.hpp
  13. +4
    -5
      source/modules/dgl/Window.hpp
  14. +27
    -5
      source/modules/dgl/src/App.cpp
  15. +0
    -0
      source/modules/dgl/src/Base.cpp
  16. +0
    -0
      source/modules/dgl/src/Geometry.cpp
  17. +62
    -9
      source/modules/dgl/src/Image.cpp
  18. +5
    -10
      source/modules/dgl/src/ImageAboutWindow.cpp
  19. +0
    -0
      source/modules/dgl/src/ImageButton.cpp
  20. +4
    -4
      source/modules/dgl/src/ImageKnob.cpp
  21. +0
    -0
      source/modules/dgl/src/ImageSlider.cpp
  22. +3
    -8
      source/modules/dgl/src/Widget.cpp
  23. +159
    -66
      source/modules/dgl/src/Window.cpp
  24. +10
    -6
      source/modules/dgl/src/pugl/copy/pugl.h
  25. +17
    -0
      source/modules/dgl/src/pugl/copy/pugl_internal.h
  26. +25
    -1
      source/modules/dgl/src/pugl/copy/pugl_osx.m
  27. +18
    -5
      source/modules/dgl/src/pugl/copy/pugl_win.cpp
  28. +44
    -61
      source/modules/dgl/src/pugl/copy/pugl_x11.c
  29. +357
    -0
      source/modules/dgl/src/pugl/pugl.h
  30. +161
    -0
      source/modules/dgl/src/pugl/pugl_internal.h
  31. +117
    -0
      source/modules/dgl/src/pugl/pugl_osx.diff
  32. +459
    -0
      source/modules/dgl/src/pugl/pugl_osx.m
  33. +9
    -1
      source/modules/dgl/src/pugl/pugl_osx_extended.h
  34. +15
    -8
      source/modules/dgl/src/pugl/pugl_osx_extended.m
  35. +387
    -0
      source/modules/dgl/src/pugl/pugl_win.cpp
  36. +397
    -0
      source/modules/dgl/src/pugl/pugl_x11.c
  37. +27
    -3
      source/modules/distrho/DistrhoPlugin.hpp
  38. +1
    -1
      source/modules/distrho/DistrhoUI.hpp
  39. +2
    -2
      source/modules/distrho/DistrhoUtils.hpp
  40. +3
    -1
      source/modules/distrho/src/DistrhoDefines.h
  41. +2
    -6
      source/modules/distrho/src/DistrhoPluginInternal.hpp
  42. +169
    -7
      source/modules/distrho/src/DistrhoPluginLV2.cpp
  43. +29
    -1
      source/modules/distrho/src/DistrhoPluginVST.cpp
  44. +0
    -3
      source/modules/distrho/src/DistrhoUIDSSI.cpp
  45. +2
    -2
      source/modules/distrho/src/DistrhoUIInternal.hpp
  46. +0
    -365
      source/modules/distrho/src/_todo/DistrhoPluginJACK.cpp
  47. +441
    -0
      source/modules/distrho/src/dssi/dssi.h
  48. +272
    -0
      source/modules/distrho/src/dssi/seq_event-compat.h
  49. +603
    -0
      source/modules/distrho/src/ladspa/ladspa.h
  50. +619
    -0
      source/modules/distrho/src/lv2/atom-forge.h
  51. +255
    -0
      source/modules/distrho/src/lv2/atom-helpers.h
  52. +401
    -0
      source/modules/distrho/src/lv2/atom-util.h
  53. +246
    -0
      source/modules/distrho/src/lv2/atom.h
  54. +30
    -0
      source/modules/distrho/src/lv2/buf-size.h
  55. +63
    -0
      source/modules/distrho/src/lv2/data-access.h
  56. +144
    -0
      source/modules/distrho/src/lv2/dynmanifest.h
  57. +263
    -0
      source/modules/distrho/src/lv2/event-helpers.h
  58. +294
    -0
      source/modules/distrho/src/lv2/event.h
  59. +37
    -0
      source/modules/distrho/src/lv2/instance-access.h
  60. +99
    -0
      source/modules/distrho/src/lv2/log.h
  61. +145
    -0
      source/modules/distrho/src/lv2/logger.h
  62. +98
    -0
      source/modules/distrho/src/lv2/lv2-midifunctions.h
  63. +175
    -0
      source/modules/distrho/src/lv2/lv2-miditype.h
  64. +454
    -0
      source/modules/distrho/src/lv2/lv2.h
  65. +107
    -0
      source/modules/distrho/src/lv2/lv2_external_ui.h
  66. +174
    -0
      source/modules/distrho/src/lv2/lv2_programs.h
  67. +105
    -0
      source/modules/distrho/src/lv2/lv2_rtmempool.h
  68. +226
    -0
      source/modules/distrho/src/lv2/midi.h
  69. +34
    -0
      source/modules/distrho/src/lv2/morph.h
  70. +132
    -0
      source/modules/distrho/src/lv2/options.h
  71. +49
    -0
      source/modules/distrho/src/lv2/parameters.h
  72. +55
    -0
      source/modules/distrho/src/lv2/patch.h
  73. +64
    -0
      source/modules/distrho/src/lv2/port-groups.h
  74. +42
    -0
      source/modules/distrho/src/lv2/port-props.h
  75. +34
    -0
      source/modules/distrho/src/lv2/presets.h
  76. +72
    -0
      source/modules/distrho/src/lv2/resize-port.h
  77. +352
    -0
      source/modules/distrho/src/lv2/state.h
  78. +49
    -0
      source/modules/distrho/src/lv2/time.h
  79. +407
    -0
      source/modules/distrho/src/lv2/ui.h
  80. +62
    -0
      source/modules/distrho/src/lv2/units.h
  81. +98
    -0
      source/modules/distrho/src/lv2/uri-map.h
  82. +129
    -0
      source/modules/distrho/src/lv2/urid.h
  83. +158
    -0
      source/modules/distrho/src/lv2/worker.h
  84. +279
    -0
      source/modules/distrho/src/vestige/aeffectx.h

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

@@ -28,6 +28,13 @@ class Window;
class App
{
public:
class IdleCallback
{
public:
~IdleCallback() {}
virtual void idleCallback() = 0;
};

App();
~App();

@@ -36,15 +43,18 @@ public:
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();
void _addWindow(Window* const window);
void _removeWindow(Window* const window);
void _oneShown();
void _oneHidden();
};

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

source/modules/distrho/dgl/Base.hpp → source/modules/dgl/Base.hpp View File

@@ -39,8 +39,10 @@
#endif

#ifndef PROPER_CPP11_SUPPORT
# ifndef __clang__
# define noexcept throw()
# endif
# define override
# define noexcept throw()
# define nullptr (0)
#endif


source/modules/distrho/dgl/CairoWidget.hpp → source/modules/dgl/CairoWidget.hpp View File

@@ -21,6 +21,8 @@

#include <cairo.h>

#include <cstdio>

START_NAMESPACE_DGL

// -----------------------------------------------------------------------
@@ -36,56 +38,63 @@ public:
{
}

protected:
virtual void cairoDisplay(cairo_t* const context) = 0;

private:
void onReshape(int width, int height) override
virtual void setWidth(int width) override
{
// handle resize
setSize(width, height);
Widget::onReshape(width, height);
if (fArea.getWidth() == width)
return;

// free previous if needed
onClose();
Widget::setWidth(width);
_recreateSurface();
}

// create new
fSurface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, width, height);
fContext = cairo_create(fSurface);
virtual void setHeight(int height) override
{
if (fArea.getHeight() == height)
return;

glGenTextures(1, &fTextureId);
Widget::setHeight(height);
_recreateSurface();
}

void onClose() override
virtual void setSize(const Size<int>& size) override
{
if (fContext != nullptr)
{
cairo_destroy(fContext);
fContext = nullptr;
}
if (fArea.getSize() == size)
return;

if (fSurface != nullptr)
{
cairo_surface_destroy(fSurface);
fSurface = nullptr;
}
Widget::setSize(size);
_recreateSurface();
}

if (fTextureId != 0)
{
glDeleteTextures(1, &fTextureId);
fTextureId = 0;
}
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 first resize
// wait for sizing
if (fSurface == nullptr || fContext == nullptr)
{
glClear(GL_COLOR_BUFFER_BIT);
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();

@@ -108,25 +117,80 @@ private:
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, surfaceData);

// draw the texture
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glBegin(GL_QUADS);
glTexCoord2i(0, height);
glVertex2i(0, height);
// 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();

glTexCoord2i(width, height);
glVertex2i(width, height);
glBegin(GL_QUADS);
//glTexCoord2i(x, y);
glTexCoord2i(0, 0);
glVertex2i(x, y);

//glTexCoord2i(x+width, y);
glTexCoord2i(width, 0);
glVertex2i(width, 0);
glVertex2i(x+width, y);

glTexCoord2i(0, 0);
glVertex2i(0, 0);
//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:

source/modules/distrho/dgl/Geometry.hpp → source/modules/dgl/Geometry.hpp View File


source/modules/distrho/dgl/Image.hpp → source/modules/dgl/Image.hpp View File

@@ -30,6 +30,7 @@ public:
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;
@@ -44,9 +45,9 @@ public:
GLenum getFormat() const noexcept;
GLenum getType() const noexcept;

void draw() const;
void draw(int x, int y) const;
void draw(const Point<int>& pos) const;
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;
@@ -57,6 +58,7 @@ private:
Size<int> fSize;
GLenum fFormat;
GLenum fType;
GLuint fTextureId;
};

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

source/modules/distrho/dgl/ImageAboutWindow.hpp → source/modules/dgl/ImageAboutWindow.hpp View File


source/modules/distrho/dgl/ImageButton.hpp → source/modules/dgl/ImageButton.hpp View File


source/modules/distrho/dgl/ImageKnob.hpp → source/modules/dgl/ImageKnob.hpp View File


source/modules/distrho/dgl/ImageSlider.hpp → source/modules/dgl/ImageSlider.hpp View File


source/modules/distrho/dgl/Makefile → source/modules/dgl/Makefile View File

@@ -4,7 +4,7 @@
# Created by falkTX
#

include ../../../Makefile.mk
include ../Makefile.mk

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

@@ -80,42 +80,42 @@ endif

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

all: ../../dgl.a
all: ../dgl.a

posix32: ../../dgl.posix32.a
posix64: ../../dgl.posix64.a
win32: ../../dgl.win32.a
win64: ../../dgl.win64.a
posix32: ../dgl.posix32.a
posix64: ../dgl.posix64.a
win32: ../dgl.win32.a
win64: ../dgl.win64.a

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

../../dgl.a: $(OBJS)
../dgl.a: $(OBJS)
$(RM) $@
$(AR) crs $@ $^

../../dgl.posix32.a: $(OBJS_posix32)
../dgl.posix32.a: $(OBJS_posix32)
$(RM) $@
$(AR) crs $@ $^

../../dgl.posix64.a: $(OBJS_posix64)
../dgl.posix64.a: $(OBJS_posix64)
$(RM) $@
$(AR) crs $@ $^

../../dgl.win32.a: $(OBJS_win32)
../dgl.win32.a: $(OBJS_win32)
$(RM) $@
$(AR) crs $@ $^

../../dgl.win64.a: $(OBJS_win64)
../dgl.win64.a: $(OBJS_win64)
$(RM) $@
$(AR) crs $@ $^

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

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

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

# --------------------------------------------------------------
@@ -136,12 +136,12 @@ win64: ../../dgl.win64.a
$(CXX) $< $(BUILD_CXX_FLAGS) $(64BIT_FLAGS) -c -o $@

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

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

clean:
$(RM) src/*.o src/pugl/*.o ../../dgl*.a ../../libdgl.*
$(RM) src/*.o src/pugl/*.o ../dgl*.a ../libdgl.*

debug:
$(MAKE) DEBUG=true

source/modules/distrho/dgl/StandaloneWindow.hpp → source/modules/dgl/StandaloneWindow.hpp View File


source/modules/distrho/dgl/Widget.hpp → source/modules/dgl/Widget.hpp View File

@@ -60,10 +60,15 @@ public:
int getHeight() const noexcept;
const Size<int>& getSize() const noexcept;

void setWidth(int width);
void setHeight(int height);
void setSize(int width, int height);
void setSize(const Size<int>& size);
// 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;

@@ -80,7 +85,7 @@ protected:
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(float dx, float dy);
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();
@@ -90,6 +95,7 @@ private:
bool fVisible;
Rectangle<int> fArea;

friend class CairoWidget;
friend class Window;
};


source/modules/distrho/dgl/Window.hpp → source/modules/dgl/Window.hpp View File

@@ -46,7 +46,6 @@ public:
void exec(bool lockWait = false);

void focus();
void idle();
void repaint();

bool isVisible() const noexcept;
@@ -55,11 +54,9 @@ public:
bool isResizable() const noexcept;
void setResizable(bool yesNo);

#ifndef DGL_OS_MAC
int getWidth() const noexcept;
int getHeight() const noexcept;
Size<int> getSize() const noexcept;
#endif
void setSize(unsigned int width, unsigned int height);

void setTitle(const char* title);
@@ -72,10 +69,12 @@ public:
private:
class PrivateData;
PrivateData* const pData;
friend class App;
friend class Widget;

void addWidget(Widget* const widget);
void removeWidget(Widget* const widget);
void _addWidget(Widget* const widget);
void _removeWidget(Widget* const widget);
void _idle();
};

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

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

@@ -27,6 +27,7 @@ struct App::PrivateData {
bool doLoop;
unsigned visibleWindows;
std::list<Window*> windows;
std::list<IdleCallback*> idleCallbacks;

PrivateData()
: doLoop(false),
@@ -43,6 +44,7 @@ App::App()
App::~App()
{
pData->windows.clear();
pData->idleCallbacks.clear();
delete pData;
}

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

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

@@ -82,25 +90,39 @@ bool App::isQuiting() const

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

void App::addWindow(Window* const window)
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)
void App::_removeWindow(Window* const window)
{
if (window != nullptr)
pData->windows.remove(window);
}

void App::oneShown()
void App::_oneShown()
{
if (++pData->visibleWindows == 1)
pData->doLoop = true;
}

void App::oneHidden()
void App::_oneHidden()
{
if (--pData->visibleWindows == 0)
pData->doLoop = false;

source/modules/distrho/dgl/src/Base.cpp → source/modules/dgl/src/Base.cpp View File


source/modules/distrho/dgl/src/Geometry.cpp → source/modules/dgl/src/Geometry.cpp View File


source/modules/distrho/dgl/src/Image.cpp → source/modules/dgl/src/Image.cpp View File

@@ -24,7 +24,8 @@ Image::Image() noexcept
: fRawData(nullptr),
fSize(0, 0),
fFormat(0),
fType(0)
fType(0),
fTextureId(0)
{
}

@@ -32,7 +33,8 @@ Image::Image(const char* rawData, int width, int height, GLenum format, GLenum t
: fRawData(rawData),
fSize(width, height),
fFormat(format),
fType(type)
fType(type),
fTextureId(0)
{
}

@@ -40,7 +42,8 @@ Image::Image(const char* rawData, const Size<int>& size, GLenum format, GLenum t
: fRawData(rawData),
fSize(size),
fFormat(format),
fType(type)
fType(type),
fTextureId(0)
{
}

@@ -48,10 +51,20 @@ Image::Image(const Image& image) noexcept
: fRawData(image.fRawData),
fSize(image.fSize),
fFormat(image.fFormat),
fType(image.fType)
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);
@@ -100,27 +113,67 @@ GLenum Image::getType() const noexcept
return fType;
}

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

void Image::draw(int x, int y) const
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);
glRasterPos2i(x, fSize.getHeight()+y);
glDrawPixels(fSize.getWidth(), fSize.getHeight(), fFormat, fType, fRawData);
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) const
void Image::draw(const Point<int>& pos)
{
draw(pos.getX(), pos.getY());
}

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

Image& Image::operator=(const Image& image) noexcept
{
fRawData = image.fRawData;

source/modules/distrho/dgl/src/ImageAboutWindow.cpp → source/modules/dgl/src/ImageAboutWindow.cpp View File

@@ -16,13 +16,6 @@

#include "../ImageAboutWindow.hpp"

// FIXME: 32bit hack
#if ! (defined (__LP64__) || defined (_LP64) || defined(WIN64) || defined(_WIN64) || defined(__WIN64__))
# define PAD_SIZE +1
#else
# define PAD_SIZE
#endif

START_NAMESPACE_DGL

// -----------------------------------------------------------------------
@@ -32,7 +25,8 @@ ImageAboutWindow::ImageAboutWindow(App& app, Window& parent, const Image& image)
Widget((Window&)*this),
fImgBackground(image)
{
Window::setSize(image.getWidth(), image.getHeight() PAD_SIZE);
Window::setResizable(false);
Window::setSize(image.getWidth(), image.getHeight());
Window::setTitle("About");
}

@@ -41,14 +35,15 @@ ImageAboutWindow::ImageAboutWindow(Widget* widget, const Image& image)
Widget((Window&)*this),
fImgBackground(image)
{
Window::setSize(image.getWidth(), image.getHeight() PAD_SIZE);
Window::setResizable(false);
Window::setSize(image.getWidth(), image.getHeight());
Window::setTitle("About");
}

void ImageAboutWindow::setImage(const Image& image)
{
fImgBackground = image;
Window::setSize(image.getWidth(), image.getHeight() PAD_SIZE);
Window::setSize(image.getWidth(), image.getHeight());
}

void ImageAboutWindow::onDisplay()

source/modules/distrho/dgl/src/ImageButton.cpp → source/modules/dgl/src/ImageButton.cpp View File


source/modules/distrho/dgl/src/ImageKnob.cpp → source/modules/dgl/src/ImageKnob.cpp View File


source/modules/distrho/dgl/src/ImageSlider.cpp → source/modules/dgl/src/ImageSlider.cpp View File


source/modules/distrho/dgl/src/Widget.cpp → source/modules/dgl/src/Widget.cpp View File

@@ -29,12 +29,12 @@ Widget::Widget(Window& parent)
: fParent(parent),
fVisible(true)
{
fParent.addWidget(this);
fParent._addWidget(this);
}

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

bool Widget::isVisible() const noexcept
@@ -153,11 +153,6 @@ void Widget::setHeight(int height)
fParent.repaint();
}

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

void Widget::setSize(const Size<int>& size)
{
if (fArea.getSize() == size)
@@ -212,7 +207,7 @@ bool Widget::onMotion(int, int)
return false;
}

bool Widget::onScroll(float, float)
bool Widget::onScroll(int, int, float, float)
{
return false;
}

source/modules/distrho/dgl/src/Window.cpp → source/modules/dgl/src/Window.cpp View File

@@ -19,6 +19,7 @@
#include "../Window.hpp"

#include <cassert>
#include <cstdio>
#include <list>

#include "pugl/pugl.h"
@@ -26,9 +27,12 @@
#if DGL_OS_WINDOWS
# include "pugl/pugl_win.cpp"
#elif DGL_OS_MAC
extern "C" {
# include "pugl/pugl_osx_extended.h"
}
extern "C" {
struct PuglViewImpl {
int width;
int height;
};}
#elif DGL_OS_LINUX
extern "C" {
# include "pugl/pugl_x11.c"
@@ -43,6 +47,16 @@ extern "C" {
#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;
@@ -60,6 +74,7 @@ public:
fFirstInit(true),
fVisible(false),
fResizable(true),
fUsingEmbed(false),
#if DGL_OS_WINDOWS
hwnd(0)
#elif DGL_OS_LINUX
@@ -69,6 +84,7 @@ public:
_dummy('\0')
#endif
{
DBG("Creating window without parent..."); DBGF;
init();
}

@@ -79,6 +95,7 @@ public:
fFirstInit(true),
fVisible(false),
fResizable(true),
fUsingEmbed(false),
fModal(parent.pData),
#if DGL_OS_WINDOWS
hwnd(0)
@@ -89,13 +106,13 @@ public:
_dummy('\0')
#endif
{
DBG("Creating window with parent..."); DBGF;
init();

#if DGL_OS_LINUX
PuglInternals* const parentImpl = parent.pData->fView->impl;
const PuglInternals* const parentImpl(parent.pData->fView->impl);

XSetTransientForHint(xDisplay, xWindow, parentImpl->win);
XFlush(xDisplay);
#endif
}

@@ -106,6 +123,7 @@ public:
fFirstInit(true),
fVisible(true),
fResizable(false),
fUsingEmbed(true),
#if DGL_OS_WINDOWS
hwnd(0)
#elif DGL_OS_LINUX
@@ -115,17 +133,22 @@ public:
_dummy('\0')
#endif
{
DBG("Creating embedded window..."); DBGF;
init();

// starts visible
fApp.oneShown();
DBG("NOTE: Embed window is always visible and non-resizable\n");
fApp._oneShown();
fFirstInit = false;
}

void init()
{
if (fView == nullptr)
if (fSelf == nullptr || fView == nullptr)
{
DBG("Failed!\n");
dgl_lastUiParent = nullptr;
return;
}

dgl_lastUiParent = fSelf;

@@ -142,47 +165,73 @@ public:
#if DGL_OS_WINDOWS
PuglInternals* impl = fView->impl;
hwnd = impl->hwnd;
assert(hwnd != 0);
#elif DGL_OS_LINUX
PuglInternals* impl = fView->impl;
xDisplay = impl->display;
xWindow = impl->win;
assert(xWindow != 0);
#endif

fApp.addWindow(fSelf);
DBG("Success!\n");

// process any initial events
puglProcessEvents(fView);

fApp._addWindow(fSelf);
}

~PrivateData()
{
DBG("Destroying window..."); DBGF;

//fOnModal = false;
fWidgets.clear();

if (fSelf != nullptr)
{
fApp._removeWindow(fSelf);
fSelf = nullptr;
}

if (fView != nullptr)
{
fApp.removeWindow(fSelf);
puglDestroy(fView);
fView = nullptr;
}

#if DGL_OS_WINDOWS
hwnd = 0;
#elif DGL_OS_LINUX
xDisplay = nullptr;
xWindow = 0;
#endif

DBG("Success!\n");
}

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

void close()
{
DBG("Window close\n");
setVisible(false);

if (! fFirstInit)
{
fApp.oneHidden();
fApp._oneHidden();
fFirstInit = true;
}
}

void exec(const bool lockWait)
{
DBG("Window exec\n");
exec_init();

if (lockWait)
{
while (fVisible && fModal.enabled)
for (; fVisible && fModal.enabled;)
{
// idle()
puglProcessEvents(fView);
@@ -205,6 +254,7 @@ public:

void focus()
{
DBG("Window focus\n");
#if DGL_OS_WINDOWS
SetForegroundWindow(hwnd);
SetActiveWindow(hwnd);
@@ -218,16 +268,9 @@ public:
#endif
}

void idle()
{
puglProcessEvents(fView);

if (fVisible && fModal.enabled && fModal.parent != nullptr)
fModal.parent->idle();
}

void repaint()
{
//DBG("Window repaint\n");
puglPostRedisplay(fView);
}

@@ -241,27 +284,28 @@ public:
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;

#ifndef DGL_OS_MAC
if (yesNo && fFirstInit)
setSize(fView->width, fView->height, true);
#endif

#if DGL_OS_WINDOWS
if (yesNo)
{
ShowWindow(hwnd, WS_VISIBLE);

if (! fFirstInit)
ShowWindow(hwnd, SW_RESTORE);
}
ShowWindow(hwnd, fFirstInit ? SW_SHOWNORMAL : SW_RESTORE);
else
{
ShowWindow(hwnd, SW_HIDE);
}

UpdateWindow(hwnd);
#elif DGL_OS_MAC
@@ -279,7 +323,7 @@ public:
{
if (fFirstInit)
{
fApp.oneShown();
fApp._oneShown();
fFirstInit = false;
}
}
@@ -297,18 +341,25 @@ public:
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;

#ifndef DGL_OS_MAC
setSize(fView->width, fView->height, true);
#endif
}

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

#ifndef DGL_OS_MAC
int getWidth() const noexcept
{
return fView->width;
@@ -323,22 +374,25 @@ public:
{
return Size<int>(fView->width, fView->height);
}
#endif

void setSize(unsigned int width, unsigned int height, const bool forced = false)
{
if (width == 0)
width = 1;
if (height == 0)
height = 1;
if (width == 0 || height == 0)
{
DBGp("Window setSize called with invalid value(s) %i %i, ignoring request\n", width, height);
return;
}

#ifndef DGL_OS_MAC
if (fView->width == (int)width && fView->height == (int)height && ! forced)
return;
if (fView->width == static_cast<int>(width) && fView->height == static_cast<int>(height) && ! forced)
{
DBG("Window setSize matches current size, ignoring request\n");
return;
}

fView->width = width;
fView->height = height;
#endif

DBGp("Window setSize called %s\n", forced ? "(forced)" : "(not forced)");

#if DGL_OS_WINDOWS
int winFlags = WS_POPUPWINDOW | WS_CAPTION;
@@ -346,13 +400,15 @@ public:
if (fResizable)
winFlags |= WS_SIZEBOX;

RECT wr = { 0, 0, (long)width, (long)height };
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);
UpdateWindow(hwnd);

if (! forced)
UpdateWindow(hwnd);
#elif DGL_OS_MAC
puglImplSetSize(fView, width, height);
puglImplSetSize(fView, width, height, forced);
#elif DGL_OS_LINUX
XResizeWindow(xDisplay, xWindow, width, height);

@@ -370,7 +426,8 @@ public:
XSetNormalHints(xDisplay, xWindow, &sizeHints);
}

XFlush(xDisplay);
if (! forced)
XFlush(xDisplay);
#endif

repaint();
@@ -380,13 +437,14 @@ public:

void setTitle(const char* const title)
{
DBGp("Window setTitle \"%s\"\n", title);

#if DGL_OS_WINDOWS
SetWindowTextA(hwnd, title);
#elif DGL_OS_MAC
puglImplSetTitle(fView, title);
#elif DGL_OS_LINUX
XStoreName(xDisplay, xWindow, title);
XFlush(xDisplay);
#endif
}

@@ -422,16 +480,28 @@ public:
fWidgets.remove(widget);
}

void idle()
{
puglProcessEvents(fView);

if (fModal.enabled && fModal.parent != nullptr)
fModal.parent->idle();
}

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

void exec_init()
{
fModal.enabled = true;
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;

#if DGL_OS_WINDOWS
@@ -452,14 +522,19 @@ public:

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

// -------------------------------------------------------------------
@@ -467,6 +542,8 @@ public:
protected:
void onDisplay()
{
//DBG("PUGL: onDisplay\n");

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

FOR_EACH_WIDGET(it)
@@ -480,6 +557,8 @@ protected:

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

@@ -494,6 +573,8 @@ protected:

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

@@ -508,6 +589,8 @@ protected:

void onMotion(const int x, const int y)
{
DBGp("PUGL: onMotion : %i %i\n", x, y);

if (fModal.childFocus != nullptr)
return;

@@ -520,8 +603,10 @@ protected:
}
}

void onScroll(const float dx, const float dy)
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;

@@ -529,13 +614,15 @@ protected:
{
Widget* const widget(*rit);

if (widget->isVisible() && widget->onScroll(dx, dy))
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;

@@ -550,7 +637,8 @@ protected:

void onReshape(const int width, const int height)
{
printf("resized: %i:%i\n", width, height);
DBGp("PUGL: onReshape : %i %i\n", width, height);

FOR_EACH_WIDGET(it)
{
Widget* const widget(*it);
@@ -560,7 +648,10 @@ protected:

void onClose()
{
fModal.enabled = false;
DBG("PUGL: onClose\n");

if (fModal.enabled && fModal.parent != nullptr)
exec_fini();

if (fModal.childFocus != nullptr)
fModal.childFocus->onClose();
@@ -577,13 +668,14 @@ protected:
// -------------------------------------------------------------------

private:
App& fApp;
Window* const fSelf;
PuglView* const fView;
App& fApp;
Window* fSelf;
PuglView* fView;

bool fFirstInit;
bool fVisible;
bool fResizable;
bool fUsingEmbed;
std::list<Widget*> fWidgets;

struct Modal {
@@ -642,9 +734,9 @@ private:
handlePtr->onMotion(x, y);
}

static void onScrollCallback(PuglView* view, float dx, float dy)
static void onScrollCallback(PuglView* view, int x, int y, float dx, float dy)
{
handlePtr->onScroll(dx, dy);
handlePtr->onScroll(x, y, dx, dy);
}

static void onSpecialCallback(PuglView* view, bool press, PuglKey key)
@@ -713,11 +805,6 @@ void Window::focus()
pData->focus();
}

void Window::idle()
{
pData->idle();
}

void Window::repaint()
{
pData->repaint();
@@ -743,7 +830,6 @@ void Window::setResizable(bool yesNo)
pData->setResizable(yesNo);
}

#ifndef DGL_OS_MAC
int Window::getWidth() const noexcept
{
return pData->getWidth();
@@ -758,7 +844,6 @@ Size<int> Window::getSize() const noexcept
{
return pData->getSize();
}
#endif

void Window::setSize(unsigned int width, unsigned int height)
{
@@ -790,16 +875,24 @@ intptr_t Window::getWindowId() const
return pData->getWindowId();
}

void Window::addWidget(Widget* const widget)
void Window::_addWidget(Widget* const widget)
{
pData->addWidget(widget);
}

void Window::removeWidget(Widget* const widget)
void Window::_removeWidget(Widget* const widget)
{
pData->removeWidget(widget);
}

void Window::_idle()
{
pData->idle();
}

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

END_NAMESPACE_DGL

#undef DBG
#undef DBGF

source/modules/distrho/dgl/src/pugl/pugl.h → source/modules/dgl/src/pugl/copy/pugl.h View File

@@ -95,7 +95,7 @@ typedef enum {
PUGL_CHAR_ESCAPE = 0x1B,
PUGL_CHAR_DELETE = 0x7F
} PuglChar;
/**
Special (non-Unicode) keyboard keys.
*/
@@ -131,12 +131,12 @@ typedef enum {
Keyboard modifier flags.
*/
typedef enum {
PUGL_MOD_SHIFT = 1, /**< Shift key */
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.
*/
@@ -199,13 +199,17 @@ typedef void (*PuglReshapeFunc)(PuglView* view, int width, int height);
@param dx The scroll x distance.
@param dx The scroll y distance.
*/
typedef void (*PuglScrollFunc)(PuglView* view, float dx, float dy);
typedef void (*PuglScrollFunc)(PuglView* view,
int x,
int y,
float dx,
float dy);

/**
A function called when a special key is pressed or released.

This callback allows the use of keys that do not have unicode points. Note
that some non-printable keys
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.

source/modules/distrho/dgl/src/pugl/pugl_internal.h → source/modules/dgl/src/pugl/copy/pugl_internal.h View File

@@ -20,10 +20,27 @@
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 {

source/modules/distrho/dgl/src/pugl/pugl_osx.m → source/modules/dgl/src/pugl/copy/pugl_osx.m View File

@@ -36,6 +36,7 @@
defer:(BOOL)flag;
- (void) setPuglview:(PuglView*)view;
- (BOOL) windowShouldClose:(id)sender;
- (BOOL) canBecomeKeyWindow:(id)sender;
@end

@implementation PuglWindow
@@ -70,6 +71,11 @@
return YES;
}

- (BOOL) canBecomeKeyWindow:(id)sender
{
return NO;
}

@end

void
@@ -99,6 +105,7 @@ puglDisplay(PuglView* view)
- (void) mouseDragged:(NSEvent*)event;
- (void) mouseDown:(NSEvent*)event;
- (void) mouseUp:(NSEvent*)event;
- (void) rightMouseDragged:(NSEvent*)event;
- (void) rightMouseDown:(NSEvent*)event;
- (void) rightMouseUp:(NSEvent*)event;
- (void) keyDown:(NSEvent*)event;
@@ -181,6 +188,10 @@ getModifiers(PuglView* view, NSEvent* ev)

view->event_timestamp_ms = fmod([ev timestamp] * 1000.0, UINT32_MAX);

double ts = [ev timestamp] * 1000.0;
ts = (uint32)ts % 500000; //ridiculously large vals won't fit
view->event_timestamp_ms = ts;

unsigned mods = 0;
mods |= (modifierFlags & NSShiftKeyMask) ? PUGL_MOD_SHIFT : 0;
mods |= (modifierFlags & NSControlKeyMask) ? PUGL_MOD_CTRL : 0;
@@ -233,6 +244,15 @@ getModifiers(PuglView* view, NSEvent* ev)
}
}

- (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) {
@@ -273,8 +293,11 @@ getModifiers(PuglView* view, NSEvent* ev)
- (void) scrollWheel:(NSEvent*)event
{
if (puglview->scrollFunc) {
NSPoint loc = [event locationInWindow];
puglview->mods = getModifiers(puglview, event);
puglview->scrollFunc(puglview, [event deltaX], [event deltaY]);
puglview->scrollFunc(puglview,
loc.x, puglview->height - loc.y,
[event deltaX], [event deltaY]);
}
[self updateTrackingAreas];
}
@@ -359,6 +382,7 @@ puglCreate(PuglNativeWindow parent,
[window setContentView:impl->glview];
[NSApp activateIgnoringOtherApps:YES];
[window makeFirstResponder:impl->glview];

[window makeKeyAndOrderFront:window];

if (! visible) {

source/modules/distrho/dgl/src/pugl/pugl_win.cpp → source/modules/dgl/src/pugl/copy/pugl_win.cpp View File

@@ -106,8 +106,12 @@ puglCreate(PuglNativeWindow parent,
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);

@@ -145,7 +149,7 @@ puglDestroy(PuglView* view)
free(view);
}

static void
void
puglReshape(PuglView* view, int width, int height)
{
wglMakeCurrent(view->impl->hdc, view->impl->hglrc);
@@ -285,22 +289,26 @@ handleMessage(PuglView* view, UINT message, WPARAM wParam, LPARAM lParam)
break;
case WM_MOUSEWHEEL:
if (view->scrollFunc) {
view->event_timestamp_ms = GetMessageTime();
view->scrollFunc(
view, 0, (int16_t)HIWORD(wParam) / (float)WHEEL_DELTA);
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, (int16_t)HIWORD(wParam) / float(WHEEL_DELTA), 0);
view, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam),
(int16_t)HIWORD(wParam) / float(WHEEL_DELTA), 0.0f);
}
break;
case WM_KEYDOWN:
view->event_timestamp_ms = (GetMessageTime());
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);
@@ -342,7 +350,12 @@ puglProcessEvents(PuglView* view)
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);

source/modules/distrho/dgl/src/pugl/pugl_x11.c → source/modules/dgl/src/pugl/copy/pugl_x11.c View File

@@ -1,7 +1,6 @@
/*
Copyright 2012 David Robillard <http://drobilla.net>
Copyright 2012-2014 David Robillard <http://drobilla.net>
Copyright 2011-2012 Ben Loftis, Harrison Consoles
Copyright 2013 Robin Gareus <robin@gareus.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
@@ -32,16 +31,6 @@

#include "pugl_internal.h"

/* work around buggy re-parent & focus issues on some systems
* where no keyboard events are passed through even if the
* app has mouse-focus and all other events are working.
*/
#define XKEYFOCUSGRAB

/* show messages during initalization
*/
//#define VERBOSE_PUGL

struct PuglInternalsImpl {
Display* display;
int screen;
@@ -101,21 +90,15 @@ puglCreate(PuglNativeWindow parent,
if (!vi) {
vi = glXChooseVisual(impl->display, impl->screen, attrListSgl);
impl->doubleBuffered = False;
#ifdef VERBOSE_PUGL
printf("puGL: singlebuffered rendering will be used, no doublebuffering available\n");
#endif
PUGL_LOG("No double buffering available\n");
} else {
impl->doubleBuffered = True;
#ifdef VERBOSE_PUGL
printf("puGL: doublebuffered rendering available\n");
#endif
PUGL_LOG("Double buffered rendering enabled\n");
}

int glxMajor, glxMinor;
glXQueryVersion(impl->display, &glxMajor, &glxMinor);
#ifdef VERBOSE_PUGL
printf("puGL: GLX-Version : %d.%d\n", glxMajor, glxMinor);
#endif
PUGL_LOGF("GLX Version %d.%d\n", glxMajor, glxMinor);

impl->ctx = glXCreateContext(impl->display, vi, 0, GL_TRUE);

@@ -168,13 +151,9 @@ puglCreate(PuglNativeWindow parent,
}

if (glXIsDirect(impl->display, impl->ctx)) {
#ifdef VERBOSE_PUGL
printf("puGL: DRI enabled\n");
#endif
PUGL_LOG("DRI enabled (to disable, set LIBGL_ALWAYS_INDIRECT=1\n");
} else {
#ifdef VERBOSE_PUGL
printf("puGL: No DRI available\n");
#endif
PUGL_LOG("No DRI available\n");
}

XFree(vi);
@@ -196,7 +175,7 @@ puglDestroy(PuglView* view)
free(view);
}

static void
void
puglReshape(PuglView* view, int width, int height)
{
glXMakeCurrent(view->impl->display, view->impl->win, view->impl->ctx);
@@ -211,7 +190,7 @@ puglReshape(PuglView* view, int width, int height)
view->height = height;
}

static void
void
puglDisplay(PuglView* view)
{
glXMakeCurrent(view->impl->display, view->impl->win, view->impl->ctx);
@@ -279,6 +258,27 @@ setModifiers(PuglView* view, unsigned xstate, unsigned xtime)
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, str[0]);
}
}

PuglStatus
puglProcessEvents(PuglView* view)
{
@@ -320,7 +320,9 @@ puglProcessEvents(PuglView* view)
case 6: dx = -1.0f; break;
case 7: dx = 1.0f; break;
}
view->scrollFunc(view, dx, dy);
view->scrollFunc(view,
event.xbutton.x, event.xbutton.y,
dx, dy);
}
break;
}
@@ -334,25 +336,12 @@ puglProcessEvents(PuglView* view)
event.xbutton.x, event.xbutton.y);
}
break;
case KeyPress: {
case KeyPress:
setModifiers(view, event.xkey.state, event.xkey.time);
KeySym sym;
char str[5];
int n = XLookupString(&event.xkey, str, 4, &sym, NULL);
PuglKey key = keySymToSpecial(sym);
if (!key && view->keyboardFunc) {
if (n == 1) {
view->keyboardFunc(view, true, str[0]);
} else {
fprintf(stderr, "warning: Unknown key %X\n", (int)sym);
}
} else if (view->specialFunc) {
view->specialFunc(view, true, key);
}
} break;
case KeyRelease: {
dispatchKey(view, &event, true);
break;
case KeyRelease:
setModifiers(view, event.xkey.state, event.xkey.time);
bool repeated = false;
if (view->ignoreKeyRepeat &&
XEventsQueued(view->impl->display, QueuedAfterReading)) {
XEvent next;
@@ -361,20 +350,11 @@ puglProcessEvents(PuglView* view)
next.xkey.time == event.xkey.time &&
next.xkey.keycode == event.xkey.keycode) {
XNextEvent(view->impl->display, &event);
repeated = true;
break;
}
}

if (!repeated && view->keyboardFunc) {
KeySym sym = XLookupKeysym(&event.xkey, 0);
PuglKey special = keySymToSpecial(sym);
if (!special) {
view->keyboardFunc(view, false, sym);
} else if (view->specialFunc) {
view->specialFunc(view, false, special);
}
}
} break;
dispatchKey(view, &event, false);
break;
case ClientMessage:
if (!strcmp(XGetAtomName(view->impl->display,
event.xclient.message_type),
@@ -384,9 +364,12 @@ puglProcessEvents(PuglView* view)
}
}
break;
#ifdef XKEYFOCUSGRAB
#ifdef PUGL_GRAB_FOCUS
case EnterNotify:
XSetInputFocus(view->impl->display, view->impl->win, RevertToPointerRoot, CurrentTime);
XSetInputFocus(view->impl->display,
view->impl->win,
RevertToPointerRoot,
CurrentTime);
break;
#endif
default:

+ 357
- 0
source/modules/dgl/src/pugl/pugl.h View File

@@ -0,0 +1,357 @@
/*
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 */

+ 161
- 0
source/modules/dgl/src/pugl/pugl_internal.h View File

@@ -0,0 +1,161 @@
/*
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;
}

+ 117
- 0
source/modules/dgl/src/pugl/pugl_osx.diff View File

@@ -0,0 +1,117 @@
--- GIT-other/pugl/pugl/pugl_osx.m 2014-01-27 21:32:59.399032199 +0000
+++ GIT-mine/DPF/dgl/src/pugl/pugl_osx.m 2014-01-27 22:43:50.754197989 +0000
@@ -36,6 +36,7 @@
defer:(BOOL)flag;
- (void) setPuglview:(PuglView*)view;
- (BOOL) windowShouldClose:(id)sender;
+- (BOOL) canBecomeKeyWindow:(id)sender;
@end
@implementation PuglWindow
@@ -70,9 +71,14 @@
return YES;
}
+- (BOOL) canBecomeKeyWindow:(id)sender
+{
+ return NO;
+}
+
@end
-static void
+void
puglDisplay(PuglView* view)
{
if (view->displayFunc) {
@@ -95,13 +101,16 @@
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) rightMouseDragged:(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;
@@ -170,7 +179,7 @@
- (void) drawRect:(NSRect)rect
{
- display(puglview);
+ puglDisplay(puglview);
glFlush();
glSwapAPPLE();
}
@@ -182,6 +191,10 @@
view->event_timestamp_ms = fmod([ev timestamp] * 1000.0, UINT32_MAX);
+ double ts = [ev timestamp] * 1000.0;
+ ts = (uint32)ts % 500000; //ridiculously large vals won't fit
+ view->event_timestamp_ms = ts;
+
unsigned mods = 0;
mods |= (modifierFlags & NSShiftKeyMask) ? PUGL_MOD_SHIFT : 0;
mods |= (modifierFlags & NSControlKeyMask) ? PUGL_MOD_CTRL : 0;
@@ -332,6 +345,7 @@
struct PuglInternalsImpl {
PuglOpenGLView* glview;
id window;
+ bool isEmbed;
};
PuglView*
@@ -367,6 +381,7 @@
impl->glview = [PuglOpenGLView new];
impl->window = window;
+ impl->isEmbed = (parent != 0);
impl->glview->puglview = view;
[window setContentView:impl->glview];
@@ -396,6 +411,36 @@
PuglStatus
puglProcessEvents(PuglView* view)
{
+ if (! view->impl->isEmbed)
+ {
+ 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];
+ }
+
[view->impl->glview setNeedsDisplay: YES];
return PUGL_SUCCESS;

+ 459
- 0
source/modules/dgl/src/pugl/pugl_osx.m View File

@@ -0,0 +1,459 @@
/*
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;
- (BOOL) canBecomeKeyWindow:(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;
}

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

- (BOOL) canBecomeKeyWindow:(id)sender
{
return NO;
}

@end

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

static unsigned
getModifiers(PuglView* view, NSEvent* ev)
{
const unsigned modifierFlags = [ev modifierFlags];

view->event_timestamp_ms = fmod([ev timestamp] * 1000.0, UINT32_MAX);

double ts = [ev timestamp] * 1000.0;
ts = (uint32)ts % 500000; //ridiculously large vals won't fit
view->event_timestamp_ms = ts;

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

- (void)mouseExited:(NSEvent*)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;
bool isEmbed;
};

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->isEmbed = (parent != 0);
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;
}

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)
{
if (! view->impl->isEmbed)
{
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];
}

[view->impl->glview setNeedsDisplay: YES];

return PUGL_SUCCESS;
}

void
puglPostRedisplay(PuglView* view)
{
view->redisplay = true;
}

PuglNativeWindow
puglGetNativeWindow(PuglView* view)
{
return (PuglNativeWindow)view->impl->glview;
}

source/modules/distrho/dgl/src/pugl/pugl_osx_extended.h → source/modules/dgl/src/pugl/pugl_osx_extended.h View File

@@ -23,7 +23,15 @@

#include "pugl.h"

#ifdef __cplusplus
extern "C" {
#endif

void puglImplFocus(PuglView* view);
void puglImplSetSize(PuglView* view, unsigned int width, unsigned int height);
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

source/modules/distrho/dgl/src/pugl/pugl_osx_extended.m → source/modules/dgl/src/pugl/pugl_osx_extended.m View File

@@ -25,20 +25,27 @@

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)
void puglImplSetSize(PuglView* view, unsigned int width, unsigned int height, bool forced)
{
//id window = view->impl->window;
id window = view->impl->window;

// TODO
//NSRect frame = [window frame];
//frame.size.width = width;
//frame.size.height = height;
NSRect frame = [window frame];
frame.origin.y -= height - frame.size.height;
frame.size.width = width;
frame.size.height = height+20;

// display:NO ?
//[window setFrame:frame display:YES animate:NO];
// if (forced) {
// [window setFrame:frame];
// } else {
[window setFrame:frame display:YES animate:NO];
// }
}

void puglImplSetTitle(PuglView* view, const char* title)

+ 387
- 0
source/modules/dgl/src/pugl/pugl_win.cpp View File

@@ -0,0 +1,387 @@
/*
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);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();

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

+ 397
- 0
source/modules/dgl/src/pugl/pugl_x11.c View File

@@ -0,0 +1,397 @@
/*
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, view->width, 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);
}

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

void
puglDisplay(PuglView* view)
{
glXMakeCurrent(view->impl->display, view->impl->win, view->impl->ctx);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();

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 xtime)
{
view->event_timestamp_ms = xtime;

view->mods = 0;
view->mods |= (xstate & ShiftMask) ? PUGL_MOD_SHIFT : 0;
view->mods |= (xstate & ControlMask) ? PUGL_MOD_CTRL : 0;
view->mods |= (xstate & Mod1Mask) ? PUGL_MOD_ALT : 0;
view->mods |= (xstate & Mod4Mask) ? PUGL_MOD_SUPER : 0;
}

static void
dispatchKey(PuglView* view, XEvent* event, bool press)
{
KeySym sym;
char str[5];
const int n = XLookupString(&event->xkey, str, 4, &sym, NULL);
if (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, 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,
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 PUGL_GRAB_FOCUS
case EnterNotify:
XSetInputFocus(view->impl->display,
view->impl->win,
RevertToPointerRoot,
CurrentTime);
break;
#endif
default:
break;
}
}

if (view->redisplay) {
puglDisplay(view);
}

return PUGL_SUCCESS;
}

void
puglPostRedisplay(PuglView* view)
{
view->redisplay = true;
}

PuglNativeWindow
puglGetNativeWindow(PuglView* view)
{
return view->impl->win;
}

+ 27
- 3
source/modules/distrho/DistrhoPlugin.hpp View File

@@ -139,12 +139,36 @@ struct MidiEvent {
struct TimePos {
bool playing;
uint64_t frame;
double bpm;

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),
bpm(120.0) {}
frame(0) {}
};

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


+ 1
- 1
source/modules/distrho/DistrhoUI.hpp View File

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

#include "DistrhoUtils.hpp"

#include "dgl/Widget.hpp"
#include "../dgl/Widget.hpp"

START_NAMESPACE_DISTRHO



+ 2
- 2
source/modules/distrho/DistrhoUtils.hpp View File

@@ -477,7 +477,7 @@ public:
for (size_t i=0; i < fBufferLen; ++i)
{
if (fBuffer[i] >= 'A' && fBuffer[i] <= 'Z')
fBuffer[i] = static_cast<char>(fBuffer[i] + kCharDiff);
fBuffer[i] += kCharDiff;
}
}

@@ -491,7 +491,7 @@ public:
for (size_t i=0; i < fBufferLen; ++i)
{
if (fBuffer[i] >= 'a' && fBuffer[i] <= 'z')
fBuffer[i] = static_cast<char>(fBuffer[i] - kCharDiff);
fBuffer[i] -= kCharDiff;
}
}



+ 3
- 1
source/modules/distrho/src/DistrhoDefines.h View File

@@ -89,8 +89,10 @@
#endif

#ifndef PROPER_CPP11_SUPPORT
# ifndef __clang__
# define noexcept throw()
# endif
# define override
# define noexcept throw()
# define nullptr (0)
#endif



+ 2
- 6
source/modules/distrho/src/DistrhoPluginInternal.hpp View File

@@ -279,14 +279,10 @@ public:
#endif

#if DISTRHO_PLUGIN_WANT_TIMEPOS
void setTimePos(const bool playing, const uint64_t frame, const double bpm)
void setTimePos(const TimePos& timePos)
{
if (fData != nullptr)
{
fData->timePos.playing = playing;
fData->timePos.frame = frame;
fData->timePos.bpm = bpm;
}
std::memcpy(&fData->timePos, &timePos, sizeof(TimePos));
}
#endif



+ 169
- 7
source/modules/distrho/src/DistrhoPluginLV2.cpp View File

@@ -38,7 +38,7 @@
#endif

#if DISTRHO_PLUGIN_WANT_STATE
# warning LV2 State still TODO
# warning LV2 State still TODO (working but needs final testing)
#endif
#if DISTRHO_PLUGIN_WANT_TIMEPOS
# warning LV2 TimePos still TODO
@@ -60,6 +60,9 @@ public:
: fPortControls(nullptr),
fLastControlValues(nullptr),
#if DISTRHO_LV2_USE_EVENTS_IN || DISTRHO_LV2_USE_EVENTS_OUT
# if DISTRHO_PLUGIN_WANT_TIMEPOS
fLastTimeSpeed(0.0f),
# endif
fURIDs(uridMap),
#endif
fUridMap(uridMap),
@@ -79,9 +82,8 @@ public:
fPortAudioOuts = nullptr;
#endif

if (const uint32_t count = fPlugin.getParameterCount())
{
const uint32_t count(fPlugin.getParameterCount());

fPortControls = new float*[count];
fLastControlValues = new float[count];

@@ -91,6 +93,11 @@ public:
fLastControlValues[i] = fPlugin.getParameterValue(i);
}
}
else
{
fPortControls = nullptr;
fLastControlValues = nullptr;
}

#if DISTRHO_LV2_USE_EVENTS_IN
fPortEventsIn = nullptr;
@@ -224,6 +231,9 @@ public:
#if DISTRHO_LV2_USE_EVENTS_IN
# if DISTRHO_PLUGIN_IS_SYNTH
uint32_t midiEventCount = 0;
# endif
# if DISTRHO_PLUGIN_WANT_TIMEPOS
bool needsFrameIncrement = true;
# endif
LV2_ATOM_SEQUENCE_FOREACH(fPortEventsIn, event)
{
@@ -254,9 +264,118 @@ public:
}
# endif
# if DISTRHO_PLUGIN_WANT_TIMEPOS
if (event->body.type == fURIDs.timePosition)
if (event->body.type == fURIDs.atomBlank)
{
// TODO
const LV2_Atom_Object* const obj((const LV2_Atom_Object*)&event->body);

if (obj->body.otype != fURIDs.timePosition)
continue;

LV2_Atom* bar = nullptr;
LV2_Atom* barBeat = nullptr;
LV2_Atom* beat = nullptr;
LV2_Atom* beatUnit = nullptr;
LV2_Atom* beatsPerBar = nullptr;
LV2_Atom* beatsPerMinute = nullptr;
LV2_Atom* frame = nullptr;
LV2_Atom* speed = nullptr;

lv2_atom_object_get(obj,
fURIDs.timeBar, &bar,
fURIDs.timeBarBeat, &barBeat,
fURIDs.timeBeat, &beat,
fURIDs.timeBeatUnit, &beatUnit,
fURIDs.timeBeatsPerBar, &beatsPerBar,
fURIDs.timeBeatsPerMinute, &beatsPerMinute,
fURIDs.timeFrame, &frame,
fURIDs.timeSpeed, &speed,
nullptr);

// TODO:
// - tick
// - barStartTick
// - ticksPerBeat

if (bar != nullptr)
{
if (bar->type == fURIDs.atomDouble)
fTimePos.bbt.bar = ((LV2_Atom_Double*)bar)->body + 1.0f;
else if (bar->type == fURIDs.atomFloat)
fTimePos.bbt.bar = ((LV2_Atom_Float*)bar)->body + 1.0f;
else if (bar->type == fURIDs.atomInt)
fTimePos.bbt.bar = ((LV2_Atom_Int*)bar)->body + 1;
else if (bar->type == fURIDs.atomLong)
fTimePos.bbt.bar = ((LV2_Atom_Long*)bar)->body + 1;
}

/*if (barBeat != nullptr && barBeat->type == fURIDs.atomFloat)
{
}*/

if (beat != nullptr)
{
if (beat->type == fURIDs.atomDouble)
fTimePos.bbt.beat = ((LV2_Atom_Double*)beat)->body + 1.0f;
else if (beat->type == fURIDs.atomFloat)
fTimePos.bbt.beat = ((LV2_Atom_Float*)beat)->body + 1.0f;
else if (beat->type == fURIDs.atomInt)
fTimePos.bbt.beat = ((LV2_Atom_Int*)beat)->body + 1;
else if (beat->type == fURIDs.atomLong)
fTimePos.bbt.beat = ((LV2_Atom_Long*)beat)->body + 1;
}

if (beatUnit != nullptr)
{
if (beatUnit->type == fURIDs.atomDouble)
fTimePos.bbt.beatType = ((LV2_Atom_Double*)beatUnit)->body;
else if (beatUnit->type == fURIDs.atomFloat)
fTimePos.bbt.beatType = ((LV2_Atom_Float*)beatUnit)->body;
else if (beatUnit->type == fURIDs.atomInt)
fTimePos.bbt.beatType = ((LV2_Atom_Int*)beatUnit)->body;
else if (beatUnit->type == fURIDs.atomLong)
fTimePos.bbt.beatType = ((LV2_Atom_Long*)beatUnit)->body;
}

if (beatsPerBar != nullptr)
{
if (beatsPerBar->type == fURIDs.atomDouble)
fTimePos.bbt.beatsPerBar = ((LV2_Atom_Double*)beatsPerBar)->body;
else if (beatsPerBar->type == fURIDs.atomFloat)
fTimePos.bbt.beatsPerBar = ((LV2_Atom_Float*)beatsPerBar)->body;
else if (beatsPerBar->type == fURIDs.atomInt)
fTimePos.bbt.beatsPerBar = ((LV2_Atom_Int*)beatsPerBar)->body;
else if (beatsPerBar->type == fURIDs.atomLong)
fTimePos.bbt.beatsPerBar = ((LV2_Atom_Long*)beatsPerBar)->body;
}

if (beatsPerMinute != nullptr)
{
if (beatsPerMinute->type == fURIDs.atomDouble)
fTimePos.bbt.beatsPerMinute = ((LV2_Atom_Double*)beatsPerMinute)->body;
else if (beatsPerMinute->type == fURIDs.atomFloat)
fTimePos.bbt.beatsPerMinute = ((LV2_Atom_Float*)beatsPerMinute)->body;
else if (beatsPerMinute->type == fURIDs.atomInt)
fTimePos.bbt.beatsPerMinute = ((LV2_Atom_Int*)beatsPerMinute)->body;
else if (beatsPerMinute->type == fURIDs.atomLong)
fTimePos.bbt.beatsPerMinute = ((LV2_Atom_Long*)beatsPerMinute)->body;
}

if (frame != nullptr && frame->type == fURIDs.atomLong)
{
fTimePos.frame = ((LV2_Atom_Long*)frame)->body;
needsFrameIncrement = false;
}

if (speed != nullptr && speed->type == fURIDs.atomFloat)
{
fLastTimeSpeed = ((LV2_Atom_Float*)speed)->body;
fTimePos.playing = (fLastTimeSpeed == 1.0f);
}

if ((! fTimePos.bbt.valid) && beatsPerMinute != nullptr && beatsPerBar != nullptr && beatUnit != nullptr)
fTimePos.bbt.valid = true;

continue;
}
# endif
# if (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI)
@@ -264,11 +383,19 @@ public:
{
const void* const data((const void*)(event + 1));
fWorker->schedule_work(fWorker->handle, event->body.size, data);

continue;
}
# endif
}
#endif

# if DISTRHO_PLUGIN_WANT_TIMEPOS
if (needsFrameIncrement && fLastTimeSpeed != 0.0f)
fTimePos.frame += fLastTimeSpeed*sampleCount;
fPlugin.setTimePos(fTimePos);
# endif

#if DISTRHO_PLUGIN_IS_SYNTH
fPlugin.run(fPortAudioIns, fPortAudioOuts, sampleCount, fMidiEvents, midiEventCount);
#else
@@ -459,20 +586,50 @@ private:
#if DISTRHO_PLUGIN_IS_SYNTH
MidiEvent fMidiEvents[kMaxMidiEvents];
#endif
#if DISTRHO_PLUGIN_WANT_TIMEPOS
TimePos fTimePos;
float fLastTimeSpeed;
#endif

// LV2 URIDs
#if DISTRHO_LV2_USE_EVENTS_IN || DISTRHO_LV2_USE_EVENTS_OUT
struct URIDs {
LV2_URID atomBlank;
LV2_URID atomDouble;
LV2_URID atomFloat;
LV2_URID atomInt;
LV2_URID atomLong;
LV2_URID atomString;
LV2_URID distrhoState;
LV2_URID midiEvent;
LV2_URID timePosition;
LV2_URID timeBar;
LV2_URID timeBarBeat;
LV2_URID timeBeat;
LV2_URID timeBeatUnit;
LV2_URID timeBeatsPerBar;
LV2_URID timeBeatsPerMinute;
LV2_URID timeFrame;
LV2_URID timeSpeed;

URIDs(const LV2_URID_Map* const uridMap)
: atomString(uridMap->map(uridMap->handle, LV2_ATOM__String)),
: atomBlank(uridMap->map(uridMap->handle, LV2_ATOM__Blank)),
atomDouble(uridMap->map(uridMap->handle, LV2_ATOM__Double)),
atomFloat(uridMap->map(uridMap->handle, LV2_ATOM__Float)),
atomInt(uridMap->map(uridMap->handle, LV2_ATOM__Int)),
atomLong(uridMap->map(uridMap->handle, LV2_ATOM__Long)),
atomString(uridMap->map(uridMap->handle, LV2_ATOM__String)),
distrhoState(uridMap->map(uridMap->handle, "urn:distrho:keyValueState")),
midiEvent(uridMap->map(uridMap->handle, LV2_MIDI__MidiEvent)),
timePosition(uridMap->map(uridMap->handle, LV2_TIME__Position)) {}
timePosition(uridMap->map(uridMap->handle, LV2_TIME__Position)),
timeBar(uridMap->map(uridMap->handle, LV2_TIME__bar)),
timeBarBeat(uridMap->map(uridMap->handle, LV2_TIME__barBeat)),
timeBeat(uridMap->map(uridMap->handle, LV2_TIME__beat)),
timeBeatUnit(uridMap->map(uridMap->handle, LV2_TIME__beatUnit)),
timeBeatsPerBar(uridMap->map(uridMap->handle, LV2_TIME__beatsPerBar)),
timeBeatsPerMinute(uridMap->map(uridMap->handle, LV2_TIME__beatsPerMinute)),
timeFrame(uridMap->map(uridMap->handle, LV2_TIME__frame)),
timeSpeed(uridMap->map(uridMap->handle, LV2_TIME__speed)) {}
} fURIDs;
#endif

@@ -563,6 +720,8 @@ static LV2_Handle lv2_instantiate(const LV2_Descriptor*, double sampleRate, cons
}
#endif

d_lastBufferSize = 0;

for (int i=0; options[i].key != 0; ++i)
{
if (options[i].key == uridMap->map(uridMap->handle, LV2_BUF_SIZE__maxBlockLength))
@@ -577,7 +736,10 @@ static LV2_Handle lv2_instantiate(const LV2_Descriptor*, double sampleRate, cons
}

if (d_lastBufferSize == 0)
{
d_stderr("Host does not provide maxBlockLength option");
d_lastBufferSize = 2048;
}

d_lastSampleRate = sampleRate;



+ 29
- 1
source/modules/distrho/src/DistrhoPluginVST.cpp View File

@@ -45,6 +45,7 @@
#define effCanBeAutomated 26
#define effGetProgramNameIndexed 29
#define effGetPlugCategory 35
#define effIdle 53
#define kPlugCategEffect 1
#define kPlugCategSynth 2
#define kVstVersion 2400
@@ -55,6 +56,13 @@ struct ERect {
# include "vst/aeffectx.h"
#endif

#if DISTRHO_PLUGIN_WANT_STATE
# warning VST State still TODO (working but needs final testing)
#endif
#if DISTRHO_PLUGIN_WANT_TIMEPOS
# warning VST TimePos still TODO
#endif

typedef std::map<d_string,d_string> StringMap;

START_NAMESPACE_DISTRHO
@@ -437,6 +445,11 @@ public:
case effEditOpen:
if (fVstUi == nullptr)
{
# if DISTRHO_OS_MAC && ! defined(__LP64__)
if ((fEffect->dispatcher(fEffect, effCanDo, 0, 0, (void*)"hasCockosViewAsConfig", 0.0f) & 0xffff0000) != 0xbeef0000)
return 0;
# endif

d_lastUiSampleRate = fAudioMaster(fEffect, audioMasterGetSampleRate, 0, 0, nullptr, 0.0f);

fVstUi = new UIVst(fAudioMaster, fEffect, &fPlugin, this, (intptr_t)ptr);
@@ -478,6 +491,7 @@ public:
break;

case effEditIdle:
case effIdle:
if (fVstUi != nullptr)
fVstUi->idle();
break;
@@ -657,7 +671,15 @@ public:
{
#if DISTRHO_PLUGIN_WANT_TIMEPOS
if (const VstTimeInfo* const timeInfo = (const VstTimeInfo*)fEffect->dispatcher(fEffect, audioMasterGetTime, 0, kVstTempoValid, nullptr, 0.0f))
fPlugin.setTimePos((timeInfo->flags & kVstTransportPlaying) != 0, timeInfo->samplePos, timeInfo->tempo);
{
fTimePos.playing = (timeInfo->flags & kVstTransportPlaying);
fTimePos.frame = timeInfo->samplePos;

// TODO: BBT
// timeInfo->tempo etc

fPlugin.setTimePos(fTimePos);
}
#endif

#if DISTRHO_PLUGIN_IS_SYNTH
@@ -681,14 +703,20 @@ private:
PluginExporter fPlugin;

#if DISTRHO_PLUGIN_WANT_PROGRAMS
// Current state
int32_t fCurProgram;
#endif

// Temporary data
#if DISTRHO_PLUGIN_IS_SYNTH
uint32_t fMidiEventCount;
MidiEvent fMidiEvents[kMaxMidiEvents];
#endif
#if DISTRHO_PLUGIN_WANT_TIMEPOS
TimePos fTimePos;
#endif

// UI stuff
#if DISTRHO_PLUGIN_HAS_UI
UIVst* fVstUi;
ERect fVstRect;


+ 0
- 3
source/modules/distrho/src/DistrhoUIDSSI.cpp View File

@@ -16,9 +16,6 @@

#include "DistrhoUIInternal.hpp"

#include "dgl/App.hpp"
#include "dgl/Window.hpp"

#include <lo/lo.h>

START_NAMESPACE_DISTRHO


+ 2
- 2
source/modules/distrho/src/DistrhoUIInternal.hpp View File

@@ -19,8 +19,8 @@

#include "../DistrhoUI.hpp"

#include "../dgl/App.hpp"
#include "../dgl/Window.hpp"
#include "../../dgl/App.hpp"
#include "../../dgl/Window.hpp"

START_NAMESPACE_DISTRHO



+ 0
- 365
source/modules/distrho/src/_todo/DistrhoPluginJACK.cpp View File

@@ -1,365 +0,0 @@
/*
* DISTRHO Plugin Toolkit (DPT)
* Copyright (C) 2012-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.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
* TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

#ifdef DISTRHO_PLUGIN_TARGET_JACK

#include "DistrhoDefines.h"

#if ! DISTRHO_PLUGIN_HAS_UI
# error Standalone JACK mode requires UI
#endif

#include "DistrhoPluginInternal.h"
#include "DistrhoUIInternal.h"

#include <jack/jack.h>
#include <jack/midiport.h>
#include <jack/transport.h>

#include <QtCore/QSettings>
#include <QtGui/QApplication>
#include <QtGui/QMainWindow>
#include <QtGui/QMessageBox>

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

START_NAMESPACE_DISTRHO

class PluginJack : public QMainWindow
{
public:
PluginJack(jack_client_t* client_)
: QMainWindow(nullptr),
widget(this),
settings("DISTRHO", DISTRHO_PLUGIN_NAME),
ui(this, widget.winId(), setParameterCallback, setStateCallback, nullptr, uiNoteCallback, uiResizeCallback),
client(client_)
{
setCentralWidget(&widget);
setFixedSize(ui.getWidth(), ui.getHeight());
setWindowTitle(DISTRHO_PLUGIN_NAME);

if (DISTRHO_PLUGIN_NUM_INPUTS > 0)
{
portsIn = new jack_port_t* [DISTRHO_PLUGIN_NUM_INPUTS];

for (int i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; i++)
portsIn[i] = jack_port_register(client, d_string("Audio Input ") + d_string(i+1), JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
}
else
portsIn = nullptr;

if (DISTRHO_PLUGIN_NUM_OUTPUTS > 0)
{
portsOut = new jack_port_t* [DISTRHO_PLUGIN_NUM_OUTPUTS];

for (int i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; i++)
portsOut[i] = jack_port_register(client, d_string("Audio Output ") + d_string(i+1), JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
}
else
portsOut = nullptr;

#if DISTRHO_PLUGIN_IS_SYNTH
portMidi = jack_port_register(client, "Midi Input", JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0);
#endif

jack_set_process_callback(client, jackProcessCallback, this);

uiTimer = startTimer(30);

// load settings
restoreGeometry(settings.value("Global/Geometry", QByteArray()).toByteArray());

for (uint32_t i=0; i < plugin.parameterCount(); i++)
{
bool ok;
float value = settings.value(QString("Parameters/%1").arg(i)).toFloat(&ok);

if (ok)
{
plugin.setParameterValue(i, value);
ui.parameterChanged(i, value);
}
}

#if DISTRHO_PLUGIN_WANT_STATE
for (uint32_t i=0; i < plugin.stateCount(); i++)
{
const char* key = plugin.stateKey(i);
QString stringValue(settings.value(key).toString());

if (! stringValue.isEmpty())
ui.stateChanged(key, stringValue.toUtf8().constData());
}
#endif
}

~PluginJack()
{
// save settings
settings.setValue("Global/Geometry", saveGeometry());

if (uiTimer)
killTimer(uiTimer);

if (portsIn)
delete[] portsIn;

if (portsOut)
delete[] portsOut;
}

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

protected:
void setParameterValue(uint32_t index, float value)
{
plugin.setParameterValue(index, value);
settings.setValue(QString("Parameters/%1").arg(index), value);
}

#if DISTRHO_PLUGIN_WANT_STATE
void setState(const char* key, const char* value)
{
plugin.setState(key, value);
settings.setValue(key, value);
}
#endif

#if DISTRHO_PLUGIN_IS_SYNTH
void uiNote(bool onOff, uint8_t channel, uint8_t note, uint8_t velocity)
{
// TODO
}
#endif

void uiResize(unsigned int width, unsigned int height)
{
widget.setFixedSize(width, height);
setFixedSize(width, height);
}

int jackProcess(jack_nframes_t nframes)
{
if (nframes <= 1)
return 1;

// Check for updated bufferSize
if (nframes != d_lastBufferSize)
{
d_lastBufferSize = nframes;
plugin.setBufferSize(nframes, true);
}

const float* ins[DISTRHO_PLUGIN_NUM_INPUTS];
float* outs[DISTRHO_PLUGIN_NUM_OUTPUTS];

for (int i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; i++)
ins[i] = (float*)jack_port_get_buffer(portsIn[i], nframes);

for (int i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; i++)
outs[i] = (float*)jack_port_get_buffer(portsOut[i], nframes);

#if DISTRHO_PLUGIN_IS_SYNTH
uint32_t midiEventCount = 0;

void* mIn = jack_port_get_buffer(portMidi, nframes);
// TODO

plugin.run(ins, outs, nframes, midiEventCount, midiEvents);
#else
plugin.run(ins, outs, nframes, 0, nullptr);
#endif

return 0;
}

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

void closeEvent(QCloseEvent* event)
{
QMainWindow::closeEvent(event);

qApp->quit();
}

void timerEvent(QTimerEvent* event)
{
if (event->timerId() == uiTimer)
ui.idle();

QMainWindow::timerEvent(event);
}

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

private:
// Qt4 stuff
int uiTimer;
QWidget widget;
QSettings settings;

PluginInternal plugin;
UIInternal ui;

jack_client_t* const client;
jack_port_t** portsIn;
jack_port_t** portsOut;

#if DISTRHO_PLUGIN_IS_SYNTH
jack_port_t* portMidi;
MidiEvent midiEvents[MAX_MIDI_EVENTS];
#endif

// ---------------------------------------------
// Callbacks

static void setParameterCallback(void* ptr, uint32_t index, float value)
{
PluginJack* _this_ = (PluginJack*)ptr;
assert(_this_);

_this_->setParameterValue(index, value);
}

static void setStateCallback(void* ptr, const char* key, const char* value)
{
#if DISTRHO_PLUGIN_WANT_STATE
PluginJack* _this_ = (PluginJack*)ptr;
assert(_this_);

_this_->setState(key, value);
#else
Q_UNUSED(ptr);
Q_UNUSED(key);
Q_UNUSED(value);
#endif
}

static void uiNoteCallback(void* ptr, bool onOff, uint8_t channel, uint8_t note, uint8_t velocity)
{
#if DISTRHO_PLUGIN_IS_SYNTH
PluginJack* _this_ = (PluginJack*)ptr;
assert(_this_);

_this_->uiNote(onOff, channel, note, velocity);
#else
Q_UNUSED(ptr);
Q_UNUSED(onOff);
Q_UNUSED(channel);
Q_UNUSED(note);
Q_UNUSED(velocity);
#endif
}

static void uiResizeCallback(void* ptr, unsigned int width, unsigned int height)
{
PluginJack* _this_ = (PluginJack*)ptr;
assert(_this_);

_this_->uiResize(width, height);
}

static int jackProcessCallback(jack_nframes_t nframes, void* arg)
{
PluginJack* _this_ = (PluginJack*)arg;
assert(_this_);

return _this_->jackProcess(nframes);
}
};

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

END_NAMESPACE_DISTRHO

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

std::string jack_status_get_error_string(const jack_status_t& status)
{
std::string errorString;

if (status & JackFailure)
errorString += "Overall operation failed;\n";
if (status & JackInvalidOption)
errorString += "The operation contained an invalid or unsupported option;\n";
if (status & JackNameNotUnique)
errorString += "The desired client name was not unique;\n";
if (status & JackServerStarted)
errorString += "The JACK server was started as a result of this operation;\n";
if (status & JackServerFailed)
errorString += "Unable to connect to the JACK server;\n";
if (status & JackServerError)
errorString += "Communication error with the JACK server;\n";
if (status & JackNoSuchClient)
errorString += "Requested client does not exist;\n";
if (status & JackLoadFailure)
errorString += "Unable to load internal client;\n";
if (status & JackInitFailure)
errorString += "Unable to initialize client;\n";
if (status & JackShmFailure)
errorString += "Unable to access shared memory;\n";
if (status & JackVersionError)
errorString += "Client's protocol version does not match;\n";
if (status & JackBackendError)
errorString += "Backend Error;\n";
if (status & JackClientZombie)
errorString += "Client is being shutdown against its will;\n";

if (errorString.size() > 0)
errorString.replace(errorString.size()-2, 2, ".");

return errorString;
}

int main(int argc, char* argv[])
{
USE_NAMESPACE_DISTRHO
QApplication app(argc, argv, true);

jack_status_t status;
jack_client_t* client = jack_client_open(DISTRHO_PLUGIN_NAME, JackNullOption, &status);

if (! client)
{
std::string errorString(jack_status_get_error_string(status));
QMessageBox::critical(nullptr, app.translate(DISTRHO_PLUGIN_NAME, "Error"),
app.translate(DISTRHO_PLUGIN_NAME,
"Could not connect to JACK, possible reasons:\n"
"%1").arg(QString::fromStdString(errorString)));
return 1;
}

d_lastBufferSize = jack_get_buffer_size(client);
d_lastSampleRate = jack_get_sample_rate(client);
setLastUiSampleRate(d_lastSampleRate);

PluginJack plugin(client);
plugin.show();

jack_activate(client);

int ret = app.exec();

jack_deactivate(client);
jack_client_close(client);

return ret;
}

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

#endif // DISTRHO_PLUGIN_TARGET_JACK

+ 441
- 0
source/modules/distrho/src/dssi/dssi.h View File

@@ -0,0 +1,441 @@
/* -*- 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 */

+ 272
- 0
source/modules/distrho/src/dssi/seq_event-compat.h View File

@@ -0,0 +1,272 @@
/*
* 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 */


+ 603
- 0
source/modules/distrho/src/ladspa/ladspa.h View File

@@ -0,0 +1,603 @@
/* 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 */

+ 619
- 0
source/modules/distrho/src/lv2/atom-forge.h View File

@@ -0,0 +1,619 @@
/*
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 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"

#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_URID Bool;
LV2_URID Chunk;
LV2_URID Double;
LV2_URID Float;
LV2_URID Int;
LV2_URID Long;
LV2_URID Literal;
LV2_URID Path;
LV2_URID Property;
LV2_URID Resource;
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)
{
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->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);
}

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 &&
lv2_atom_forge_deref(forge, forge->stack->ref)->type == type;
}

/**
@}
@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 = 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 + 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, 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:Resource.

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

// Write object header
LV2_Atom_Forge_Frame frame;
lv2_atom_forge_resource(forge, &frame, 1, eg_Cat);

// Write property: eg:name = "Hobbes"
lv2_atom_forge_property_head(forge, eg_name, 0);
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_resource(LV2_Atom_Forge* forge,
LV2_Atom_Forge_Frame* frame,
LV2_URID id,
LV2_URID otype)
{
const LV2_Atom_Object a = {
{ sizeof(LV2_Atom_Object) - sizeof(LV2_Atom), forge->Resource },
{ id, otype }
};
LV2_Atom_Forge_Ref out = lv2_atom_forge_write(forge, &a, sizeof(a));
return lv2_atom_forge_push(forge, frame, out);
}

/**
The same as lv2_atom_forge_resource(), but for object:Blank.
*/
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)
{
const LV2_Atom_Object a = {
{ sizeof(LV2_Atom_Object) - sizeof(LV2_Atom), forge->Blank },
{ id, otype }
};
LV2_Atom_Forge_Ref out = lv2_atom_forge_write(forge, &a, sizeof(a));
return lv2_atom_forge_push(forge, frame, out);
}

/**
Write the header for a property body (likely in an Object).
See lv2_atom_forge_resource() documentation for an example.
*/
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 * 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 = {
{ sizeof(LV2_Atom_Sequence) - sizeof(LV2_Atom), forge->Sequence },
{ unit, 0 }
};
LV2_Atom_Forge_Ref out = lv2_atom_forge_write(forge, &a, sizeof(a));
return lv2_atom_forge_push(forge, frame, out);
}

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

+ 255
- 0
source/modules/distrho/src/lv2/atom-helpers.h View File

@@ -0,0 +1,255 @@
// lv2_atom_helpers.h
//
/****************************************************************************
Copyright (C) 2005-2012, 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.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;


// Pad a size to 64 bits (for LV2 atom:Sequence event sizes).
//
static inline
uint32_t lv2_atom_buffer_pad_size ( uint32_t size )
{
return (size + 7) & (~7);
}


// 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);
else
buf->atoms.atom.size = buf->capacity;

buf->atoms.atom.type = buf->sequence_type;
buf->atoms.body.unit = 0;
buf->atoms.body.pad = 0;
}


// Allocate a new, empty LV2 atom:Sequence buffer.
//
static inline
LV2_Atom_Buffer *lv2_atom_buffer_new (
uint32_t capacity, 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->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 )
{
return buf->atoms.atom.size - sizeof(LV2_Atom_Sequence_Body);
}


// 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_buffer_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_buffer_pad_size(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_buffer_pad_size(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

+ 401
- 0
source/modules/distrho/src/lv2/atom-util.h View File

@@ -0,0 +1,401 @@
/*
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 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 + 7) & (~7);
}

/** Return the total size of @p atom, including the header. */
static inline uint32_t
lv2_atom_total_size(const LV2_Atom* atom)
{
return 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 const LV2_Atom_Event*
lv2_atom_sequence_end(const LV2_Atom_Sequence_Body* body, uint32_t size)
{
return (const LV2_Atom_Event*)((const 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)
{
if (!i) return NULL;
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 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, 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 (LV2_Atom* (iter) = lv2_atom_tuple_begin(tuple); \
!lv2_atom_tuple_is_end(LV2_ATOM_BODY(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 (LV2_Atom* (iter) = (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(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 */

+ 246
- 0
source/modules/distrho/src/lv2/atom.h View File

@@ -0,0 +1,246 @@
/*
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 (atom:Resource) or blank ID (atom: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 */

+ 30
- 0
source/modules/distrho/src/lv2/buf-size.h View File

@@ -0,0 +1,30 @@
/*
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 */

+ 63
- 0
source/modules/distrho/src/lv2/data-access.h View File

@@ -0,0 +1,63 @@
/*
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 */

+ 144
- 0
source/modules/distrho/src/lv2/dynmanifest.h View File

@@ -0,0 +1,144 @@
/*
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 */

+ 263
- 0
source/modules/distrho/src/lv2/event-helpers.h View File

@@ -0,0 +1,263 @@
/*
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 (size + 7) & (~7);
}


/** 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(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(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)
{
if (iter->buf->capacity - iter->buf->size < sizeof(LV2_Event) + 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;

size = lv2_event_pad_size(sizeof(LV2_Event) + size);
iter->buf->size += size;
iter->offset += 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)
{
if (iter->buf->capacity - iter->buf->size < sizeof(LV2_Event) + ev->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 size = lv2_event_pad_size(sizeof(LV2_Event) + ev->size);
iter->buf->size += size;
iter->offset += size;

return true;
}

#ifdef __cplusplus
} /* extern "C" */
#endif

#endif /* LV2_EVENT_HELPERS_H */


+ 294
- 0
source/modules/distrho/src/lv2/event.h View File

@@ -0,0 +1,294 @@
/*
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 */

+ 37
- 0
source/modules/distrho/src/lv2/instance-access.h View File

@@ -0,0 +1,37 @@
/*
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 */


+ 99
- 0
source/modules/distrho/src/lv2/log.h View File

@@ -0,0 +1,99 @@
/*
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 */

+ 145
- 0
source/modules/distrho/src/lv2/logger.h View File

@@ -0,0 +1,145 @@
/*
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 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 "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 */

+ 98
- 0
source/modules/distrho/src/lv2/lv2-midifunctions.h View File

@@ -0,0 +1,98 @@
/****************************************************************************
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 = *(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 += sizeof(double);
size_t size = *(size_t*)(state->midi->data + state->position);
state->position += sizeof(size_t);
state->position += 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 += sizeof(double);
*((size_t*)(state->midi->data + state->midi->size)) = size;
state->midi->size += 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


+ 175
- 0
source/modules/distrho/src/lv2/lv2-miditype.h View File

@@ -0,0 +1,175 @@
/****************************************************************************
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

+ 454
- 0
source/modules/distrho/src/lv2/lv2.h View File

@@ -0,0 +1,454 @@
/*
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: 6.5
*/

#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__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 */

+ 107
- 0
source/modules/distrho/src/lv2/lv2_external_ui.h View File

@@ -0,0 +1,107 @@
/*
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 UI must be reinstantiated.
*
* @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 */

+ 174
- 0
source/modules/distrho/src/lv2/lv2_programs.h View File

@@ -0,0 +1,174 @@
/*
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 */

+ 105
- 0
source/modules/distrho/src/lv2/lv2_rtmempool.h View File

@@ -0,0 +1,105 @@
/*
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

#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;

#ifdef __cplusplus
} /* extern "C" */
#endif

#endif /* LV2_RTMEMPOOL_H */

+ 226
- 0
source/modules/distrho/src/lv2/midi.h View File

@@ -0,0 +1,226 @@
/*
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 */

+ 34
- 0
source/modules/distrho/src/lv2/morph.h View File

@@ -0,0 +1,34 @@
/*
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/lv2plug.in/ns/lv2core/lv2.h"
#include "lv2/lv2plug.in/ns/ext/urid/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 */

+ 132
- 0
source/modules/distrho/src/lv2/options.h View File

@@ -0,0 +1,132 @@
/*
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 */

+ 49
- 0
source/modules/distrho/src/lv2/parameters.h View File

@@ -0,0 +1,49 @@
/*
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 */

+ 55
- 0
source/modules/distrho/src/lv2/patch.h View File

@@ -0,0 +1,55 @@
/*
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__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 */

+ 64
- 0
source/modules/distrho/src/lv2/port-groups.h View File

@@ -0,0 +1,64 @@
/*
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 */

+ 42
- 0
source/modules/distrho/src/lv2/port-props.h View File

@@ -0,0 +1,42 @@
/*
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 */

+ 34
- 0
source/modules/distrho/src/lv2/presets.h View File

@@ -0,0 +1,34 @@
/*
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 */

+ 72
- 0
source/modules/distrho/src/lv2/resize-port.h View File

@@ -0,0 +1,72 @@
/*
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 */


+ 352
- 0
source/modules/distrho/src/lv2/state.h View File

@@ -0,0 +1,352 @@
/*
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 */

+ 49
- 0
source/modules/distrho/src/lv2/time.h View File

@@ -0,0 +1,49 @@
/*
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 */

+ 407
- 0
source/modules/distrho/src/lv2/ui.h View File

@@ -0,0 +1,407 @@
/*
LV2 UI Extension
Copyright 2009-2012 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__touch LV2_UI_PREFIX "touch"
#define LV2_UI__ui LV2_UI_PREFIX "ui"

/**
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 LV2_UI_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__idle)

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;

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

+ 62
- 0
source/modules/distrho/src/lv2/units.h View File

@@ -0,0 +1,62 @@
/*
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 */

+ 98
- 0
source/modules/distrho/src/lv2/uri-map.h View File

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

+ 129
- 0
source/modules/distrho/src/lv2/urid.h View File

@@ -0,0 +1,129 @@
/*
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 */

+ 158
- 0
source/modules/distrho/src/lv2/worker.h View File

@@ -0,0 +1,158 @@
/*
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 */

+ 279
- 0
source/modules/distrho/src/vestige/aeffectx.h View File

@@ -0,0 +1,279 @@
/*
* 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

Loading…
Cancel
Save