@@ -127,6 +127,10 @@ endif | |||
cp -r modguis/MVerb.modgui/modgui $(DESTDIR)$(PREFIX)/lib/lv2/MVerb.lv2/ | |||
cp modguis/MVerb.modgui/manifest.ttl $(DESTDIR)$(PREFIX)/lib/lv2/MVerb.lv2/modgui.ttl | |||
# Nekobi | |||
cp -r modguis/Nekobi.modgui/modgui $(DESTDIR)$(PREFIX)/lib/lv2/Nekobi.lv2/ | |||
cp modguis/Nekobi.modgui/manifest.ttl $(DESTDIR)$(PREFIX)/lib/lv2/Nekobi.lv2/modgui.ttl | |||
# Max-Gen stuff | |||
# -------------------------------------------------------------- | |||
@@ -1,6 +1,6 @@ | |||
/* | |||
* DISTRHO Plugin Framework (DPF) | |||
* Copyright (C) 2012-2015 Filipe Coelho <falktx@falktx.com> | |||
* Copyright (C) 2012-2016 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 | |||
@@ -20,7 +20,10 @@ | |||
#include "extra/LeakDetector.hpp" | |||
#include "src/DistrhoPluginChecks.h" | |||
#if DISTRHO_UI_USE_NANOVG | |||
#ifndef HAVE_DGL | |||
# include "extra/ExternalWindow.hpp" | |||
typedef DISTRHO_NAMESPACE::ExternalWindow UIWidget; | |||
#elif DISTRHO_UI_USE_NANOVG | |||
# include "../dgl/NanoVG.hpp" | |||
typedef DGL::NanoWidget UIWidget; | |||
#else | |||
@@ -41,9 +44,8 @@ START_NAMESPACE_DISTRHO | |||
/** | |||
DPF UI class from where UI instances are created. | |||
TODO. | |||
must call setSize during construction, | |||
@note You must call setSize during construction, | |||
@TODO Detailed information about this class. | |||
*/ | |||
class UI : public UIWidget | |||
{ | |||
@@ -69,25 +71,29 @@ public: | |||
double getSampleRate() const noexcept; | |||
/** | |||
TODO: Document this. | |||
editParameter. | |||
@TODO Document this. | |||
*/ | |||
void editParameter(uint32_t index, bool started); | |||
/** | |||
TODO: Document this. | |||
setParameterValue. | |||
@TODO Document this. | |||
*/ | |||
void setParameterValue(uint32_t index, float value); | |||
#if DISTRHO_PLUGIN_WANT_STATE | |||
/** | |||
TODO: Document this. | |||
setState. | |||
@TODO Document this. | |||
*/ | |||
void setState(const char* key, const char* value); | |||
#endif | |||
#if DISTRHO_PLUGIN_IS_SYNTH | |||
/** | |||
TODO: Document this. | |||
sendNote. | |||
@TODO Document this. | |||
*/ | |||
void sendNote(uint8_t channel, uint8_t note, uint8_t velocity); | |||
#endif | |||
@@ -97,11 +103,24 @@ public: | |||
* Direct DSP access - DO NOT USE THIS UNLESS STRICTLY NECESSARY!! */ | |||
/** | |||
TODO: Document this. | |||
getPluginInstancePointer. | |||
@TODO Document this. | |||
*/ | |||
void* getPluginInstancePointer() const noexcept; | |||
#endif | |||
#if DISTRHO_PLUGIN_HAS_EMBED_UI && DISTRHO_PLUGIN_HAS_EXTERNAL_UI | |||
/* -------------------------------------------------------------------------------------------------------- | |||
* External embeddable UI helpers */ | |||
/** | |||
Get the Window Id that will be used for the next created window. | |||
@note: This function is only valid during createUI(), | |||
it will return 0 when called from anywhere else. | |||
*/ | |||
static uintptr_t getNextWindowId() noexcept; | |||
#endif | |||
protected: | |||
/* -------------------------------------------------------------------------------------------------------- | |||
* DSP/Plugin Callbacks */ | |||
@@ -137,11 +156,13 @@ protected: | |||
*/ | |||
virtual void sampleRateChanged(double newSampleRate); | |||
#ifdef HAVE_DGL | |||
/* -------------------------------------------------------------------------------------------------------- | |||
* UI Callbacks (optional) */ | |||
/** | |||
TODO: Document this. | |||
uiIdle. | |||
@TODO Document this. | |||
*/ | |||
virtual void uiIdle() {} | |||
@@ -167,6 +188,7 @@ protected: | |||
@see Widget::onResize(const ResizeEvent&) | |||
*/ | |||
void onResize(const ResizeEvent& ev) override; | |||
#endif | |||
// ------------------------------------------------------------------------------------------------------- | |||
@@ -176,11 +198,13 @@ private: | |||
friend class UIExporter; | |||
friend class UIExporterWindow; | |||
#ifdef HAVE_DGL | |||
// these should not be used | |||
void setAbsoluteX(int) const noexcept {} | |||
void setAbsoluteY(int) const noexcept {} | |||
void setAbsolutePos(int, int) const noexcept {} | |||
void setAbsolutePos(const DGL::Point<int>&) const noexcept {} | |||
#endif | |||
DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(UI) | |||
}; | |||
@@ -196,7 +220,8 @@ private: | |||
*/ | |||
/** | |||
TODO. | |||
createUI. | |||
@TODO Document this. | |||
*/ | |||
extern UI* createUI(); | |||
@@ -1,6 +1,6 @@ | |||
/* | |||
* DISTRHO Plugin Framework (DPF) | |||
* Copyright (C) 2012-2015 Filipe Coelho <falktx@falktx.com> | |||
* Copyright (C) 2012-2016 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 | |||
@@ -24,7 +24,30 @@ | |||
// ----------------------------------------------------------------------- | |||
// base64 stuff, based on http://www.adp-gmbh.ch/cpp/common/base64.html | |||
// Copyright (C) 2004-2008 René Nyffenegger | |||
/* | |||
Copyright (C) 2004-2008 René Nyffenegger | |||
This source code is provided 'as-is', without any express or implied | |||
warranty. In no event will the author be held liable for any damages | |||
arising from the use of this software. | |||
Permission is granted to anyone to use this software for any purpose, | |||
including commercial applications, and to alter it and redistribute it | |||
freely, subject to the following restrictions: | |||
1. The origin of this source code must not be misrepresented; you must not | |||
claim that you wrote the original source code. If you use this source code | |||
in a product, an acknowledgment in the product documentation would be | |||
appreciated but is not required. | |||
2. Altered source versions must be plainly marked as such, and must not be | |||
misrepresented as being the original source code. | |||
3. This notice may not be removed or altered from any source distribution. | |||
René Nyffenegger rene.nyffenegger@adp-gmbh.ch | |||
*/ | |||
// ----------------------------------------------------------------------- | |||
// Helpers | |||
@@ -0,0 +1,171 @@ | |||
/* | |||
* DISTRHO Plugin Framework (DPF) | |||
* Copyright (C) 2012-2016 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 | |||
* permission notice appear in all copies. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD | |||
* TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN | |||
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL | |||
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER | |||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | |||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |||
*/ | |||
#ifndef DISTRHO_EXTERNAL_WINDOW_HPP_INCLUDED | |||
#define DISTRHO_EXTERNAL_WINDOW_HPP_INCLUDED | |||
#include "String.hpp" | |||
#ifdef DISTRHO_OS_UNIX | |||
# include <cerrno> | |||
# include <sys/wait.h> | |||
# include <unistd.h> | |||
#else | |||
# error Unsupported platform! | |||
#endif | |||
START_NAMESPACE_DISTRHO | |||
// ----------------------------------------------------------------------- | |||
// ExternalWindow class | |||
class ExternalWindow | |||
{ | |||
public: | |||
ExternalWindow(const uint w = 1, const uint h = 1, const char* const t = "") | |||
: width(w), | |||
height(h), | |||
title(t), | |||
pid(0) {} | |||
virtual ~ExternalWindow() | |||
{ | |||
terminateAndWaitForProcess(); | |||
} | |||
uint getWidth() const noexcept | |||
{ | |||
return width; | |||
} | |||
uint getHeight() const noexcept | |||
{ | |||
return height; | |||
} | |||
const char* getTitle() const noexcept | |||
{ | |||
return title; | |||
} | |||
void setTitle(const char* const t) noexcept | |||
{ | |||
title = t; | |||
} | |||
bool isRunning() noexcept | |||
{ | |||
if (pid <= 0) | |||
return false; | |||
const pid_t p = ::waitpid(pid, nullptr, WNOHANG); | |||
if (p == pid || (p == -1 && errno == ECHILD)) | |||
{ | |||
printf("NOTICE: Child process exited while idle\n"); | |||
pid = 0; | |||
return false; | |||
} | |||
return true; | |||
} | |||
protected: | |||
bool startExternalProcess(const char* args[]) | |||
{ | |||
terminateAndWaitForProcess(); | |||
pid = vfork(); | |||
switch (pid) | |||
{ | |||
case 0: | |||
execvp(args[0], (char**)args); | |||
_exit(1); | |||
return false; | |||
case -1: | |||
printf("Could not start external ui\n"); | |||
return false; | |||
default: | |||
return true; | |||
} | |||
} | |||
private: | |||
uint width; | |||
uint height; | |||
String title; | |||
pid_t pid; | |||
friend class UIExporter; | |||
void terminateAndWaitForProcess() | |||
{ | |||
if (pid <= 0) | |||
return; | |||
printf("Waiting for previous process to stop,,,\n"); | |||
bool sendTerm = true; | |||
for (pid_t p;;) | |||
{ | |||
p = ::waitpid(pid, nullptr, WNOHANG); | |||
switch (p) | |||
{ | |||
case 0: | |||
if (sendTerm) | |||
{ | |||
sendTerm = false; | |||
::kill(pid, SIGTERM); | |||
} | |||
break; | |||
case -1: | |||
if (errno == ECHILD) | |||
{ | |||
printf("Done! (no such process)\n"); | |||
pid = 0; | |||
return; | |||
} | |||
break; | |||
default: | |||
if (p == pid) | |||
{ | |||
printf("Done! (clean wait)\n"); | |||
pid = 0; | |||
return; | |||
} | |||
break; | |||
} | |||
// 5 msec | |||
usleep(5*1000); | |||
} | |||
} | |||
DISTRHO_DECLARE_NON_COPY_CLASS(ExternalWindow) | |||
}; | |||
// ----------------------------------------------------------------------- | |||
END_NAMESPACE_DISTRHO | |||
#endif // DISTRHO_EXTERNAL_WINDOW_HPP_INCLUDED |
@@ -42,6 +42,10 @@ | |||
# 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 | |||
@@ -45,6 +45,10 @@ | |||
# define DISTRHO_PLUGIN_HAS_UI 0 | |||
#endif | |||
#ifndef DISTRHO_PLUGIN_HAS_EXTERNAL_UI | |||
# define DISTRHO_PLUGIN_HAS_EXTERNAL_UI 0 | |||
#endif | |||
#ifndef DISTRHO_PLUGIN_IS_RT_SAFE | |||
# define DISTRHO_PLUGIN_IS_RT_SAFE 0 | |||
#endif | |||
@@ -85,6 +89,17 @@ | |||
# define DISTRHO_UI_USE_NANOVG 0 | |||
#endif | |||
// ----------------------------------------------------------------------- | |||
// Define DISTRHO_PLUGIN_HAS_EMBED_UI if needed | |||
#ifndef DISTRHO_PLUGIN_HAS_EMBED_UI | |||
# ifdef HAVE_DGL | |||
# define DISTRHO_PLUGIN_HAS_EMBED_UI 1 | |||
# else | |||
# define DISTRHO_PLUGIN_HAS_EMBED_UI 0 | |||
# endif | |||
#endif | |||
// ----------------------------------------------------------------------- | |||
// Define DISTRHO_UI_URI if needed | |||
@@ -117,9 +132,9 @@ | |||
#endif | |||
// ----------------------------------------------------------------------- | |||
// Disable UI if DGL is not available | |||
// Disable UI if DGL or External UI is not available | |||
#if DISTRHO_PLUGIN_HAS_UI && ! defined(HAVE_DGL) | |||
#if DISTRHO_PLUGIN_HAS_UI && ! DISTRHO_PLUGIN_HAS_EXTERNAL_UI && ! defined(HAVE_DGL) | |||
# undef DISTRHO_PLUGIN_HAS_UI | |||
# define DISTRHO_PLUGIN_HAS_UI 0 | |||
#endif | |||
@@ -16,7 +16,7 @@ | |||
#include "DistrhoPluginInternal.hpp" | |||
#if DISTRHO_PLUGIN_HAS_UI && ! defined(HAVE_DGL) | |||
#if DISTRHO_PLUGIN_HAS_UI && ! DISTRHO_PLUGIN_HAS_EMBED_UI | |||
# undef DISTRHO_PLUGIN_HAS_UI | |||
# define DISTRHO_PLUGIN_HAS_UI 0 | |||
#endif | |||
@@ -49,12 +49,7 @@ | |||
# define DISTRHO_PLUGIN_USES_MODGUI 0 | |||
#endif | |||
#if DISTRHO_PLUGIN_HAS_UI && ! defined(HAVE_DGL) | |||
# undef DISTRHO_PLUGIN_HAS_UI | |||
# define DISTRHO_PLUGIN_HAS_UI 0 | |||
#endif | |||
#if DISTRHO_PLUGIN_HAS_UI | |||
#if DISTRHO_PLUGIN_HAS_EMBED_UI | |||
# if DISTRHO_OS_HAIKU | |||
# define DISTRHO_LV2_UI_TYPE "BeUI" | |||
# elif DISTRHO_OS_MAC | |||
@@ -64,6 +59,8 @@ | |||
# else | |||
# define DISTRHO_LV2_UI_TYPE "X11UI" | |||
# endif | |||
#else | |||
# define DISTRHO_LV2_UI_TYPE "UI" | |||
#endif | |||
#define DISTRHO_LV2_USE_EVENTS_IN (DISTRHO_PLUGIN_WANT_MIDI_INPUT || DISTRHO_PLUGIN_WANT_TIMEPOS || (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI)) | |||
@@ -137,10 +134,12 @@ void lv2_generate_ttl(const char* const basename) | |||
manifestString += " ui:showInterface ;\n"; | |||
# endif | |||
manifestString += "\n"; | |||
# if DISTRHO_PLUGIN_HAS_EMBED_UI | |||
manifestString += " lv2:optionalFeature ui:noUserResize ,\n"; | |||
manifestString += " ui:resize ,\n"; | |||
manifestString += " ui:touch ;\n"; | |||
manifestString += "\n"; | |||
# endif | |||
manifestString += " lv2:requiredFeature <" LV2_DATA_ACCESS_URI "> ,\n"; | |||
manifestString += " <" LV2_INSTANCE_ACCESS_URI "> ,\n"; | |||
manifestString += " <" LV2_OPTIONS__options "> ,\n"; | |||
@@ -558,10 +557,12 @@ void lv2_generate_ttl(const char* const basename) | |||
uiString += " ui:showInterface ;\n"; | |||
# endif | |||
uiString += "\n"; | |||
# if DISTRHO_PLUGIN_HAS_EMBED_UI | |||
uiString += " lv2:optionalFeature ui:noUserResize ,\n"; | |||
uiString += " ui:resize ,\n"; | |||
uiString += " ui:touch ;\n"; | |||
uiString += "\n"; | |||
# endif | |||
uiString += " lv2:requiredFeature <" LV2_OPTIONS__options "> ,\n"; | |||
uiString += " <" LV2_URID__map "> .\n"; | |||
@@ -1,6 +1,6 @@ | |||
/* | |||
* DISTRHO Plugin Framework (DPF) | |||
* Copyright (C) 2012-2015 Filipe Coelho <falktx@falktx.com> | |||
* Copyright (C) 2012-2016 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 | |||
@@ -16,7 +16,7 @@ | |||
#include "DistrhoPluginInternal.hpp" | |||
#if DISTRHO_PLUGIN_HAS_UI && ! defined(HAVE_DGL) | |||
#if DISTRHO_PLUGIN_HAS_UI && ! DISTRHO_PLUGIN_HAS_EMBED_UI | |||
# undef DISTRHO_PLUGIN_HAS_UI | |||
# define DISTRHO_PLUGIN_HAS_UI 0 | |||
#endif | |||
@@ -340,6 +340,10 @@ public: | |||
intptr_t vst_dispatcher(const int32_t opcode, const int32_t index, const intptr_t value, void* const ptr, const float opt) | |||
{ | |||
#if DISTRHO_PLUGIN_WANT_STATE | |||
intptr_t ret = 0; | |||
#endif | |||
switch (opcode) | |||
{ | |||
case effGetProgram: | |||
@@ -512,7 +516,7 @@ public: | |||
{ | |||
fStateChunk = new char[1]; | |||
fStateChunk[0] = '\0'; | |||
return 1; | |||
ret = 1; | |||
} | |||
else | |||
{ | |||
@@ -554,11 +558,11 @@ public: | |||
fStateChunk[i] = '\0'; | |||
} | |||
return chunkSize; | |||
ret = chunkSize; | |||
} | |||
*(void**)ptr = fStateChunk; | |||
break; | |||
return ret; | |||
case effSetChunk: | |||
{ | |||
@@ -634,36 +638,38 @@ public: | |||
} | |||
break; | |||
#if DISTRHO_PLUGIN_WANT_MIDI_INPUT || DISTRHO_PLUGIN_WANT_MIDI_OUTPUT || DISTRHO_PLUGIN_WANT_TIMEPOS || DISTRHO_OS_MAC | |||
case effCanDo: | |||
if (const char* const canDo = (const char*)ptr) | |||
{ | |||
# if DISTRHO_OS_MAC && DISTRHO_PLUGIN_HAS_UI | |||
#if DISTRHO_OS_MAC && DISTRHO_PLUGIN_HAS_UI | |||
if (std::strcmp(canDo, "hasCockosViewAsConfig") == 0) | |||
{ | |||
fUsingNsView = true; | |||
return 0xbeef0000; | |||
} | |||
# endif | |||
# if DISTRHO_PLUGIN_WANT_MIDI_INPUT | |||
if (std::strcmp(canDo, "receiveVstEvents") == 0) | |||
return 1; | |||
if (std::strcmp(canDo, "receiveVstMidiEvent") == 0) | |||
return 1; | |||
# endif | |||
# if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT | |||
if (std::strcmp(canDo, "sendVstEvents") == 0) | |||
#endif | |||
if (std::strcmp(canDo, "receiveVstEvents") == 0 || | |||
std::strcmp(canDo, "receiveVstMidiEvent") == 0) | |||
#if DISTRHO_PLUGIN_WANT_MIDI_INPUT | |||
return 1; | |||
if (std::strcmp(canDo, "sendVstMidiEvent") == 0) | |||
#else | |||
return -1; | |||
#endif | |||
if (std::strcmp(canDo, "sendVstEvents") == 0 || | |||
std::strcmp(canDo, "sendVstMidiEvent") == 0) | |||
#if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT | |||
return 1; | |||
# endif | |||
# if DISTRHO_PLUGIN_WANT_TIMEPOS | |||
#else | |||
return -1; | |||
#endif | |||
if (std::strcmp(canDo, "receiveVstTimeInfo") == 0) | |||
#if DISTRHO_PLUGIN_WANT_TIMEPOS | |||
return 1; | |||
# endif | |||
#else | |||
return -1; | |||
#endif | |||
} | |||
break; | |||
#endif | |||
//case effStartProcess: | |||
//case effStopProcess: | |||
@@ -1,6 +1,6 @@ | |||
/* | |||
* DISTRHO Plugin Framework (DPF) | |||
* Copyright (C) 2012-2015 Filipe Coelho <falktx@falktx.com> | |||
* Copyright (C) 2012-2016 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 | |||
@@ -15,20 +15,27 @@ | |||
*/ | |||
#include "DistrhoUIInternal.hpp" | |||
#include "src/WidgetPrivateData.hpp" | |||
#ifdef HAVE_DGL | |||
# include "src/WidgetPrivateData.hpp" | |||
#endif | |||
START_NAMESPACE_DISTRHO | |||
/* ------------------------------------------------------------------------------------------------------------ | |||
* Static data, see DistrhoUIInternal.hpp */ | |||
double d_lastUiSampleRate = 0.0; | |||
void* d_lastUiDspPtr = nullptr; | |||
Window* d_lastUiWindow = nullptr; | |||
double d_lastUiSampleRate = 0.0; | |||
void* d_lastUiDspPtr = nullptr; | |||
#ifdef HAVE_DGL | |||
Window* d_lastUiWindow = nullptr; | |||
#endif | |||
uintptr_t g_nextWindowId = 0; | |||
/* ------------------------------------------------------------------------------------------------------------ | |||
* UI */ | |||
#ifdef HAVE_DGL | |||
UI::UI(uint width, uint height) | |||
: UIWidget(*d_lastUiWindow), | |||
pData(new PrivateData()) | |||
@@ -38,6 +45,11 @@ UI::UI(uint width, uint height) | |||
if (width > 0 && height > 0) | |||
setSize(width, height); | |||
} | |||
#else | |||
UI::UI(uint width, uint height) | |||
: UIWidget(width, height), | |||
pData(new PrivateData()) {} | |||
#endif | |||
UI::~UI() | |||
{ | |||
@@ -86,11 +98,22 @@ void* UI::getPluginInstancePointer() const noexcept | |||
} | |||
#endif | |||
#if DISTRHO_PLUGIN_HAS_EMBED_UI && DISTRHO_PLUGIN_HAS_EXTERNAL_UI | |||
/* ------------------------------------------------------------------------------------------------------------ | |||
* External embeddable UI helpers */ | |||
uintptr_t UI::getNextWindowId() noexcept | |||
{ | |||
return g_nextWindowId; | |||
} | |||
#endif | |||
/* ------------------------------------------------------------------------------------------------------------ | |||
* DSP/Plugin Callbacks (optional) */ | |||
void UI::sampleRateChanged(double) {} | |||
#ifdef HAVE_DGL | |||
/* ------------------------------------------------------------------------------------------------------------ | |||
* UI Callbacks (optional) */ | |||
@@ -117,6 +140,7 @@ void UI::onResize(const ResizeEvent& ev) | |||
{ | |||
pData->setSizeCallback(ev.size.getWidth(), ev.size.getHeight()); | |||
} | |||
#endif | |||
// ----------------------------------------------------------------------------------------------------------- | |||
@@ -1,6 +1,6 @@ | |||
/* | |||
* DISTRHO Plugin Framework (DPF) | |||
* Copyright (C) 2012-2015 Filipe Coelho <falktx@falktx.com> | |||
* Copyright (C) 2012-2016 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 | |||
@@ -18,21 +18,26 @@ | |||
#define DISTRHO_UI_INTERNAL_HPP_INCLUDED | |||
#include "../DistrhoUI.hpp" | |||
#include "../../dgl/Application.hpp" | |||
#include "../../dgl/Window.hpp" | |||
#ifdef HAVE_DGL | |||
# include "../../dgl/Application.hpp" | |||
# include "../../dgl/Window.hpp" | |||
using DGL::Application; | |||
using DGL::IdleCallback; | |||
using DGL::Window; | |||
#endif | |||
START_NAMESPACE_DISTRHO | |||
// ----------------------------------------------------------------------- | |||
// Static data, see DistrhoUI.cpp | |||
extern double d_lastUiSampleRate; | |||
extern void* d_lastUiDspPtr; | |||
extern Window* d_lastUiWindow; | |||
extern double d_lastUiSampleRate; | |||
extern void* d_lastUiDspPtr; | |||
#ifdef HAVE_DGL | |||
extern Window* d_lastUiWindow; | |||
#endif | |||
extern uintptr_t g_nextWindowId; | |||
// ----------------------------------------------------------------------- | |||
// UI callbacks | |||
@@ -128,6 +133,7 @@ struct UI::PrivateData { | |||
// ----------------------------------------------------------------------- | |||
// Plugin Window, needed to take care of resize properly | |||
#ifdef HAVE_DGL | |||
static inline | |||
UI* createUiWrapper(void* const dspPtr, Window* const window) | |||
{ | |||
@@ -191,6 +197,18 @@ private: | |||
UI* const fUI; | |||
bool fIsReady; | |||
}; | |||
#else | |||
static inline | |||
UI* createUiWrapper(void* const dspPtr, const uintptr_t winId) | |||
{ | |||
d_lastUiDspPtr = dspPtr; | |||
g_nextWindowId = winId; | |||
UI* const ret = createUI(); | |||
d_lastUiDspPtr = nullptr; | |||
g_nextWindowId = 0; | |||
return ret; | |||
} | |||
#endif | |||
// ----------------------------------------------------------------------- | |||
// UI exporter class | |||
@@ -201,10 +219,14 @@ public: | |||
UIExporter(void* const ptr, const intptr_t winId, | |||
const editParamFunc editParamCall, const setParamFunc setParamCall, const setStateFunc setStateCall, const sendNoteFunc sendNoteCall, const setSizeFunc setSizeCall, | |||
void* const dspPtr = nullptr) | |||
#ifdef HAVE_DGL | |||
: glApp(), | |||
glWindow(glApp, winId, dspPtr), | |||
fChangingSize(false), | |||
fUI(glWindow.getUI()), | |||
#else | |||
: fUI(createUiWrapper(dspPtr, winId)), | |||
#endif | |||
fData((fUI != nullptr) ? fUI->pData : nullptr) | |||
{ | |||
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,); | |||
@@ -222,24 +244,43 @@ public: | |||
uint getWidth() const noexcept | |||
{ | |||
#ifdef HAVE_DGL | |||
return glWindow.getWidth(); | |||
#else | |||
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr, 1); | |||
return fUI->getWidth(); | |||
#endif | |||
} | |||
uint getHeight() const noexcept | |||
{ | |||
#ifdef HAVE_DGL | |||
return glWindow.getHeight(); | |||
#else | |||
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr, 1); | |||
return fUI->getHeight(); | |||
#endif | |||
} | |||
bool isVisible() const noexcept | |||
{ | |||
#ifdef HAVE_DGL | |||
return glWindow.isVisible(); | |||
#else | |||
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr, false); | |||
return fUI->isRunning(); | |||
#endif | |||
} | |||
// ------------------------------------------------------------------- | |||
intptr_t getWindowId() const noexcept | |||
{ | |||
#ifdef HAVE_DGL | |||
return glWindow.getWindowId(); | |||
#else | |||
return 0; | |||
#endif | |||
} | |||
// ------------------------------------------------------------------- | |||
@@ -282,6 +323,7 @@ public: | |||
// ------------------------------------------------------------------- | |||
#ifdef HAVE_DGL | |||
void exec(IdleCallback* const cb) | |||
{ | |||
DISTRHO_SAFE_ASSERT_RETURN(cb != nullptr,); | |||
@@ -297,27 +339,48 @@ public: | |||
if (glWindow.isReady()) | |||
fUI->uiIdle(); | |||
} | |||
#endif | |||
bool idle() | |||
{ | |||
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr, false); | |||
#ifdef HAVE_DGL | |||
glApp.idle(); | |||
if (glWindow.isReady()) | |||
fUI->uiIdle(); | |||
return ! glApp.isQuiting(); | |||
#else | |||
return fUI->isRunning(); | |||
#endif | |||
} | |||
void quit() | |||
{ | |||
#ifdef HAVE_DGL | |||
glWindow.close(); | |||
glApp.quit(); | |||
#else | |||
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,); | |||
fUI->terminateAndWaitForProcess(); | |||
#endif | |||
} | |||
// ------------------------------------------------------------------- | |||
void setWindowTitle(const char* const uiTitle) | |||
{ | |||
#ifdef HAVE_DGL | |||
glWindow.setTitle(uiTitle); | |||
#else | |||
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,); | |||
fUI->setTitle(uiTitle); | |||
#endif | |||
} | |||
#ifdef HAVE_DGL | |||
void setWindowSize(const uint width, const uint height, const bool updateUI = false) | |||
{ | |||
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,); | |||
@@ -333,11 +396,6 @@ public: | |||
fChangingSize = false; | |||
} | |||
void setWindowTitle(const char* const uiTitle) | |||
{ | |||
glWindow.setTitle(uiTitle); | |||
} | |||
void setWindowTransientWinId(const uintptr_t winId) | |||
{ | |||
glWindow.setTransientWinId(winId); | |||
@@ -349,6 +407,11 @@ public: | |||
return ! glApp.isQuiting(); | |||
} | |||
#else | |||
void setWindowSize(const uint width, const uint height, const bool updateUI = false) {} | |||
void setWindowTransientWinId(const uintptr_t winId) {} | |||
bool setWindowVisible(const bool yesNo) { return true; } | |||
#endif | |||
// ------------------------------------------------------------------- | |||
@@ -368,6 +431,7 @@ public: | |||
} | |||
private: | |||
#ifdef HAVE_DGL | |||
// ------------------------------------------------------------------- | |||
// DGL Application and Window for this widget | |||
@@ -376,6 +440,7 @@ private: | |||
// prevent recursion | |||
bool fChangingSize; | |||
#endif | |||
// ------------------------------------------------------------------- | |||
// Widget and DistrhoUI data | |||
@@ -0,0 +1,13 @@ | |||
@prefix mod: <http://moddevices.com/ns/mod#>. | |||
@prefix modgui: <http://moddevices.com/ns/modgui#>. | |||
<http://distrho.sf.net/plugins/Nekobi> | |||
mod:brand "DISTRHO"; | |||
mod:label "Nekobi"; | |||
modgui:gui [ | |||
modgui:resourcesDirectory <modgui>; | |||
modgui:iconTemplate <modgui/icon-nekobi.html>; | |||
modgui:stylesheet <modgui/stylesheet-nekobi.css>; | |||
modgui:screenshot <modgui/screenshot-nekobi.png>; | |||
modgui:thumbnail <modgui/thumb-nekobi.png>; | |||
]. |
@@ -0,0 +1,57 @@ | |||
<div class="dpf-nekobi mod-pedal mod-pedal-boxy{{{cns}}}"> | |||
<div mod-role="drag-handle" class="mod-drag-handle"></div> | |||
<div class="mod-light on" mod-role="bypass-light"></div> | |||
<div class="mod-control-group clearfix"> | |||
<div class="mod-knob dpf-nekobi-knob_tuning"> | |||
<div class="mod-knob-image" mod-role="input-control-port" mod-port-symbol="tuning"></div> | |||
</div> | |||
<div class="mod-knob dpf-nekobi-knob_cutoff"> | |||
<div class="mod-knob-image" mod-role="input-control-port" mod-port-symbol="cutoff"></div> | |||
</div> | |||
<div class="mod-knob dpf-nekobi-knob_resonance"> | |||
<div class="mod-knob-image" mod-role="input-control-port" mod-port-symbol="resonance"></div> | |||
</div> | |||
<div class="mod-knob dpf-nekobi-knob_env_mod"> | |||
<div class="mod-knob-image" mod-role="input-control-port" mod-port-symbol="env_mod"></div> | |||
</div> | |||
<div class="mod-knob dpf-nekobi-knob_decay"> | |||
<div class="mod-knob-image" mod-role="input-control-port" mod-port-symbol="decay"></div> | |||
</div> | |||
<div class="mod-knob dpf-nekobi-knob_accent"> | |||
<div class="mod-knob-image" mod-role="input-control-port" mod-port-symbol="accent"></div> | |||
</div> | |||
<div class="mod-knob dpf-nekobi-knob_volume"> | |||
<div class="mod-knob-image" mod-role="input-control-port" mod-port-symbol="volume"></div> | |||
</div> | |||
<div class="mod-footswitch dpf-nekobi-knob_waveform" mod-role="input-control-port" mod-port-symbol="waveform"></div> | |||
</div> | |||
<div class="mod-footswitch" mod-role="bypass"></div> | |||
<div class="mod-pedal-input"> | |||
{{#effect.ports.audio.input}} | |||
<div class="mod-input mod-input-disconnected" title="{{name}}" mod-role="input-audio-port" mod-port-symbol="{{symbol}}"> | |||
<div class="mod-pedal-input-image"></div> | |||
</div> | |||
{{/effect.ports.audio.input}} | |||
{{#effect.ports.midi.input}} | |||
<div class="mod-input mod-input-disconnected" title="{{name}}" mod-role="input-midi-port" mod-port-symbol="{{symbol}}"> | |||
<div class="mod-pedal-input-image"></div> | |||
</div> | |||
{{/effect.ports.midi.input}} | |||
</div> | |||
<div class="mod-pedal-output"> | |||
{{#effect.ports.audio.output}} | |||
<div class="mod-output mod-output-disconnected" title="{{name}}" mod-role="output-audio-port" mod-port-symbol="{{symbol}}"> | |||
<div class="mod-pedal-output-image"></div> | |||
</div> | |||
{{/effect.ports.audio.output}} | |||
{{#effect.ports.midi.output}} | |||
<div class="mod-output mod-output-disconnected" title="{{name}}" mod-role="output-midi-port" mod-port-symbol="{{symbol}}"> | |||
<div class="mod-pedal-input-image"></div> | |||
</div> | |||
{{/effect.ports.midi.output}} | |||
</div> | |||
</div> |
@@ -0,0 +1,278 @@ | |||
/* STYLES FOR THE BOXY PEDAL */ | |||
@import url(/fonts/nexa/stylesheet.css); | |||
@import url(/fonts/questrial/stylesheet.css); | |||
/* = CONTAINER | |||
================================================ */ | |||
.mod-pedal-boxy{{{cns}}} { | |||
background-position:center center; | |||
background-repeat:no-repeat; | |||
background-size:954px 162px; | |||
width:954px; | |||
height:162px; | |||
position:absolute; | |||
border-radius: 0px; | |||
} | |||
/* = PLUGIN'S AUTHOR | |||
================================================ */ | |||
.mod-pedal-boxy{{{cns}}} .mod-plugin-brand { | |||
left:0; | |||
position:absolute; | |||
right:0; | |||
text-align:center; | |||
text-transform:uppercase; | |||
top:160px; | |||
} | |||
.mod-pedal-boxy{{{cns}}} .mod-plugin-brand h1 { | |||
border-color:#000; | |||
border-radius:12px; | |||
border-style:solid; | |||
border-width:4px; | |||
display:inline-block; | |||
font-family:"Nexa"; | |||
font-size:32px; | |||
padding:3px 9px 0; | |||
} | |||
/* = PLUGIN'S NAME | |||
================================================ */ | |||
.mod-pedal-boxy{{{cns}}} .mod-plugin-name { | |||
left:30px; | |||
overflow:hidden; | |||
position:absolute; | |||
right:30px; | |||
text-align:center; | |||
top:340px; | |||
} | |||
.mod-pedal-boxy{{{cns}}} .mod-plugin-name h1 { | |||
font-family:"Questrial"; | |||
font-size:21px; | |||
line-height:1; | |||
} | |||
/* = LIGHT ON/OFF | |||
================================================ */ | |||
.mod-pedal-boxy{{{cns}}} .mod-light { | |||
background-position:center center; | |||
background-repeat:no-repeat; | |||
height:32px; | |||
left:10px; | |||
position:absolute; | |||
right:10px; | |||
top:235px; | |||
} | |||
/* = KNOBS | |||
================================================ */ | |||
.mod-pedal-boxy{{{cns}}} .mod-control-group { | |||
margin:20px; | |||
position:relative; | |||
text-align:center; | |||
z-index:30; | |||
} | |||
.mod-pedal-boxy{{{cns}}} .mod-control-group .mod-knob { | |||
overflow:hidden; | |||
position:relative; | |||
} | |||
.mod-pedal-boxy{{{cns}}} .mod-control-group .mod-knob { | |||
height:110px; | |||
} | |||
.mod-pedal-boxy{{{cns}}} .mod-control-group .mod-knob > span.mod-knob-title { | |||
bottom:0px; | |||
display:block; | |||
font-size:11px; | |||
font-weight:bold; | |||
height:12px; | |||
left:0; | |||
line-height:1; | |||
margin:0; | |||
overflow:hidden; | |||
padding:0; | |||
position:absolute; | |||
right:0; | |||
text-transform:uppercase; | |||
} | |||
/* = ENUMERATED LIST | |||
================================================ */ | |||
.mod-pedal-boxy{{{cns}}} .mod-enumerated-group { | |||
height:31px; | |||
margin:20px auto 0 !important; | |||
position:relative; | |||
width:190px; | |||
z-index:35; | |||
} | |||
.mod-pedal-boxy{{{cns}}} .mod-enumerated { | |||
background-position:right center; | |||
background-repeat:no-repeat; | |||
font-size:11px; | |||
font-weight:bold; | |||
left:0; | |||
line-height:2; | |||
overflow:hidden; | |||
position:absolute; | |||
right:0; | |||
text-align:left; | |||
} | |||
.mod-pedal-boxy{{{cns}}} .mod-enumerated .mod-enumerated-selected { | |||
background-color:rgba(0,0,0,.3); | |||
box-shadow:inset 0 0 4px rgba(0,0,0,.3); | |||
border-radius:4px; | |||
padding:3px 9px; | |||
} | |||
.mod-pedal-boxy{{{cns}}} .mod-enumerated .mod-enumerated-selected { | |||
border-radius:4px 4px 0 0; | |||
} | |||
.mod-pedal-boxy{{{cns}}} .mod-enumerated .mod-enumerated-list { | |||
display:none; | |||
color:#fff; | |||
} | |||
.mod-pedal-boxy{{{cns}}} .mod-enumerated .mod-enumerated-list { | |||
background-color:rgba(0,0,0,.9); | |||
display:none; | |||
height:115px; | |||
overflow:auto; | |||
position:relative; | |||
} | |||
.mod-pedal-boxy{{{cns}}} .mod-enumerated .mod-enumerated-list > div { | |||
padding:3px 9px; | |||
} | |||
.mod-pedal-boxy{{{cns}}} .mod-enumerated .mod-enumerated-list > div:hover { | |||
background-color:rgba(255,255,255,.2); | |||
cursor:pointer; | |||
} | |||
/* STYLES FOR THE PLUGIN */ | |||
.dpf-nekobi * { | |||
color:black !important; | |||
} | |||
.dpf-nekobi { | |||
background-image:url(/resources/background.png{{{ns}}}) !important; | |||
background-size:954px 162px; | |||
width:954px; | |||
height:162px; | |||
border-radius: 0; | |||
} | |||
.dpf-nekobi .mod-control-group { | |||
width:821px; | |||
height:65px; | |||
top:68px; | |||
left:67px; | |||
margin:0px; | |||
} | |||
.dpf-nekobi .mod-control-group .mod-knob { | |||
height:65px !important; | |||
} | |||
.dpf-nekobi .mod-control-group .mod-knob .mod-knob-image { | |||
background-image:url(/resources/knob.png{{{ns}}}); | |||
background-position:left center; | |||
background-repeat:no-repeat; | |||
background-size:auto 65px; | |||
height:65px; | |||
width:65px; | |||
margin:0 auto; | |||
cursor:pointer; | |||
position:relative; | |||
overflow:hidden; | |||
} | |||
.dpf-nekobi .mod-control-group .dpf-nekobi-knob_tuning { | |||
left:0px; | |||
position:absolute; | |||
} | |||
.dpf-nekobi .mod-control-group .dpf-nekobi-knob_cutoff { | |||
left:215px; | |||
position:absolute; | |||
} | |||
.dpf-nekobi .mod-control-group .dpf-nekobi-knob_resonance { | |||
left:323px; | |||
position:absolute; | |||
} | |||
.dpf-nekobi .mod-control-group .dpf-nekobi-knob_env_mod { | |||
left:432px; | |||
position:absolute; | |||
} | |||
.dpf-nekobi .mod-control-group .dpf-nekobi-knob_decay { | |||
left:540px; | |||
position:absolute; | |||
} | |||
.dpf-nekobi .mod-control-group .dpf-nekobi-knob_accent { | |||
left:648px; | |||
position:absolute; | |||
} | |||
.dpf-nekobi .mod-control-group .dpf-nekobi-knob_volume { | |||
left:756px; | |||
position:absolute; | |||
} | |||
.dpf-nekobi .mod-light { | |||
background-position:top left; | |||
background-repeat:no-repeat; | |||
background-size:26px 27px; | |||
height:26px; | |||
width: 27px; | |||
top:12px; | |||
left:804px; | |||
} | |||
.dpf-nekobi .mod-light.on { | |||
background-image:url(/resources/led-on.png{{{ns}}}); | |||
} | |||
.dpf-nekobi .mod-light.off { | |||
background-image:url(/resources/led-off.png{{{ns}}}); | |||
} | |||
.dpf-nekobi .mod-footswitch { | |||
background-image:url(/resources/slider-horizontal.png{{{ns}}}); | |||
background-position:top left; | |||
background-repeat:no-repeat; | |||
background-size:156px 48px; | |||
top:3px; | |||
right:57px; | |||
cursor:pointer; | |||
height:48px; | |||
width: 78px; | |||
position:absolute; | |||
} | |||
.dpf-nekobi .mod-footswitch.on { | |||
background-position:top left; | |||
} | |||
.dpf-nekobi .mod-footswitch.off { | |||
background-position:top right; | |||
} | |||
.dpf-nekobi .dpf-nekobi-knob_waveform { | |||
background-image:url(/resources/slider-vertical.png{{{ns}}}); | |||
background-position:top left; | |||
background-repeat:no-repeat; | |||
background-size:78px 101px; | |||
top:-17px; | |||
left:136px; | |||
height:101px; | |||
cursor:pointer; | |||
width:39px; | |||
position:absolute; | |||
} | |||
.dpf-nekobi .dpf-nekobi-knob_waveform.on { | |||
background-position:top left; | |||
} | |||
.dpf-nekobi .dpf-nekobi-knob_waveform.off { | |||
background-position:top right; | |||
} | |||
.dpf-nekobi .mod-pedal-input , .dpf-nekobi .mod-pedal-output { | |||
top: 60px; | |||
} | |||
.dpf-nekobi .mod-pedal-input .mod-input , .dpf-nekobi .mod-pedal-output .mod-output { | |||
margin-bottom: 40px !important | |||
} |
@@ -1,7 +1,7 @@ | |||
<div class="pingpongpan mod-pedal mod-pedal-boxy{{{cns}}}"> | |||
<div mod-role="drag-handle" class="mod-drag-handle"></div> | |||
<div class="mod-light on" mod-role="bypass-light"></div> | |||
<div mod-role="bypass-light"></div> | |||
<div class="mod-control-group clearfix"> | |||
<div class="mod-knob pingpongpan-knob_freq"> | |||
@@ -9,10 +9,10 @@ | |||
.mod-pedal-boxy{{{cns}}} { | |||
background-position:center center; | |||
background-repeat:no-repeat; | |||
background-size:230px 431px; | |||
height:431px; | |||
background-size:385px 212px; | |||
width:385px; | |||
height:212px; | |||
position:absolute; | |||
width:230px; | |||
border-radius: 26px; | |||
} | |||
@@ -164,64 +164,61 @@ | |||
} | |||
.pingpongpan { | |||
background-image:url(/resources/background.png{{{ns}}}) !important; | |||
background-size:615px 344px; | |||
width:615px; | |||
height:344px; | |||
background-size:385px 212px; | |||
width:385px; | |||
height:212px; | |||
border-radius: 0; | |||
} | |||
.pingpongpan .mod-control-group { | |||
width:500px; | |||
height:220px; | |||
width:237px; | |||
height:85px; | |||
top:71px; | |||
left:73px; | |||
margin:0px; | |||
} | |||
.pingpongpan .mod-control-group .mod-knob { | |||
height:220px !important; | |||
height:85px !important; | |||
} | |||
.pingpongpan .mod-control-group .mod-knob .mod-knob-image { | |||
background-image:url(/resources/knob.png{{{ns}}}); | |||
background-position:left center; | |||
background-repeat:no-repeat; | |||
background-size:auto 220px; | |||
height:220px; | |||
width:220px; | |||
background-size:auto 85px; | |||
height:85px; | |||
width:85px; | |||
margin:0 auto; | |||
cursor:pointer; | |||
position:relative; | |||
overflow:hidden; | |||
} | |||
.pingpongpan .mod-control-group .pingpongpan-knob_freq { | |||
top:55px; | |||
left:58px; | |||
left:0px; | |||
position:absolute; | |||
} | |||
.pingpongpan .mod-control-group .pingpongpan-knob_width { | |||
top:55px; | |||
left:302px; | |||
left:152px; | |||
position:absolute; | |||
} | |||
.pingpongpan .mod-light { | |||
top:32px; | |||
left:320px; | |||
} | |||
.pingpongpan .mod-footswitch { | |||
background-image:url(/resources/footswitch.png{{{ns}}}); | |||
background-position:top center; | |||
background-image:url(/resources/slider.png{{{ns}}}); | |||
background-position:top left; | |||
background-repeat:no-repeat; | |||
background-size:auto 132px; | |||
top:15px; | |||
right:55px; | |||
background-size:120px 37px; | |||
top:5px; | |||
right:37px; | |||
cursor:pointer; | |||
height:66px; | |||
width: 66px; | |||
height:37px; | |||
width: 60px; | |||
position:absolute; | |||
} | |||
.pingpongpan .mod-footswitch.on { | |||
background-position:top center; | |||
background-position:top left; | |||
} | |||
.pingpongpan .mod-footswitch.off { | |||
background-position:bottom center; | |||
background-position:top right; | |||
} | |||
.pingpongpan .mod-pedal-input , .pingpongpan .mod-pedal-output { | |||
top: 60px; | |||
top: 30px; | |||
} | |||
.pingpongpan .mod-pedal-input .mod-input , .pingpongpan .mod-pedal-output .mod-output { | |||
margin-bottom: 40px !important | |||
@@ -27,5 +27,6 @@ | |||
#define DISTRHO_PLUGIN_IS_SYNTH 1 | |||
#define DISTRHO_PLUGIN_NUM_INPUTS 0 | |||
#define DISTRHO_PLUGIN_NUM_OUTPUTS 1 | |||
#define DISTRHO_PLUGIN_USES_MODGUI 1 | |||
#endif // DISTRHO_PLUGIN_INFO_H_INCLUDED |