Browse Source

Merge branch 'develop'

pull/173/head
falkTX 5 years ago
parent
commit
4c8d448b10
16 changed files with 543 additions and 131 deletions
  1. +3
    -1
      Makefile
  2. +1
    -1
      Makefile.base.mk
  3. +87
    -2
      dgl/src/Cairo.cpp
  4. +4
    -5
      dgl/src/NanoVG.cpp
  5. +201
    -0
      dgl/src/Window.cpp
  6. +3
    -0
      dgl/src/pugl/pugl_x11.c
  7. +2
    -1
      dgl/src/sofd/libsofd.c
  8. +21
    -5
      distrho/DistrhoPlugin.hpp
  9. +8
    -14
      distrho/DistrhoPluginUtils.hpp
  10. +12
    -0
      distrho/extra/String.hpp
  11. +14
    -0
      distrho/src/DistrhoPluginInternal.hpp
  12. +11
    -1
      distrho/src/DistrhoPluginLV2.cpp
  13. +161
    -89
      distrho/src/DistrhoPluginLV2export.cpp
  14. +5
    -1
      distrho/src/DistrhoPluginVST.cpp
  15. +2
    -2
      examples/CairoUI/DistrhoPluginInfo.h
  16. +8
    -9
      utils/generate-vst-bundles.sh

+ 3
- 1
Makefile View File

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

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


+ 1
- 1
Makefile.base.mk View File

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


+ 87
- 2
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
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
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
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
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
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;


+ 8
- 14
distrho/DistrhoPluginUtils.hpp View File

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


+ 12
- 0
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


+ 14
- 0
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
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
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
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;


+ 2
- 2
examples/CairoUI/DistrhoPluginInfo.h View File

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


+ 8
- 9
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 ..

Loading…
Cancel
Save