summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Zammit <damien@zamaudio.com>2014-07-01 10:13:53 +1000
committerDamien Zammit <damien@zamaudio.com>2014-07-01 10:13:53 +1000
commit6fa6eca23b325440e4ab0b446778b45557ef9e06 (patch)
tree17d7a75ea0a33dbdd85a7c62b107750e66af0cd5
parentb51773a233035475a3c037b499e45e13d646bbb0 (diff)
parent0eb196951d47e45fe44af0d38d453a5fdedb2e40 (diff)
Merge pull request #15 from falkTX/master
Update libs
-rw-r--r--.gitignore1
-rw-r--r--libs/dgl/NanoVG.hpp42
-rw-r--r--libs/dgl/Widget.hpp11
-rw-r--r--libs/dgl/src/NanoVG.cpp86
-rw-r--r--libs/dgl/src/Widget.cpp6
-rw-r--r--libs/dgl/src/Window.cpp35
-rw-r--r--libs/dgl/src/nanovg/stb_image.c16
-rw-r--r--libs/dgl/src/pugl/pugl_osx_extended.h38
-rw-r--r--libs/dgl/src/pugl/pugl_osx_extended.m104
-rw-r--r--libs/distrho/src/DistrhoPluginLADSPA+DSSI.cpp2
-rw-r--r--libs/distrho/src/DistrhoPluginLV2export.cpp2
-rw-r--r--libs/distrho/src/DistrhoUI.cpp14
-rw-r--r--libs/distrho/src/DistrhoUIInternal.hpp30
-rw-r--r--libs/distrho/src/DistrhoUILV2.cpp24
-rw-r--r--libs/distrho/src/lv2/lv2.h21
-rw-r--r--libs/distrho/src/lv2/ui.h200
16 files changed, 242 insertions, 390 deletions
diff --git a/.gitignore b/.gitignore
index 0607f31..48752df 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,6 +12,7 @@ bin/*-dssi/
bin/*.lv2/
libs/lv2_ttl_generator
+bin/ZamAutoSat
bin/ZaMultiComp
bin/ZaMultiCompX2
bin/ZamComp
diff --git a/libs/dgl/NanoVG.hpp b/libs/dgl/NanoVG.hpp
index f3b1b1d..8d6642b 100644
--- a/libs/dgl/NanoVG.hpp
+++ b/libs/dgl/NanoVG.hpp
@@ -38,21 +38,11 @@ class NanoImage
{
public:
/**
- Constructor for null image.
- */
- NanoImage() noexcept;
-
- /**
Destructor.
*/
~NanoImage();
/**
- Check if this is a valid image.
- */
- bool isValid() const noexcept;
-
- /**
Get size.
*/
Size<int> getSize() const;
@@ -62,25 +52,19 @@ public:
*/
void updateImage(const uchar* data);
- /**
- Operator =.
- Takes the image data from @a img, invalidating it.
- */
- NanoImage operator=(NanoImage img) noexcept;
-
protected:
/**
Constructors are protected.
NanoImages must be created within a NanoVG or NanoWidget class.
*/
- NanoImage(const char* filename);
- NanoImage(uchar* data, int ndata);
- NanoImage(int w, int h, const uchar* data);
+ NanoImage(NVGcontext* context, int imageId) noexcept;
private:
NVGcontext* fContext;
int fImageId;
friend class NanoVG;
+
+ DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(NanoImage)
};
// -----------------------------------------------------------------------
@@ -299,6 +283,11 @@ public:
void beginFrame(int width, int height, float scaleFactor = 1.0f, Alpha alpha = PREMULTIPLIED_ALPHA);
/**
+ Begin drawing a new frame inside a widget.
+ */
+ void beginFrame(Widget* widget);
+
+ /**
Ends drawing flushing remaining render state.
*/
void endFrame();
@@ -529,17 +518,17 @@ public:
/**
Creates image by loading it from the disk from specified file name.
*/
- NanoImage createImage(const char* filename);
+ NanoImage* createImage(const char* filename);
/**
Creates image by loading it from the specified chunk of memory.
*/
- NanoImage createImageMem(uchar* data, int ndata);
+ NanoImage* createImageMem(uchar* data, int ndata);
/**
Creates image from specified image data.
*/
- NanoImage createImageRGBA(int w, int h, const uchar* data);
+ NanoImage* createImageRGBA(int w, int h, const uchar* data);
/* --------------------------------------------------------------------
* Paints */
@@ -568,12 +557,12 @@ public:
Paint radialGradient(float cx, float cy, float inr, float outr, const Color& icol, const Color& ocol);
/**
- Creates and returns an image patter. Parameters (ox,oy) specify the left-top location of the image pattern,
+ Creates and returns an image pattern. Parameters (ox,oy) specify the left-top location of the image pattern,
(ex,ey) the size of one image, angle rotation around the top-left corner, image is handle to the image to render,
and repeat tells if the image should be repeated across x or y.
The gradient is transformed by the current transform when it is passed to fillPaint() or strokePaint().
*/
- Paint imagePattern(float ox, float oy, float ex, float ey, float angle, const NanoImage& image, PatternRepeat repeat);
+ Paint imagePattern(float ox, float oy, float ex, float ey, float angle, const NanoImage* image, PatternRepeat repeat);
/* --------------------------------------------------------------------
* Scissoring */
@@ -794,7 +783,10 @@ public:
*/
NanoWidget(Window& parent)
: Widget(parent),
- NanoVG() {}
+ NanoVG()
+ {
+ setNeedsScaling(true);
+ }
protected:
/**
diff --git a/libs/dgl/Widget.hpp b/libs/dgl/Widget.hpp
index 5d112aa..74b4f80 100644
--- a/libs/dgl/Widget.hpp
+++ b/libs/dgl/Widget.hpp
@@ -297,16 +297,25 @@ protected:
virtual void onResize(const ResizeEvent&);
/**
- Tell the parent window this widget this the full viewport.
+ Tell the parent window this widget needs the full viewport.
When enabled, the local widget coordinates are ignored.
@note: This is an internal function;
You do not need it under normal circumstances.
*/
void setNeedsFullViewport(bool yesNo) noexcept;
+ /**
+ Tell the parent window this widget needs scaling.
+ When enabled, the widget viewport is scaled to match width&height.
+ @note: This is an internal function;
+ You do not need it under normal circumstances.
+ */
+ void setNeedsScaling(bool yesNo) noexcept;
+
private:
Window& fParent;
bool fNeedsFullViewport;
+ bool fNeedsScaling;
bool fVisible;
Rectangle<int> fArea;
diff --git a/libs/dgl/src/NanoVG.cpp b/libs/dgl/src/NanoVG.cpp
index b4e3103..78b6bc2 100644
--- a/libs/dgl/src/NanoVG.cpp
+++ b/libs/dgl/src/NanoVG.cpp
@@ -15,6 +15,7 @@
*/
#include "../NanoVG.hpp"
+#include "../Window.hpp"
// -----------------------------------------------------------------------
@@ -48,7 +49,7 @@ NanoVG::Color::Color(const NVGcolor& c) noexcept
NanoVG::Color::operator NVGcolor() const noexcept
{
- NVGcolor nc = { r, g, b, a };
+ NVGcolor nc = {{{ r, g, b, a }}};
return nc;
}
@@ -83,33 +84,9 @@ NanoVG::Paint::operator NVGpaint() const noexcept
// -----------------------------------------------------------------------
// NanoImage
-static NVGcontext* sLastContext = nullptr;
-
-NanoImage::NanoImage() noexcept
- : fContext(nullptr),
- fImageId(0) {}
-
-#if 0
-NanoImage::NanoImage(NanoImage& img) noexcept
- : fContext(img.fContext),
- fImageId(img.fImageId)
-{
- img.fContext = nullptr;
- img.fImageId = 0;
-}
-#endif
-
-NanoImage::NanoImage(const char* filename)
- : fContext(sLastContext),
- fImageId((fContext != nullptr) ? nvgCreateImage(fContext, filename) : 0) {}
-
-NanoImage::NanoImage(uchar* data, int ndata)
- : fContext(sLastContext),
- fImageId((fContext != nullptr) ? nvgCreateImageMem(fContext, data, ndata) : 0) {}
-
-NanoImage::NanoImage(int w, int h, const uchar* data)
- : fContext(sLastContext),
- fImageId((fContext != nullptr) ? nvgCreateImageRGBA(fContext, w, h, data) : 0) {}
+NanoImage::NanoImage(NVGcontext* context, int imageId) noexcept
+ : fContext(context),
+ fImageId(imageId) {}
NanoImage::~NanoImage()
{
@@ -117,11 +94,6 @@ NanoImage::~NanoImage()
nvgDeleteImage(fContext, fImageId);
}
-bool NanoImage::isValid() const noexcept
-{
- return (fContext != nullptr && fImageId != 0);
-}
-
Size<int> NanoImage::getSize() const
{
int w=0, h=0;
@@ -138,20 +110,6 @@ void NanoImage::updateImage(const uchar* data)
nvgUpdateImage(fContext, fImageId, data);
}
-NanoImage NanoImage::operator=(NanoImage img) noexcept
-{
- if (fContext != nullptr && fImageId != 0)
- nvgDeleteImage(fContext, fImageId);
-
- fContext = img.fContext;
- fImageId = img.fImageId;
-
- img.fContext = nullptr;
- img.fImageId = 0;
-
- return *this;
-}
-
// -----------------------------------------------------------------------
// NanoVG
@@ -182,6 +140,14 @@ void NanoVG::beginFrame(int width, int height, float scaleFactor, Alpha alpha)
nvgBeginFrame(fContext, width, height, scaleFactor, static_cast<NVGalpha>(alpha));
}
+void NanoVG::beginFrame(Widget* widget)
+{
+ DISTRHO_SAFE_ASSERT_RETURN(widget != nullptr,);
+
+ Window& window(widget->getParentWindow());
+ nvgBeginFrame(fContext, window.getWidth(), window.getHeight(), 1.0f, NVG_PREMULTIPLIED_ALPHA);
+}
+
void NanoVG::endFrame()
{
nvgEndFrame(fContext);
@@ -392,22 +358,25 @@ float NanoVG::radToDeg(float rad)
// -----------------------------------------------------------------------
// Images
-NanoImage NanoVG::createImage(const char* filename)
+NanoImage* NanoVG::createImage(const char* filename)
{
- sLastContext = fContext;
- return NanoImage(filename);
+ if (const int imageId = nvgCreateImage(fContext, filename))
+ return new NanoImage(fContext, imageId);
+ return nullptr;
}
-NanoImage NanoVG::createImageMem(uchar* data, int ndata)
+NanoImage* NanoVG::createImageMem(uchar* data, int ndata)
{
- sLastContext = fContext;
- return NanoImage(data, ndata);
+ if (const int imageId = nvgCreateImageMem(fContext, data, ndata))
+ return new NanoImage(fContext, imageId);
+ return nullptr;
}
-NanoImage NanoVG::createImageRGBA(int w, int h, const uchar* data)
+NanoImage* NanoVG::createImageRGBA(int w, int h, const uchar* data)
{
- sLastContext = fContext;
- return NanoImage(w, h, data);
+ if (const int imageId = nvgCreateImageRGBA(fContext, w, h, data))
+ return new NanoImage(fContext, imageId);
+ return nullptr;
}
// -----------------------------------------------------------------------
@@ -428,9 +397,10 @@ NanoVG::Paint NanoVG::radialGradient(float cx, float cy, float inr, float outr,
return nvgRadialGradient(fContext, cx, cy, inr, outr, icol, ocol);
}
-NanoVG::Paint NanoVG::imagePattern(float ox, float oy, float ex, float ey, float angle, const NanoImage& image, NanoVG::PatternRepeat repeat)
+NanoVG::Paint NanoVG::imagePattern(float ox, float oy, float ex, float ey, float angle, const NanoImage* image, NanoVG::PatternRepeat repeat)
{
- return nvgImagePattern(fContext, ox, oy, ex, ey, angle, image.fImageId, repeat);
+ DISTRHO_SAFE_ASSERT_RETURN(image != nullptr, Paint());
+ return nvgImagePattern(fContext, ox, oy, ex, ey, angle, image->fImageId, repeat);
}
// -----------------------------------------------------------------------
diff --git a/libs/dgl/src/Widget.cpp b/libs/dgl/src/Widget.cpp
index aee727b..a494d1b 100644
--- a/libs/dgl/src/Widget.cpp
+++ b/libs/dgl/src/Widget.cpp
@@ -25,6 +25,7 @@ START_NAMESPACE_DGL
Widget::Widget(Window& parent)
: fParent(parent),
fNeedsFullViewport(false),
+ fNeedsScaling(false),
fVisible(true)
{
fParent._addWidget(this);
@@ -230,6 +231,11 @@ void Widget::setNeedsFullViewport(bool yesNo) noexcept
fNeedsFullViewport = yesNo;
}
+void Widget::setNeedsScaling(bool yesNo) noexcept
+{
+ fNeedsScaling = yesNo;
+}
+
// -----------------------------------------------------------------------
END_NAMESPACE_DGL
diff --git a/libs/dgl/src/Window.cpp b/libs/dgl/src/Window.cpp
index 0ee57f4..f2c92e7 100644
--- a/libs/dgl/src/Window.cpp
+++ b/libs/dgl/src/Window.cpp
@@ -26,9 +26,7 @@
#if defined(DISTRHO_OS_WINDOWS)
# include "pugl/pugl_win.cpp"
#elif defined(DISTRHO_OS_MAC)
-extern "C" {
# include "pugl/pugl_osx.m"
-}
#elif defined(DISTRHO_OS_LINUX)
# include <sys/types.h>
# include <unistd.h>
@@ -57,8 +55,6 @@ extern "C" {
START_NAMESPACE_DGL
-Window* dgl_lastUiParent = nullptr;
-
// -----------------------------------------------------------------------
// Window Private
@@ -164,12 +160,9 @@ struct Window::PrivateData {
if (fSelf == nullptr || fView == nullptr)
{
DBG("Failed!\n");
- dgl_lastUiParent = nullptr;
return;
}
- dgl_lastUiParent = fSelf;
-
puglInitResizable(fView, fResizable);
puglSetHandle(fView, this);
@@ -569,6 +562,8 @@ struct Window::PrivateData {
{
fSelf->onDisplayBefore();
+ bool needsDisableScissor = false;
+
FOR_EACH_WIDGET(it)
{
Widget* const widget(*it);
@@ -582,24 +577,30 @@ struct Window::PrivateData {
{
// full viewport size
glViewport(0, 0, fView->width, fView->height);
+ }
+ else if (! widget->fNeedsScaling)
+ {
+ // only set viewport pos
+ glViewport(widget->getAbsoluteX(), /*fView->height - widget->getHeight()*/ - widget->getAbsoluteY(), fView->width, fView->height);
- // display widget
- widget->onDisplay();
+ // then cut the outer bounds
+ glScissor(widget->getAbsoluteX(), fView->height - widget->getHeight() - widget->getAbsoluteY(), widget->getWidth(), widget->getHeight());
+ glEnable(GL_SCISSOR_TEST);
+ needsDisableScissor = true;
}
else
{
// limit viewport to widget bounds
glViewport(widget->getAbsoluteX(), fView->height - widget->getHeight() - widget->getAbsoluteY(), widget->getWidth(), widget->getHeight());
+ }
- // scale contents to match viewport size
- glPushMatrix();
- glScalef(float(fView->width)/float(widget->getWidth()), float(fView->height)/float(widget->getHeight()), 1.0f);
-
- // display widget
- widget->onDisplay();
+ // display widget
+ widget->onDisplay();
- // done
- glPopMatrix();
+ if (needsDisableScissor)
+ {
+ glDisable(GL_SCISSOR_TEST);
+ needsDisableScissor = false;
}
}
}
diff --git a/libs/dgl/src/nanovg/stb_image.c b/libs/dgl/src/nanovg/stb_image.c
index 1ec363b..d72ee6a 100644
--- a/libs/dgl/src/nanovg/stb_image.c
+++ b/libs/dgl/src/nanovg/stb_image.c
@@ -2261,13 +2261,13 @@ static void init_defaults(void)
int stbi_png_partial; // a quick hack to only allow decoding some of a PNG... I should implement real streaming support instead
static int parse_zlib(zbuf *a, int parse_header)
{
- int final, type;
+ int final_, type;
if (parse_header)
if (!parse_zlib_header(a)) return 0;
a->num_bits = 0;
a->code_buffer = 0;
do {
- final = zreceive(a,1);
+ final_ = zreceive(a,1);
type = zreceive(a,2);
if (type == 0) {
if (!parse_uncompressed_block(a)) return 0;
@@ -2286,7 +2286,7 @@ static int parse_zlib(zbuf *a, int parse_header)
}
if (stbi_png_partial && a->zout - a->zout_start > 65536)
break;
- } while (!final);
+ } while (!final_);
return 1;
}
@@ -2519,7 +2519,7 @@ static int create_png_image_raw(png *a, uint8 *raw, uint32 raw_len, int out_n, u
static int create_png_image(png *a, uint8 *raw, uint32 raw_len, int out_n, int interlaced)
{
- uint8 *final;
+ uint8 *final_;
int p;
int save;
if (!interlaced)
@@ -2528,7 +2528,7 @@ static int create_png_image(png *a, uint8 *raw, uint32 raw_len, int out_n, int i
stbi_png_partial = 0;
// de-interlacing
- final = (uint8 *) malloc(a->s->img_x * a->s->img_y * out_n);
+ final_ = (uint8 *) malloc(a->s->img_x * a->s->img_y * out_n);
for (p=0; p < 7; ++p) {
int xorig[] = { 0,4,0,2,0,1,0 };
int yorig[] = { 0,0,4,0,2,0,1 };
@@ -2540,19 +2540,19 @@ static int create_png_image(png *a, uint8 *raw, uint32 raw_len, int out_n, int i
y = (a->s->img_y - yorig[p] + yspc[p]-1) / yspc[p];
if (x && y) {
if (!create_png_image_raw(a, raw, raw_len, out_n, x, y)) {
- free(final);
+ free(final_);
return 0;
}
for (j=0; j < y; ++j)
for (i=0; i < x; ++i)
- memcpy(final + (j*yspc[p]+yorig[p])*a->s->img_x*out_n + (i*xspc[p]+xorig[p])*out_n,
+ memcpy(final_ + (j*yspc[p]+yorig[p])*a->s->img_x*out_n + (i*xspc[p]+xorig[p])*out_n,
a->out + (j*x+i)*out_n, out_n);
free(a->out);
raw += (x*out_n+1)*y;
raw_len -= (x*out_n+1)*y;
}
}
- a->out = final;
+ a->out = final_;
stbi_png_partial = save;
return 1;
diff --git a/libs/dgl/src/pugl/pugl_osx_extended.h b/libs/dgl/src/pugl/pugl_osx_extended.h
deleted file mode 100644
index d718eb5..0000000
--- a/libs/dgl/src/pugl/pugl_osx_extended.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- Copyright 2012 David Robillard <http://drobilla.net>
- Copyright 2013 Filipe Coelho <falktx@falktx.com>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-
-/**
- @file pugl_osx_extended.h Extended OSX/Cocoa Pugl Implementation.
-*/
-
-#include <stdbool.h>
-
-#include "pugl.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-void puglImplIdle(PuglView* view);
-void puglImplFocus(PuglView* view);
-void puglImplSetSize(PuglView* view, unsigned int width, unsigned int height, bool forced);
-void puglImplSetTitle(PuglView* view, const char* title);
-void puglImplSetVisible(PuglView* view, bool yesNo);
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
diff --git a/libs/dgl/src/pugl/pugl_osx_extended.m b/libs/dgl/src/pugl/pugl_osx_extended.m
deleted file mode 100644
index d638dc0..0000000
--- a/libs/dgl/src/pugl/pugl_osx_extended.m
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- Copyright 2012 David Robillard <http://drobilla.net>
- Copyright 2013 Filipe Coelho <falktx@falktx.com>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-
-/**
- @file pugl_osx_extended.m Extended OSX/Cocoa Pugl Implementation.
-*/
-
-#import "pugl_osx.m"
-
-#include "pugl_osx_extended.h"
-
-void puglImplIdle(PuglView* view)
-{
- NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
- NSEvent* event;
-
- static const NSUInteger eventMask = (NSLeftMouseDownMask | NSLeftMouseUpMask |
- NSRightMouseDownMask | NSRightMouseUpMask |
- NSMouseMovedMask |
- NSLeftMouseDraggedMask | NSRightMouseDraggedMask |
- NSMouseEnteredMask | NSMouseExitedMask |
- NSKeyDownMask | NSKeyUpMask |
- NSFlagsChangedMask |
- NSCursorUpdateMask | NSScrollWheelMask);
-
- for (;;) {
- event = [view->impl->window
- nextEventMatchingMask:eventMask
- untilDate:[NSDate distantPast]
- inMode:NSEventTrackingRunLoopMode
- dequeue:YES];
-
- if (event == nil)
- break;
-
- [view->impl->window sendEvent: event];
- }
-
- [pool release];
-}
-
-void puglImplFocus(PuglView* view)
-{
- id window = view->impl->window;
-
- // TODO
- [NSApp activateIgnoringOtherApps:YES];
- [window makeKeyAndOrderFront:window];
-}
-
-void puglImplSetSize(PuglView* view, unsigned int width, unsigned int height, bool forced)
-{
- id window = view->impl->window;
-
- NSRect frame = [window frame];
- frame.origin.y -= height - frame.size.height;
- frame.size.width = width;
- frame.size.height = height+20;
-
-// if (forced) {
-// [window setFrame:frame];
-// } else {
- [window setFrame:frame display:YES animate:NO];
-// }
-
- // unused
- return; (void)forced;
-}
-
-void puglImplSetTitle(PuglView* view, const char* title)
-{
- id window = view->impl->window;
-
- NSString* titleString = [[NSString alloc]
- initWithBytes:title
- length:strlen(title)
- encoding:NSUTF8StringEncoding];
-
- [window setTitle:titleString];
-}
-
-void puglImplSetVisible(PuglView* view, bool yesNo)
-{
- id window = view->impl->window;
-
- if (yesNo)
- [window setIsVisible:YES];
- else
- [window setIsVisible:NO];
-}
diff --git a/libs/distrho/src/DistrhoPluginLADSPA+DSSI.cpp b/libs/distrho/src/DistrhoPluginLADSPA+DSSI.cpp
index 0cb062d..1194624 100644
--- a/libs/distrho/src/DistrhoPluginLADSPA+DSSI.cpp
+++ b/libs/distrho/src/DistrhoPluginLADSPA+DSSI.cpp
@@ -557,7 +557,7 @@ public:
// Set latency port
portNames[port] = strdup("_latency");
portDescriptors[port] = LADSPA_PORT_CONTROL | LADSPA_PORT_OUTPUT;
- portRangeHints[port].HintDescriptor = LADSPA_HINT_SAMPLE_RATE;
+ portRangeHints[port].HintDescriptor = LADSPA_HINT_SAMPLE_RATE|LADSPA_HINT_INTEGER;
portRangeHints[port].LowerBound = 0.0f;
portRangeHints[port].UpperBound = 1.0f;
++port;
diff --git a/libs/distrho/src/DistrhoPluginLV2export.cpp b/libs/distrho/src/DistrhoPluginLV2export.cpp
index 189d941..556d466 100644
--- a/libs/distrho/src/DistrhoPluginLV2export.cpp
+++ b/libs/distrho/src/DistrhoPluginLV2export.cpp
@@ -275,7 +275,7 @@ void lv2_generate_ttl(const char* const basename)
pluginString += " lv2:name \"Latency\" ;\n";
pluginString += " lv2:symbol \"lv2_latency\" ;\n";
pluginString += " lv2:designation lv2:latency ;\n";
- pluginString += " lv2:portProperty lv2:reportsLatency ;\n";
+ pluginString += " lv2:portProperty lv2:reportsLatency, lv2:integer ;\n";
pluginString += " ] ;\n\n";
++portIndex;
#endif
diff --git a/libs/distrho/src/DistrhoUI.cpp b/libs/distrho/src/DistrhoUI.cpp
index a2e0368..c46425e 100644
--- a/libs/distrho/src/DistrhoUI.cpp
+++ b/libs/distrho/src/DistrhoUI.cpp
@@ -16,28 +16,22 @@
#include "DistrhoUIInternal.hpp"
-START_NAMESPACE_DGL
-extern Window* dgl_lastUiParent;
-END_NAMESPACE_DGL
-
START_NAMESPACE_DISTRHO
// -----------------------------------------------------------------------
// Static data, see DistrhoUIInternal.hpp
-double d_lastUiSampleRate = 0.0;
+double d_lastUiSampleRate = 0.0;
+void* d_lastUiDspPtr = nullptr;
+Window* d_lastUiWindow = nullptr;
// -----------------------------------------------------------------------
// UI
UI::UI()
- : UIWidget(*DGL::dgl_lastUiParent),
+ : UIWidget(*d_lastUiWindow),
pData(new PrivateData())
{
- DISTRHO_SAFE_ASSERT(DGL::dgl_lastUiParent != nullptr);
-
- DGL::dgl_lastUiParent = nullptr;
-
Widget::setNeedsFullViewport(true);
}
diff --git a/libs/distrho/src/DistrhoUIInternal.hpp b/libs/distrho/src/DistrhoUIInternal.hpp
index 00cddf8..15b65ca 100644
--- a/libs/distrho/src/DistrhoUIInternal.hpp
+++ b/libs/distrho/src/DistrhoUIInternal.hpp
@@ -31,7 +31,9 @@ START_NAMESPACE_DISTRHO
// -----------------------------------------------------------------------
// Static data, see DistrhoUI.cpp
-extern double d_lastUiSampleRate;
+extern double d_lastUiSampleRate;
+extern void* d_lastUiDspPtr;
+extern Window* d_lastUiWindow;
// -----------------------------------------------------------------------
// UI callbacks
@@ -65,7 +67,7 @@ struct UI::PrivateData {
: sampleRate(d_lastUiSampleRate),
parameterOffset(0),
#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
- dspPtr(nullptr),
+ dspPtr(d_lastUiDspPtr),
#endif
editParamCallbackFunc(nullptr),
setParamCallbackFunc(nullptr),
@@ -127,12 +129,23 @@ struct UI::PrivateData {
// -----------------------------------------------------------------------
// Plugin Window, needed to take care of resize properly
+static inline
+UI* createUiWrapper(void* const dspPtr, Window* const window)
+{
+ d_lastUiDspPtr = dspPtr;
+ d_lastUiWindow = window;
+ UI* const ret = createUI();
+ d_lastUiDspPtr = nullptr;
+ d_lastUiWindow = nullptr;
+ return ret;
+}
+
class UIExporterWindow : public Window
{
public:
- UIExporterWindow(App& app, const intptr_t winId)
+ UIExporterWindow(App& app, const intptr_t winId, void* const dspPtr)
: Window(app, winId),
- fUi(createUI()),
+ fUi(createUiWrapper(dspPtr, this)),
fIsReady(false)
{
DISTRHO_SAFE_ASSERT_RETURN(fUi != nullptr,);
@@ -182,7 +195,7 @@ public:
const editParamFunc editParamCall, const setParamFunc setParamCall, const setStateFunc setStateCall, const sendNoteFunc sendNoteCall, const setSizeFunc setSizeCall,
void* const dspPtr = nullptr)
: glApp(),
- glWindow(glApp, winId),
+ glWindow(glApp, winId, dspPtr),
fUi(glWindow.getUI()),
fData((fUi != nullptr) ? fUi->pData : nullptr)
{
@@ -195,13 +208,6 @@ public:
fData->setStateCallbackFunc = setStateCall;
fData->sendNoteCallbackFunc = sendNoteCall;
fData->setSizeCallbackFunc = setSizeCall;
-
-#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
- fData->dspPtr = dspPtr;
-#else
- return; // unused
- (void)dspPtr;
-#endif
}
// -------------------------------------------------------------------
diff --git a/libs/distrho/src/DistrhoUILV2.cpp b/libs/distrho/src/DistrhoUILV2.cpp
index 93feefb..fbce23e 100644
--- a/libs/distrho/src/DistrhoUILV2.cpp
+++ b/libs/distrho/src/DistrhoUILV2.cpp
@@ -47,9 +47,7 @@ public:
fKeyValueURID(uridMap->map(uridMap->handle, "urn:distrho:keyValueState")),
fWinIdWasNull(winId == 0)
{
- if (winId == 0)
- fUI.setTitle(fUI.getName());
- else if (fUiResize != nullptr)
+ if (fUiResize != nullptr && winId != 0)
fUiResize->ui_resize(fUiResize->handle, fUI.getWidth(), fUI.getHeight());
#if DISTRHO_PLUGIN_WANT_STATE
@@ -60,8 +58,11 @@ public:
if (winId != 0)
return;
+ const LV2_URID uridWindowTitle(uridMap->map(uridMap->handle, LV2_UI__windowTitle));
const LV2_URID uridFrontendWinId(uridMap->map(uridMap->handle, "http://kxstudio.sf.net/ns/carla/frontendWinId"));
+ bool hasTitle = false;
+
for (int i=0; options[i].key != 0; ++i)
{
if (options[i].key == uridFrontendWinId)
@@ -73,9 +74,24 @@ public:
}
else
d_stderr("Host provides frontendWinId but has wrong value type");
- break;
+ }
+ else if (options[i].key == uridWindowTitle)
+ {
+ if (options[i].type == uridMap->map(uridMap->handle, LV2_ATOM__String))
+ {
+ if (const char* const windowTitle = (const char*)options[i].value)
+ {
+ hasTitle = true;
+ fUI.setTitle(windowTitle);
+ }
+ }
+ else
+ d_stderr("Host provides windowTitle but has wrong value type");
}
}
+
+ if (! hasTitle)
+ fUI.setTitle(fUI.getName());
}
// -------------------------------------------------------------------
diff --git a/libs/distrho/src/lv2/lv2.h b/libs/distrho/src/lv2/lv2.h
index 220fbb0..6e0edaa 100644
--- a/libs/distrho/src/lv2/lv2.h
+++ b/libs/distrho/src/lv2/lv2.h
@@ -353,19 +353,15 @@ typedef struct _LV2_Descriptor {
/**
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).
+ This is the simple plugin discovery API, suitable for most statically
+ defined plugins. Advanced plugins that need access to their bundle during
+ discovery can use lv2_lib_descriptor() instead. Plugin libraries MUST
+ include a function called "lv2_descriptor" or "lv2_lib_descriptor" with
+ C-style linkage, but SHOULD provide "lv2_descriptor" wherever possible.
When it is time to load a plugin (designated by its URI), the host loads the
plugin's library, gets the lv2_descriptor() function from it, and uses this
@@ -431,6 +427,13 @@ typedef struct {
/**
Prototype for library accessor function.
+ This is the more advanced discovery API, which allows plugin libraries to
+ access their bundles during discovery, which makes it possible for plugins to
+ be dynamically defined by files in their bundle. This API also has an
+ explicit cleanup function, removing any need for non-portable shared library
+ destructors. Simple plugins that do not require these features may use
+ lv2_descriptor() instead.
+
This is the entry point for a plugin library. Hosts load this symbol from
the library and call this function to obtain a library descriptor which can
be used to access all the contained plugins. The returned object must not
diff --git a/libs/distrho/src/lv2/ui.h b/libs/distrho/src/lv2/ui.h
index e2418d3..9ee4bd1 100644
--- a/libs/distrho/src/lv2/ui.h
+++ b/libs/distrho/src/lv2/ui.h
@@ -1,6 +1,6 @@
/*
LV2 UI Extension
- Copyright 2009-2013 David Robillard <d@drobilla.net>
+ Copyright 2009-2014 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
@@ -17,8 +17,9 @@
*/
/**
- @file ui.h
- C header for the LV2 UI extension <http://lv2plug.in/ns/extensions/ui>.
+ @file ui.h User Interface API.
+
+ For high-level documentation, see <http://lv2plug.in/ns/extensions/ui>.
*/
#ifndef LV2_UI_H
@@ -55,6 +56,7 @@
#define LV2_UI__touch LV2_UI_PREFIX "touch"
#define LV2_UI__ui LV2_UI_PREFIX "ui"
#define LV2_UI__updateRate LV2_UI_PREFIX "updateRate"
+#define LV2_UI__windowTitle LV2_UI_PREFIX "windowTitle"
/**
The index returned by LV2_UI_Port_Port::port_index() for unknown ports.
@@ -75,20 +77,16 @@ extern "C" {
typedef void* LV2UI_Widget;
/**
- A pointer to an instance of a UI.
+ A pointer to UI instance internals.
- 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.
+ The host may compare this to NULL, but otherwise MUST NOT interpret it.
*/
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.
+ The UI may compare this to NULL, but otherwise MUST NOT interpret it.
*/
typedef void* LV2UI_Controller;
@@ -98,22 +96,20 @@ typedef void* LV2UI_Controller;
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.
+ A host-provided function that sends data to a plugin's input ports.
- The @p buffer parameter must point to a block of data, @c buffer_size bytes
+ The @p buffer parameter must point to a block of data, @p 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 port MUST be an lv2:ControlPort input, @p buffer MUST point to a single
+ float value, and @p 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.
+ The UI SHOULD NOT use a protocol not supported by the host, but the host
+ MUST gracefully ignore any protocol it does not understand.
*/
typedef void (*LV2UI_Write_Function)(LV2UI_Controller controller,
uint32_t port_index,
@@ -122,7 +118,7 @@ typedef void (*LV2UI_Write_Function)(LV2UI_Controller controller,
const void* buffer);
/**
- The implementation of a UI.
+ A plugin UI.
A pointer to an object of this type is returned by the lv2ui_descriptor()
function.
@@ -134,32 +130,29 @@ typedef struct _LV2UI_Descriptor {
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.
+ Create a new UI and return a handle to it. This function works
+ similarly to LV2_Descriptor::instantiate().
- @param descriptor The descriptor for the UI that you want to instantiate.
+ @param descriptor The descriptor for the UI 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 bundle_path The path to the bundle containing this UI, including
+ the trailing directory separator.
- @param write_function A function provided by the host that the UI can use
- to send data to the plugin's input ports.
+ @param write_function A function 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 controller A handle for the plugin instance to be passed as the
+ first parameter of UI methods.
- @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 widget (output) widget pointer. The UI points this at its main
+ widget, which has the type defined by the UI type in the data file.
- @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.
+ @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, as
+ in LV2_Descriptor::instantiate(). Note that UI features and plugin
+ features are not necessarily the same.
*/
LV2UI_Handle (*instantiate)(const struct _LV2UI_Descriptor* descriptor,
@@ -172,33 +165,29 @@ typedef struct _LV2UI_Descriptor {
/**
- Destroy the UI object and the associated widget. The host must not try
- to access the widget after calling this function.
+ Destroy the UI. 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.
+ What is "interesting" and how it is written to @p buffer is defined by
+ @p format, which has the same meaning as in LV2UI_Write_Function().
+ Format 0 is a special case for lv2:ControlPort, where this function
+ should be called when the port value changes (but not necessarily for
+ every change), @p buffer_size must be sizeof(float), and @p buffer
+ points to a single IEEE-754 float.
+
+ By default, the host should only call this function for lv2:ControlPort
+ inputs. However, the UI can request updates for other ports statically
+ with ui:portNotification or dynamicaly with ui:portSubscribe.
+
+ The UI MUST NOT retain any reference to @p buffer after this function
+ returns, it is only valid for the duration of the call.
+
+ This member may be NULL if the UI is not interested in any port events.
*/
void (*port_event)(LV2UI_Handle ui,
uint32_t port_index,
@@ -207,22 +196,21 @@ typedef struct _LV2UI_Descriptor {
const void* buffer);
/**
- Return a data structure associated with an extension URI, for example
- a struct containing additional function pointers.
+ Return a data structure associated with an extension URI, typically an
+ interface struct with 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.
+ This member may be set to NULL if the UI is not interested in supporting
+ any extensions. This is similar to LV2_Descriptor::extension_data().
+
*/
const void* (*extension_data)(const char* uri);
} LV2UI_Descriptor;
/**
- UI Resize Feature (LV2_UI__resize)
+ Feature/interface for resizable UIs (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
+ This structure is used in two ways: as a feature passed by the host via
+ LV2UI_Descriptor::instantiate(), or as an interface provided by a UI via
LV2UI_Descriptor::extension_data()).
*/
typedef struct _LV2UI_Resize {
@@ -232,13 +220,13 @@ typedef struct _LV2UI_Resize {
LV2UI_Feature_Handle handle;
/**
- Request or advertise a size change.
+ Request/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 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.
+ When 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.
*/
@@ -246,16 +234,15 @@ typedef struct _LV2UI_Resize {
} LV2UI_Resize;
/**
- Port Map Feature (LV2_UI__portMap).
+ Feature to map port symbols to UIs.
- 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).
+ This 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, unlike index, is a stable port identifier).
*/
typedef struct _LV2UI_Port_Map {
/**
- Pointer to opaque data which must be passed to ui_resize().
+ Pointer to opaque data which must be passed to port_index().
*/
LV2UI_Feature_Handle handle;
@@ -269,11 +256,12 @@ typedef struct _LV2UI_Port_Map {
} LV2UI_Port_Map;
/**
- Port subscription feature (LV2_UI__portSubscribe);
+ Feature to subscribe to port updates (LV2_UI__portSubscribe).
*/
typedef struct _LV2UI_Port_Subscribe {
/**
- Pointer to opaque data which must be passed to ui_resize().
+ Pointer to opaque data which must be passed to subscribe() and
+ unsubscribe().
*/
LV2UI_Feature_Handle handle;
@@ -319,7 +307,7 @@ typedef struct _LV2UI_Port_Subscribe {
} LV2UI_Port_Subscribe;
/**
- A feature to notify the host the user has grabbed a UI control.
+ A feature to notify the host that the user has grabbed a UI control.
*/
typedef struct _LV2UI_Touch {
/**
@@ -330,6 +318,9 @@ typedef struct _LV2UI_Touch {
/**
Notify the host that a control has been grabbed or released.
+ The host should cease automating the port or otherwise manipulating the
+ port value until the control has been ungrabbed.
+
@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
@@ -341,19 +332,23 @@ typedef struct _LV2UI_Touch {
} LV2UI_Touch;
/**
- UI Idle Feature (LV2_UI__idleInterface)
+ UI Idle Interface (LV2_UI__idleInterface)
- This feature is an addition to the UI API that provides a callback for the
- host to call rapidly, e.g. to drive the idle callback of a toolkit.
+ UIs can provide this interface to have an idle() callback called by the host
+ rapidly to update the UI.
*/
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.
+ This will be called rapidly in the UI thread at a rate appropriate
+ for a toolkit main loop. There are no precise timing guarantees, but
+ the host should attempt to call idle() at a high enough rate for smooth
+ animation, at least 30Hz.
- @return 0 on success, or anything else to stop being called.
+ @return non-zero if the UI has been closed, in which case the host
+ should stop calling idle(), and can either completely destroy the UI, or
+ re-show it and resume calling idle().
*/
int (*idle)(LV2UI_Handle ui);
} LV2UI_Idle_Interface;
@@ -361,16 +356,24 @@ typedef struct _LV2UI_Idle_Interface {
/**
UI Show Interface (LV2_UI__showInterface)
- UIs can use this interface to provide show/hide methods to pop up a window,
- which allows them to function in hosts unable to embed their widget type.
+ UIs can provide this interface to show and hide a window, which allows them
+ to function in hosts unable to embed their widget. This allows any UI to
+ provide a fallback for embedding that works in any host.
- If used, LV2UI_Idle_Interface should also be used to drive the UI. The UI
- should return non-zero from idle() when the window has been closed.
+ If used:
+ - The host MUST use LV2UI_Idle_Interface to drive the UI.
+ - The UI MUST return non-zero from LV2UI_Idle_Interface::idle() when it has been closed.
+ - If idle() returns non-zero, the host MUST call hide() and stop calling
+ idle(). It MAY later call show() then resume calling idle().
*/
typedef struct _LV2UI_Show_Interface {
/**
Show a window for this UI.
+ The window title MAY have been passed by the host to
+ LV2UI_Descriptor::instantiate() as an LV2_Options_Option with key
+ LV2_UI__windowTitle.
+
@return 0 on success, or anything else to stop being called.
*/
int (*show)(LV2UI_Handle ui);
@@ -407,17 +410,10 @@ typedef struct _LV2UI_Peak_Data {
} 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.
+ Prototype for UI accessor function.
+
+ This is the entry point to a UI library, which works in the same way as
+ lv2_descriptor() but for UIs rather than plugins.
*/
LV2_SYMBOL_EXPORT
const LV2UI_Descriptor* lv2ui_descriptor(uint32_t index);