Browse Source

Update DPF and plugins

tags/v1.4
falkTX 5 years ago
parent
commit
8aa27dbd84
Signed by: falkTX <falktx@gmail.com> GPG Key ID: 2D3445A829213837
17 changed files with 597 additions and 247 deletions
  1. +3
    -1
      dpf/Makefile.base.mk
  2. +5
    -0
      dpf/README.md
  3. +87
    -2
      dpf/dgl/src/Cairo.cpp
  4. +4
    -5
      dpf/dgl/src/NanoVG.cpp
  5. +201
    -0
      dpf/dgl/src/Window.cpp
  6. +3
    -0
      dpf/dgl/src/pugl/pugl_x11.c
  7. +2
    -1
      dpf/dgl/src/sofd/libsofd.c
  8. +21
    -5
      dpf/distrho/DistrhoPlugin.hpp
  9. +40
    -0
      dpf/distrho/DistrhoUtils.hpp
  10. +12
    -0
      dpf/distrho/extra/String.hpp
  11. +17
    -1
      dpf/distrho/src/DistrhoDefines.h
  12. +14
    -0
      dpf/distrho/src/DistrhoPluginInternal.hpp
  13. +11
    -1
      dpf/distrho/src/DistrhoPluginLV2.cpp
  14. +161
    -89
      dpf/distrho/src/DistrhoPluginLV2export.cpp
  15. +5
    -1
      dpf/distrho/src/DistrhoPluginVST.cpp
  16. +8
    -9
      dpf/utils/generate-vst-bundles.sh
  17. +3
    -132
      plugins/Kars/DistrhoPluginKars.cpp

+ 3
- 1
dpf/Makefile.base.mk View File

@@ -213,13 +213,15 @@ 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)
ifeq ($(HAVE_X11),true)
DGL_FLAGS += $(shell $(PKG_CONFIG) --cflags x11)
DGL_SYSTEM_LIBS += $(shell $(PKG_CONFIG) --libs x11)
endif
endif

# ---------------------------------------------------------------------------------------------------------------------
# Set Cairo specific stuff


+ 5
- 0
dpf/README.md View File

@@ -30,6 +30,11 @@ List of plugins made with DPF:<br/>
- [DragonFly-Reverb](https://github.com/michaelwillis/dragonfly-reverb)
- [Wolf-Shaper](https://github.com/pdesaulniers/wolf-shaper) and [Wolf-Spectrum](https://github.com/pdesaulniers/wolf-spectrum)
- [YK Chorus](https://github.com/SpotlightKid/ykchorus)
- [Ninjas2](https://github.com/rghvdberg/ninjas2)
- [String-machine](https://github.com/jpcima/string-machine)
- [Rezonateur](https://github.com/jpcima/rezonateur)
- [QuadraFuzz](https://github.com/jpcima/quadrafuzz)
- [Shiru Plugins](https://github.com/linuxmao-org/shiru-plugins)


Plugin examples are available in the `example/` folder inside this repo.<br/>


+ 87
- 2
dpf/dgl/src/Cairo.cpp View File

@@ -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<typename T>
void Line<T>::draw()
{
notImplemented("Line::draw");
}

// -----------------------------------------------------------------------
// Circle

template<typename T>
void Circle<T>::_draw(const bool outline)
{
notImplemented("Circle::draw");
}

// -----------------------------------------------------------------------
// Triangle

template<typename T>
void Triangle<T>::_draw(const bool outline)
{
notImplemented("Triangle::draw");
}

// -----------------------------------------------------------------------
// Rectangle

template<typename T>
void Rectangle<T>::_draw(const bool outline)
{
notImplemented("Rectangle::draw");
}

// -----------------------------------------------------------------------
// Possible template data types

template class Point<double>;
template class Point<float>;
template class Point<int>;
template class Point<uint>;
template class Point<short>;
template class Point<ushort>;

template class Size<double>;
template class Size<float>;
template class Size<int>;
template class Size<uint>;
template class Size<short>;
template class Size<ushort>;

template class Line<double>;
template class Line<float>;
template class Line<int>;
template class Line<uint>;
template class Line<short>;
template class Line<ushort>;

template class Circle<double>;
template class Circle<float>;
template class Circle<int>;
template class Circle<uint>;
template class Circle<short>;
template class Circle<ushort>;

template class Triangle<double>;
template class Triangle<float>;
template class Triangle<int>;
template class Triangle<uint>;
template class Triangle<short>;
template class Triangle<ushort>;

template class Rectangle<double>;
template class Rectangle<float>;
template class Rectangle<int>;
template class Rectangle<uint>;
template class Rectangle<short>;
template class Rectangle<ushort>;

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



+ 4
- 5
dpf/dgl/src/NanoVG.cpp View File

@@ -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);
}
@@ -918,6 +915,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;



+ 201
- 0
dpf/dgl/src/Window.cpp View File

@@ -1,6 +1,8 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2019 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2019 Jean Pierre Cimalando <jp-dev@inbox.ru>
* Copyright (C) 2019 Robin Gareus <robin@gareus.org>
*
* Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above 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");
}

@@ -687,6 +714,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
}

@@ -774,6 +804,15 @@ struct Window::PrivateData {
}
#endif

#if defined(DISTRHO_OS_WINDOWS) && !defined(DGL_FILE_BROWSER_DISABLED)
if (fSelectedFile.isNotEmpty())
{
char* const buffer = fSelectedFile.getAndReleaseBuffer();
fView->fileSelectedFunc(fView, buffer);
std::free(buffer);
}
#endif

if (fModal.enabled && fModal.parent != nullptr)
fModal.parent->idle();
}
@@ -1050,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;
@@ -1095,11 +1167,18 @@ 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<PuglGenericView>* mView;
id mWindow;
id mParentWindow;
# ifndef DGL_FILE_BROWSER_DISABLED
NSOpenPanel* fOpenFilePanel;
id fFilePanelDelegate;
# endif
#else
Display* xDisplay;
::Window xWindow;
@@ -1216,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
@@ -1278,6 +1371,93 @@ 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<WCHAR> 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<WCHAR> 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<WCHAR> 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<char> 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;
# 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
return false;
@@ -1286,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;


+ 3
- 0
dpf/dgl/src/pugl/pugl_x11.c View File

@@ -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) {


+ 2
- 1
dpf/dgl/src/sofd/libsofd.c View File

@@ -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, "/");


+ 21
- 5
dpf/distrho/DistrhoPlugin.hpp View File

@@ -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
@@ -399,6 +406,12 @@ struct Parameter {
*/
String unit;

/**
An extensive description/comment about the parameter.
@note This value is optional and only used for LV2.
*/
String description;

/**
Ranges of this parameter.@n
The ranges describe the default, minimum and maximum values.
@@ -430,6 +443,7 @@ struct Parameter {
Parameter() noexcept
: hints(0x0),
name(),
shortName(),
symbol(),
unit(),
ranges(),
@@ -443,6 +457,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 +477,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;


+ 40
- 0
dpf/distrho/DistrhoUtils.hpp View File

@@ -156,6 +156,46 @@ void d_safe_assert(const char* const assertion, const char* const file, const in
d_stderr2("assertion failure: \"%s\" in file %s, line %i", assertion, file, line);
}

/*
* Print a safe assertion error message, with 1 extra signed integer value.
*/
static inline
void d_safe_assert_int(const char* const assertion, const char* const file,
const int line, const int value) noexcept
{
d_stderr2("assertion failure: \"%s\" in file %s, line %i, value %i", assertion, file, line, value);
}

/*
* Print a safe assertion error message, with 1 extra unsigned integer value.
*/
static inline
void d_safe_assert_uint(const char* const assertion, const char* const file,
const int line, const uint value) noexcept
{
d_stderr2("assertion failure: \"%s\" in file %s, line %i, value %u", assertion, file, line, value);
}

/*
* Print a safe assertion error message, with 2 extra signed integer values.
*/
static inline
void d_safe_assert_int2(const char* const assertion, const char* const file,
const int line, const int v1, const int v2) noexcept
{
d_stderr2("assertion failure: \"%s\" in file %s, line %i, v1 %i, v2 %i", assertion, file, line, v1, v2);
}

/*
* Print a safe assertion error message, with 2 extra unsigned integer values.
*/
static inline
void d_safe_assert_uint2(const char* const assertion, const char* const file,
const int line, const uint v1, const uint v2) noexcept
{
d_stderr2("assertion failure: \"%s\" in file %s, line %i, v1 %u, v2 %u", assertion, file, line, v1, v2);
}

/*
* Print a safe exception error message.
*/


+ 12
- 0
dpf/distrho/extra/String.hpp View File

@@ -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


+ 17
- 1
dpf/distrho/src/DistrhoDefines.h View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2016 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2019 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
@@ -81,6 +81,22 @@
#define DISTRHO_SAFE_ASSERT_CONTINUE(cond) if (! (cond)) { d_safe_assert(#cond, __FILE__, __LINE__); continue; }
#define DISTRHO_SAFE_ASSERT_RETURN(cond, ret) if (! (cond)) { d_safe_assert(#cond, __FILE__, __LINE__); return ret; }

#define DISTRHO_SAFE_ASSERT_INT_BREAK(cond, value) if (! (cond)) { d_safe_assert_int(#cond, __FILE__, __LINE__, static_cast<int>(value); break; }
#define DISTRHO_SAFE_ASSERT_INT_CONTINUE(cond, value) if (! (cond)) { d_safe_assert_int(#cond, __FILE__, __LINE__, static_cast<int>(value)); continue; }
#define DISTRHO_SAFE_ASSERT_INT_RETURN(cond, value, ret) if (! (cond)) { d_safe_assert_int(#cond, __FILE__, __LINE__, static_cast<int>(value)); return ret; }

#define DISTRHO_SAFE_ASSERT_INT2_BREAK(cond, v1, v2) if (! (cond)) { d_safe_assert_int2(#cond, __FILE__, __LINE__, static_cast<int>(v1), static_cast<int>(v2)); break; }
#define DISTRHO_SAFE_ASSERT_INT2_CONTINUE(cond, v1, v2) if (! (cond)) { d_safe_assert_int2(#cond, __FILE__, __LINE__, static_cast<int>(v1), static_cast<int>(v2)); continue; }
#define DISTRHO_SAFE_ASSERT_INT2_RETURN(cond, v1, v2, ret) if (! (cond)) { d_safe_assert_int2(#cond, __FILE__, __LINE__, static_cast<int>(v1), static_cast<int>(v2)); return ret; }

#define DISTRHO_SAFE_ASSERT_UINT_BREAK(cond, value) if (! (cond)) { d_safe_assert_uint(#cond, __FILE__, __LINE__, static_cast<uint>(value); break; }
#define DISTRHO_SAFE_ASSERT_UINT_CONTINUE(cond, value) if (! (cond)) { d_safe_assert_uint(#cond, __FILE__, __LINE__, static_cast<uint>(value)); continue; }
#define DISTRHO_SAFE_ASSERT_UINT_RETURN(cond, value, ret) if (! (cond)) { d_safe_assert_uint(#cond, __FILE__, __LINE__, static_cast<uint>(value)); return ret; }

#define DISTRHO_SAFE_ASSERT_UINT2_BREAK(cond, v1, v2) if (! (cond)) { d_safe_assert_uint2(#cond, __FILE__, __LINE__, static_cast<uint>(v1), static_cast<uint>(v2)); break; }
#define DISTRHO_SAFE_ASSERT_UINT2_CONTINUE(cond, v1, v2) if (! (cond)) { d_safe_assert_uint2(#cond, __FILE__, __LINE__, static_cast<uint>(v1), static_cast<uint>(v2)); continue; }
#define DISTRHO_SAFE_ASSERT_UINT2_RETURN(cond, v1, v2, ret) if (! (cond)) { d_safe_assert_uint2(#cond, __FILE__, __LINE__, static_cast<uint>(v1), static_cast<uint>(v2)); return ret; }

/* Define DISTRHO_SAFE_EXCEPTION */
#define DISTRHO_SAFE_EXCEPTION(msg) catch(...) { d_safe_exception(msg, __FILE__, __LINE__); }
#define DISTRHO_SAFE_EXCEPTION_BREAK(msg) catch(...) { d_safe_exception(msg, __FILE__, __LINE__); break; }


+ 14
- 0
dpf/distrho/src/DistrhoPluginInternal.hpp View File

@@ -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);
@@ -389,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);


+ 11
- 1
dpf/distrho/src/DistrhoPluginLV2.cpp View File

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


+ 161
- 89
dpf/distrho/src/DistrhoPluginLV2export.cpp View File

@@ -70,6 +70,140 @@
#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[] =
{
"opts:interface",
#if DISTRHO_PLUGIN_WANT_STATE
LV2_STATE__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[] =
{
"opts: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[] =
{
"opts: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[] =
{
"opts:options",
#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
LV2_DATA_ACCESS_URI,
LV2_INSTANCE_ACCESS_URI,
#endif
LV2_URID__map,
nullptr
};

static const char* const lv2ManifestUiSupportedOptions[] =
{
LV2_PARAMETERS__sampleRate,
nullptr
};
#endif // DISTRHO_PLUGIN_HAS_UI

static void addAttribute(String& text,
const char* const attribute,
const char* const values[],
const uint indent,
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);

for (uint i = 0; values[i] != nullptr; ++i)
{
for (uint j = 0; j < indent; ++j)
text += " ";

if (i == 0)
{
text += attribute;
}
else
{
for (uint j = 0; j < attributeLength; ++j)
text += " ";
}

text += " ";

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" : (endInDot ? " .\n\n" : " ;\n\n");
}
}

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

DISTRHO_PLUGIN_EXPORT
@@ -132,32 +266,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
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, "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
@@ -214,7 +326,9 @@ void lv2_generate_ttl(const char* const basename)
pluginString += "@prefix opts: <" LV2_OPTIONS_PREFIX "> .\n";
pluginString += "@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .\n";
pluginString += "@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\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
@@ -232,45 +346,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, "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
@@ -440,6 +519,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));

@@ -528,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));

@@ -560,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
@@ -629,30 +720,11 @@ 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, "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();


+ 5
- 1
dpf/distrho/src/DistrhoPluginVST.cpp View File

@@ -1294,7 +1294,11 @@ static intptr_t vst_dispatcherCallback(AEffect* effect, int32_t opcode, int32_t
case effGetParamName:
if (ptr != nullptr && index < static_cast<int32_t>(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;


+ 8
- 9
dpf/utils/generate-vst-bundles.sh View File

@@ -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 ../dpf/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 ..

+ 3
- 132
plugins/Kars/DistrhoPluginKars.cpp View File

@@ -15,6 +15,7 @@
*/
#include "DistrhoPluginKars.hpp"
#include "DistrhoPluginUtils.hpp"
START_NAMESPACE_DISTRHO
@@ -117,136 +118,6 @@ void DistrhoPluginKars::activate()
}
}
/**
Handy class to help keep audio buffer in sync with incoming MIDI events.
To use it, create a local variable (on the stack) and call nextEvent() until it returns false.
@code
for (AudioMidiSyncHelper amsh(outputs, frames, midiEvents, midiEventCount); amsh.nextEvent();)
{
float* const outL = amsh.outputs[0];
float* const outR = amsh.outputs[1];
for (uint32_t i=0; i<amsh.midiEventCount; ++i)
{
const MidiEvent& ev(amsh.midiEvents[i]);
// ... do something with the midi event
}
renderSynth(outL, outR, amsh.frames);
}
@endcode
Some important notes when using this class:
1. MidiEvent::frame retains its original value, but it is useless, do not use it.
2. The class variables names are be the same as the default ones in the run function.
Keep that in mind and try to avoid typos. :)
*/
class AudioMidiSyncHelper {
public:
/** Parameters from the run function, adjusted for event sync */
float** outputs;
uint32_t frames;
const MidiEvent* midiEvents;
uint32_t midiEventCount;
/**
Constructor, using values from the run function.
*/
AudioMidiSyncHelper(float** const o, uint32_t f, const MidiEvent* m, uint32_t mc)
: outputs(o),
frames(0),
midiEvents(m),
midiEventCount(0),
remainingFrames(f),
remainingMidiEventCount(mc),
totalFramesUsed(0) {}
/**
Process a batch of events untill no more are available.
You must not read any more values from this class after this function returns false.
*/
bool nextEvent()
{
// nothing else to do
if (remainingFrames == 0)
return false;
// initial setup, need to find first MIDI event
if (totalFramesUsed == 0)
{
// no MIDI events at all in this process cycle
if (remainingMidiEventCount == 0)
{
frames = remainingFrames;
remainingFrames = 0;
totalFramesUsed += frames;
return true;
}
// render audio until first midi event, if needed
if (const uint32_t firstEventFrame = midiEvents[0].frame)
{
frames = midiEvents[0].frame;
remainingFrames -= frames;
totalFramesUsed += frames;
return true;
}
}
else
{
for (uint32_t i=0; i<DISTRHO_PLUGIN_NUM_OUTPUTS; ++i)
outputs[i] += frames;
}
// no more MIDI events available
if (remainingMidiEventCount == 0)
{
frames = remainingFrames;
midiEvents = nullptr;
midiEventCount = 0;
remainingFrames = 0;
totalFramesUsed += frames;
return true;
}
// if there were midi events before, increment pointer
if (midiEventCount != 0)
midiEvents += midiEventCount;
const uint32_t firstEventFrame = midiEvents[0].frame;
DISTRHO_SAFE_ASSERT_RETURN((firstEventFrame - frames) < remainingFrames, false);
midiEventCount = 1;
while (midiEventCount < remainingMidiEventCount)
{
if (midiEvents[midiEventCount].frame == firstEventFrame)
++midiEventCount;
else
break;
}
if (totalFramesUsed != 0)
{
// need to modify timestamp of midi events
MidiEvent* const rwEvents = const_cast<MidiEvent*>(midiEvents);
for (uint32_t i=0; i < midiEventCount; ++i)
rwEvents[i].frame -= totalFramesUsed;
}
frames = remainingFrames - firstEventFrame;
remainingFrames -= frames;
remainingMidiEventCount -= midiEventCount;
totalFramesUsed += frames;
return true;
}
private:
/** @internal */
uint32_t remainingFrames;
uint32_t remainingMidiEventCount;
uint32_t totalFramesUsed;
};
void DistrhoPluginKars::run(const float**, float** outputs, uint32_t frames, const MidiEvent* midiEvents, uint32_t midiEventCount)
{
uint8_t note, velo;
@@ -270,7 +141,7 @@ void DistrhoPluginKars::run(const float**, float** outputs, uint32_t frames, con
DISTRHO_SAFE_ASSERT_BREAK(note < 128); // kMaxNotes
if (velo > 0)
{
fNotes[note].on = fBlockStart + amsh.midiEvents[i].frame;
fNotes[note].on = fBlockStart;
fNotes[note].off = kNoteNull;
fNotes[note].velocity = velo;
break;
@@ -279,7 +150,7 @@ void DistrhoPluginKars::run(const float**, float** outputs, uint32_t frames, con
case 0x80:
note = data[1];
DISTRHO_SAFE_ASSERT_BREAK(note < 128); // kMaxNotes
fNotes[note].off = fBlockStart + amsh.midiEvents[i].frame;
fNotes[note].off = fBlockStart;
break;
}
}


Loading…
Cancel
Save