diff options
author | Damien Zammit <damien@zamaudio.com> | 2014-07-01 10:13:53 +1000 |
---|---|---|
committer | Damien Zammit <damien@zamaudio.com> | 2014-07-01 10:13:53 +1000 |
commit | 6fa6eca23b325440e4ab0b446778b45557ef9e06 (patch) | |
tree | 17d7a75ea0a33dbdd85a7c62b107750e66af0cd5 | |
parent | b51773a233035475a3c037b499e45e13d646bbb0 (diff) | |
parent | 0eb196951d47e45fe44af0d38d453a5fdedb2e40 (diff) |
Merge pull request #15 from falkTX/master
Update libs
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | libs/dgl/NanoVG.hpp | 42 | ||||
-rw-r--r-- | libs/dgl/Widget.hpp | 11 | ||||
-rw-r--r-- | libs/dgl/src/NanoVG.cpp | 86 | ||||
-rw-r--r-- | libs/dgl/src/Widget.cpp | 6 | ||||
-rw-r--r-- | libs/dgl/src/Window.cpp | 35 | ||||
-rw-r--r-- | libs/dgl/src/nanovg/stb_image.c | 16 | ||||
-rw-r--r-- | libs/dgl/src/pugl/pugl_osx_extended.h | 38 | ||||
-rw-r--r-- | libs/dgl/src/pugl/pugl_osx_extended.m | 104 | ||||
-rw-r--r-- | libs/distrho/src/DistrhoPluginLADSPA+DSSI.cpp | 2 | ||||
-rw-r--r-- | libs/distrho/src/DistrhoPluginLV2export.cpp | 2 | ||||
-rw-r--r-- | libs/distrho/src/DistrhoUI.cpp | 14 | ||||
-rw-r--r-- | libs/distrho/src/DistrhoUIInternal.hpp | 30 | ||||
-rw-r--r-- | libs/distrho/src/DistrhoUILV2.cpp | 24 | ||||
-rw-r--r-- | libs/distrho/src/lv2/lv2.h | 21 | ||||
-rw-r--r-- | libs/distrho/src/lv2/ui.h | 200 |
16 files changed, 242 insertions, 390 deletions
@@ -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); |