@@ -2,33 +2,33 @@ | |||
set -e | |||
# cp -v /home/falktx/FOSS/GIT-mine/DISTRHO/DPF/dgl/*.hpp /home/falktx/FOSS/GIT-mine/Carla/source/modules/dgl/ | |||
# cp -r -v /home/falktx/FOSS/GIT-mine/DISTRHO/DPF/dgl/src /home/falktx/FOSS/GIT-mine/Carla/source/modules/dgl/ | |||
cp -r -v /home/falktx/FOSS/GIT-mine/DISTRHO/DPF/distrho/* /home/falktx/FOSS/GIT-mine/Carla/source/modules/distrho/ | |||
cp -v /home/falktx/FOSS/GIT-mine/DISTRHO/DISTRHO_mini-series/plugins/3BandEQ/{*.cpp,*.hpp,*.h} /home/falktx/FOSS/GIT-mine/Carla/source/modules/native-plugins/3bandeq/ | |||
cp -v /home/falktx/FOSS/GIT-mine/DISTRHO/DISTRHO_mini-series/plugins/3BandSplitter/{*.cpp,*.hpp,*.h} /home/falktx/FOSS/GIT-mine/Carla/source/modules/native-plugins/3bandsplitter/ | |||
cp -v /home/falktx/FOSS/GIT-mine/DISTRHO/DISTRHO_mini-series/plugins/PingPongPan/{*.cpp,*.hpp,*.h} /home/falktx/FOSS/GIT-mine/Carla/source/modules/native-plugins/pingpongpan/ | |||
cp -v /home/falktx/FOSS/GIT-mine/DISTRHO/DISTRHO_nekobi/plugins/Nekobi/{*.cpp,*.hpp,*.h} /home/falktx/FOSS/GIT-mine/Carla/source/modules/native-plugins/nekobi/ | |||
cp -v /home/falktx/FOSS/GIT-mine/DISTRHO/DISTRHO_nekobi/plugins/Nekobi/nekobee-src/{*.c,*.h} /home/falktx/FOSS/GIT-mine/Carla/source/modules/native-plugins/nekobi/nekobee-src/ | |||
cp -v /home/falktx/FOSS/GIT-mine/DISTRHO/DISTRHO_prom/plugins/ProM/{*.cpp,*.hpp,*.h} /home/falktx/FOSS/GIT-mine/Carla/source/modules/native-plugins/prom/ | |||
cp -v /home/falktx/FOSS/GIT-mine/DISTRHO/JuicePlugins/plugins/GrooveJuice/{*.cpp,*.hpp,*.hxx,*.h} /home/falktx/FOSS/GIT-mine/Carla/source/modules/native-plugins/groovejuice/ | |||
cp -v /home/falktx/FOSS/GIT-mine/DISTRHO/JuicePlugins/plugins/PowerJuice/{*.cpp,*.hpp,*.h} /home/falktx/FOSS/GIT-mine/Carla/source/modules/native-plugins/powerjuice/ | |||
# cp -v /home/falktx/FOSS/GIT-mine/DISTRHO/JuicePlugins/plugins/PowerJuiceX2/{*.cpp,*.hpp,*.hxx,*.h} /home/falktx/FOSS/GIT-mine/Carla/source/modules/native-plugins/powerjuicex2/ | |||
cp -v /home/falktx/FOSS/GIT-mine/DISTRHO/JuicePlugins/plugins/SegmentJuice/{*.cpp,*.hpp,*.hxx,*.h} /home/falktx/FOSS/GIT-mine/Carla/source/modules/native-plugins/segmentjuice/ | |||
# cp -v /home/falktx/FOSS/GIT-mine/DISTRHO/JuicePlugins/plugins/StutterJuice/{*.cpp,*.hpp,*.hxx,*.h} /home/falktx/FOSS/GIT-mine/Carla/source/modules/native-plugins/stutterjuice/ | |||
# cp -v /home/falktx/FOSS/GIT-mine/DISTRHO/JuicePlugins/plugins/TriggerJuice/{*.cpp,*.hpp,*.hxx,*.h} /home/falktx/FOSS/GIT-mine/Carla/source/modules/native-plugins/triggerjuice/ | |||
cp -v /home/falktx/FOSS/GIT-mine/DISTRHO/JuicePlugins/plugins/VectorJuice/{*.cpp,*.hpp,*.h} /home/falktx/FOSS/GIT-mine/Carla/source/modules/native-plugins/vectorjuice/ | |||
cp -v /home/falktx/FOSS/GIT-mine/DISTRHO/JuicePlugins/plugins/WobbleJuice/{*.cpp,*.hpp,*.hxx,*.h} /home/falktx/FOSS/GIT-mine/Carla/source/modules/native-plugins/wobblejuice/ | |||
cp -v /home/falktx/FOSS/GIT-mine/zam-plugins-DPF/plugins/ZamComp/{*.cpp,*.hpp,*.h} /home/falktx/FOSS/GIT-mine/Carla/source/modules/native-plugins/zamcomp/ | |||
cp -v /home/falktx/FOSS/GIT-mine/zam-plugins-DPF/plugins/ZamCompX2/{*.cpp,*.hpp,*.h} /home/falktx/FOSS/GIT-mine/Carla/source/modules/native-plugins/zamcompx2/ | |||
cp -v /home/falktx/FOSS/GIT-mine/zam-plugins-DPF/plugins/ZamEQ2/{*.cpp,*.hpp,*.h} /home/falktx/FOSS/GIT-mine/Carla/source/modules/native-plugins/zameq2/ | |||
cp -v /home/falktx/FOSS/GIT-mine/zam-plugins-DPF/plugins/ZamSynth/{*.cpp,*.hpp,*.h} /home/falktx/FOSS/GIT-mine/Carla/source/modules/native-plugins/zamsynth/ | |||
cp -v /home/falktx/FOSS/GIT-mine/zam-plugins-DPF/plugins/ZamTube/{*.cpp,*.hpp,*.h} /home/falktx/FOSS/GIT-mine/Carla/source/modules/native-plugins/zamtube/ | |||
cp -v /home/falktx/FOSS/GIT-mine/zam-plugins-DPF/plugins/ZaMultiComp/{*.cpp,*.hpp,*.h} /home/falktx/FOSS/GIT-mine/Carla/source/modules/native-plugins/zamulticomp/ | |||
cp -v /home/falktx/FOSS/GIT-mine/zam-plugins-DPF/plugins/ZaMultiCompX2/{*.cpp,*.hpp,*.h} /home/falktx/FOSS/GIT-mine/Carla/source/modules/native-plugins/zamulticompx2/ | |||
cp -v /home/falktx/FOSS/GIT-mine/DISTRHO/DPF/dgl/*.hpp /home/falktx/FOSS/GIT-mine/falkTX/Carla/source/modules/dgl/ | |||
cp -r -v /home/falktx/FOSS/GIT-mine/DISTRHO/DPF/dgl/src /home/falktx/FOSS/GIT-mine/falkTX/Carla/source/modules/dgl/ | |||
cp -r -v /home/falktx/FOSS/GIT-mine/DISTRHO/DPF/distrho/* /home/falktx/FOSS/GIT-mine/falkTX/Carla/source/modules/distrho/ | |||
# cp -v /home/falktx/FOSS/GIT-mine/DISTRHO/DISTRHO_mini-series/plugins/3BandEQ/{*.cpp,*.hpp,*.h} /home/falktx/FOSS/GIT-mine/falkTX/Carla/source/modules/native-plugins/3bandeq/ | |||
# cp -v /home/falktx/FOSS/GIT-mine/DISTRHO/DISTRHO_mini-series/plugins/3BandSplitter/{*.cpp,*.hpp,*.h} /home/falktx/FOSS/GIT-mine/falkTX/Carla/source/modules/native-plugins/3bandsplitter/ | |||
# cp -v /home/falktx/FOSS/GIT-mine/DISTRHO/DISTRHO_mini-series/plugins/PingPongPan/{*.cpp,*.hpp,*.h} /home/falktx/FOSS/GIT-mine/falkTX/Carla/source/modules/native-plugins/pingpongpan/ | |||
# | |||
# cp -v /home/falktx/FOSS/GIT-mine/DISTRHO/DISTRHO_nekobi/plugins/Nekobi/{*.cpp,*.hpp,*.h} /home/falktx/FOSS/GIT-mine/falkTX/Carla/source/modules/native-plugins/nekobi/ | |||
# cp -v /home/falktx/FOSS/GIT-mine/DISTRHO/DISTRHO_nekobi/plugins/Nekobi/nekobee-src/{*.c,*.h} /home/falktx/FOSS/GIT-mine/falkTX/Carla/source/modules/native-plugins/nekobi/nekobee-src/ | |||
# | |||
# cp -v /home/falktx/FOSS/GIT-mine/DISTRHO/DISTRHO_prom/plugins/ProM/{*.cpp,*.hpp,*.h} /home/falktx/FOSS/GIT-mine/falkTX/Carla/source/modules/native-plugins/prom/ | |||
# | |||
# cp -v /home/falktx/FOSS/GIT-mine/DISTRHO/JuicePlugins/plugins/GrooveJuice/{*.cpp,*.hpp,*.hxx,*.h} /home/falktx/FOSS/GIT-mine/falkTX/Carla/source/modules/native-plugins/groovejuice/ | |||
# cp -v /home/falktx/FOSS/GIT-mine/DISTRHO/JuicePlugins/plugins/PowerJuice/{*.cpp,*.hpp,*.h} /home/falktx/FOSS/GIT-mine/falkTX/Carla/source/modules/native-plugins/powerjuice/ | |||
# # cp -v /home/falktx/FOSS/GIT-mine/DISTRHO/JuicePlugins/plugins/PowerJuiceX2/{*.cpp,*.hpp,*.hxx,*.h} /home/falktx/FOSS/GIT-mine/falkTX/Carla/source/modules/native-plugins/powerjuicex2/ | |||
# cp -v /home/falktx/FOSS/GIT-mine/DISTRHO/JuicePlugins/plugins/SegmentJuice/{*.cpp,*.hpp,*.hxx,*.h} /home/falktx/FOSS/GIT-mine/falkTX/Carla/source/modules/native-plugins/segmentjuice/ | |||
# # cp -v /home/falktx/FOSS/GIT-mine/DISTRHO/JuicePlugins/plugins/StutterJuice/{*.cpp,*.hpp,*.hxx,*.h} /home/falktx/FOSS/GIT-mine/falkTX/Carla/source/modules/native-plugins/stutterjuice/ | |||
# # cp -v /home/falktx/FOSS/GIT-mine/DISTRHO/JuicePlugins/plugins/TriggerJuice/{*.cpp,*.hpp,*.hxx,*.h} /home/falktx/FOSS/GIT-mine/falkTX/Carla/source/modules/native-plugins/triggerjuice/ | |||
# cp -v /home/falktx/FOSS/GIT-mine/DISTRHO/JuicePlugins/plugins/VectorJuice/{*.cpp,*.hpp,*.h} /home/falktx/FOSS/GIT-mine/falkTX/Carla/source/modules/native-plugins/vectorjuice/ | |||
# cp -v /home/falktx/FOSS/GIT-mine/DISTRHO/JuicePlugins/plugins/WobbleJuice/{*.cpp,*.hpp,*.hxx,*.h} /home/falktx/FOSS/GIT-mine/falkTX/Carla/source/modules/native-plugins/wobblejuice/ | |||
# | |||
# cp -v /home/falktx/FOSS/GIT-mine/zam-plugins-DPF/plugins/ZamComp/{*.cpp,*.hpp,*.h} /home/falktx/FOSS/GIT-mine/falkTX/Carla/source/modules/native-plugins/zamcomp/ | |||
# cp -v /home/falktx/FOSS/GIT-mine/zam-plugins-DPF/plugins/ZamCompX2/{*.cpp,*.hpp,*.h} /home/falktx/FOSS/GIT-mine/falkTX/Carla/source/modules/native-plugins/zamcompx2/ | |||
# cp -v /home/falktx/FOSS/GIT-mine/zam-plugins-DPF/plugins/ZamEQ2/{*.cpp,*.hpp,*.h} /home/falktx/FOSS/GIT-mine/falkTX/Carla/source/modules/native-plugins/zameq2/ | |||
# cp -v /home/falktx/FOSS/GIT-mine/zam-plugins-DPF/plugins/ZamSynth/{*.cpp,*.hpp,*.h} /home/falktx/FOSS/GIT-mine/falkTX/Carla/source/modules/native-plugins/zamsynth/ | |||
# cp -v /home/falktx/FOSS/GIT-mine/zam-plugins-DPF/plugins/ZamTube/{*.cpp,*.hpp,*.h} /home/falktx/FOSS/GIT-mine/falkTX/Carla/source/modules/native-plugins/zamtube/ | |||
# cp -v /home/falktx/FOSS/GIT-mine/zam-plugins-DPF/plugins/ZaMultiComp/{*.cpp,*.hpp,*.h} /home/falktx/FOSS/GIT-mine/falkTX/Carla/source/modules/native-plugins/zamulticomp/ | |||
# cp -v /home/falktx/FOSS/GIT-mine/zam-plugins-DPF/plugins/ZaMultiCompX2/{*.cpp,*.hpp,*.h} /home/falktx/FOSS/GIT-mine/falkTX/Carla/source/modules/native-plugins/zamulticompx2/ |
@@ -192,10 +192,10 @@ private: | |||
@code | |||
const char* txt = "Text me up."; | |||
textBounds(vg, x,y, txt, NULL, bounds); | |||
beginPath(vg); | |||
roundedRect(vg, bounds[0], bounds[1], bounds[2]-bounds[0], bounds[3]-bounds[1]); | |||
fill(vg); | |||
vg.textBounds(x,y, txt, NULL, bounds); | |||
vg.beginPath(); | |||
vg.roundedRect(bounds[0], bounds[1], bounds[2]-bounds[0], bounds[3]-bounds[1]); | |||
vg.fill(); | |||
@endcode | |||
Note: currently only solid color fill is supported for text. | |||
@@ -111,7 +111,7 @@ public: | |||
/** | |||
Mouse event. | |||
@a button The button number (1 = left, 2 = middle, 3 = right). | |||
@a press True if the key was pressed, false if released. | |||
@a press True if the button was pressed, false if released. | |||
@a pos The widget-relative coordinates of the pointer. | |||
@see onMouse | |||
*/ | |||
@@ -19,6 +19,10 @@ | |||
#include "Geometry.hpp" | |||
START_NAMESPACE_DISTRHO | |||
class UIExporter; | |||
END_NAMESPACE_DISTRHO | |||
START_NAMESPACE_DGL | |||
// ----------------------------------------------------------------------- | |||
@@ -125,11 +129,15 @@ private: | |||
friend class Application; | |||
friend class Widget; | |||
friend class StandaloneWindow; | |||
friend class DISTRHO_NAMESPACE::UIExporter; | |||
virtual void _addWidget(Widget* const widget); | |||
virtual void _removeWidget(Widget* const widget); | |||
void _idle(); | |||
bool handlePluginKeyboard(const bool press, const uint key); | |||
bool handlePluginSpecial(const bool press, const Key key); | |||
DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(Window) | |||
}; | |||
@@ -68,7 +68,9 @@ Image::~Image() | |||
{ | |||
if (fTextureId != 0) | |||
{ | |||
#ifndef DISTRHO_OS_MAC // FIXME | |||
glDeleteTextures(1, &fTextureId); | |||
#endif | |||
fTextureId = 0; | |||
} | |||
} | |||
@@ -1,6 +1,6 @@ | |||
/* | |||
* DISTRHO Plugin Framework (DPF) | |||
* Copyright (C) 2012-2016 Filipe Coelho <falktx@falktx.com> | |||
* Copyright (C) 2012-2018 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 | |||
@@ -1,6 +1,6 @@ | |||
/* | |||
* DISTRHO Plugin Framework (DPF) | |||
* Copyright (C) 2012-2016 Filipe Coelho <falktx@falktx.com> | |||
* Copyright (C) 2012-2018 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 | |||
@@ -34,14 +34,12 @@ | |||
# include "pugl/pugl_win.cpp" | |||
#elif defined(DISTRHO_OS_MAC) | |||
# include "pugl/pugl_osx.m" | |||
#elif defined(DISTRHO_OS_LINUX) | |||
#else | |||
# include <sys/types.h> | |||
# include <unistd.h> | |||
extern "C" { | |||
# include "pugl/pugl_x11.c" | |||
} | |||
#else | |||
# error Unsupported platform | |||
#endif | |||
#if defined(__GNUC__) && (__GNUC__ >= 7) | |||
@@ -90,13 +88,13 @@ struct Window::PrivateData { | |||
fModal(), | |||
#if defined(DISTRHO_OS_WINDOWS) | |||
hwnd(0) | |||
#elif defined(DISTRHO_OS_LINUX) | |||
xDisplay(nullptr), | |||
xWindow(0) | |||
#elif defined(DISTRHO_OS_MAC) | |||
fNeedsIdle(true), | |||
mView(nullptr), | |||
mWindow(nullptr) | |||
#else | |||
xDisplay(nullptr), | |||
xWindow(0) | |||
#endif | |||
{ | |||
DBG("Creating window without parent..."); DBGF; | |||
@@ -118,27 +116,30 @@ struct Window::PrivateData { | |||
fModal(parent.pData), | |||
#if defined(DISTRHO_OS_WINDOWS) | |||
hwnd(0) | |||
#elif defined(DISTRHO_OS_LINUX) | |||
xDisplay(nullptr), | |||
xWindow(0) | |||
#elif defined(DISTRHO_OS_MAC) | |||
fNeedsIdle(false), | |||
mView(nullptr), | |||
mWindow(nullptr) | |||
#else | |||
xDisplay(nullptr), | |||
xWindow(0) | |||
#endif | |||
{ | |||
DBG("Creating window with parent..."); DBGF; | |||
init(); | |||
const PuglInternals* const parentImpl(parent.pData->fView->impl); | |||
#if defined(DISTRHO_OS_LINUX) | |||
XSetTransientForHint(xDisplay, xWindow, parentImpl->win); | |||
//#elif defined(DISTRHO_OS_MAC) | |||
// [parentImpl->window orderWindow:NSWindowBelow relativeTo:[[mView window] windowNumber]]; | |||
#if defined(DISTRHO_OS_WINDOWS) | |||
// TODO | |||
#elif defined(DISTRHO_OS_MAC) | |||
[parentImpl->window orderWindow:NSWindowBelow relativeTo:[[mView window] windowNumber]]; | |||
#else | |||
// unused | |||
return; (void)parentImpl; | |||
XSetTransientForHint(xDisplay, xWindow, parentImpl->win); | |||
#endif | |||
return; | |||
// maybe unused | |||
(void)parentImpl; | |||
} | |||
PrivateData(Application& app, Window* const self, const intptr_t parentId) | |||
@@ -156,13 +157,13 @@ struct Window::PrivateData { | |||
fModal(), | |||
#if defined(DISTRHO_OS_WINDOWS) | |||
hwnd(0) | |||
#elif defined(DISTRHO_OS_LINUX) | |||
xDisplay(nullptr), | |||
xWindow(0) | |||
#elif defined(DISTRHO_OS_MAC) | |||
fNeedsIdle(parentId == 0), | |||
mView(nullptr), | |||
mWindow(nullptr) | |||
#else | |||
xDisplay(nullptr), | |||
xWindow(0) | |||
#endif | |||
{ | |||
if (fUsingEmbed) | |||
@@ -226,7 +227,7 @@ struct Window::PrivateData { | |||
} else { | |||
DISTRHO_SAFE_ASSERT(mWindow != nullptr); | |||
} | |||
#elif defined(DISTRHO_OS_LINUX) | |||
#else | |||
xDisplay = impl->display; | |||
xWindow = impl->win; | |||
DISTRHO_SAFE_ASSERT(xWindow != 0); | |||
@@ -286,7 +287,7 @@ struct Window::PrivateData { | |||
#elif defined(DISTRHO_OS_MAC) | |||
mView = nullptr; | |||
mWindow = nullptr; | |||
#elif defined(DISTRHO_OS_LINUX) | |||
#else | |||
xDisplay = nullptr; | |||
xWindow = 0; | |||
#endif | |||
@@ -380,7 +381,7 @@ struct Window::PrivateData { | |||
// TODO | |||
#elif defined(DISTRHO_OS_MAC) | |||
// TODO | |||
#elif defined(DISTRHO_OS_LINUX) | |||
#else | |||
int i, wx, wy; | |||
uint u; | |||
::Window w; | |||
@@ -404,7 +405,7 @@ struct Window::PrivateData { | |||
#elif defined(DISTRHO_OS_MAC) | |||
if (mWindow != nullptr) | |||
[mWindow makeKeyWindow]; | |||
#elif defined(DISTRHO_OS_LINUX) | |||
#else | |||
XRaiseWindow(xDisplay, xWindow); | |||
XSetInputFocus(xDisplay, xWindow, RevertToPointerRoot, CurrentTime); | |||
XFlush(xDisplay); | |||
@@ -455,7 +456,7 @@ struct Window::PrivateData { | |||
else | |||
[mView setHidden:YES]; | |||
} | |||
#elif defined(DISTRHO_OS_LINUX) | |||
#else | |||
if (yesNo) | |||
XMapRaised(xDisplay, xWindow); | |||
else | |||
@@ -559,7 +560,7 @@ struct Window::PrivateData { | |||
[[mWindow standardWindowButton:NSWindowZoomButton] setHidden:YES]; | |||
} | |||
} | |||
#elif defined(DISTRHO_OS_LINUX) | |||
#else | |||
XResizeWindow(xDisplay, xWindow, width, height); | |||
if (! fResizable) | |||
@@ -615,7 +616,7 @@ struct Window::PrivateData { | |||
[mWindow setTitle:titleString]; | |||
} | |||
#elif defined(DISTRHO_OS_LINUX) | |||
#else | |||
XStoreName(xDisplay, xWindow, title); | |||
#endif | |||
} | |||
@@ -624,14 +625,16 @@ struct Window::PrivateData { | |||
{ | |||
DISTRHO_SAFE_ASSERT_RETURN(winId != 0,); | |||
#if defined(DISTRHO_OS_MAC) | |||
NSWindow* window = [NSApp windowWithWindowNumber:winId]; | |||
#if defined(DISTRHO_OS_WINDOWS) | |||
// TODO | |||
#elif defined(DISTRHO_OS_MAC) | |||
NSWindow* const window = [NSApp windowWithWindowNumber:winId]; | |||
DISTRHO_SAFE_ASSERT_RETURN(window != nullptr,); | |||
[window addChildWindow:mWindow | |||
ordered:NSWindowAbove]; | |||
[mWindow makeKeyWindow]; | |||
#elif defined(DISTRHO_OS_LINUX) | |||
#else | |||
XSetTransientForHint(xDisplay, xWindow, static_cast< ::Window>(winId)); | |||
#endif | |||
} | |||
@@ -859,6 +862,90 @@ struct Window::PrivateData { | |||
// ------------------------------------------------------------------- | |||
bool handlePluginKeyboard(const bool press, const uint key) | |||
{ | |||
DBGp("PUGL: handlePluginKeyboard : %i %i\n", press, key); | |||
if (fModal.childFocus != nullptr) | |||
{ | |||
fModal.childFocus->focus(); | |||
return true; | |||
} | |||
Widget::KeyboardEvent ev; | |||
ev.press = press; | |||
ev.key = key; | |||
ev.mod = static_cast<Modifier>(fView->mods); | |||
ev.time = 0; | |||
if ((ev.mod & kModifierShift) != 0 && ev.key >= 'a' && ev.key <= 'z') | |||
ev.key -= 'a' - 'A'; // a-z -> A-Z | |||
FOR_EACH_WIDGET_INV(rit) | |||
{ | |||
Widget* const widget(*rit); | |||
if (widget->isVisible() && widget->onKeyboard(ev)) | |||
return true; | |||
} | |||
return false; | |||
} | |||
bool handlePluginSpecial(const bool press, const Key key) | |||
{ | |||
DBGp("PUGL: handlePluginSpecial : %i %i\n", press, key); | |||
if (fModal.childFocus != nullptr) | |||
{ | |||
fModal.childFocus->focus(); | |||
return true; | |||
} | |||
int mods = 0x0; | |||
switch (key) | |||
{ | |||
case kKeyShift: | |||
mods |= kModifierShift; | |||
break; | |||
case kKeyControl: | |||
mods |= kModifierControl; | |||
break; | |||
case kKeyAlt: | |||
mods |= kModifierAlt; | |||
break; | |||
default: | |||
break; | |||
} | |||
if (mods != 0x0) | |||
{ | |||
if (press) | |||
fView->mods |= mods; | |||
else | |||
fView->mods &= ~(mods); | |||
} | |||
Widget::SpecialEvent ev; | |||
ev.press = press; | |||
ev.key = key; | |||
ev.mod = static_cast<Modifier>(fView->mods); | |||
ev.time = 0; | |||
FOR_EACH_WIDGET_INV(rit) | |||
{ | |||
Widget* const widget(*rit); | |||
if (widget->isVisible() && widget->onSpecial(ev)) | |||
return true; | |||
} | |||
return false; | |||
} | |||
// ------------------------------------------------------------------- | |||
Application& fApp; | |||
Window* fSelf; | |||
PuglView* fView; | |||
@@ -898,13 +985,13 @@ struct Window::PrivateData { | |||
#if defined(DISTRHO_OS_WINDOWS) | |||
HWND hwnd; | |||
#elif defined(DISTRHO_OS_LINUX) | |||
Display* xDisplay; | |||
::Window xWindow; | |||
#elif defined(DISTRHO_OS_MAC) | |||
bool fNeedsIdle; | |||
PuglOpenGLView* mView; | |||
id mWindow; | |||
#else | |||
Display* xDisplay; | |||
::Window xWindow; | |||
#endif | |||
// ------------------------------------------------------------------- | |||
@@ -1020,7 +1107,7 @@ void Window::repaint() noexcept | |||
#ifndef DGL_FILE_BROWSER_DISABLED | |||
bool Window::openFileBrowser(const FileBrowserOptions& options) | |||
{ | |||
#ifdef SOFD_HAVE_X11 | |||
# ifdef SOFD_HAVE_X11 | |||
using DISTRHO_NAMESPACE::String; | |||
// -------------------------------------------------------------------------- | |||
@@ -1078,10 +1165,10 @@ bool Window::openFileBrowser(const FileBrowserOptions& options) | |||
// show | |||
return (x_fib_show(pData->xDisplay, pData->xWindow, /*options.width*/0, /*options.height*/0) == 0); | |||
#else | |||
# else | |||
// not implemented | |||
return false; | |||
#endif | |||
# endif | |||
} | |||
#endif | |||
@@ -1220,6 +1307,26 @@ void Window::fileBrowserSelected(const char*) | |||
} | |||
#endif | |||
bool Window::handlePluginKeyboard(const bool press, const uint key) | |||
{ | |||
return pData->handlePluginKeyboard(press, key); | |||
} | |||
bool Window::handlePluginSpecial(const bool press, const Key key) | |||
{ | |||
return pData->handlePluginSpecial(press, key); | |||
} | |||
bool Window::handlePluginKeyboard(const bool press, const uint key) | |||
{ | |||
return pData->handlePluginKeyboard(press, key); | |||
} | |||
bool Window::handlePluginSpecial(const bool press, const Key key) | |||
{ | |||
return pData->handlePluginSpecial(press, key); | |||
} | |||
// ----------------------------------------------------------------------- | |||
StandaloneWindow::StandaloneWindow() | |||
@@ -202,8 +202,6 @@ puglDisplay(PuglView* view) | |||
- (void) reshape | |||
{ | |||
[[self openGLContext] update]; | |||
if (!puglview) { | |||
/* NOTE: Apparently reshape gets called when the GC gets around to | |||
deleting the view (?), so we must have reset puglview to NULL when | |||
@@ -212,6 +210,8 @@ puglDisplay(PuglView* view) | |||
return; | |||
} | |||
[[self openGLContext] update]; | |||
NSRect bounds = [self bounds]; | |||
int width = bounds.size.width; | |||
int height = bounds.size.height; | |||
@@ -445,7 +445,7 @@ dispatchKey(PuglView* view, XEvent* event, bool press) | |||
view->redisplay = false; | |||
return; | |||
} | |||
if (n == 0) { | |||
if (n == 0 && sym == 0) { | |||
goto send_event; | |||
return; | |||
} | |||
@@ -133,6 +133,29 @@ struct AudioPort { | |||
symbol() {} | |||
}; | |||
/** | |||
Parameter designation.@n | |||
Allows a parameter to be specially designated for a task, like bypass. | |||
Each designation is unique, there must be only one parameter that uses it.@n | |||
The use of designated parameters is completely optional. | |||
@note Designated parameters have strict ranges. | |||
@see ParameterRanges::adjustForDesignation() | |||
*/ | |||
enum ParameterDesignation { | |||
/** | |||
Null or unset designation. | |||
*/ | |||
kParameterDesignationNull = 0, | |||
/** | |||
Bypass designation.@n | |||
When on (> 0.5f), it means the plugin must run in a bypassed state. | |||
*/ | |||
kParameterDesignationBypass = 1 | |||
}; | |||
/** | |||
Parameter ranges.@n | |||
This is used to set the default, minimum and maximum values of a parameter. | |||
@@ -289,6 +312,19 @@ struct Parameter { | |||
*/ | |||
ParameterRanges ranges; | |||
/** | |||
Designation for this parameter. | |||
*/ | |||
ParameterDesignation designation; | |||
/** | |||
MIDI CC to use by default on this parameter.@n | |||
A value of 0 or 32 (bank change) is considered invalid.@n | |||
Must also be less or equal to 120. | |||
@note This value is only a hint! Hosts might map it automatically or completely ignore it. | |||
*/ | |||
uint8_t midiCC; | |||
/** | |||
Default constructor for a null parameter. | |||
*/ | |||
@@ -297,7 +333,9 @@ struct Parameter { | |||
name(), | |||
symbol(), | |||
unit(), | |||
ranges() {} | |||
ranges(), | |||
designation(kParameterDesignationNull), | |||
midiCC(0) {} | |||
/** | |||
Constructor using custom values. | |||
@@ -307,7 +345,33 @@ struct Parameter { | |||
name(n), | |||
symbol(s), | |||
unit(u), | |||
ranges(def, min, max) {} | |||
ranges(def, min, max), | |||
designation(kParameterDesignationNull), | |||
midiCC(0) {} | |||
/** | |||
Initialize a parameter for a specific designation. | |||
*/ | |||
void initDesignation(ParameterDesignation d) noexcept | |||
{ | |||
designation = d; | |||
switch (d) | |||
{ | |||
case kParameterDesignationNull: | |||
break; | |||
case kParameterDesignationBypass: | |||
hints = kParameterIsAutomable|kParameterIsBoolean|kParameterIsInteger; | |||
name = "Bypass"; | |||
symbol = "dpf_bypass"; | |||
unit = ""; | |||
midiCC = 0; | |||
ranges.def = 0.0f; | |||
ranges.min = 0.0f; | |||
ranges.max = 1.0f; | |||
break; | |||
} | |||
} | |||
}; | |||
/** | |||
@@ -531,7 +595,7 @@ public: | |||
Returns false when the host buffer is full, in which case do not call this again until the next run(). | |||
@note This function is not implemented yet!@n | |||
It's here so that developers can prepare MIDI plugins in advance.@n | |||
If you plan to use this, please report to DPF authos so it can be implemented. | |||
If you plan to use this, please report to DPF authors so it can be implemented. | |||
*/ | |||
bool writeMidiEvent(const MidiEvent& midiEvent) noexcept; | |||
#endif | |||
@@ -651,7 +715,7 @@ protected: | |||
/** | |||
Get the value of an internal state.@n | |||
The host may call this function from any non-realtime context.@n | |||
Must be implemented by your plugin class if DISTRHO_PLUGIN_WANT_PROGRAMS or DISTRHO_PLUGIN_WANT_FULL_STATE is enabled. | |||
Must be implemented by your plugin class if DISTRHO_PLUGIN_WANT_FULL_STATE is enabled. | |||
@note The use of this function breaks compatibility with the DSSI format. | |||
*/ | |||
virtual String getState(const char* key) const = 0; | |||
@@ -1,6 +1,6 @@ | |||
/* | |||
* DISTRHO Plugin Framework (DPF) | |||
* Copyright (C) 2012-2016 Filipe Coelho <falktx@falktx.com> | |||
* Copyright (C) 2012-2018 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 | |||
@@ -19,13 +19,13 @@ | |||
#include "String.hpp" | |||
#ifdef DISTRHO_OS_UNIX | |||
#ifdef DISTRHO_OS_WINDOWS | |||
# error Unsupported platform! | |||
#else | |||
# include <cerrno> | |||
# include <signal.h> | |||
# include <sys/wait.h> | |||
# include <unistd.h> | |||
#else | |||
# error Unsupported platform! | |||
#endif | |||
START_NAMESPACE_DISTRHO | |||
@@ -579,7 +579,7 @@ public: | |||
"abcdefghijklmnopqrstuvwxyz" | |||
"0123456789+/"; | |||
const std::size_t kTmpBufSize = std::min(d_nextPowerOf2(static_cast<uint32_t>(dataSize/3)), 65536U); | |||
const std::size_t kTmpBufSize = std::min(d_nextPowerOf2(dataSize/3), 65536U); | |||
const uchar* bytesToEncode((const uchar*)data); | |||
@@ -21,7 +21,7 @@ | |||
#include "Sleep.hpp" | |||
#include "String.hpp" | |||
#ifdef DISTRHO_OS_LINUX_FULL | |||
#ifdef DISTRHO_OS_LINUX | |||
# include <sys/prctl.h> | |||
#endif | |||
@@ -198,7 +198,7 @@ public: | |||
{ | |||
DISTRHO_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0',); | |||
#ifdef DISTRHO_OS_LINUX_FULL | |||
#ifdef DISTRHO_OS_LINUX | |||
prctl(PR_SET_NAME, name, 0, 0, 0); | |||
#endif | |||
#if defined(__GLIBC__) && (__GLIBC__ * 1000 + __GLIBC_MINOR__) >= 2012 | |||
@@ -38,17 +38,10 @@ | |||
# elif defined(__HAIKU__) | |||
# define DISTRHO_OS_HAIKU 1 | |||
# elif defined(__linux__) || defined(__linux) | |||
# define DISTRHO_OS_LINUX 1 | |||
# define DISTRHO_OS_LINUX_FULL 1 | |||
# elif defined(__FreeBSD__) || defined(__GNU__) | |||
# define DISTRHO_OS_LINUX 1 | |||
# define DISTRHO_OS_LINUX 1 | |||
# endif | |||
#endif | |||
#if defined(DISTRHO_OS_LINUX) || defined(DISTRHO_OS_MAC) | |||
# define DISTRHO_OS_UNIX | |||
#endif | |||
#ifndef DISTRHO_DLL_EXTENSION | |||
# define DISTRHO_DLL_EXTENSION "so" | |||
#endif | |||
@@ -43,6 +43,7 @@ struct Plugin::PrivateData { | |||
#endif | |||
uint32_t parameterCount; | |||
uint32_t parameterOffset; | |||
Parameter* parameters; | |||
#if DISTRHO_PLUGIN_WANT_PROGRAMS | |||
@@ -73,6 +74,7 @@ struct Plugin::PrivateData { | |||
audioPorts(nullptr), | |||
#endif | |||
parameterCount(0), | |||
parameterOffset(0), | |||
parameters(nullptr), | |||
#if DISTRHO_PLUGIN_WANT_PROGRAMS | |||
programCount(0), | |||
@@ -91,6 +93,22 @@ struct Plugin::PrivateData { | |||
{ | |||
DISTRHO_SAFE_ASSERT(bufferSize != 0); | |||
DISTRHO_SAFE_ASSERT(d_isNotZero(sampleRate)); | |||
#if defined(DISTRHO_PLUGIN_TARGET_DSSI) || defined(DISTRHO_PLUGIN_TARGET_LV2) | |||
parameterOffset += DISTRHO_PLUGIN_NUM_INPUTS + DISTRHO_PLUGIN_NUM_OUTPUTS; | |||
# if DISTRHO_PLUGIN_WANT_LATENCY | |||
parameterOffset += 1; | |||
# endif | |||
#endif | |||
#ifdef DISTRHO_PLUGIN_TARGET_LV2 | |||
# if (DISTRHO_PLUGIN_IS_SYNTH || DISTRHO_PLUGIN_WANT_TIMEPOS || DISTRHO_PLUGIN_WANT_STATE) | |||
parameterOffset += 1; | |||
# if DISTRHO_PLUGIN_WANT_STATE | |||
parameterOffset += 1; | |||
# endif | |||
# endif | |||
#endif | |||
} | |||
~PrivateData() noexcept | |||
@@ -283,6 +301,13 @@ public: | |||
return fData->parameterCount; | |||
} | |||
uint32_t getParameterOffset() const noexcept | |||
{ | |||
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0); | |||
return fData->parameterOffset; | |||
} | |||
uint32_t getParameterHints(const uint32_t index) const noexcept | |||
{ | |||
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, 0x0); | |||
@@ -290,6 +315,13 @@ public: | |||
return fData->parameters[index].hints; | |||
} | |||
ParameterDesignation getParameterDesignation(const uint32_t index) const noexcept | |||
{ | |||
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, kParameterDesignationNull); | |||
return fData->parameters[index].designation; | |||
} | |||
bool isParameterOutput(const uint32_t index) const noexcept | |||
{ | |||
return (getParameterHints(index) & kParameterIsOutput); | |||
@@ -323,6 +355,13 @@ public: | |||
return fData->parameters[index].ranges; | |||
} | |||
uint8_t getParameterMidiCC(const uint32_t index) const noexcept | |||
{ | |||
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, 0); | |||
return fData->parameters[index].midiCC; | |||
} | |||
float getParameterValue(const uint32_t index) const | |||
{ | |||
DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, 0.0f); | |||
@@ -70,20 +70,14 @@ static void closeSignalHandler(int) noexcept | |||
static void initSignalHandler() | |||
{ | |||
struct sigaction sint; | |||
struct sigaction sterm; | |||
sint.sa_handler = closeSignalHandler; | |||
sint.sa_flags = SA_RESTART; | |||
sint.sa_restorer = nullptr; | |||
sigemptyset(&sint.sa_mask); | |||
sigaction(SIGINT, &sint, nullptr); | |||
sterm.sa_handler = closeSignalHandler; | |||
sterm.sa_flags = SA_RESTART; | |||
sterm.sa_restorer = nullptr; | |||
sigemptyset(&sterm.sa_mask); | |||
sigaction(SIGTERM, &sterm, nullptr); | |||
struct sigaction sig; | |||
memset(&sig, 0, sizeof(sig)); | |||
sig.sa_handler = closeSignalHandler; | |||
sig.sa_flags = SA_RESTART; | |||
sigemptyset(&sig.sa_mask); | |||
sigaction(SIGINT, &sig, nullptr); | |||
sigaction(SIGTERM, &sig, nullptr); | |||
} | |||
#endif | |||
@@ -103,28 +97,27 @@ public: | |||
#endif | |||
fClient(client) | |||
{ | |||
#if DISTRHO_PLUGIN_NUM_INPUTS > 0 || DISTRHO_PLUGIN_NUM_OUTPUTS > 0 | |||
char strBuf[0xff+1]; | |||
strBuf[0xff] = '\0'; | |||
#if DISTRHO_PLUGIN_NUM_INPUTS > 0 | |||
# if DISTRHO_PLUGIN_NUM_INPUTS > 0 | |||
for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i) | |||
{ | |||
std::snprintf(strBuf, 0xff, "in%i", i+1); | |||
fPortAudioIns[i] = jack_port_register(fClient, strBuf, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); | |||
} | |||
#endif | |||
#if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 | |||
# endif | |||
# if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 | |||
for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i) | |||
{ | |||
std::snprintf(strBuf, 0xff, "out%i", i+1); | |||
fPortAudioOuts[i] = jack_port_register(fClient, strBuf, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); | |||
} | |||
# endif | |||
#endif | |||
#if DISTRHO_PLUGIN_IS_SYNTH | |||
fPortMidiIn = jack_port_register(fClient, "midi-in", JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0); | |||
#endif | |||
fPortEventsIn = jack_port_register(fClient, "events-in", JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0); | |||
#if DISTRHO_PLUGIN_WANT_PROGRAMS | |||
if (fPlugin.getProgramCount() > 0) | |||
@@ -134,11 +127,18 @@ public: | |||
fUI.programLoaded(0); | |||
# endif | |||
} | |||
# if DISTRHO_PLUGIN_HAS_UI | |||
fProgramChanged = -1; | |||
# endif | |||
#endif | |||
if (const uint32_t count = fPlugin.getParameterCount()) | |||
{ | |||
fLastOutputValues = new float[count]; | |||
#if DISTRHO_PLUGIN_HAS_UI | |||
fParametersChanged = new bool[count]; | |||
std::memset(fParametersChanged, 0, sizeof(bool)*count); | |||
#endif | |||
for (uint32_t i=0; i < count; ++i) | |||
{ | |||
@@ -149,15 +149,18 @@ public: | |||
else | |||
{ | |||
fLastOutputValues[i] = 0.0f; | |||
# if DISTRHO_PLUGIN_HAS_UI | |||
#if DISTRHO_PLUGIN_HAS_UI | |||
fUI.parameterChanged(i, fPlugin.getParameterValue(i)); | |||
# endif | |||
#endif | |||
} | |||
} | |||
} | |||
else | |||
{ | |||
fLastOutputValues = nullptr; | |||
#if DISTRHO_PLUGIN_HAS_UI | |||
fParametersChanged = nullptr; | |||
#endif | |||
} | |||
jack_set_buffer_size_callback(fClient, jackBufferSizeCallback, this); | |||
@@ -198,10 +201,8 @@ public: | |||
if (fClient == nullptr) | |||
return; | |||
#if DISTRHO_PLUGIN_IS_SYNTH | |||
jack_port_unregister(fClient, fPortMidiIn); | |||
fPortMidiIn = nullptr; | |||
#endif | |||
jack_port_unregister(fClient, fPortEventsIn); | |||
fPortEventsIn = nullptr; | |||
#if DISTRHO_PLUGIN_NUM_INPUTS > 0 | |||
for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i) | |||
@@ -231,20 +232,31 @@ protected: | |||
if (gCloseSignalReceived) | |||
return fUI.quit(); | |||
float value; | |||
# if DISTRHO_PLUGIN_WANT_PROGRAMS | |||
if (fProgramChanged >= 0) | |||
{ | |||
fUI.programLoaded(fProgramChanged); | |||
fProgramChanged = -1; | |||
} | |||
# endif | |||
for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i) | |||
{ | |||
if (! fPlugin.isParameterOutput(i)) | |||
continue; | |||
value = fPlugin.getParameterValue(i); | |||
if (fPlugin.isParameterOutput(i)) | |||
{ | |||
const float value = fPlugin.getParameterValue(i); | |||
if (fLastOutputValues[i] == value) | |||
continue; | |||
if (d_isEqual(fLastOutputValues[i], value)) | |||
continue; | |||
fLastOutputValues[i] = value; | |||
fUI.parameterChanged(i, value); | |||
fLastOutputValues[i] = value; | |||
fUI.parameterChanged(i, value); | |||
} | |||
else if (fParametersChanged[i]) | |||
{ | |||
fParametersChanged[i] = false; | |||
fUI.parameterChanged(i, fPlugin.getParameterValue(i)); | |||
} | |||
} | |||
fUI.exec_idle(); | |||
@@ -316,14 +328,14 @@ protected: | |||
fPlugin.setTimePosition(fTimePosition); | |||
#endif | |||
#if DISTRHO_PLUGIN_IS_SYNTH | |||
void* const midiBuf = jack_port_get_buffer(fPortMidiIn, nframes); | |||
void* const midiBuf = jack_port_get_buffer(fPortEventsIn, nframes); | |||
if (const uint32_t eventCount = jack_midi_get_event_count(midiBuf)) | |||
{ | |||
#if DISTRHO_PLUGIN_IS_SYNTH | |||
uint32_t midiEventCount = 0; | |||
MidiEvent midiEvents[eventCount]; | |||
#endif | |||
jack_midi_event_t jevent; | |||
for (uint32_t i=0; i < eventCount; ++i) | |||
@@ -331,6 +343,47 @@ protected: | |||
if (jack_midi_event_get(&jevent, midiBuf, i) != 0) | |||
break; | |||
// Check if message is control change on channel 1 | |||
if (jevent.buffer[0] == 0xB0 && jevent.size == 3) | |||
{ | |||
const uint8_t control = jevent.buffer[1]; | |||
const uint8_t value = jevent.buffer[2]; | |||
/* NOTE: This is not optimal, we're iterating all parameters on every CC message. | |||
Since the JACK standalone is more of a test tool, this will do for now. */ | |||
for (uint32_t j=0, paramCount=fPlugin.getParameterCount(); j < paramCount; ++j) | |||
{ | |||
if (fPlugin.isParameterOutput(j)) | |||
continue; | |||
if (fPlugin.getParameterMidiCC(j) != control) | |||
continue; | |||
const float scaled = static_cast<float>(value)/127.0f; | |||
const float fvalue = fPlugin.getParameterRanges(j).getUnnormalizedValue(scaled); | |||
fPlugin.setParameterValue(j, fvalue); | |||
#if DISTRHO_PLUGIN_HAS_UI | |||
fParametersChanged[j] = true; | |||
#endif | |||
break; | |||
} | |||
} | |||
#if DISTRHO_PLUGIN_WANT_PROGRAMS | |||
// Check if message is program change on channel 1 | |||
else if (jevent.buffer[0] == 0xC0 && jevent.size == 2) | |||
{ | |||
const uint8_t program = jevent.buffer[1]; | |||
if (program < fPlugin.getProgramCount()) | |||
{ | |||
fPlugin.loadProgram(program); | |||
# if DISTRHO_PLUGIN_HAS_UI | |||
fProgramChanged = program; | |||
# endif | |||
} | |||
} | |||
#endif | |||
#if DISTRHO_PLUGIN_IS_SYNTH | |||
MidiEvent& midiEvent(midiEvents[midiEventCount++]); | |||
midiEvent.frame = jevent.time; | |||
@@ -340,10 +393,14 @@ protected: | |||
midiEvent.dataExt = jevent.buffer; | |||
else | |||
std::memcpy(midiEvent.data, jevent.buffer, midiEvent.size); | |||
#endif | |||
} | |||
#if DISTRHO_PLUGIN_IS_SYNTH | |||
fPlugin.run(audioIns, audioOuts, nframes, midiEvents, midiEventCount); | |||
#endif | |||
} | |||
#if DISTRHO_PLUGIN_IS_SYNTH | |||
else | |||
{ | |||
fPlugin.run(audioIns, audioOuts, nframes, nullptr, 0); | |||
@@ -399,9 +456,7 @@ private: | |||
#if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 | |||
jack_port_t* fPortAudioOuts[DISTRHO_PLUGIN_NUM_OUTPUTS]; | |||
#endif | |||
#if DISTRHO_PLUGIN_IS_SYNTH | |||
jack_port_t* fPortMidiIn; | |||
#endif | |||
jack_port_t* fPortEventsIn; | |||
#if DISTRHO_PLUGIN_WANT_TIMEPOS | |||
TimePosition fTimePosition; | |||
#endif | |||
@@ -409,6 +464,14 @@ private: | |||
// Temporary data | |||
float* fLastOutputValues; | |||
#if DISTRHO_PLUGIN_HAS_UI | |||
// Store DSP changes to send to UI | |||
bool* fParametersChanged; | |||
# if DISTRHO_PLUGIN_WANT_PROGRAMS | |||
int fProgramChanged; | |||
# endif | |||
#endif | |||
// ------------------------------------------------------------------- | |||
// Callbacks | |||
@@ -250,17 +250,16 @@ public: | |||
midiEvents[j].data[2] = 0; | |||
midiEvents[j].data[3] = 0; | |||
break; | |||
#if 0 // TODO | |||
case SND_SEQ_EVENT_PITCHBEND: | |||
j = midiEventCount++; | |||
midiEvents[j].frame = seqEvent.time.tick; | |||
midiEvents[j].size = 3; | |||
midiEvents[j].data[0] = 0xE0 + seqEvent.data.control.channel; | |||
midiEvents[j].data[1] = 0; | |||
midiEvents[j].data[2] = 0; | |||
uint16_t tempvalue = seqEvent.data.control.value + 8192; | |||
midiEvents[j].data[1] = tempvalue & 0x7F; | |||
midiEvents[j].data[2] = tempvalue >> 7; | |||
midiEvents[j].data[3] = 0; | |||
break; | |||
#endif | |||
} | |||
} | |||
@@ -329,6 +328,21 @@ public: | |||
} | |||
} | |||
# endif | |||
int dssi_get_midi_controller_for_port(const ulong port) noexcept | |||
{ | |||
const uint32_t parameterOffset = fPlugin.getParameterOffset(); | |||
if (port > parameterOffset) | |||
return DSSI_NONE; | |||
const uint8_t midiCC = fPlugin.getParameterMidiCC(port-parameterOffset); | |||
if (midiCC == 0 || midiCC == 32 || midiCC >= 0x78) | |||
return DSSI_NONE; | |||
return DSSI_CC(midiCC); | |||
} | |||
#endif | |||
// ------------------------------------------------------------------- | |||
@@ -435,6 +449,11 @@ static void dssi_select_program(LADSPA_Handle instance, ulong bank, ulong progra | |||
} | |||
# endif | |||
static int dssi_get_midi_controller_for_port(LADSPA_Handle instance, ulong port) | |||
{ | |||
return instancePtr->dssi_get_midi_controller_for_port(port); | |||
} | |||
# if DISTRHO_PLUGIN_WANT_MIDI_INPUT | |||
static void dssi_run_synth(LADSPA_Handle instance, ulong sampleCount, snd_seq_event_t* events, ulong eventCount) | |||
{ | |||
@@ -489,7 +508,7 @@ static DSSI_Descriptor sDssiDescriptor = { | |||
/* get_program */ nullptr, | |||
/* select_program */ nullptr, | |||
# endif | |||
/* get_midi_controller_for_port */ nullptr, | |||
dssi_get_midi_controller_for_port, | |||
# if DISTRHO_PLUGIN_WANT_MIDI_INPUT | |||
dssi_run_synth, | |||
# else | |||
@@ -614,11 +633,16 @@ public: | |||
const uint32_t hints(plugin.getParameterHints(i)); | |||
if (hints & kParameterIsBoolean) | |||
{ | |||
portRangeHints[port].HintDescriptor |= LADSPA_HINT_TOGGLED; | |||
if (hints & kParameterIsInteger) | |||
portRangeHints[port].HintDescriptor |= LADSPA_HINT_INTEGER; | |||
if (hints & kParameterIsLogarithmic) | |||
portRangeHints[port].HintDescriptor |= LADSPA_HINT_LOGARITHMIC; | |||
} | |||
else | |||
{ | |||
if (hints & kParameterIsInteger) | |||
portRangeHints[port].HintDescriptor |= LADSPA_HINT_INTEGER; | |||
if (hints & kParameterIsLogarithmic) | |||
portRangeHints[port].HintDescriptor |= LADSPA_HINT_LOGARITHMIC; | |||
} | |||
} | |||
} | |||
@@ -30,6 +30,10 @@ | |||
#include "lv2/lv2_kxstudio_properties.h" | |||
#include "lv2/lv2_programs.h" | |||
#ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD | |||
# include "libmodauth.h" | |||
#endif | |||
#ifdef noexcept | |||
# undef noexcept | |||
#endif | |||
@@ -58,6 +62,9 @@ class PluginLv2 | |||
public: | |||
PluginLv2(const double sampleRate, const LV2_URID_Map* const uridMap, const LV2_Worker_Schedule* const worker, const bool usingNominal) | |||
: fUsingNominal(usingNominal), | |||
#ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD | |||
fRunCount(0), | |||
#endif | |||
fPortControls(nullptr), | |||
fLastControlValues(nullptr), | |||
fSampleRate(sampleRate), | |||
@@ -512,6 +519,12 @@ public: | |||
if (fLastControlValues[i] != curValue && ! fPlugin.isParameterOutput(i)) | |||
{ | |||
fLastControlValues[i] = curValue; | |||
if (fPlugin.getParameterDesignation(i) == kParameterDesignationBypass) | |||
{ | |||
curValue = 1.0f - curValue; | |||
} | |||
fPlugin.setParameterValue(i, curValue); | |||
} | |||
} | |||
@@ -519,12 +532,21 @@ public: | |||
// Run plugin | |||
if (sampleCount != 0) | |||
{ | |||
#ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD | |||
fRunCount = mod_license_run_begin(fRunCount, sampleCount); | |||
#endif | |||
#if DISTRHO_PLUGIN_WANT_MIDI_INPUT | |||
fPlugin.run(fPortAudioIns, fPortAudioOuts, sampleCount, fMidiEvents, midiEventCount); | |||
#else | |||
fPlugin.run(fPortAudioIns, fPortAudioOuts, sampleCount); | |||
#endif | |||
#ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD | |||
for (uint32_t i=0; i<DISTRHO_PLUGIN_NUM_OUTPUTS; ++i) | |||
mod_license_run_noise(fRunCount, fPortAudioOuts[i], sampleCount, i); | |||
#endif | |||
#if DISTRHO_PLUGIN_WANT_TIMEPOS | |||
// update timePos for next callback | |||
if (d_isNotZero(fLastPositionData.speed)) | |||
@@ -589,10 +611,14 @@ public: | |||
#if DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI | |||
const uint32_t capacity = fPortEventsOut->atom.size; | |||
bool needsInit = true; | |||
uint32_t size, offset = 0; | |||
LV2_Atom_Event* aev; | |||
fPortEventsOut->atom.size = sizeof(LV2_Atom_Sequence_Body); | |||
fPortEventsOut->atom.type = fURIDs.atomSequence; | |||
fPortEventsOut->body.unit = 0; | |||
fPortEventsOut->body.pad = 0; | |||
// TODO - MIDI Output | |||
for (uint32_t i=0, count=fPlugin.getStateCount(); i < count; ++i) | |||
@@ -617,15 +643,6 @@ public: | |||
if (sizeof(LV2_Atom_Event) + msgSize > capacity - offset) | |||
break; | |||
if (needsInit) | |||
{ | |||
fPortEventsOut->atom.size = 0; | |||
fPortEventsOut->atom.type = fURIDs.atomSequence; | |||
fPortEventsOut->body.unit = 0; | |||
fPortEventsOut->body.pad = 0; | |||
needsInit = false; | |||
} | |||
// reserve msg space | |||
char msgBuf[msgSize]; | |||
std::memset(msgBuf, 0, msgSize); | |||
@@ -846,6 +863,10 @@ private: | |||
PluginExporter fPlugin; | |||
const bool fUsingNominal; // if false use maxBlockLength | |||
#ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD | |||
uint32_t fRunCount; | |||
#endif | |||
// LV2 ports | |||
#if DISTRHO_PLUGIN_NUM_INPUTS > 0 | |||
const float* fPortAudioIns[DISTRHO_PLUGIN_NUM_INPUTS]; | |||
@@ -1034,6 +1055,10 @@ static LV2_Handle lv2_instantiate(const LV2_Descriptor*, double sampleRate, cons | |||
} | |||
#endif | |||
#ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD | |||
mod_check_license(features, DISTRHO_PLUGIN_URI); | |||
#endif | |||
d_lastBufferSize = 0; | |||
bool usingNominal = false; | |||
@@ -1193,7 +1218,11 @@ static const void* lv2_extension_data(const char* uri) | |||
return &directaccess; | |||
#endif | |||
#ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD | |||
return mod_license_interface(uri); | |||
#else | |||
return nullptr; | |||
#endif | |||
} | |||
#undef instancePtr | |||
@@ -1,6 +1,6 @@ | |||
/* | |||
* DISTRHO Plugin Framework (DPF) | |||
* Copyright (C) 2012-2016 Filipe Coelho <falktx@falktx.com> | |||
* Copyright (C) 2012-2017 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 | |||
@@ -34,6 +34,10 @@ | |||
#include "lv2/lv2_kxstudio_properties.h" | |||
#include "lv2/lv2_programs.h" | |||
#ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD | |||
# include "mod-license.h" | |||
#endif | |||
#include <fstream> | |||
#include <iostream> | |||
@@ -224,6 +228,9 @@ void lv2_generate_ttl(const char* const basename) | |||
#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"; | |||
@@ -241,6 +248,9 @@ void lv2_generate_ttl(const char* const basename) | |||
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"; | |||
@@ -359,7 +369,7 @@ void lv2_generate_ttl(const char* const basename) | |||
pluginString += " lv2:name \"Latency\" ;\n"; | |||
pluginString += " lv2:symbol \"lv2_latency\" ;\n"; | |||
pluginString += " lv2:designation lv2:latency ;\n"; | |||
pluginString += " lv2:portProperty lv2:reportsLatency, lv2:integer ;\n"; | |||
pluginString += " lv2:portProperty lv2:reportsLatency, lv2:integer, <" LV2_PORT_PROPS__notOnGUI "> ;\n"; | |||
pluginString += " ] ;\n\n"; | |||
++portIndex; | |||
#endif | |||
@@ -377,10 +387,34 @@ void lv2_generate_ttl(const char* const basename) | |||
pluginString += " a lv2:InputPort, lv2:ControlPort ;\n"; | |||
pluginString += " lv2:index " + String(portIndex) + " ;\n"; | |||
pluginString += " lv2:name \"" + plugin.getParameterName(i) + "\" ;\n"; | |||
// symbol | |||
bool designated = false; | |||
// designation | |||
if (! plugin.isParameterOutput(i)) | |||
{ | |||
switch (plugin.getParameterDesignation(i)) | |||
{ | |||
case kParameterDesignationNull: | |||
break; | |||
case kParameterDesignationBypass: | |||
designated = true; | |||
pluginString += " lv2:name \"Enabled\" ;\n"; | |||
pluginString += " lv2:symbol \"lv2_enabled\" ;\n"; | |||
pluginString += " lv2:default 1 ;\n"; | |||
pluginString += " lv2:minimum 0 ;\n"; | |||
pluginString += " lv2:maximum 1 ;\n"; | |||
pluginString += " lv2:portProperty lv2:toggled , lv2:integer ;\n"; | |||
pluginString += " lv2:designation lv2:enabled ;\n"; | |||
break; | |||
} | |||
} | |||
// name and symbol | |||
if (! designated) | |||
{ | |||
pluginString += " lv2:name \"" + plugin.getParameterName(i) + "\" ;\n"; | |||
String symbol(plugin.getParameterSymbol(i)); | |||
if (symbol.isEmpty()) | |||
@@ -390,24 +424,28 @@ void lv2_generate_ttl(const char* const basename) | |||
} | |||
// ranges | |||
if (! designated) | |||
{ | |||
const ParameterRanges& ranges(plugin.getParameterRanges(i)); | |||
if (plugin.getParameterHints(i) & kParameterIsInteger) | |||
{ | |||
pluginString += " lv2:default " + String(int(plugin.getParameterValue(i))) + " ;\n"; | |||
if (! plugin.isParameterOutput(i)) | |||
pluginString += " lv2:default " + String(int(plugin.getParameterValue(i))) + " ;\n"; | |||
pluginString += " lv2:minimum " + String(int(ranges.min)) + " ;\n"; | |||
pluginString += " lv2:maximum " + String(int(ranges.max)) + " ;\n"; | |||
} | |||
else | |||
{ | |||
pluginString += " lv2:default " + String(plugin.getParameterValue(i)) + " ;\n"; | |||
if (! plugin.isParameterOutput(i)) | |||
pluginString += " lv2:default " + String(plugin.getParameterValue(i)) + " ;\n"; | |||
pluginString += " lv2:minimum " + String(ranges.min) + " ;\n"; | |||
pluginString += " lv2:maximum " + String(ranges.max) + " ;\n"; | |||
} | |||
} | |||
// unit | |||
if (! designated) | |||
{ | |||
const String& unit(plugin.getParameterUnit(i)); | |||
@@ -453,6 +491,7 @@ void lv2_generate_ttl(const char* const basename) | |||
} | |||
// hints | |||
if (! designated) | |||
{ | |||
const uint32_t hints(plugin.getParameterHints(i)); | |||
@@ -606,7 +645,18 @@ void lv2_generate_ttl(const char* const basename) | |||
plugin.loadProgram(i); | |||
presetString = "<" DISTRHO_PLUGIN_URI + presetSeparator + "preset" + strBuf + ">\n"; | |||
presetString = "<" DISTRHO_PLUGIN_URI + presetSeparator + "preset" + strBuf + ">\n"; | |||
# if DISTRHO_PLUGIN_WANT_FULL_STATE | |||
if (numParameters == 0 && numStates == 0) | |||
#else | |||
if (numParameters == 0) | |||
#endif | |||
{ | |||
presetString += " ."; | |||
presetsString += presetString; | |||
continue; | |||
} | |||
# if DISTRHO_PLUGIN_WANT_FULL_STATE | |||
presetString += " state:state [\n"; | |||
@@ -629,12 +679,22 @@ void lv2_generate_ttl(const char* const basename) | |||
presetString += " ] .\n\n"; | |||
# endif | |||
bool firstParameter = true; | |||
for (uint32_t j=0; j <numParameters; ++j) | |||
{ | |||
if (j == 0) | |||
if (plugin.isParameterOutput(j)) | |||
continue; | |||
if (firstParameter) | |||
{ | |||
presetString += " lv2:port [\n"; | |||
firstParameter = false; | |||
} | |||
else | |||
{ | |||
presetString += " [\n"; | |||
} | |||
presetString += " lv2:symbol \"" + plugin.getParameterSymbol(j) + "\" ;\n"; | |||
@@ -643,7 +703,7 @@ void lv2_generate_ttl(const char* const basename) | |||
else | |||
presetString += " pset:value " + String(plugin.getParameterValue(j)) + " ;\n"; | |||
if (j+1 == numParameters) | |||
if (j+1 == numParameters || plugin.isParameterOutput(j+1)) | |||
presetString += " ] .\n\n"; | |||
else | |||
presetString += " ] ,\n"; | |||
@@ -52,6 +52,8 @@ | |||
#define effGetProgramNameIndexed 29 | |||
#define effGetPlugCategory 35 | |||
#define effIdle 53 | |||
#define effEditKeyDown 59 | |||
#define effEditKeyUp 60 | |||
#define kPlugCategEffect 1 | |||
#define kPlugCategSynth 2 | |||
#define kVstVersion 2400 | |||
@@ -122,8 +124,20 @@ public: | |||
fEffect(effect), | |||
fUiHelper(uiHelper), | |||
fPlugin(plugin), | |||
fUI(this, winId, editParameterCallback, setParameterCallback, setStateCallback, sendNoteCallback, setSizeCallback, plugin->getInstancePointer()) | |||
fUI(this, winId, editParameterCallback, setParameterCallback, setStateCallback, sendNoteCallback, setSizeCallback, plugin->getInstancePointer()), | |||
fShouldCaptureVstKeys(false) | |||
{ | |||
// FIXME only needed for windows? | |||
//#ifdef DISTRHO_OS_WINDOWS | |||
char strBuf[0xff+1]; | |||
std::memset(strBuf, 0, sizeof(char)*(0xff+1)); | |||
hostCallback(audioMasterGetProductString, 0, 0, strBuf); | |||
d_stdout("Plugin UI running in '%s'", strBuf); | |||
// TODO make a white-list of needed hosts | |||
if (/*std::strcmp(strBuf, "") == 0*/ true) | |||
fShouldCaptureVstKeys = true; | |||
//#endif | |||
} | |||
// ------------------------------------------------------------------- | |||
@@ -167,6 +181,60 @@ public: | |||
} | |||
# endif | |||
int handlePluginKeyEvent(const bool down, int32_t index, const intptr_t value) | |||
{ | |||
# if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI | |||
if (! fShouldCaptureVstKeys) | |||
return 0; | |||
d_stdout("handlePluginKeyEvent %i %i %li\n", down, index, (long int)value); | |||
int special = 0; | |||
switch (value) | |||
{ | |||
// convert some specials to normal keys | |||
case 1: index = kCharBackspace; break; | |||
case 6: index = kCharEscape; break; | |||
case 7: index = ' '; break; | |||
case 22: index = kCharDelete; break; | |||
// handle rest of special keys | |||
case 40: special = kKeyF1; break; | |||
case 41: special = kKeyF2; break; | |||
case 42: special = kKeyF3; break; | |||
case 43: special = kKeyF4; break; | |||
case 44: special = kKeyF5; break; | |||
case 45: special = kKeyF6; break; | |||
case 46: special = kKeyF7; break; | |||
case 47: special = kKeyF8; break; | |||
case 48: special = kKeyF9; break; | |||
case 49: special = kKeyF10; break; | |||
case 50: special = kKeyF11; break; | |||
case 51: special = kKeyF12; break; | |||
case 11: special = kKeyLeft; break; | |||
case 12: special = kKeyUp; break; | |||
case 13: special = kKeyRight; break; | |||
case 14: special = kKeyDown; break; | |||
case 15: special = kKeyPageUp; break; | |||
case 16: special = kKeyPageDown; break; | |||
case 10: special = kKeyHome; break; | |||
case 9: special = kKeyEnd; break; | |||
case 21: special = kKeyInsert; break; | |||
case 54: special = kKeyShift; break; | |||
case 55: special = kKeyControl; break; | |||
case 56: special = kKeyAlt; break; | |||
} | |||
if (special != 0) | |||
return fUI.handlePluginSpecial(down, static_cast<Key>(special)); | |||
if (index >= 0) | |||
return fUI.handlePluginKeyboard(down, static_cast<uint>(index)); | |||
# endif | |||
return 0; | |||
} | |||
// ------------------------------------------------------------------- | |||
protected: | |||
@@ -231,6 +299,7 @@ private: | |||
// Plugin UI | |||
UIExporter fUI; | |||
bool fShouldCaptureVstKeys; | |||
// ------------------------------------------------------------------- | |||
// Callbacks | |||
@@ -499,6 +568,16 @@ public: | |||
if (fVstUI != nullptr) | |||
fVstUI->idle(); | |||
break; | |||
case effEditKeyDown: | |||
if (fVstUI != nullptr) | |||
return fVstUI->handlePluginKeyEvent(true, index, value); | |||
break; | |||
case effEditKeyUp: | |||
if (fVstUI != nullptr) | |||
return fVstUI->handlePluginKeyEvent(false, index, value); | |||
break; | |||
#endif // DISTRHO_PLUGIN_HAS_UI | |||
#if DISTRHO_PLUGIN_WANT_STATE | |||
@@ -418,6 +418,16 @@ public: | |||
return ! glApp.isQuiting(); | |||
} | |||
bool handlePluginKeyboard(const bool press, const uint key) | |||
{ | |||
return glWindow.handlePluginKeyboard(press, key); | |||
} | |||
bool handlePluginSpecial(const bool press, const Key key) | |||
{ | |||
return glWindow.handlePluginKeyboard(press, key); | |||
} | |||
#else | |||
void setWindowSize(const uint width, const uint height, const bool updateUI = false) {} | |||
void setWindowTransientWinId(const uintptr_t winId) {} | |||
@@ -23,6 +23,7 @@ | |||
#include "lv2/data-access.h" | |||
#include "lv2/instance-access.h" | |||
#include "lv2/options.h" | |||
#include "lv2/parameters.h" | |||
#include "lv2/ui.h" | |||
#include "lv2/urid.h" | |||
#include "lv2/lv2_kxstudio_properties.h" | |||
@@ -114,7 +115,9 @@ public: | |||
{ | |||
const uint32_t parameterOffset(fUI.getParameterOffset()); | |||
DISTRHO_SAFE_ASSERT_RETURN(rindex >= parameterOffset,) | |||
if (rindex < parameterOffset) | |||
return; | |||
DISTRHO_SAFE_ASSERT_RETURN(bufferSize == sizeof(float),) | |||
const float value(*(const float*)buffer); | |||
@@ -173,17 +176,17 @@ public: | |||
{ | |||
for (int i=0; options[i].key != 0; ++i) | |||
{ | |||
if (options[i].key == fUridMap->map(fUridMap->handle, LV2_CORE__sampleRate)) | |||
if (options[i].key == fUridMap->map(fUridMap->handle, LV2_PARAMETERS__sampleRate)) | |||
{ | |||
if (options[i].type == fUridMap->map(fUridMap->handle, LV2_ATOM__Double)) | |||
if (options[i].type == fUridMap->map(fUridMap->handle, LV2_ATOM__Float)) | |||
{ | |||
const double sampleRate(*(const double*)options[i].value); | |||
const float sampleRate(*(const float*)options[i].value); | |||
fUI.setSampleRate(sampleRate); | |||
continue; | |||
} | |||
else | |||
{ | |||
d_stderr("Host changed sampleRate but with wrong value type"); | |||
d_stderr("Host changed UI sample-rate but with wrong value type"); | |||
continue; | |||
} | |||
} | |||
@@ -237,7 +240,7 @@ protected: | |||
const size_t msgSize(tmpStr.length()+1); | |||
// reserve atom space | |||
const size_t atomSize(lv2_atom_pad_size(sizeof(LV2_Atom) + msgSize)); | |||
const size_t atomSize(sizeof(LV2_Atom) + msgSize); | |||
char atomBuf[atomSize]; | |||
std::memset(atomBuf, 0, atomSize); | |||
@@ -400,23 +403,23 @@ static LV2UI_Handle lv2ui_instantiate(const LV2UI_Descriptor*, const char* uri, | |||
if (options != nullptr) | |||
{ | |||
const LV2_URID uridSampleRate(uridMap->map(uridMap->handle, LV2_CORE__sampleRate)); | |||
const LV2_URID uridSampleRate(uridMap->map(uridMap->handle, LV2_PARAMETERS__sampleRate)); | |||
for (int i=0; options[i].key != 0; ++i) | |||
{ | |||
if (options[i].key == uridSampleRate) | |||
{ | |||
if (options[i].type == uridMap->map(uridMap->handle, LV2_ATOM__Double)) | |||
d_lastUiSampleRate = *(const double*)options[i].value; | |||
if (options[i].type == uridMap->map(uridMap->handle, LV2_ATOM__Float)) | |||
d_lastUiSampleRate = *(const float*)options[i].value; | |||
else | |||
d_stderr("Host provides sampleRate but has wrong value type"); | |||
d_stderr("Host provides UI sample-rate but has wrong value type"); | |||
break; | |||
} | |||
} | |||
} | |||
if (d_lastUiSampleRate == 0.0) | |||
if (d_lastUiSampleRate < 1.0) | |||
{ | |||
d_stdout("WARNING: this host does not send sample-rate information for LV2 UIs, using 44100 as fallback (this could be wrong)"); | |||
d_lastUiSampleRate = 44100.0; | |||