@@ -2,33 +2,33 @@ | |||||
set -e | 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 | @code | ||||
const char* txt = "Text me up."; | 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 | @endcode | ||||
Note: currently only solid color fill is supported for text. | Note: currently only solid color fill is supported for text. | ||||
@@ -111,7 +111,7 @@ public: | |||||
/** | /** | ||||
Mouse event. | Mouse event. | ||||
@a button The button number (1 = left, 2 = middle, 3 = right). | @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. | @a pos The widget-relative coordinates of the pointer. | ||||
@see onMouse | @see onMouse | ||||
*/ | */ | ||||
@@ -19,6 +19,10 @@ | |||||
#include "Geometry.hpp" | #include "Geometry.hpp" | ||||
START_NAMESPACE_DISTRHO | |||||
class UIExporter; | |||||
END_NAMESPACE_DISTRHO | |||||
START_NAMESPACE_DGL | START_NAMESPACE_DGL | ||||
// ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
@@ -125,11 +129,15 @@ private: | |||||
friend class Application; | friend class Application; | ||||
friend class Widget; | friend class Widget; | ||||
friend class StandaloneWindow; | friend class StandaloneWindow; | ||||
friend class DISTRHO_NAMESPACE::UIExporter; | |||||
virtual void _addWidget(Widget* const widget); | virtual void _addWidget(Widget* const widget); | ||||
virtual void _removeWidget(Widget* const widget); | virtual void _removeWidget(Widget* const widget); | ||||
void _idle(); | 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) | DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(Window) | ||||
}; | }; | ||||
@@ -68,7 +68,9 @@ Image::~Image() | |||||
{ | { | ||||
if (fTextureId != 0) | if (fTextureId != 0) | ||||
{ | { | ||||
#ifndef DISTRHO_OS_MAC // FIXME | |||||
glDeleteTextures(1, &fTextureId); | glDeleteTextures(1, &fTextureId); | ||||
#endif | |||||
fTextureId = 0; | fTextureId = 0; | ||||
} | } | ||||
} | } | ||||
@@ -1,6 +1,6 @@ | |||||
/* | /* | ||||
* DISTRHO Plugin Framework (DPF) | * 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 | * 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 | * or without fee is hereby granted, provided that the above copyright notice and this | ||||
@@ -1,6 +1,6 @@ | |||||
/* | /* | ||||
* DISTRHO Plugin Framework (DPF) | * 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 | * 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 | * or without fee is hereby granted, provided that the above copyright notice and this | ||||
@@ -34,14 +34,12 @@ | |||||
# include "pugl/pugl_win.cpp" | # include "pugl/pugl_win.cpp" | ||||
#elif defined(DISTRHO_OS_MAC) | #elif defined(DISTRHO_OS_MAC) | ||||
# include "pugl/pugl_osx.m" | # include "pugl/pugl_osx.m" | ||||
#elif defined(DISTRHO_OS_LINUX) | |||||
#else | |||||
# include <sys/types.h> | # include <sys/types.h> | ||||
# include <unistd.h> | # include <unistd.h> | ||||
extern "C" { | extern "C" { | ||||
# include "pugl/pugl_x11.c" | # include "pugl/pugl_x11.c" | ||||
} | } | ||||
#else | |||||
# error Unsupported platform | |||||
#endif | #endif | ||||
#if defined(__GNUC__) && (__GNUC__ >= 7) | #if defined(__GNUC__) && (__GNUC__ >= 7) | ||||
@@ -90,13 +88,13 @@ struct Window::PrivateData { | |||||
fModal(), | fModal(), | ||||
#if defined(DISTRHO_OS_WINDOWS) | #if defined(DISTRHO_OS_WINDOWS) | ||||
hwnd(0) | hwnd(0) | ||||
#elif defined(DISTRHO_OS_LINUX) | |||||
xDisplay(nullptr), | |||||
xWindow(0) | |||||
#elif defined(DISTRHO_OS_MAC) | #elif defined(DISTRHO_OS_MAC) | ||||
fNeedsIdle(true), | fNeedsIdle(true), | ||||
mView(nullptr), | mView(nullptr), | ||||
mWindow(nullptr) | mWindow(nullptr) | ||||
#else | |||||
xDisplay(nullptr), | |||||
xWindow(0) | |||||
#endif | #endif | ||||
{ | { | ||||
DBG("Creating window without parent..."); DBGF; | DBG("Creating window without parent..."); DBGF; | ||||
@@ -118,27 +116,30 @@ struct Window::PrivateData { | |||||
fModal(parent.pData), | fModal(parent.pData), | ||||
#if defined(DISTRHO_OS_WINDOWS) | #if defined(DISTRHO_OS_WINDOWS) | ||||
hwnd(0) | hwnd(0) | ||||
#elif defined(DISTRHO_OS_LINUX) | |||||
xDisplay(nullptr), | |||||
xWindow(0) | |||||
#elif defined(DISTRHO_OS_MAC) | #elif defined(DISTRHO_OS_MAC) | ||||
fNeedsIdle(false), | fNeedsIdle(false), | ||||
mView(nullptr), | mView(nullptr), | ||||
mWindow(nullptr) | mWindow(nullptr) | ||||
#else | |||||
xDisplay(nullptr), | |||||
xWindow(0) | |||||
#endif | #endif | ||||
{ | { | ||||
DBG("Creating window with parent..."); DBGF; | DBG("Creating window with parent..."); DBGF; | ||||
init(); | init(); | ||||
const PuglInternals* const parentImpl(parent.pData->fView->impl); | 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 | #else | ||||
// unused | |||||
return; (void)parentImpl; | |||||
XSetTransientForHint(xDisplay, xWindow, parentImpl->win); | |||||
#endif | #endif | ||||
return; | |||||
// maybe unused | |||||
(void)parentImpl; | |||||
} | } | ||||
PrivateData(Application& app, Window* const self, const intptr_t parentId) | PrivateData(Application& app, Window* const self, const intptr_t parentId) | ||||
@@ -156,13 +157,13 @@ struct Window::PrivateData { | |||||
fModal(), | fModal(), | ||||
#if defined(DISTRHO_OS_WINDOWS) | #if defined(DISTRHO_OS_WINDOWS) | ||||
hwnd(0) | hwnd(0) | ||||
#elif defined(DISTRHO_OS_LINUX) | |||||
xDisplay(nullptr), | |||||
xWindow(0) | |||||
#elif defined(DISTRHO_OS_MAC) | #elif defined(DISTRHO_OS_MAC) | ||||
fNeedsIdle(parentId == 0), | fNeedsIdle(parentId == 0), | ||||
mView(nullptr), | mView(nullptr), | ||||
mWindow(nullptr) | mWindow(nullptr) | ||||
#else | |||||
xDisplay(nullptr), | |||||
xWindow(0) | |||||
#endif | #endif | ||||
{ | { | ||||
if (fUsingEmbed) | if (fUsingEmbed) | ||||
@@ -226,7 +227,7 @@ struct Window::PrivateData { | |||||
} else { | } else { | ||||
DISTRHO_SAFE_ASSERT(mWindow != nullptr); | DISTRHO_SAFE_ASSERT(mWindow != nullptr); | ||||
} | } | ||||
#elif defined(DISTRHO_OS_LINUX) | |||||
#else | |||||
xDisplay = impl->display; | xDisplay = impl->display; | ||||
xWindow = impl->win; | xWindow = impl->win; | ||||
DISTRHO_SAFE_ASSERT(xWindow != 0); | DISTRHO_SAFE_ASSERT(xWindow != 0); | ||||
@@ -286,7 +287,7 @@ struct Window::PrivateData { | |||||
#elif defined(DISTRHO_OS_MAC) | #elif defined(DISTRHO_OS_MAC) | ||||
mView = nullptr; | mView = nullptr; | ||||
mWindow = nullptr; | mWindow = nullptr; | ||||
#elif defined(DISTRHO_OS_LINUX) | |||||
#else | |||||
xDisplay = nullptr; | xDisplay = nullptr; | ||||
xWindow = 0; | xWindow = 0; | ||||
#endif | #endif | ||||
@@ -380,7 +381,7 @@ struct Window::PrivateData { | |||||
// TODO | // TODO | ||||
#elif defined(DISTRHO_OS_MAC) | #elif defined(DISTRHO_OS_MAC) | ||||
// TODO | // TODO | ||||
#elif defined(DISTRHO_OS_LINUX) | |||||
#else | |||||
int i, wx, wy; | int i, wx, wy; | ||||
uint u; | uint u; | ||||
::Window w; | ::Window w; | ||||
@@ -404,7 +405,7 @@ struct Window::PrivateData { | |||||
#elif defined(DISTRHO_OS_MAC) | #elif defined(DISTRHO_OS_MAC) | ||||
if (mWindow != nullptr) | if (mWindow != nullptr) | ||||
[mWindow makeKeyWindow]; | [mWindow makeKeyWindow]; | ||||
#elif defined(DISTRHO_OS_LINUX) | |||||
#else | |||||
XRaiseWindow(xDisplay, xWindow); | XRaiseWindow(xDisplay, xWindow); | ||||
XSetInputFocus(xDisplay, xWindow, RevertToPointerRoot, CurrentTime); | XSetInputFocus(xDisplay, xWindow, RevertToPointerRoot, CurrentTime); | ||||
XFlush(xDisplay); | XFlush(xDisplay); | ||||
@@ -455,7 +456,7 @@ struct Window::PrivateData { | |||||
else | else | ||||
[mView setHidden:YES]; | [mView setHidden:YES]; | ||||
} | } | ||||
#elif defined(DISTRHO_OS_LINUX) | |||||
#else | |||||
if (yesNo) | if (yesNo) | ||||
XMapRaised(xDisplay, xWindow); | XMapRaised(xDisplay, xWindow); | ||||
else | else | ||||
@@ -559,7 +560,7 @@ struct Window::PrivateData { | |||||
[[mWindow standardWindowButton:NSWindowZoomButton] setHidden:YES]; | [[mWindow standardWindowButton:NSWindowZoomButton] setHidden:YES]; | ||||
} | } | ||||
} | } | ||||
#elif defined(DISTRHO_OS_LINUX) | |||||
#else | |||||
XResizeWindow(xDisplay, xWindow, width, height); | XResizeWindow(xDisplay, xWindow, width, height); | ||||
if (! fResizable) | if (! fResizable) | ||||
@@ -615,7 +616,7 @@ struct Window::PrivateData { | |||||
[mWindow setTitle:titleString]; | [mWindow setTitle:titleString]; | ||||
} | } | ||||
#elif defined(DISTRHO_OS_LINUX) | |||||
#else | |||||
XStoreName(xDisplay, xWindow, title); | XStoreName(xDisplay, xWindow, title); | ||||
#endif | #endif | ||||
} | } | ||||
@@ -624,14 +625,16 @@ struct Window::PrivateData { | |||||
{ | { | ||||
DISTRHO_SAFE_ASSERT_RETURN(winId != 0,); | 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,); | DISTRHO_SAFE_ASSERT_RETURN(window != nullptr,); | ||||
[window addChildWindow:mWindow | [window addChildWindow:mWindow | ||||
ordered:NSWindowAbove]; | ordered:NSWindowAbove]; | ||||
[mWindow makeKeyWindow]; | [mWindow makeKeyWindow]; | ||||
#elif defined(DISTRHO_OS_LINUX) | |||||
#else | |||||
XSetTransientForHint(xDisplay, xWindow, static_cast< ::Window>(winId)); | XSetTransientForHint(xDisplay, xWindow, static_cast< ::Window>(winId)); | ||||
#endif | #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; | Application& fApp; | ||||
Window* fSelf; | Window* fSelf; | ||||
PuglView* fView; | PuglView* fView; | ||||
@@ -898,13 +985,13 @@ struct Window::PrivateData { | |||||
#if defined(DISTRHO_OS_WINDOWS) | #if defined(DISTRHO_OS_WINDOWS) | ||||
HWND hwnd; | HWND hwnd; | ||||
#elif defined(DISTRHO_OS_LINUX) | |||||
Display* xDisplay; | |||||
::Window xWindow; | |||||
#elif defined(DISTRHO_OS_MAC) | #elif defined(DISTRHO_OS_MAC) | ||||
bool fNeedsIdle; | bool fNeedsIdle; | ||||
PuglOpenGLView* mView; | PuglOpenGLView* mView; | ||||
id mWindow; | id mWindow; | ||||
#else | |||||
Display* xDisplay; | |||||
::Window xWindow; | |||||
#endif | #endif | ||||
// ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
@@ -1020,7 +1107,7 @@ void Window::repaint() noexcept | |||||
#ifndef DGL_FILE_BROWSER_DISABLED | #ifndef DGL_FILE_BROWSER_DISABLED | ||||
bool Window::openFileBrowser(const FileBrowserOptions& options) | bool Window::openFileBrowser(const FileBrowserOptions& options) | ||||
{ | { | ||||
#ifdef SOFD_HAVE_X11 | |||||
# ifdef SOFD_HAVE_X11 | |||||
using DISTRHO_NAMESPACE::String; | using DISTRHO_NAMESPACE::String; | ||||
// -------------------------------------------------------------------------- | // -------------------------------------------------------------------------- | ||||
@@ -1078,10 +1165,10 @@ bool Window::openFileBrowser(const FileBrowserOptions& options) | |||||
// show | // show | ||||
return (x_fib_show(pData->xDisplay, pData->xWindow, /*options.width*/0, /*options.height*/0) == 0); | return (x_fib_show(pData->xDisplay, pData->xWindow, /*options.width*/0, /*options.height*/0) == 0); | ||||
#else | |||||
# else | |||||
// not implemented | // not implemented | ||||
return false; | return false; | ||||
#endif | |||||
# endif | |||||
} | } | ||||
#endif | #endif | ||||
@@ -1220,6 +1307,26 @@ void Window::fileBrowserSelected(const char*) | |||||
} | } | ||||
#endif | #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() | StandaloneWindow::StandaloneWindow() | ||||
@@ -202,8 +202,6 @@ puglDisplay(PuglView* view) | |||||
- (void) reshape | - (void) reshape | ||||
{ | { | ||||
[[self openGLContext] update]; | |||||
if (!puglview) { | if (!puglview) { | ||||
/* NOTE: Apparently reshape gets called when the GC gets around to | /* NOTE: Apparently reshape gets called when the GC gets around to | ||||
deleting the view (?), so we must have reset puglview to NULL when | deleting the view (?), so we must have reset puglview to NULL when | ||||
@@ -212,6 +210,8 @@ puglDisplay(PuglView* view) | |||||
return; | return; | ||||
} | } | ||||
[[self openGLContext] update]; | |||||
NSRect bounds = [self bounds]; | NSRect bounds = [self bounds]; | ||||
int width = bounds.size.width; | int width = bounds.size.width; | ||||
int height = bounds.size.height; | int height = bounds.size.height; | ||||
@@ -445,7 +445,7 @@ dispatchKey(PuglView* view, XEvent* event, bool press) | |||||
view->redisplay = false; | view->redisplay = false; | ||||
return; | return; | ||||
} | } | ||||
if (n == 0) { | |||||
if (n == 0 && sym == 0) { | |||||
goto send_event; | goto send_event; | ||||
return; | return; | ||||
} | } | ||||
@@ -133,6 +133,29 @@ struct AudioPort { | |||||
symbol() {} | 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 | Parameter ranges.@n | ||||
This is used to set the default, minimum and maximum values of a parameter. | This is used to set the default, minimum and maximum values of a parameter. | ||||
@@ -289,6 +312,19 @@ struct Parameter { | |||||
*/ | */ | ||||
ParameterRanges ranges; | 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. | Default constructor for a null parameter. | ||||
*/ | */ | ||||
@@ -297,7 +333,9 @@ struct Parameter { | |||||
name(), | name(), | ||||
symbol(), | symbol(), | ||||
unit(), | unit(), | ||||
ranges() {} | |||||
ranges(), | |||||
designation(kParameterDesignationNull), | |||||
midiCC(0) {} | |||||
/** | /** | ||||
Constructor using custom values. | Constructor using custom values. | ||||
@@ -307,7 +345,33 @@ struct Parameter { | |||||
name(n), | name(n), | ||||
symbol(s), | symbol(s), | ||||
unit(u), | 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(). | 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 | @note This function is not implemented yet!@n | ||||
It's here so that developers can prepare MIDI plugins in advance.@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; | bool writeMidiEvent(const MidiEvent& midiEvent) noexcept; | ||||
#endif | #endif | ||||
@@ -651,7 +715,7 @@ protected: | |||||
/** | /** | ||||
Get the value of an internal state.@n | Get the value of an internal state.@n | ||||
The host may call this function from any non-realtime context.@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. | @note The use of this function breaks compatibility with the DSSI format. | ||||
*/ | */ | ||||
virtual String getState(const char* key) const = 0; | virtual String getState(const char* key) const = 0; | ||||
@@ -1,6 +1,6 @@ | |||||
/* | /* | ||||
* DISTRHO Plugin Framework (DPF) | * 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 | * 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 | * or without fee is hereby granted, provided that the above copyright notice and this | ||||
@@ -19,13 +19,13 @@ | |||||
#include "String.hpp" | #include "String.hpp" | ||||
#ifdef DISTRHO_OS_UNIX | |||||
#ifdef DISTRHO_OS_WINDOWS | |||||
# error Unsupported platform! | |||||
#else | |||||
# include <cerrno> | # include <cerrno> | ||||
# include <signal.h> | # include <signal.h> | ||||
# include <sys/wait.h> | # include <sys/wait.h> | ||||
# include <unistd.h> | # include <unistd.h> | ||||
#else | |||||
# error Unsupported platform! | |||||
#endif | #endif | ||||
START_NAMESPACE_DISTRHO | START_NAMESPACE_DISTRHO | ||||
@@ -579,7 +579,7 @@ public: | |||||
"abcdefghijklmnopqrstuvwxyz" | "abcdefghijklmnopqrstuvwxyz" | ||||
"0123456789+/"; | "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); | const uchar* bytesToEncode((const uchar*)data); | ||||
@@ -21,7 +21,7 @@ | |||||
#include "Sleep.hpp" | #include "Sleep.hpp" | ||||
#include "String.hpp" | #include "String.hpp" | ||||
#ifdef DISTRHO_OS_LINUX_FULL | |||||
#ifdef DISTRHO_OS_LINUX | |||||
# include <sys/prctl.h> | # include <sys/prctl.h> | ||||
#endif | #endif | ||||
@@ -198,7 +198,7 @@ public: | |||||
{ | { | ||||
DISTRHO_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0',); | 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); | prctl(PR_SET_NAME, name, 0, 0, 0); | ||||
#endif | #endif | ||||
#if defined(__GLIBC__) && (__GLIBC__ * 1000 + __GLIBC_MINOR__) >= 2012 | #if defined(__GLIBC__) && (__GLIBC__ * 1000 + __GLIBC_MINOR__) >= 2012 | ||||
@@ -38,17 +38,10 @@ | |||||
# elif defined(__HAIKU__) | # elif defined(__HAIKU__) | ||||
# define DISTRHO_OS_HAIKU 1 | # define DISTRHO_OS_HAIKU 1 | ||||
# elif defined(__linux__) || defined(__linux) | # 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 | ||||
#endif | #endif | ||||
#if defined(DISTRHO_OS_LINUX) || defined(DISTRHO_OS_MAC) | |||||
# define DISTRHO_OS_UNIX | |||||
#endif | |||||
#ifndef DISTRHO_DLL_EXTENSION | #ifndef DISTRHO_DLL_EXTENSION | ||||
# define DISTRHO_DLL_EXTENSION "so" | # define DISTRHO_DLL_EXTENSION "so" | ||||
#endif | #endif | ||||
@@ -43,6 +43,7 @@ struct Plugin::PrivateData { | |||||
#endif | #endif | ||||
uint32_t parameterCount; | uint32_t parameterCount; | ||||
uint32_t parameterOffset; | |||||
Parameter* parameters; | Parameter* parameters; | ||||
#if DISTRHO_PLUGIN_WANT_PROGRAMS | #if DISTRHO_PLUGIN_WANT_PROGRAMS | ||||
@@ -73,6 +74,7 @@ struct Plugin::PrivateData { | |||||
audioPorts(nullptr), | audioPorts(nullptr), | ||||
#endif | #endif | ||||
parameterCount(0), | parameterCount(0), | ||||
parameterOffset(0), | |||||
parameters(nullptr), | parameters(nullptr), | ||||
#if DISTRHO_PLUGIN_WANT_PROGRAMS | #if DISTRHO_PLUGIN_WANT_PROGRAMS | ||||
programCount(0), | programCount(0), | ||||
@@ -91,6 +93,22 @@ struct Plugin::PrivateData { | |||||
{ | { | ||||
DISTRHO_SAFE_ASSERT(bufferSize != 0); | DISTRHO_SAFE_ASSERT(bufferSize != 0); | ||||
DISTRHO_SAFE_ASSERT(d_isNotZero(sampleRate)); | 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 | ~PrivateData() noexcept | ||||
@@ -283,6 +301,13 @@ public: | |||||
return fData->parameterCount; | 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 | uint32_t getParameterHints(const uint32_t index) const noexcept | ||||
{ | { | ||||
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, 0x0); | DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, 0x0); | ||||
@@ -290,6 +315,13 @@ public: | |||||
return fData->parameters[index].hints; | 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 | bool isParameterOutput(const uint32_t index) const noexcept | ||||
{ | { | ||||
return (getParameterHints(index) & kParameterIsOutput); | return (getParameterHints(index) & kParameterIsOutput); | ||||
@@ -323,6 +355,13 @@ public: | |||||
return fData->parameters[index].ranges; | 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 | float getParameterValue(const uint32_t index) const | ||||
{ | { | ||||
DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, 0.0f); | DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, 0.0f); | ||||
@@ -70,20 +70,14 @@ static void closeSignalHandler(int) noexcept | |||||
static void initSignalHandler() | 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 | #endif | ||||
@@ -103,28 +97,27 @@ public: | |||||
#endif | #endif | ||||
fClient(client) | fClient(client) | ||||
{ | { | ||||
#if DISTRHO_PLUGIN_NUM_INPUTS > 0 || DISTRHO_PLUGIN_NUM_OUTPUTS > 0 | |||||
char strBuf[0xff+1]; | char strBuf[0xff+1]; | ||||
strBuf[0xff] = '\0'; | 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) | for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i) | ||||
{ | { | ||||
std::snprintf(strBuf, 0xff, "in%i", i+1); | std::snprintf(strBuf, 0xff, "in%i", i+1); | ||||
fPortAudioIns[i] = jack_port_register(fClient, strBuf, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); | 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) | for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i) | ||||
{ | { | ||||
std::snprintf(strBuf, 0xff, "out%i", i+1); | std::snprintf(strBuf, 0xff, "out%i", i+1); | ||||
fPortAudioOuts[i] = jack_port_register(fClient, strBuf, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); | fPortAudioOuts[i] = jack_port_register(fClient, strBuf, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); | ||||
} | } | ||||
# endif | |||||
#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 DISTRHO_PLUGIN_WANT_PROGRAMS | ||||
if (fPlugin.getProgramCount() > 0) | if (fPlugin.getProgramCount() > 0) | ||||
@@ -134,11 +127,18 @@ public: | |||||
fUI.programLoaded(0); | fUI.programLoaded(0); | ||||
# endif | # endif | ||||
} | } | ||||
# if DISTRHO_PLUGIN_HAS_UI | |||||
fProgramChanged = -1; | |||||
# endif | |||||
#endif | #endif | ||||
if (const uint32_t count = fPlugin.getParameterCount()) | if (const uint32_t count = fPlugin.getParameterCount()) | ||||
{ | { | ||||
fLastOutputValues = new float[count]; | 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) | for (uint32_t i=0; i < count; ++i) | ||||
{ | { | ||||
@@ -149,15 +149,18 @@ public: | |||||
else | else | ||||
{ | { | ||||
fLastOutputValues[i] = 0.0f; | fLastOutputValues[i] = 0.0f; | ||||
# if DISTRHO_PLUGIN_HAS_UI | |||||
#if DISTRHO_PLUGIN_HAS_UI | |||||
fUI.parameterChanged(i, fPlugin.getParameterValue(i)); | fUI.parameterChanged(i, fPlugin.getParameterValue(i)); | ||||
# endif | |||||
#endif | |||||
} | } | ||||
} | } | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
fLastOutputValues = nullptr; | fLastOutputValues = nullptr; | ||||
#if DISTRHO_PLUGIN_HAS_UI | |||||
fParametersChanged = nullptr; | |||||
#endif | |||||
} | } | ||||
jack_set_buffer_size_callback(fClient, jackBufferSizeCallback, this); | jack_set_buffer_size_callback(fClient, jackBufferSizeCallback, this); | ||||
@@ -198,10 +201,8 @@ public: | |||||
if (fClient == nullptr) | if (fClient == nullptr) | ||||
return; | 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 | #if DISTRHO_PLUGIN_NUM_INPUTS > 0 | ||||
for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i) | for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i) | ||||
@@ -231,20 +232,31 @@ protected: | |||||
if (gCloseSignalReceived) | if (gCloseSignalReceived) | ||||
return fUI.quit(); | 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) | 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(); | fUI.exec_idle(); | ||||
@@ -316,14 +328,14 @@ protected: | |||||
fPlugin.setTimePosition(fTimePosition); | fPlugin.setTimePosition(fTimePosition); | ||||
#endif | #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 (const uint32_t eventCount = jack_midi_get_event_count(midiBuf)) | ||||
{ | { | ||||
#if DISTRHO_PLUGIN_IS_SYNTH | |||||
uint32_t midiEventCount = 0; | uint32_t midiEventCount = 0; | ||||
MidiEvent midiEvents[eventCount]; | MidiEvent midiEvents[eventCount]; | ||||
#endif | |||||
jack_midi_event_t jevent; | jack_midi_event_t jevent; | ||||
for (uint32_t i=0; i < eventCount; ++i) | for (uint32_t i=0; i < eventCount; ++i) | ||||
@@ -331,6 +343,47 @@ protected: | |||||
if (jack_midi_event_get(&jevent, midiBuf, i) != 0) | if (jack_midi_event_get(&jevent, midiBuf, i) != 0) | ||||
break; | 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& midiEvent(midiEvents[midiEventCount++]); | ||||
midiEvent.frame = jevent.time; | midiEvent.frame = jevent.time; | ||||
@@ -340,10 +393,14 @@ protected: | |||||
midiEvent.dataExt = jevent.buffer; | midiEvent.dataExt = jevent.buffer; | ||||
else | else | ||||
std::memcpy(midiEvent.data, jevent.buffer, midiEvent.size); | std::memcpy(midiEvent.data, jevent.buffer, midiEvent.size); | ||||
#endif | |||||
} | } | ||||
#if DISTRHO_PLUGIN_IS_SYNTH | |||||
fPlugin.run(audioIns, audioOuts, nframes, midiEvents, midiEventCount); | fPlugin.run(audioIns, audioOuts, nframes, midiEvents, midiEventCount); | ||||
#endif | |||||
} | } | ||||
#if DISTRHO_PLUGIN_IS_SYNTH | |||||
else | else | ||||
{ | { | ||||
fPlugin.run(audioIns, audioOuts, nframes, nullptr, 0); | fPlugin.run(audioIns, audioOuts, nframes, nullptr, 0); | ||||
@@ -399,9 +456,7 @@ private: | |||||
#if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 | #if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 | ||||
jack_port_t* fPortAudioOuts[DISTRHO_PLUGIN_NUM_OUTPUTS]; | jack_port_t* fPortAudioOuts[DISTRHO_PLUGIN_NUM_OUTPUTS]; | ||||
#endif | #endif | ||||
#if DISTRHO_PLUGIN_IS_SYNTH | |||||
jack_port_t* fPortMidiIn; | |||||
#endif | |||||
jack_port_t* fPortEventsIn; | |||||
#if DISTRHO_PLUGIN_WANT_TIMEPOS | #if DISTRHO_PLUGIN_WANT_TIMEPOS | ||||
TimePosition fTimePosition; | TimePosition fTimePosition; | ||||
#endif | #endif | ||||
@@ -409,6 +464,14 @@ private: | |||||
// Temporary data | // Temporary data | ||||
float* fLastOutputValues; | 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 | // Callbacks | ||||
@@ -250,17 +250,16 @@ public: | |||||
midiEvents[j].data[2] = 0; | midiEvents[j].data[2] = 0; | ||||
midiEvents[j].data[3] = 0; | midiEvents[j].data[3] = 0; | ||||
break; | break; | ||||
#if 0 // TODO | |||||
case SND_SEQ_EVENT_PITCHBEND: | case SND_SEQ_EVENT_PITCHBEND: | ||||
j = midiEventCount++; | j = midiEventCount++; | ||||
midiEvents[j].frame = seqEvent.time.tick; | midiEvents[j].frame = seqEvent.time.tick; | ||||
midiEvents[j].size = 3; | midiEvents[j].size = 3; | ||||
midiEvents[j].data[0] = 0xE0 + seqEvent.data.control.channel; | 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; | midiEvents[j].data[3] = 0; | ||||
break; | break; | ||||
#endif | |||||
} | } | ||||
} | } | ||||
@@ -329,6 +328,21 @@ public: | |||||
} | } | ||||
} | } | ||||
# endif | # 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 | #endif | ||||
// ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
@@ -435,6 +449,11 @@ static void dssi_select_program(LADSPA_Handle instance, ulong bank, ulong progra | |||||
} | } | ||||
# endif | # 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 | # if DISTRHO_PLUGIN_WANT_MIDI_INPUT | ||||
static void dssi_run_synth(LADSPA_Handle instance, ulong sampleCount, snd_seq_event_t* events, ulong eventCount) | 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, | /* get_program */ nullptr, | ||||
/* select_program */ nullptr, | /* select_program */ nullptr, | ||||
# endif | # endif | ||||
/* get_midi_controller_for_port */ nullptr, | |||||
dssi_get_midi_controller_for_port, | |||||
# if DISTRHO_PLUGIN_WANT_MIDI_INPUT | # if DISTRHO_PLUGIN_WANT_MIDI_INPUT | ||||
dssi_run_synth, | dssi_run_synth, | ||||
# else | # else | ||||
@@ -614,11 +633,16 @@ public: | |||||
const uint32_t hints(plugin.getParameterHints(i)); | const uint32_t hints(plugin.getParameterHints(i)); | ||||
if (hints & kParameterIsBoolean) | if (hints & kParameterIsBoolean) | ||||
{ | |||||
portRangeHints[port].HintDescriptor |= LADSPA_HINT_TOGGLED; | 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_kxstudio_properties.h" | ||||
#include "lv2/lv2_programs.h" | #include "lv2/lv2_programs.h" | ||||
#ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD | |||||
# include "libmodauth.h" | |||||
#endif | |||||
#ifdef noexcept | #ifdef noexcept | ||||
# undef noexcept | # undef noexcept | ||||
#endif | #endif | ||||
@@ -58,6 +62,9 @@ class PluginLv2 | |||||
public: | public: | ||||
PluginLv2(const double sampleRate, const LV2_URID_Map* const uridMap, const LV2_Worker_Schedule* const worker, const bool usingNominal) | PluginLv2(const double sampleRate, const LV2_URID_Map* const uridMap, const LV2_Worker_Schedule* const worker, const bool usingNominal) | ||||
: fUsingNominal(usingNominal), | : fUsingNominal(usingNominal), | ||||
#ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD | |||||
fRunCount(0), | |||||
#endif | |||||
fPortControls(nullptr), | fPortControls(nullptr), | ||||
fLastControlValues(nullptr), | fLastControlValues(nullptr), | ||||
fSampleRate(sampleRate), | fSampleRate(sampleRate), | ||||
@@ -512,6 +519,12 @@ public: | |||||
if (fLastControlValues[i] != curValue && ! fPlugin.isParameterOutput(i)) | if (fLastControlValues[i] != curValue && ! fPlugin.isParameterOutput(i)) | ||||
{ | { | ||||
fLastControlValues[i] = curValue; | fLastControlValues[i] = curValue; | ||||
if (fPlugin.getParameterDesignation(i) == kParameterDesignationBypass) | |||||
{ | |||||
curValue = 1.0f - curValue; | |||||
} | |||||
fPlugin.setParameterValue(i, curValue); | fPlugin.setParameterValue(i, curValue); | ||||
} | } | ||||
} | } | ||||
@@ -519,12 +532,21 @@ public: | |||||
// Run plugin | // Run plugin | ||||
if (sampleCount != 0) | if (sampleCount != 0) | ||||
{ | { | ||||
#ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD | |||||
fRunCount = mod_license_run_begin(fRunCount, sampleCount); | |||||
#endif | |||||
#if DISTRHO_PLUGIN_WANT_MIDI_INPUT | #if DISTRHO_PLUGIN_WANT_MIDI_INPUT | ||||
fPlugin.run(fPortAudioIns, fPortAudioOuts, sampleCount, fMidiEvents, midiEventCount); | fPlugin.run(fPortAudioIns, fPortAudioOuts, sampleCount, fMidiEvents, midiEventCount); | ||||
#else | #else | ||||
fPlugin.run(fPortAudioIns, fPortAudioOuts, sampleCount); | fPlugin.run(fPortAudioIns, fPortAudioOuts, sampleCount); | ||||
#endif | #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 | #if DISTRHO_PLUGIN_WANT_TIMEPOS | ||||
// update timePos for next callback | // update timePos for next callback | ||||
if (d_isNotZero(fLastPositionData.speed)) | if (d_isNotZero(fLastPositionData.speed)) | ||||
@@ -589,10 +611,14 @@ public: | |||||
#if DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI | #if DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI | ||||
const uint32_t capacity = fPortEventsOut->atom.size; | const uint32_t capacity = fPortEventsOut->atom.size; | ||||
bool needsInit = true; | |||||
uint32_t size, offset = 0; | uint32_t size, offset = 0; | ||||
LV2_Atom_Event* aev; | 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 | // TODO - MIDI Output | ||||
for (uint32_t i=0, count=fPlugin.getStateCount(); i < count; ++i) | for (uint32_t i=0, count=fPlugin.getStateCount(); i < count; ++i) | ||||
@@ -617,15 +643,6 @@ public: | |||||
if (sizeof(LV2_Atom_Event) + msgSize > capacity - offset) | if (sizeof(LV2_Atom_Event) + msgSize > capacity - offset) | ||||
break; | 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 | // reserve msg space | ||||
char msgBuf[msgSize]; | char msgBuf[msgSize]; | ||||
std::memset(msgBuf, 0, msgSize); | std::memset(msgBuf, 0, msgSize); | ||||
@@ -846,6 +863,10 @@ private: | |||||
PluginExporter fPlugin; | PluginExporter fPlugin; | ||||
const bool fUsingNominal; // if false use maxBlockLength | const bool fUsingNominal; // if false use maxBlockLength | ||||
#ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD | |||||
uint32_t fRunCount; | |||||
#endif | |||||
// LV2 ports | // LV2 ports | ||||
#if DISTRHO_PLUGIN_NUM_INPUTS > 0 | #if DISTRHO_PLUGIN_NUM_INPUTS > 0 | ||||
const float* fPortAudioIns[DISTRHO_PLUGIN_NUM_INPUTS]; | const float* fPortAudioIns[DISTRHO_PLUGIN_NUM_INPUTS]; | ||||
@@ -1034,6 +1055,10 @@ static LV2_Handle lv2_instantiate(const LV2_Descriptor*, double sampleRate, cons | |||||
} | } | ||||
#endif | #endif | ||||
#ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD | |||||
mod_check_license(features, DISTRHO_PLUGIN_URI); | |||||
#endif | |||||
d_lastBufferSize = 0; | d_lastBufferSize = 0; | ||||
bool usingNominal = false; | bool usingNominal = false; | ||||
@@ -1193,7 +1218,11 @@ static const void* lv2_extension_data(const char* uri) | |||||
return &directaccess; | return &directaccess; | ||||
#endif | #endif | ||||
#ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD | |||||
return mod_license_interface(uri); | |||||
#else | |||||
return nullptr; | return nullptr; | ||||
#endif | |||||
} | } | ||||
#undef instancePtr | #undef instancePtr | ||||
@@ -1,6 +1,6 @@ | |||||
/* | /* | ||||
* DISTRHO Plugin Framework (DPF) | * 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 | * 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 | * 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_kxstudio_properties.h" | ||||
#include "lv2/lv2_programs.h" | #include "lv2/lv2_programs.h" | ||||
#ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD | |||||
# include "mod-license.h" | |||||
#endif | |||||
#include <fstream> | #include <fstream> | ||||
#include <iostream> | #include <iostream> | ||||
@@ -224,6 +228,9 @@ void lv2_generate_ttl(const char* const basename) | |||||
#endif | #endif | ||||
#if DISTRHO_PLUGIN_WANT_PROGRAMS | #if DISTRHO_PLUGIN_WANT_PROGRAMS | ||||
pluginString += ",\n <" LV2_PROGRAMS__Interface "> "; | pluginString += ",\n <" LV2_PROGRAMS__Interface "> "; | ||||
#endif | |||||
#ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD | |||||
pluginString += ",\n <" MOD_LICENSE__interface "> "; | |||||
#endif | #endif | ||||
pluginString += ";\n\n"; | pluginString += ";\n\n"; | ||||
@@ -241,6 +248,9 @@ void lv2_generate_ttl(const char* const basename) | |||||
pluginString += ",\n <" LV2_URID__map "> "; | pluginString += ",\n <" LV2_URID__map "> "; | ||||
#if DISTRHO_PLUGIN_WANT_STATE | #if DISTRHO_PLUGIN_WANT_STATE | ||||
pluginString += ",\n <" LV2_WORKER__schedule "> "; | pluginString += ",\n <" LV2_WORKER__schedule "> "; | ||||
#endif | |||||
#ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD | |||||
pluginString += ",\n <" MOD_LICENSE__feature "> "; | |||||
#endif | #endif | ||||
pluginString += ";\n\n"; | pluginString += ";\n\n"; | ||||
@@ -359,7 +369,7 @@ void lv2_generate_ttl(const char* const basename) | |||||
pluginString += " lv2:name \"Latency\" ;\n"; | pluginString += " lv2:name \"Latency\" ;\n"; | ||||
pluginString += " lv2:symbol \"lv2_latency\" ;\n"; | pluginString += " lv2:symbol \"lv2_latency\" ;\n"; | ||||
pluginString += " lv2:designation 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"; | pluginString += " ] ;\n\n"; | ||||
++portIndex; | ++portIndex; | ||||
#endif | #endif | ||||
@@ -377,10 +387,34 @@ void lv2_generate_ttl(const char* const basename) | |||||
pluginString += " a lv2:InputPort, lv2:ControlPort ;\n"; | pluginString += " a lv2:InputPort, lv2:ControlPort ;\n"; | ||||
pluginString += " lv2:index " + String(portIndex) + " ;\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)); | String symbol(plugin.getParameterSymbol(i)); | ||||
if (symbol.isEmpty()) | if (symbol.isEmpty()) | ||||
@@ -390,24 +424,28 @@ void lv2_generate_ttl(const char* const basename) | |||||
} | } | ||||
// ranges | // ranges | ||||
if (! designated) | |||||
{ | { | ||||
const ParameterRanges& ranges(plugin.getParameterRanges(i)); | const ParameterRanges& ranges(plugin.getParameterRanges(i)); | ||||
if (plugin.getParameterHints(i) & kParameterIsInteger) | 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:minimum " + String(int(ranges.min)) + " ;\n"; | ||||
pluginString += " lv2:maximum " + String(int(ranges.max)) + " ;\n"; | pluginString += " lv2:maximum " + String(int(ranges.max)) + " ;\n"; | ||||
} | } | ||||
else | 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:minimum " + String(ranges.min) + " ;\n"; | ||||
pluginString += " lv2:maximum " + String(ranges.max) + " ;\n"; | pluginString += " lv2:maximum " + String(ranges.max) + " ;\n"; | ||||
} | } | ||||
} | } | ||||
// unit | // unit | ||||
if (! designated) | |||||
{ | { | ||||
const String& unit(plugin.getParameterUnit(i)); | const String& unit(plugin.getParameterUnit(i)); | ||||
@@ -453,6 +491,7 @@ void lv2_generate_ttl(const char* const basename) | |||||
} | } | ||||
// hints | // hints | ||||
if (! designated) | |||||
{ | { | ||||
const uint32_t hints(plugin.getParameterHints(i)); | const uint32_t hints(plugin.getParameterHints(i)); | ||||
@@ -606,7 +645,18 @@ void lv2_generate_ttl(const char* const basename) | |||||
plugin.loadProgram(i); | 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 | # if DISTRHO_PLUGIN_WANT_FULL_STATE | ||||
presetString += " state:state [\n"; | presetString += " state:state [\n"; | ||||
@@ -629,12 +679,22 @@ void lv2_generate_ttl(const char* const basename) | |||||
presetString += " ] .\n\n"; | presetString += " ] .\n\n"; | ||||
# endif | # endif | ||||
bool firstParameter = true; | |||||
for (uint32_t j=0; j <numParameters; ++j) | for (uint32_t j=0; j <numParameters; ++j) | ||||
{ | { | ||||
if (j == 0) | |||||
if (plugin.isParameterOutput(j)) | |||||
continue; | |||||
if (firstParameter) | |||||
{ | |||||
presetString += " lv2:port [\n"; | presetString += " lv2:port [\n"; | ||||
firstParameter = false; | |||||
} | |||||
else | else | ||||
{ | |||||
presetString += " [\n"; | presetString += " [\n"; | ||||
} | |||||
presetString += " lv2:symbol \"" + plugin.getParameterSymbol(j) + "\" ;\n"; | presetString += " lv2:symbol \"" + plugin.getParameterSymbol(j) + "\" ;\n"; | ||||
@@ -643,7 +703,7 @@ void lv2_generate_ttl(const char* const basename) | |||||
else | else | ||||
presetString += " pset:value " + String(plugin.getParameterValue(j)) + " ;\n"; | presetString += " pset:value " + String(plugin.getParameterValue(j)) + " ;\n"; | ||||
if (j+1 == numParameters) | |||||
if (j+1 == numParameters || plugin.isParameterOutput(j+1)) | |||||
presetString += " ] .\n\n"; | presetString += " ] .\n\n"; | ||||
else | else | ||||
presetString += " ] ,\n"; | presetString += " ] ,\n"; | ||||
@@ -52,6 +52,8 @@ | |||||
#define effGetProgramNameIndexed 29 | #define effGetProgramNameIndexed 29 | ||||
#define effGetPlugCategory 35 | #define effGetPlugCategory 35 | ||||
#define effIdle 53 | #define effIdle 53 | ||||
#define effEditKeyDown 59 | |||||
#define effEditKeyUp 60 | |||||
#define kPlugCategEffect 1 | #define kPlugCategEffect 1 | ||||
#define kPlugCategSynth 2 | #define kPlugCategSynth 2 | ||||
#define kVstVersion 2400 | #define kVstVersion 2400 | ||||
@@ -122,8 +124,20 @@ public: | |||||
fEffect(effect), | fEffect(effect), | ||||
fUiHelper(uiHelper), | fUiHelper(uiHelper), | ||||
fPlugin(plugin), | 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 | # 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: | protected: | ||||
@@ -231,6 +299,7 @@ private: | |||||
// Plugin UI | // Plugin UI | ||||
UIExporter fUI; | UIExporter fUI; | ||||
bool fShouldCaptureVstKeys; | |||||
// ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
// Callbacks | // Callbacks | ||||
@@ -499,6 +568,16 @@ public: | |||||
if (fVstUI != nullptr) | if (fVstUI != nullptr) | ||||
fVstUI->idle(); | fVstUI->idle(); | ||||
break; | 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 | #endif // DISTRHO_PLUGIN_HAS_UI | ||||
#if DISTRHO_PLUGIN_WANT_STATE | #if DISTRHO_PLUGIN_WANT_STATE | ||||
@@ -418,6 +418,16 @@ public: | |||||
return ! glApp.isQuiting(); | 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 | #else | ||||
void setWindowSize(const uint width, const uint height, const bool updateUI = false) {} | void setWindowSize(const uint width, const uint height, const bool updateUI = false) {} | ||||
void setWindowTransientWinId(const uintptr_t winId) {} | void setWindowTransientWinId(const uintptr_t winId) {} | ||||
@@ -23,6 +23,7 @@ | |||||
#include "lv2/data-access.h" | #include "lv2/data-access.h" | ||||
#include "lv2/instance-access.h" | #include "lv2/instance-access.h" | ||||
#include "lv2/options.h" | #include "lv2/options.h" | ||||
#include "lv2/parameters.h" | |||||
#include "lv2/ui.h" | #include "lv2/ui.h" | ||||
#include "lv2/urid.h" | #include "lv2/urid.h" | ||||
#include "lv2/lv2_kxstudio_properties.h" | #include "lv2/lv2_kxstudio_properties.h" | ||||
@@ -114,7 +115,9 @@ public: | |||||
{ | { | ||||
const uint32_t parameterOffset(fUI.getParameterOffset()); | const uint32_t parameterOffset(fUI.getParameterOffset()); | ||||
DISTRHO_SAFE_ASSERT_RETURN(rindex >= parameterOffset,) | |||||
if (rindex < parameterOffset) | |||||
return; | |||||
DISTRHO_SAFE_ASSERT_RETURN(bufferSize == sizeof(float),) | DISTRHO_SAFE_ASSERT_RETURN(bufferSize == sizeof(float),) | ||||
const float value(*(const float*)buffer); | const float value(*(const float*)buffer); | ||||
@@ -173,17 +176,17 @@ public: | |||||
{ | { | ||||
for (int i=0; options[i].key != 0; ++i) | 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); | fUI.setSampleRate(sampleRate); | ||||
continue; | continue; | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
d_stderr("Host changed sampleRate but with wrong value type"); | |||||
d_stderr("Host changed UI sample-rate but with wrong value type"); | |||||
continue; | continue; | ||||
} | } | ||||
} | } | ||||
@@ -237,7 +240,7 @@ protected: | |||||
const size_t msgSize(tmpStr.length()+1); | const size_t msgSize(tmpStr.length()+1); | ||||
// reserve atom space | // 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]; | char atomBuf[atomSize]; | ||||
std::memset(atomBuf, 0, atomSize); | std::memset(atomBuf, 0, atomSize); | ||||
@@ -400,23 +403,23 @@ static LV2UI_Handle lv2ui_instantiate(const LV2UI_Descriptor*, const char* uri, | |||||
if (options != nullptr) | 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) | for (int i=0; options[i].key != 0; ++i) | ||||
{ | { | ||||
if (options[i].key == uridSampleRate) | 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 | else | ||||
d_stderr("Host provides sampleRate but has wrong value type"); | |||||
d_stderr("Host provides UI sample-rate but has wrong value type"); | |||||
break; | 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_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; | d_lastUiSampleRate = 44100.0; | ||||