From bcf84559a524a8100922804f040bf600fb2d894e Mon Sep 17 00:00:00 2001 From: JP Cimalando Date: Sat, 6 Jul 2019 18:01:40 +0200 Subject: [PATCH 01/23] Set UTF8 window title using NetWM hints --- dgl/src/Window.cpp | 3 +++ dgl/src/pugl/pugl_x11.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/dgl/src/Window.cpp b/dgl/src/Window.cpp index bb9db161..0eec7972 100644 --- a/dgl/src/Window.cpp +++ b/dgl/src/Window.cpp @@ -687,6 +687,9 @@ struct Window::PrivateData { } #else XStoreName(xDisplay, xWindow, title); + Atom netWmName = XInternAtom(xDisplay, "_NET_WM_NAME", False); + Atom utf8String = XInternAtom(xDisplay, "UTF8_STRING", False); + XChangeProperty(xDisplay, xWindow, netWmName, utf8String, 8, PropModeReplace, (unsigned char *)title, strlen(title)); #endif } diff --git a/dgl/src/pugl/pugl_x11.c b/dgl/src/pugl/pugl_x11.c index 3146cfcc..2783bbbf 100644 --- a/dgl/src/pugl/pugl_x11.c +++ b/dgl/src/pugl/pugl_x11.c @@ -274,6 +274,9 @@ puglCreateWindow(PuglView* view, const char* title) if (title) { XStoreName(impl->display, impl->win, title); + Atom netWmName = XInternAtom(impl->display, "_NET_WM_NAME", False); + Atom utf8String = XInternAtom(impl->display, "UTF8_STRING", False); + XChangeProperty(impl->display, impl->win, netWmName, utf8String, 8, PropModeReplace, (unsigned char *)title, strlen(title)); } if (view->transient_parent > 0) { From a7706f24a3f76c56a44eafe16ccd0618c07ce831 Mon Sep 17 00:00:00 2001 From: JP Cimalando Date: Sat, 20 Jul 2019 09:44:14 +0200 Subject: [PATCH 02/23] Add simple file selection for Windows (#152) * Add simple file selection for Windows * Fake async for Windows file dialogs --- Makefile.base.mk | 2 +- dgl/src/Window.cpp | 56 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/Makefile.base.mk b/Makefile.base.mk index ea4d0547..6c7d17aa 100644 --- a/Makefile.base.mk +++ b/Makefile.base.mk @@ -213,7 +213,7 @@ DGL_SYSTEM_LIBS += -framework Cocoa endif ifeq ($(WINDOWS),true) -DGL_SYSTEM_LIBS += -lgdi32 +DGL_SYSTEM_LIBS += -lgdi32 -lcomdlg32 endif ifneq ($(HAIKU_OR_MACOS_OR_WINDOWS),true) diff --git a/dgl/src/Window.cpp b/dgl/src/Window.cpp index 0eec7972..b5dc1715 100644 --- a/dgl/src/Window.cpp +++ b/dgl/src/Window.cpp @@ -777,6 +777,14 @@ struct Window::PrivateData { } #endif +#if defined(DISTRHO_OS_WINDOWS) && !defined(DGL_FILE_BROWSER_DISABLED) + if (fSelectedFile.isNotEmpty()) + { + fView->fileSelectedFunc(fView, fSelectedFile.buffer()); + fSelectedFile.clear(); + } +#endif + if (fModal.enabled && fModal.parent != nullptr) fModal.parent->idle(); } @@ -1098,6 +1106,9 @@ struct Window::PrivateData { #if defined(DISTRHO_OS_WINDOWS) HWND hwnd; HWND hwndParent; +# ifndef DGL_FILE_BROWSER_DISABLED + String fSelectedFile; +# endif #elif defined(DISTRHO_OS_MAC) bool fNeedsIdle; NSView* mView; @@ -1281,6 +1292,51 @@ bool Window::openFileBrowser(const FileBrowserOptions& options) // show return (x_fib_show(pData->xDisplay, pData->xWindow, /*options.width*/0, /*options.height*/0) == 0); +# elif defined(DISTRHO_OS_WINDOWS) + // the old and compatible dialog API + OPENFILENAMEW ofn; + memset(&ofn, 0, sizeof(ofn)); + + ofn.lStructSize = sizeof(ofn); + ofn.hwndOwner = pData->hwnd; + + // set initial directory in UTF-16 coding + std::vector startDirW; + if (options.startDir) + { + startDirW.resize(strlen(options.startDir) + 1); + if (MultiByteToWideChar(CP_UTF8, 0, options.startDir, -1, startDirW.data(), startDirW.size())) + ofn.lpstrInitialDir = startDirW.data(); + } + + // set title in UTF-16 coding + std::vector titleW; + if (options.title) + { + titleW.resize(strlen(options.title) + 1); + if (MultiByteToWideChar(CP_UTF8, 0, options.title, -1, titleW.data(), titleW.size())) + ofn.lpstrTitle = titleW.data(); + } + + // prepare a buffer to receive the result + std::vector fileNameW(32768); // the Unicode maximum + ofn.lpstrFile = fileNameW.data(); + ofn.nMaxFile = (DWORD)fileNameW.size(); + + // TODO synchronous only, can't do better with WinAPI native dialogs. + // threading might work, if someone is motivated to risk it. + if (GetOpenFileNameW(&ofn)) + { + // back to UTF-8 + std::vector fileNameA(4 * 32768); + if (WideCharToMultiByte(CP_UTF8, 0, fileNameW.data(), -1, fileNameA.data(), (int)fileNameA.size(), nullptr, nullptr)) + { + // handle it during the next idle cycle (fake async) + pData->fSelectedFile = fileNameA.data(); + } + } + + return true; # else // not implemented return false; From cc720fe821de52c5691c59b8fe21fd0793155a91 Mon Sep 17 00:00:00 2001 From: falkTX Date: Sat, 20 Jul 2019 12:38:40 +0200 Subject: [PATCH 03/23] win32: clear file dialog string before triggering callback Things would go weird if a plugin opens a new file dialog in the file callback, prevent this by clearing the string before the callback. --- dgl/src/Window.cpp | 5 +++-- distrho/extra/String.hpp | 12 ++++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/dgl/src/Window.cpp b/dgl/src/Window.cpp index b5dc1715..09c47ac4 100644 --- a/dgl/src/Window.cpp +++ b/dgl/src/Window.cpp @@ -780,8 +780,9 @@ struct Window::PrivateData { #if defined(DISTRHO_OS_WINDOWS) && !defined(DGL_FILE_BROWSER_DISABLED) if (fSelectedFile.isNotEmpty()) { - fView->fileSelectedFunc(fView, fSelectedFile.buffer()); - fSelectedFile.clear(); + char* const buffer = fSelectedFile.getAndReleaseBuffer(); + fView->fileSelectedFunc(fView, buffer); + std::free(buffer); } #endif diff --git a/distrho/extra/String.hpp b/distrho/extra/String.hpp index 650c5bbd..5e258402 100644 --- a/distrho/extra/String.hpp +++ b/distrho/extra/String.hpp @@ -568,6 +568,18 @@ public: return fBuffer; } + /* + * Get and release the string buffer, while also clearing this string. + * Result must be freed. + */ + char* getAndReleaseBuffer() noexcept + { + char* const ret = fBuffer; + fBuffer = _null(); + fBufferLen = 0; + return ret; + } + // ------------------------------------------------------------------- // base64 stuff, based on http://www.adp-gmbh.ch/cpp/common/base64.html // Copyright (C) 2004-2008 René Nyffenegger From 7066dd1b544f5319526580bde682f6df0d99ac80 Mon Sep 17 00:00:00 2001 From: JP Cimalando Date: Tue, 30 Jul 2019 18:53:41 +0200 Subject: [PATCH 04/23] cairo: define geometry functions, fixes debug link --- dgl/src/Cairo.cpp | 89 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 87 insertions(+), 2 deletions(-) diff --git a/dgl/src/Cairo.cpp b/dgl/src/Cairo.cpp index 2c9e42ee..ac9fff5c 100644 --- a/dgl/src/Cairo.cpp +++ b/dgl/src/Cairo.cpp @@ -14,13 +14,98 @@ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include "../Base.hpp" +#include "../Geometry.hpp" +#include "../Cairo.hpp" START_NAMESPACE_DGL // ----------------------------------------------------------------------- -// nothing here yet +static void notImplemented(const char *name) +{ + d_stderr2("cairo function not implemented: %s", name); +} + +// ----------------------------------------------------------------------- +// Line + +template +void Line::draw() +{ + notImplemented("Line::draw"); +} + +// ----------------------------------------------------------------------- +// Circle + +template +void Circle::_draw(const bool outline) +{ + notImplemented("Circle::draw"); +} + +// ----------------------------------------------------------------------- +// Triangle + +template +void Triangle::_draw(const bool outline) +{ + notImplemented("Triangle::draw"); +} + +// ----------------------------------------------------------------------- +// Rectangle + +template +void Rectangle::_draw(const bool outline) +{ + notImplemented("Rectangle::draw"); +} + +// ----------------------------------------------------------------------- +// Possible template data types + +template class Point; +template class Point; +template class Point; +template class Point; +template class Point; +template class Point; + +template class Size; +template class Size; +template class Size; +template class Size; +template class Size; +template class Size; + +template class Line; +template class Line; +template class Line; +template class Line; +template class Line; +template class Line; + +template class Circle; +template class Circle; +template class Circle; +template class Circle; +template class Circle; +template class Circle; + +template class Triangle; +template class Triangle; +template class Triangle; +template class Triangle; +template class Triangle; +template class Triangle; + +template class Rectangle; +template class Rectangle; +template class Rectangle; +template class Rectangle; +template class Rectangle; +template class Rectangle; // ----------------------------------------------------------------------- From 1ae79e9a5303ec6873ecc26a0834d5a1017ecee6 Mon Sep 17 00:00:00 2001 From: JP Cimalando Date: Tue, 30 Jul 2019 18:35:58 +0200 Subject: [PATCH 05/23] sofd: skip strcpy in case of same source and destination --- dgl/src/sofd/libsofd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dgl/src/sofd/libsofd.c b/dgl/src/sofd/libsofd.c index 914a6e29..06273d4c 100644 --- a/dgl/src/sofd/libsofd.c +++ b/dgl/src/sofd/libsofd.c @@ -1257,7 +1257,8 @@ static int fib_opendir (Display *dpy, const char* path, const char *sel) { } else { int i; struct dirent *de; - strcpy (_cur_path, path); + if (path != _cur_path) + strcpy (_cur_path, path); if (_cur_path[strlen (_cur_path) -1] != '/') strcat (_cur_path, "/"); From 5dff90ad277abb857db274fff5fbe84dd6489b6a Mon Sep 17 00:00:00 2001 From: JP Cimalando Date: Thu, 1 Aug 2019 03:00:17 +0200 Subject: [PATCH 06/23] add file dialog for macOS (#161) * add file dialog for macOS * mac: use the 10.6 setDirectory API * mac: rewrite file dialog without a for-each loop * some minor style changes * mac: use file dialog compatibility API, not using blocks * add some copyright notices --- dgl/src/Window.cpp | 141 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 141 insertions(+) diff --git a/dgl/src/Window.cpp b/dgl/src/Window.cpp index 09c47ac4..f715e549 100644 --- a/dgl/src/Window.cpp +++ b/dgl/src/Window.cpp @@ -1,6 +1,8 @@ /* * DISTRHO Plugin Framework (DPF) * Copyright (C) 2012-2019 Filipe Coelho + * Copyright (C) 2019 Jean Pierre Cimalando + * Copyright (C) 2019 Robin Gareus * * 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 @@ -105,6 +107,10 @@ struct Window::PrivateData { mView(nullptr), mWindow(nullptr), mParentWindow(nullptr) +# ifndef DGL_FILE_BROWSER_DISABLED + , fOpenFilePanel(nullptr), + fFilePanelDelegate(nullptr) +# endif #else xDisplay(nullptr), xWindow(0) @@ -137,6 +143,10 @@ struct Window::PrivateData { mView(nullptr), mWindow(nullptr), mParentWindow(nullptr) +# ifndef DGL_FILE_BROWSER_DISABLED + , fOpenFilePanel(nullptr), + fFilePanelDelegate(nullptr) +# endif #else xDisplay(nullptr), xWindow(0) @@ -181,6 +191,10 @@ struct Window::PrivateData { mView(nullptr), mWindow(nullptr), mParentWindow(nullptr) +# ifndef DGL_FILE_BROWSER_DISABLED + , fOpenFilePanel(nullptr), + fFilePanelDelegate(nullptr) +# endif #else xDisplay(nullptr), xWindow(0) @@ -323,6 +337,19 @@ struct Window::PrivateData { xWindow = 0; #endif +#if defined(DISTRHO_OS_MAC) && !defined(DGL_FILE_BROWSER_DISABLED) + if (fOpenFilePanel) + { + [fOpenFilePanel release]; + fOpenFilePanel = nullptr; + } + if (fFilePanelDelegate) + { + [fFilePanelDelegate release]; + fFilePanelDelegate = nullptr; + } +#endif + DBG("Success!\n"); } @@ -1062,6 +1089,39 @@ struct Window::PrivateData { return false; } +#if defined(DISTRHO_OS_MAC) && !defined(DGL_FILE_BROWSER_DISABLED) + static void openPanelDidEnd(NSOpenPanel* panel, int returnCode, void *userData) + { + PrivateData* pData = (PrivateData*)userData; + + if (returnCode == NSOKButton) + { + NSArray* urls = [panel URLs]; + NSURL* fileUrl = nullptr; + + for (NSUInteger i = 0, n = [urls count]; i < n && !fileUrl; ++i) + { + NSURL* url = (NSURL*)[urls objectAtIndex:i]; + if ([url isFileURL]) + fileUrl = url; + } + + if (fileUrl) + { + PuglView* view = pData->fView; + if (view->fileSelectedFunc) + { + const char* fileName = [fileUrl.path UTF8String]; + view->fileSelectedFunc(view, fileName); + } + } + } + + [pData->fOpenFilePanel release]; + pData->fOpenFilePanel = nullptr; + } +#endif + // ------------------------------------------------------------------- Application& fApp; @@ -1115,6 +1175,10 @@ struct Window::PrivateData { NSView* mView; id mWindow; id mParentWindow; +# ifndef DGL_FILE_BROWSER_DISABLED + NSOpenPanel* fOpenFilePanel; + id fFilePanelDelegate; +# endif #else Display* xDisplay; ::Window xWindow; @@ -1231,6 +1295,20 @@ void Window::repaint() noexcept // } #ifndef DGL_FILE_BROWSER_DISABLED + +#ifdef DISTRHO_OS_MAC +END_NAMESPACE_DGL +@interface FilePanelDelegate : NSObject +{ + void (*fCallback)(NSOpenPanel*, int, void*); + void* fUserData; +} +-(id)initWithCallback:(void(*)(NSOpenPanel*, int, void*))callback userData:(void*)userData; +-(void)openPanelDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo; +@end +START_NAMESPACE_DGL +#endif + bool Window::openFileBrowser(const FileBrowserOptions& options) { # ifdef SOFD_HAVE_X11 @@ -1337,6 +1415,48 @@ bool Window::openFileBrowser(const FileBrowserOptions& options) } } + return true; +# elif defined(DISTRHO_OS_MAC) + if (pData->fOpenFilePanel) // permit one dialog at most + { + [pData->fOpenFilePanel makeKeyAndOrderFront:nil]; + return false; + } + + NSOpenPanel* panel = [NSOpenPanel openPanel]; + pData->fOpenFilePanel = [panel retain]; + + [panel setCanChooseFiles:YES]; + [panel setCanChooseDirectories:NO]; + [panel setAllowsMultipleSelection:NO]; + + if (options.startDir) + [panel setDirectory:[NSString stringWithUTF8String:options.startDir]]; + + if (options.title) + { + NSString* titleString = [[NSString alloc] + initWithBytes:options.title + length:strlen(options.title) + encoding:NSUTF8StringEncoding]; + [panel setTitle:titleString]; + } + + id delegate = pData->fFilePanelDelegate; + if (!delegate) + { + delegate = [[FilePanelDelegate alloc] initWithCallback:&PrivateData::openPanelDidEnd + userData:pData]; + pData->fFilePanelDelegate = [delegate retain]; + } + + [panel beginSheetForDirectory:nullptr + file:nullptr + modalForWindow:nullptr + modalDelegate:delegate + didEndSelector:@selector(openPanelDidEnd:returnCode:contextInfo:) + contextInfo:nullptr]; + return true; # else // not implemented @@ -1346,8 +1466,29 @@ bool Window::openFileBrowser(const FileBrowserOptions& options) (void)options; # endif } + +#ifdef DISTRHO_OS_MAC +END_NAMESPACE_DGL +@implementation FilePanelDelegate +-(id)initWithCallback:(void(*)(NSOpenPanel*, int, void*))callback userData:(void *)userData +{ + [super init]; + self->fCallback = callback; + self->fUserData = userData; + return self; +} + +-(void)openPanelDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo +{ + self->fCallback(sheet, returnCode, self->fUserData); + (void)contextInfo; +} +@end +START_NAMESPACE_DGL #endif +#endif // !defined(DGL_FILE_BROWSER_DISABLED) + bool Window::isEmbed() const noexcept { return pData->fUsingEmbed; From a80da9156e120d13e7ec0cb6d8a7d11108ca8640 Mon Sep 17 00:00:00 2001 From: Luke Esquivel Date: Tue, 23 Jul 2019 09:25:39 -0700 Subject: [PATCH 07/23] fixed macos vst buildfile errors --- Makefile | 4 +++- utils/generate-vst-bundles.sh | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index b8b23a22..d16647c0 100644 --- a/Makefile +++ b/Makefile @@ -53,7 +53,6 @@ endif clean: $(MAKE) clean -C dgl $(MAKE) clean -C examples/CairoUI - $(MAKE) clean -C examples/ExternalUI $(MAKE) clean -C examples/Info $(MAKE) clean -C examples/Latency $(MAKE) clean -C examples/Meters @@ -61,6 +60,9 @@ clean: $(MAKE) clean -C examples/Parameters $(MAKE) clean -C examples/States $(MAKE) clean -C utils/lv2-ttl-generator +ifneq ($(MACOS_OR_WINDOWS),true) + $(MAKE) clean -C examples/ExternalUI +endif rm -rf bin build # -------------------------------------------------------------- diff --git a/utils/generate-vst-bundles.sh b/utils/generate-vst-bundles.sh index b4afdb83..5e5c8b9c 100755 --- a/utils/generate-vst-bundles.sh +++ b/utils/generate-vst-bundles.sh @@ -17,7 +17,7 @@ PLUGINS=`ls | grep vst.dylib` for i in $PLUGINS; do FILE=`echo $i | awk 'sub("-vst.dylib","")'` - cp -r ../dpf/utils/plugin.vst/ $FILE.vst + cp -r ../utils/plugin.vst/ $FILE.vst mv $i $FILE.vst/Contents/MacOS/$FILE rm -f $FILE.vst/Contents/MacOS/deleteme sed -i -e "s/X-PROJECTNAME-X/$FILE/" $FILE.vst/Contents/Info.plist From f4f44ab0cdef7e258ebb82a69875999f5e6cf31c Mon Sep 17 00:00:00 2001 From: falkTX Date: Fri, 2 Aug 2019 19:19:17 +0100 Subject: [PATCH 08/23] Add Parameter short name support, used in LV2 and VST Closes #163 Signed-off-by: falkTX --- distrho/DistrhoPlugin.hpp | 20 +++++++++++++++----- distrho/src/DistrhoPluginInternal.hpp | 7 +++++++ distrho/src/DistrhoPluginLV2export.cpp | 6 ++++++ distrho/src/DistrhoPluginVST.cpp | 6 +++++- 4 files changed, 33 insertions(+), 6 deletions(-) diff --git a/distrho/DistrhoPlugin.hpp b/distrho/DistrhoPlugin.hpp index ebc54077..cf4237da 100644 --- a/distrho/DistrhoPlugin.hpp +++ b/distrho/DistrhoPlugin.hpp @@ -384,6 +384,13 @@ struct Parameter { */ String name; + /** + The short name of this parameter.@n + Used when displaying the parameter name in a very limited space. + @note This value is optional, the full name is used when the short one is missing. + */ + String shortName; + /** The symbol of this parameter.@n A parameter symbol is a short restricted name used as a machine and human readable identifier.@n @@ -430,6 +437,7 @@ struct Parameter { Parameter() noexcept : hints(0x0), name(), + shortName(), symbol(), unit(), ranges(), @@ -443,6 +451,7 @@ struct Parameter { Parameter(uint32_t h, const char* n, const char* s, const char* u, float def, float min, float max) noexcept : hints(h), name(n), + shortName(), symbol(s), unit(u), ranges(def, min, max), @@ -462,11 +471,12 @@ struct Parameter { case kParameterDesignationNull: break; case kParameterDesignationBypass: - hints = kParameterIsAutomable|kParameterIsBoolean|kParameterIsInteger; - name = "Bypass"; - symbol = "dpf_bypass"; - unit = ""; - midiCC = 0; + hints = kParameterIsAutomable|kParameterIsBoolean|kParameterIsInteger; + name = "Bypass"; + shortName = "Bypass"; + symbol = "dpf_bypass"; + unit = ""; + midiCC = 0; ranges.def = 0.0f; ranges.min = 0.0f; ranges.max = 1.0f; diff --git a/distrho/src/DistrhoPluginInternal.hpp b/distrho/src/DistrhoPluginInternal.hpp index 604f4d98..3dd2c27f 100644 --- a/distrho/src/DistrhoPluginInternal.hpp +++ b/distrho/src/DistrhoPluginInternal.hpp @@ -375,6 +375,13 @@ public: return fData->parameters[index].name; } + const String& getParameterShortName(const uint32_t index) const noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, sFallbackString); + + return fData->parameters[index].shortName; + } + const String& getParameterSymbol(const uint32_t index) const noexcept { DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, sFallbackString); diff --git a/distrho/src/DistrhoPluginLV2export.cpp b/distrho/src/DistrhoPluginLV2export.cpp index a43ec4b7..70b01738 100644 --- a/distrho/src/DistrhoPluginLV2export.cpp +++ b/distrho/src/DistrhoPluginLV2export.cpp @@ -440,6 +440,12 @@ void lv2_generate_ttl(const char* const basename) pluginString += " lv2:symbol \"" + symbol + "\" ;\n"; + // short name + const String& shortName(plugin.getParameterShortName(i)); + + if (shortName.isNotEmpty()) + pluginString += " lv2:shortName \"" + shortName + "\" ;\n"; + // ranges const ParameterRanges& ranges(plugin.getParameterRanges(i)); diff --git a/distrho/src/DistrhoPluginVST.cpp b/distrho/src/DistrhoPluginVST.cpp index d8e7640f..c77b7af4 100644 --- a/distrho/src/DistrhoPluginVST.cpp +++ b/distrho/src/DistrhoPluginVST.cpp @@ -1294,7 +1294,11 @@ static intptr_t vst_dispatcherCallback(AEffect* effect, int32_t opcode, int32_t case effGetParamName: if (ptr != nullptr && index < static_cast(plugin.getParameterCount())) { - DISTRHO_NAMESPACE::strncpy((char*)ptr, plugin.getParameterName(index), 16); + const String& shortName(plugin.getParameterShortName(index)); + if (shortName.isNotEmpty()) + DISTRHO_NAMESPACE::strncpy((char*)ptr, shortName, 16); + else + DISTRHO_NAMESPACE::strncpy((char*)ptr, plugin.getParameterName(index), 16); return 1; } return 0; From 93528a9d3c9c427d4f1354b7b0f147a8b97a49bb Mon Sep 17 00:00:00 2001 From: falkTX Date: Fri, 2 Aug 2019 19:22:53 +0100 Subject: [PATCH 09/23] Triple-quote lv2 short name as precaution Signed-off-by: falkTX --- distrho/src/DistrhoPluginLV2export.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/distrho/src/DistrhoPluginLV2export.cpp b/distrho/src/DistrhoPluginLV2export.cpp index 70b01738..b73585b8 100644 --- a/distrho/src/DistrhoPluginLV2export.cpp +++ b/distrho/src/DistrhoPluginLV2export.cpp @@ -444,7 +444,7 @@ void lv2_generate_ttl(const char* const basename) const String& shortName(plugin.getParameterShortName(i)); if (shortName.isNotEmpty()) - pluginString += " lv2:shortName \"" + shortName + "\" ;\n"; + pluginString += " lv2:shortName \"\"\"" + shortName + "\"\"\" ;\n"; // ranges const ParameterRanges& ranges(plugin.getParameterRanges(i)); From b4d02d79209565708af9d7063df5f2f3ba663677 Mon Sep 17 00:00:00 2001 From: JP Cimalando Date: Sat, 3 Aug 2019 05:56:27 +0200 Subject: [PATCH 10/23] nanovg: guard loadSharedResources against init failure --- dgl/src/NanoVG.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dgl/src/NanoVG.cpp b/dgl/src/NanoVG.cpp index 06fc49f7..44eb21f2 100644 --- a/dgl/src/NanoVG.cpp +++ b/dgl/src/NanoVG.cpp @@ -918,6 +918,8 @@ int NanoVG::textBreakLines(const char* string, const char* end, float breakRowWi #ifndef DGL_NO_SHARED_RESOURCES void NanoVG::loadSharedResources() { + if (fContext == nullptr) return; + if (nvgFindFont(fContext, NANOVG_DEJAVU_SANS_TTF) >= 0) return; From daad9769114cf24d4ccc1f3ea298040dc6ac7908 Mon Sep 17 00:00:00 2001 From: JP Cimalando Date: Sat, 3 Aug 2019 05:58:53 +0200 Subject: [PATCH 11/23] nanovg: check openGL function validity on next inits --- dgl/src/NanoVG.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/dgl/src/NanoVG.cpp b/dgl/src/NanoVG.cpp index 44eb21f2..b62bc4c1 100644 --- a/dgl/src/NanoVG.cpp +++ b/dgl/src/NanoVG.cpp @@ -81,11 +81,8 @@ static NVGcontext* nvgCreateGL_helper(int flags) { #if defined(DISTRHO_OS_WINDOWS) static bool needsInit = true; - if (needsInit) - { - needsInit = false; # define DGL_EXT(PROC, func) \ - func = (PROC) wglGetProcAddress ( #func ); \ + if (needsInit) func = (PROC) wglGetProcAddress ( #func ); \ DISTRHO_SAFE_ASSERT_RETURN(func != nullptr, nullptr); DGL_EXT(PFNGLACTIVETEXTUREPROC, glActiveTexture) DGL_EXT(PFNGLATTACHSHADERPROC, glAttachShader) @@ -115,7 +112,7 @@ DGL_EXT(PFNGLUNIFORM4FVPROC, glUniform4fv) DGL_EXT(PFNGLUSEPROGRAMPROC, glUseProgram) DGL_EXT(PFNGLVERTEXATTRIBPOINTERPROC, glVertexAttribPointer) # undef DGL_EXT - } + needsInit = false; #endif return nvgCreateGL(flags); } From 31a4cf3e46bb22ea478cd5c34147e64bccd152e8 Mon Sep 17 00:00:00 2001 From: JP Cimalando Date: Sat, 3 Aug 2019 10:25:20 +0200 Subject: [PATCH 12/23] exporter: attributes into arrays, to simplify dealing with syntax --- distrho/src/DistrhoPluginLV2export.cpp | 219 +++++++++++++++---------- 1 file changed, 131 insertions(+), 88 deletions(-) diff --git a/distrho/src/DistrhoPluginLV2export.cpp b/distrho/src/DistrhoPluginLV2export.cpp index b73585b8..0d84f5e2 100644 --- a/distrho/src/DistrhoPluginLV2export.cpp +++ b/distrho/src/DistrhoPluginLV2export.cpp @@ -70,6 +70,123 @@ #define DISTRHO_LV2_USE_EVENTS_IN (DISTRHO_PLUGIN_WANT_MIDI_INPUT || DISTRHO_PLUGIN_WANT_TIMEPOS || (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI)) #define DISTRHO_LV2_USE_EVENTS_OUT (DISTRHO_PLUGIN_WANT_MIDI_OUTPUT || (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI)) +// ----------------------------------------------------------------------- +static const char *const lv2ManifestPluginExtensionData[] = +{ +#if DISTRHO_PLUGIN_WANT_STATE + LV2_STATE__interface, + LV2_OPTIONS__interface, + LV2_WORKER__interface, +#endif +#if DISTRHO_PLUGIN_WANT_PROGRAMS + LV2_PROGRAMS__Interface, +#endif +#ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD + MOD_LICENSE__interface, +#endif + nullptr +}; + +static const char *const lv2ManifestPluginOptionalFeatures[] = +{ +#if DISTRHO_PLUGIN_IS_RT_SAFE + LV2_CORE__hardRTCapable, +#endif + LV2_BUF_SIZE__boundedBlockLength, + nullptr +}; + +static const char *const lv2ManifestPluginRequiredFeatures[] = +{ + LV2_OPTIONS__options, + LV2_URID__map, +#if DISTRHO_PLUGIN_WANT_STATE + LV2_WORKER__schedule, +#endif +#ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD + MOD_LICENSE__feature, +#endif + nullptr +}; + +static const char *const lv2ManifestPluginSupportedOptions[] = +{ + LV2_BUF_SIZE__nominalBlockLength, + LV2_BUF_SIZE__maxBlockLength, + LV2_PARAMETERS__sampleRate, + nullptr +}; + +#if DISTRHO_PLUGIN_HAS_UI +static const char *const lv2ManifestUiExtensionData[] = +{ + LV2_OPTIONS__interface, + "ui:idleInterface", + "ui:showInterface", + "ui:resize", +#if DISTRHO_PLUGIN_WANT_PROGRAMS + LV2_PROGRAMS__UIInterface, +#endif + nullptr +}; + +static const char *const lv2ManifestUiOptionalFeatures[] = +{ +#if DISTRHO_PLUGIN_HAS_EMBED_UI +# if !DISTRHO_UI_USER_RESIZABLE + "ui:noUserResize", +# endif + "ui:resize", + "ui:touch", +#endif + nullptr +}; + +static const char *const lv2ManifestUiRequiredFeatures[] = +{ +#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS + LV2_DATA_ACCESS_URI, + LV2_INSTANCE_ACCESS_URI, +#endif + LV2_OPTIONS__options, + LV2_URID__map, + nullptr +}; + +static const char *lv2ManifestUiSupportedOptions[] = +{ + LV2_PARAMETERS__sampleRate, + nullptr +}; +#endif // DISTRHO_PLUGIN_HAS_UI + +static void addAttribute(String &text, unsigned indent, const char *attribute, const char* const values[]) +{ + if (!values[0]) + return; + + size_t attributeLength = strlen(attribute); + + for (unsigned i = 0; values[i]; ++i) + { + for (unsigned l = 0; l < indent; ++l) + text += " "; + + if (i == 0) + text += attribute; + else + for (unsigned l = 0; l < attributeLength; ++l) + text += " "; + text += " "; + + bool isUrl = strstr(values[i], "://") != nullptr; + if (isUrl) text += "<"; + text += values[i]; + if (isUrl) text += ">"; + text += values[i + 1] ? " ,\n" : " ;\n\n"; + } +} + // ----------------------------------------------------------------------- DISTRHO_PLUGIN_EXPORT @@ -132,32 +249,11 @@ void lv2_generate_ttl(const char* const basename) manifestString += " a ui:" DISTRHO_LV2_UI_TYPE " ;\n"; manifestString += " ui:binary <" + pluginUI + "." DISTRHO_DLL_EXTENSION "> ;\n"; # if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS - manifestString += "\n"; - manifestString += " lv2:extensionData ui:idleInterface ,\n"; -# if DISTRHO_PLUGIN_WANT_PROGRAMS - manifestString += " ui:showInterface ,\n"; - manifestString += " <" LV2_PROGRAMS__Interface "> ;\n"; -# else - manifestString += " ui:showInterface ;\n"; -# endif - manifestString += "\n"; -# if DISTRHO_PLUGIN_HAS_EMBED_UI -# if DISTRHO_UI_USER_RESIZABLE - manifestString += " lv2:optionalFeature ui:resize ,\n"; - manifestString += " ui:touch ;\n"; - manifestString += "\n"; -# else // DISTRHO_UI_USER_RESIZABLE - manifestString += " lv2:optionalFeature ui:noUserResize ,\n"; - manifestString += " ui:resize ,\n"; - manifestString += " ui:touch ;\n"; - manifestString += "\n"; -# endif // DISTRHO_UI_USER_RESIZABLE -# endif // DISTRHO_PLUGIN_HAS_EMBED_UI - manifestString += " lv2:requiredFeature <" LV2_DATA_ACCESS_URI "> ,\n"; - manifestString += " <" LV2_INSTANCE_ACCESS_URI "> ,\n"; - manifestString += " <" LV2_OPTIONS__options "> ,\n"; - manifestString += " <" LV2_URID__map "> ;\n"; - manifestString += " opts:supportedOption <" LV2_PARAMETERS__sampleRate "> .\n"; + addAttribute(manifestString, 4, "lv2:extensionData", lv2ManifestUiExtensionData); + addAttribute(manifestString, 4, "lv2:optionalFeature", lv2ManifestUiOptionalFeatures); + addAttribute(manifestString, 4, "lv2:requiredFeature", lv2ManifestUiRequiredFeatures); + addAttribute(manifestString, 4, "opts:supportedOption", lv2ManifestUiSupportedOptions); + manifestString[manifestString.rfind(';')] = '.'; # else // DISTRHO_PLUGIN_WANT_DIRECT_ACCESS manifestString += " rdfs:seeAlso <" + uiTTL + "> .\n"; # endif // DISTRHO_PLUGIN_WANT_DIRECT_ACCESS @@ -232,45 +328,10 @@ void lv2_generate_ttl(const char* const basename) #endif pluginString += "\n"; - // extensionData - pluginString += " lv2:extensionData <" LV2_STATE__interface "> "; -#if DISTRHO_PLUGIN_WANT_STATE - pluginString += ",\n <" LV2_OPTIONS__interface "> "; - pluginString += ",\n <" LV2_WORKER__interface "> "; -#endif -#if DISTRHO_PLUGIN_WANT_PROGRAMS - pluginString += ",\n <" LV2_PROGRAMS__Interface "> "; -#endif -#ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD - pluginString += ",\n <" MOD_LICENSE__interface "> "; -#endif - pluginString += ";\n\n"; - - // optionalFeatures -#if DISTRHO_PLUGIN_IS_RT_SAFE - pluginString += " lv2:optionalFeature <" LV2_CORE__hardRTCapable "> ,\n"; - pluginString += " <" LV2_BUF_SIZE__boundedBlockLength "> ;\n"; -#else - pluginString += " lv2:optionalFeature <" LV2_BUF_SIZE__boundedBlockLength "> ;\n"; -#endif - pluginString += "\n"; - - // requiredFeatures - pluginString += " lv2:requiredFeature <" LV2_OPTIONS__options "> "; - pluginString += ",\n <" LV2_URID__map "> "; -#if DISTRHO_PLUGIN_WANT_STATE - pluginString += ",\n <" LV2_WORKER__schedule "> "; -#endif -#ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD - pluginString += ",\n <" MOD_LICENSE__feature "> "; -#endif - pluginString += ";\n\n"; - - // supportedOptions - pluginString += " opts:supportedOption <" LV2_BUF_SIZE__nominalBlockLength "> ,\n"; - pluginString += " <" LV2_BUF_SIZE__maxBlockLength "> ,\n"; - pluginString += " <" LV2_PARAMETERS__sampleRate "> ;\n"; - pluginString += "\n"; + addAttribute(pluginString, 4, "lv2:extensionData", lv2ManifestPluginExtensionData); + addAttribute(pluginString, 4, "lv2:optionalFeature", lv2ManifestPluginOptionalFeatures); + addAttribute(pluginString, 4, "lv2:requiredFeature", lv2ManifestPluginRequiredFeatures); + addAttribute(pluginString, 4, "opts:supportedOption", lv2ManifestPluginSupportedOptions); // UI #if DISTRHO_PLUGIN_HAS_UI @@ -635,30 +696,12 @@ void lv2_generate_ttl(const char* const basename) uiString += "\n"; uiString += "<" DISTRHO_UI_URI ">\n"; - uiString += " lv2:extensionData ui:idleInterface ,\n"; -# if DISTRHO_PLUGIN_WANT_PROGRAMS - uiString += " ui:showInterface ,\n"; - uiString += " <" LV2_PROGRAMS__Interface "> ;\n"; -# else - uiString += " ui:showInterface ;\n"; -# endif - uiString += "\n"; -# if DISTRHO_PLUGIN_HAS_EMBED_UI -# if DISTRHO_UI_USER_RESIZABLE - uiString += " lv2:optionalFeature ui:resize ,\n"; - uiString += " ui:touch ;\n"; - uiString += "\n"; -# else // DISTRHO_UI_USER_RESIZABLE - uiString += " lv2:optionalFeature ui:noUserResize ,\n"; - uiString += " ui:resize ,\n"; - uiString += " ui:touch ;\n"; - uiString += "\n"; -# endif // DISTRHO_UI_USER_RESIZABLE -# endif // DISTRHO_PLUGIN_HAS_EMBED_UI - uiString += " lv2:requiredFeature <" LV2_OPTIONS__options "> ,\n"; - uiString += " <" LV2_URID__map "> ;\n"; - uiString += " opts:supportedOption <" LV2_PARAMETERS__sampleRate "> .\n"; + addAttribute(uiString, 4, "lv2:extensionData", lv2ManifestUiExtensionData); + addAttribute(uiString, 4, "lv2:optionalFeature", lv2ManifestUiOptionalFeatures); + addAttribute(uiString, 4, "lv2:requiredFeature", lv2ManifestUiRequiredFeatures); + addAttribute(uiString, 4, "opts:supportedOption", lv2ManifestUiSupportedOptions); + uiString[uiString.rfind(';')] = '.'; uiFile << uiString << std::endl; uiFile.close(); From 795730f3cbcdc7ebea12aaec09aed2503b3ecd95 Mon Sep 17 00:00:00 2001 From: JP Cimalando Date: Sat, 3 Aug 2019 11:01:33 +0200 Subject: [PATCH 13/23] Fix the unimplemented worker response function --- distrho/src/DistrhoPluginLV2.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/distrho/src/DistrhoPluginLV2.cpp b/distrho/src/DistrhoPluginLV2.cpp index ed970528..5410bf17 100644 --- a/distrho/src/DistrhoPluginLV2.cpp +++ b/distrho/src/DistrhoPluginLV2.cpp @@ -846,6 +846,11 @@ public: return LV2_WORKER_SUCCESS; } + + LV2_Worker_Status lv2_work_response(uint32_t, const void*) + { + return LV2_WORKER_SUCCESS; + } #endif // ------------------------------------------------------------------- @@ -1243,6 +1248,11 @@ LV2_Worker_Status lv2_work(LV2_Handle instance, LV2_Worker_Respond_Function, LV2 { return instancePtr->lv2_work(data); } + +LV2_Worker_Status lv2_work_response(LV2_Handle instance, uint32_t size, const void* body) +{ + return instancePtr->lv2_work_response(size, body); +} #endif // ----------------------------------------------------------------------- @@ -1272,7 +1282,7 @@ static const void* lv2_extension_data(const char* uri) #if DISTRHO_PLUGIN_WANT_STATE static const LV2_State_Interface state = { lv2_save, lv2_restore }; - static const LV2_Worker_Interface worker = { lv2_work, nullptr, nullptr }; + static const LV2_Worker_Interface worker = { lv2_work, lv2_work_response, nullptr }; if (std::strcmp(uri, LV2_STATE__interface) == 0) return &state; From f609e5c3a13a836650b05e4d7eae51e7b9796b0c Mon Sep 17 00:00:00 2001 From: falkTX Date: Mon, 5 Aug 2019 12:37:54 +0100 Subject: [PATCH 14/23] Put CairoUI's metadata in consistency with the rest of examples Signed-off-by: falkTX --- examples/CairoUI/DistrhoPluginInfo.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/CairoUI/DistrhoPluginInfo.h b/examples/CairoUI/DistrhoPluginInfo.h index b3839886..8ab79fb4 100644 --- a/examples/CairoUI/DistrhoPluginInfo.h +++ b/examples/CairoUI/DistrhoPluginInfo.h @@ -19,7 +19,7 @@ This is used to identify your plugin before a Plugin instance can be created. @note This macro is required. */ -#define DISTRHO_PLUGIN_NAME "Cairo DPF example" +#define DISTRHO_PLUGIN_NAME "CairoUI" /** Number of audio inputs the plugin has. @@ -37,7 +37,7 @@ The plugin URI when exporting in LV2 format. @note This macro is required. */ -#define DISTRHO_PLUGIN_URI "urn:jpcima:cairo-dpf-example" +#define DISTRHO_PLUGIN_URI "http://distrho.sf.net/examples/CairoUI" /** Wherever the plugin has a custom %UI. From fd55d1002c4437efe4673e07ba6b33a3e210690c Mon Sep 17 00:00:00 2001 From: falkTX Date: Mon, 5 Aug 2019 12:59:48 +0100 Subject: [PATCH 15/23] Adjust latest changes to be more in DPF style Signed-off-by: falkTX --- distrho/src/DistrhoPluginLV2export.cpp | 67 ++++++++++++++------------ 1 file changed, 37 insertions(+), 30 deletions(-) diff --git a/distrho/src/DistrhoPluginLV2export.cpp b/distrho/src/DistrhoPluginLV2export.cpp index 0d84f5e2..e202d759 100644 --- a/distrho/src/DistrhoPluginLV2export.cpp +++ b/distrho/src/DistrhoPluginLV2export.cpp @@ -71,7 +71,7 @@ #define DISTRHO_LV2_USE_EVENTS_OUT (DISTRHO_PLUGIN_WANT_MIDI_OUTPUT || (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI)) // ----------------------------------------------------------------------- -static const char *const lv2ManifestPluginExtensionData[] = +static const char* const lv2ManifestPluginExtensionData[] = { #if DISTRHO_PLUGIN_WANT_STATE LV2_STATE__interface, @@ -87,7 +87,7 @@ static const char *const lv2ManifestPluginExtensionData[] = nullptr }; -static const char *const lv2ManifestPluginOptionalFeatures[] = +static const char* const lv2ManifestPluginOptionalFeatures[] = { #if DISTRHO_PLUGIN_IS_RT_SAFE LV2_CORE__hardRTCapable, @@ -96,7 +96,7 @@ static const char *const lv2ManifestPluginOptionalFeatures[] = nullptr }; -static const char *const lv2ManifestPluginRequiredFeatures[] = +static const char* const lv2ManifestPluginRequiredFeatures[] = { LV2_OPTIONS__options, LV2_URID__map, @@ -109,7 +109,7 @@ static const char *const lv2ManifestPluginRequiredFeatures[] = nullptr }; -static const char *const lv2ManifestPluginSupportedOptions[] = +static const char* const lv2ManifestPluginSupportedOptions[] = { LV2_BUF_SIZE__nominalBlockLength, LV2_BUF_SIZE__maxBlockLength, @@ -118,7 +118,7 @@ static const char *const lv2ManifestPluginSupportedOptions[] = }; #if DISTRHO_PLUGIN_HAS_UI -static const char *const lv2ManifestUiExtensionData[] = +static const char* const lv2ManifestUiExtensionData[] = { LV2_OPTIONS__interface, "ui:idleInterface", @@ -130,7 +130,7 @@ static const char *const lv2ManifestUiExtensionData[] = nullptr }; -static const char *const lv2ManifestUiOptionalFeatures[] = +static const char* const lv2ManifestUiOptionalFeatures[] = { #if DISTRHO_PLUGIN_HAS_EMBED_UI # if !DISTRHO_UI_USER_RESIZABLE @@ -142,7 +142,7 @@ static const char *const lv2ManifestUiOptionalFeatures[] = nullptr }; -static const char *const lv2ManifestUiRequiredFeatures[] = +static const char* const lv2ManifestUiRequiredFeatures[] = { #if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS LV2_DATA_ACCESS_URI, @@ -153,37 +153,46 @@ static const char *const lv2ManifestUiRequiredFeatures[] = nullptr }; -static const char *lv2ManifestUiSupportedOptions[] = +static const char* const lv2ManifestUiSupportedOptions[] = { LV2_PARAMETERS__sampleRate, nullptr }; #endif // DISTRHO_PLUGIN_HAS_UI -static void addAttribute(String &text, unsigned indent, const char *attribute, const char* const values[]) +static void addAttribute(String& text, + const char* const attribute, + const char* const values[], + const uint indent, + const bool endInDot = false) { - if (!values[0]) + if (values[0] == nullptr) return; - size_t attributeLength = strlen(attribute); + const size_t attributeLength = std::strlen(attribute); - for (unsigned i = 0; values[i]; ++i) + for (uint i = 0; values[i] != nullptr; ++i) { - for (unsigned l = 0; l < indent; ++l) + for (uint j = 0; j < indent; ++j) text += " "; if (i == 0) + { text += attribute; + } else - for (unsigned l = 0; l < attributeLength; ++l) + { + for (uint j = 0; j < attributeLength; ++j) text += " "; + } + text += " "; - bool isUrl = strstr(values[i], "://") != nullptr; + const bool isUrl = std::strstr(values[i], "://") != nullptr || std::strncmp(values[i], "urn:", 4) == 0; if (isUrl) text += "<"; text += values[i]; if (isUrl) text += ">"; - text += values[i + 1] ? " ,\n" : " ;\n\n"; + text += values[i + 1] ? " ,\n" : (endInDot ? " .\n\n" : " ;\n\n"); } } @@ -249,11 +258,10 @@ void lv2_generate_ttl(const char* const basename) manifestString += " a ui:" DISTRHO_LV2_UI_TYPE " ;\n"; manifestString += " ui:binary <" + pluginUI + "." DISTRHO_DLL_EXTENSION "> ;\n"; # if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS - addAttribute(manifestString, 4, "lv2:extensionData", lv2ManifestUiExtensionData); - addAttribute(manifestString, 4, "lv2:optionalFeature", lv2ManifestUiOptionalFeatures); - addAttribute(manifestString, 4, "lv2:requiredFeature", lv2ManifestUiRequiredFeatures); - addAttribute(manifestString, 4, "opts:supportedOption", lv2ManifestUiSupportedOptions); - manifestString[manifestString.rfind(';')] = '.'; + addAttribute(manifestString, "lv2:extensionData", lv2ManifestUiExtensionData, 4); + addAttribute(manifestString, "lv2:optionalFeature", lv2ManifestUiOptionalFeatures, 4); + addAttribute(manifestString, "lv2:requiredFeature", lv2ManifestUiRequiredFeatures, 4); + addAttribute(manifestString, "opts:supportedOption", lv2ManifestUiSupportedOptions, 4, true); # else // DISTRHO_PLUGIN_WANT_DIRECT_ACCESS manifestString += " rdfs:seeAlso <" + uiTTL + "> .\n"; # endif // DISTRHO_PLUGIN_WANT_DIRECT_ACCESS @@ -328,10 +336,10 @@ void lv2_generate_ttl(const char* const basename) #endif pluginString += "\n"; - addAttribute(pluginString, 4, "lv2:extensionData", lv2ManifestPluginExtensionData); - addAttribute(pluginString, 4, "lv2:optionalFeature", lv2ManifestPluginOptionalFeatures); - addAttribute(pluginString, 4, "lv2:requiredFeature", lv2ManifestPluginRequiredFeatures); - addAttribute(pluginString, 4, "opts:supportedOption", lv2ManifestPluginSupportedOptions); + addAttribute(pluginString, "lv2:extensionData", lv2ManifestPluginExtensionData, 4); + addAttribute(pluginString, "lv2:optionalFeature", lv2ManifestPluginOptionalFeatures, 4); + addAttribute(pluginString, "lv2:requiredFeature", lv2ManifestPluginRequiredFeatures, 4); + addAttribute(pluginString, "opts:supportedOption", lv2ManifestPluginSupportedOptions, 4); // UI #if DISTRHO_PLUGIN_HAS_UI @@ -697,11 +705,10 @@ void lv2_generate_ttl(const char* const basename) uiString += "<" DISTRHO_UI_URI ">\n"; - addAttribute(uiString, 4, "lv2:extensionData", lv2ManifestUiExtensionData); - addAttribute(uiString, 4, "lv2:optionalFeature", lv2ManifestUiOptionalFeatures); - addAttribute(uiString, 4, "lv2:requiredFeature", lv2ManifestUiRequiredFeatures); - addAttribute(uiString, 4, "opts:supportedOption", lv2ManifestUiSupportedOptions); - uiString[uiString.rfind(';')] = '.'; + addAttribute(uiString, "lv2:extensionData", lv2ManifestUiExtensionData, 4); + addAttribute(uiString, "lv2:optionalFeature", lv2ManifestUiOptionalFeatures, 4); + addAttribute(uiString, "lv2:requiredFeature", lv2ManifestUiRequiredFeatures, 4); + addAttribute(uiString, "opts:supportedOption", lv2ManifestUiSupportedOptions, 4, true); uiFile << uiString << std::endl; uiFile.close(); From b5c5ff366194a3d9418aee81a36d1900f120ff12 Mon Sep 17 00:00:00 2001 From: falkTX Date: Mon, 5 Aug 2019 13:01:10 +0100 Subject: [PATCH 16/23] Always use "opts" prefix Signed-off-by: falkTX --- distrho/src/DistrhoPluginLV2export.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/distrho/src/DistrhoPluginLV2export.cpp b/distrho/src/DistrhoPluginLV2export.cpp index e202d759..8e6cef63 100644 --- a/distrho/src/DistrhoPluginLV2export.cpp +++ b/distrho/src/DistrhoPluginLV2export.cpp @@ -74,8 +74,8 @@ static const char* const lv2ManifestPluginExtensionData[] = { #if DISTRHO_PLUGIN_WANT_STATE + "opts:interface", LV2_STATE__interface, - LV2_OPTIONS__interface, LV2_WORKER__interface, #endif #if DISTRHO_PLUGIN_WANT_PROGRAMS @@ -98,7 +98,7 @@ static const char* const lv2ManifestPluginOptionalFeatures[] = static const char* const lv2ManifestPluginRequiredFeatures[] = { - LV2_OPTIONS__options, + "opts:options", LV2_URID__map, #if DISTRHO_PLUGIN_WANT_STATE LV2_WORKER__schedule, @@ -120,7 +120,7 @@ static const char* const lv2ManifestPluginSupportedOptions[] = #if DISTRHO_PLUGIN_HAS_UI static const char* const lv2ManifestUiExtensionData[] = { - LV2_OPTIONS__interface, + "opts:interface", "ui:idleInterface", "ui:showInterface", "ui:resize", @@ -144,11 +144,11 @@ static const char* const lv2ManifestUiOptionalFeatures[] = static const char* const lv2ManifestUiRequiredFeatures[] = { + "opts:options", #if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS LV2_DATA_ACCESS_URI, LV2_INSTANCE_ACCESS_URI, #endif - LV2_OPTIONS__options, LV2_URID__map, nullptr }; From 5ffcbe5e0a7104f64702a832c9a696ad43adba83 Mon Sep 17 00:00:00 2001 From: falkTX Date: Mon, 5 Aug 2019 13:07:50 +0100 Subject: [PATCH 17/23] Only define rsz prefix when needed Signed-off-by: falkTX --- distrho/src/DistrhoPluginLV2export.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/distrho/src/DistrhoPluginLV2export.cpp b/distrho/src/DistrhoPluginLV2export.cpp index 8e6cef63..4248cfad 100644 --- a/distrho/src/DistrhoPluginLV2export.cpp +++ b/distrho/src/DistrhoPluginLV2export.cpp @@ -318,7 +318,9 @@ void lv2_generate_ttl(const char* const basename) pluginString += "@prefix opts: <" LV2_OPTIONS_PREFIX "> .\n"; pluginString += "@prefix rdf: .\n"; pluginString += "@prefix rdfs: .\n"; +#if DISTRHO_LV2_USE_EVENTS_IN || DISTRHO_LV2_USE_EVENTS_OUT pluginString += "@prefix rsz: <" LV2_RESIZE_PORT_PREFIX "> .\n"; +#endif #if DISTRHO_PLUGIN_HAS_UI pluginString += "@prefix ui: <" LV2_UI_PREFIX "> .\n"; #endif From a26f5a241db42ddabf345028994373a0a5929a26 Mon Sep 17 00:00:00 2001 From: falkTX Date: Mon, 5 Aug 2019 14:48:29 +0100 Subject: [PATCH 18/23] Handle situation of addAttribute values being empty Does not happen right now, but might in the future Signed-off-by: falkTX --- distrho/src/DistrhoPluginLV2export.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/distrho/src/DistrhoPluginLV2export.cpp b/distrho/src/DistrhoPluginLV2export.cpp index 4248cfad..c2924fec 100644 --- a/distrho/src/DistrhoPluginLV2export.cpp +++ b/distrho/src/DistrhoPluginLV2export.cpp @@ -167,7 +167,15 @@ static void addAttribute(String& text, const bool endInDot = false) { if (values[0] == nullptr) + { + if (endInDot) + { + bool found; + const size_t index = text.rfind(';', &found); + if (found) text[index] = '.'; + } return; + } const size_t attributeLength = std::strlen(attribute); From 2cb3b7d3e323b85b1bbdb68cde5101ae282941bf Mon Sep 17 00:00:00 2001 From: falkTX Date: Mon, 5 Aug 2019 16:51:44 +0100 Subject: [PATCH 19/23] Try to make utils/generate-vst-bundles.sh work anywhere Please test Signed-off-by: falkTX --- utils/generate-vst-bundles.sh | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/utils/generate-vst-bundles.sh b/utils/generate-vst-bundles.sh index 5e5c8b9c..1cf784a4 100755 --- a/utils/generate-vst-bundles.sh +++ b/utils/generate-vst-bundles.sh @@ -9,19 +9,18 @@ else exit fi -PWD=`pwd` +DPF_DIR=$(dirname $0)/.. +PLUGINS=$(ls | grep vst.dylib) rm -rf *.vst/ -PLUGINS=`ls | grep vst.dylib` - for i in $PLUGINS; do - FILE=`echo $i | awk 'sub("-vst.dylib","")'` - cp -r ../utils/plugin.vst/ $FILE.vst - mv $i $FILE.vst/Contents/MacOS/$FILE - rm -f $FILE.vst/Contents/MacOS/deleteme - sed -i -e "s/X-PROJECTNAME-X/$FILE/" $FILE.vst/Contents/Info.plist - rm -f $FILE.vst/Contents/Info.plist-e + BUNDLE=$(echo ${i} | awk 'sub("-vst.dylib","")') + cp -r ${DPF_DIR}/utils/plugin.vst/ ${BUNDLE}.vst + mv ${i} ${BUNDLE}.vst/Contents/MacOS/${BUNDLE} + rm -f ${BUNDLE}.vst/Contents/MacOS/deleteme + sed -i -e "s/X-PROJECTNAME-X/${BUNDLE}/" ${BUNDLE}.vst/Contents/Info.plist + rm -f ${BUNDLE}.vst/Contents/Info.plist-e done cd .. From b77d143ca737f709ea587d47340102ce4a4d57cf Mon Sep 17 00:00:00 2001 From: JP Cimalando Date: Wed, 7 Aug 2019 11:36:39 +0200 Subject: [PATCH 20/23] Fix an 'opts:interface not defined' warning --- distrho/src/DistrhoPluginLV2export.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/distrho/src/DistrhoPluginLV2export.cpp b/distrho/src/DistrhoPluginLV2export.cpp index c2924fec..63110301 100644 --- a/distrho/src/DistrhoPluginLV2export.cpp +++ b/distrho/src/DistrhoPluginLV2export.cpp @@ -73,8 +73,8 @@ // ----------------------------------------------------------------------- static const char* const lv2ManifestPluginExtensionData[] = { -#if DISTRHO_PLUGIN_WANT_STATE "opts:interface", +#if DISTRHO_PLUGIN_WANT_STATE LV2_STATE__interface, LV2_WORKER__interface, #endif From 126595f1a540d3cfdb085c583629c943ccb7c6d8 Mon Sep 17 00:00:00 2001 From: JP Cimalando Date: Wed, 7 Aug 2019 11:21:53 +0200 Subject: [PATCH 21/23] Add LV2 parameter comments --- distrho/DistrhoPlugin.hpp | 6 ++++++ distrho/src/DistrhoPluginInternal.hpp | 7 +++++++ distrho/src/DistrhoPluginLV2export.cpp | 8 +++++++- 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/distrho/DistrhoPlugin.hpp b/distrho/DistrhoPlugin.hpp index cf4237da..8070982f 100644 --- a/distrho/DistrhoPlugin.hpp +++ b/distrho/DistrhoPlugin.hpp @@ -406,6 +406,12 @@ struct Parameter { */ String unit; + /** + An extensive comment/description about the parameter. + @note This value is optional. + */ + String description; + /** Ranges of this parameter.@n The ranges describe the default, minimum and maximum values. diff --git a/distrho/src/DistrhoPluginInternal.hpp b/distrho/src/DistrhoPluginInternal.hpp index 3dd2c27f..b05663ef 100644 --- a/distrho/src/DistrhoPluginInternal.hpp +++ b/distrho/src/DistrhoPluginInternal.hpp @@ -396,6 +396,13 @@ public: return fData->parameters[index].unit; } + const String& getParameterDescription(const uint32_t index) const noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, sFallbackString); + + return fData->parameters[index].description; + } + const ParameterEnumerationValues& getParameterEnumValues(const uint32_t index) const noexcept { DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, sFallbackEnumValues); diff --git a/distrho/src/DistrhoPluginLV2export.cpp b/distrho/src/DistrhoPluginLV2export.cpp index 63110301..3c44b872 100644 --- a/distrho/src/DistrhoPluginLV2export.cpp +++ b/distrho/src/DistrhoPluginLV2export.cpp @@ -613,6 +613,12 @@ void lv2_generate_ttl(const char* const basename) } } + // comment + const String& comment(plugin.getParameterDescription(i)); + + if (comment.isNotEmpty()) + pluginString += " rdfs:comment \"\"\"" + comment + "\"\"\" ;\n"; + // hints const uint32_t hints(plugin.getParameterHints(i)); @@ -645,7 +651,7 @@ void lv2_generate_ttl(const char* const basename) const String comment(plugin.getDescription()); if (comment.isNotEmpty()) - pluginString += " rdfs:comment \"\"\"\n" + comment + "\n\"\"\" ;\n\n"; + pluginString += " rdfs:comment \"\"\"" + comment + "\"\"\" ;\n\n"; } #ifdef DISTRHO_PLUGIN_BRAND From 3fddc2794fa55f9e9cd8fdb592a6c690f19a74b7 Mon Sep 17 00:00:00 2001 From: falkTX Date: Wed, 7 Aug 2019 12:46:25 +0100 Subject: [PATCH 22/23] Mention that parameter description is LV2 only Signed-off-by: falkTX --- distrho/DistrhoPlugin.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/distrho/DistrhoPlugin.hpp b/distrho/DistrhoPlugin.hpp index 8070982f..913f7ddd 100644 --- a/distrho/DistrhoPlugin.hpp +++ b/distrho/DistrhoPlugin.hpp @@ -407,8 +407,8 @@ struct Parameter { String unit; /** - An extensive comment/description about the parameter. - @note This value is optional. + An extensive description/comment about the parameter. + @note This value is optional and only used for LV2. */ String description; From bbc188db8d03e30cd29b67b5fc0257efe9ae67b5 Mon Sep 17 00:00:00 2001 From: falkTX Date: Sun, 11 Aug 2019 05:37:53 +0100 Subject: [PATCH 23/23] AudioMidiSyncHelper: Fix run cycles with many events --- distrho/DistrhoPluginUtils.hpp | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/distrho/DistrhoPluginUtils.hpp b/distrho/DistrhoPluginUtils.hpp index f4c153ae..7c343033 100644 --- a/distrho/DistrhoPluginUtils.hpp +++ b/distrho/DistrhoPluginUtils.hpp @@ -92,9 +92,11 @@ public: // render audio until first midi event, if needed if (const uint32_t firstEventFrame = midiEvents[0].frame) { - frames = midiEvents[0].frame; - remainingFrames -= frames; - totalFramesUsed += frames; + DISTRHO_SAFE_ASSERT_UINT2_RETURN(firstEventFrame < remainingFrames, + firstEventFrame, remainingFrames, false); + frames = firstEventFrame; + remainingFrames -= firstEventFrame; + totalFramesUsed += firstEventFrame; return true; } } @@ -120,7 +122,8 @@ public: midiEvents += midiEventCount; const uint32_t firstEventFrame = midiEvents[0].frame; - DISTRHO_SAFE_ASSERT_RETURN((firstEventFrame - frames) < remainingFrames, false); + DISTRHO_SAFE_ASSERT_UINT2_RETURN(firstEventFrame >= totalFramesUsed, + firstEventFrame, totalFramesUsed, false); midiEventCount = 1; while (midiEventCount < remainingMidiEventCount) @@ -131,16 +134,7 @@ public: break; } - if (totalFramesUsed != 0) - { - for (uint32_t i=0; i < midiEventCount; ++i) - { - DISTRHO_SAFE_ASSERT_UINT2_BREAK(midiEvents[i].frame - totalFramesUsed == 0, - midiEvents[i].frame, totalFramesUsed); - } - } - - frames = remainingFrames - firstEventFrame; + frames = firstEventFrame - totalFramesUsed; remainingFrames -= frames; remainingMidiEventCount -= midiEventCount; totalFramesUsed += frames;