commit 7f486d3836504874e1561dc4d46188b6ee637034
parent 34a62b6e284ce1009fbf2b27d366657a442ffcf7
Author: falkTX <falktx@falktx.com>
Date: Fri, 15 Jul 2022 00:04:27 +0100
Share VST2 and VST3 keycode handling and a few other things
Diffstat:
8 files changed, 518 insertions(+), 533 deletions(-)
diff --git a/distrho/src/DistrhoPluginInternal.hpp b/distrho/src/DistrhoPluginInternal.hpp
@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
- * Copyright (C) 2012-2021 Filipe Coelho <falktx@falktx.com>
+ * Copyright (C) 2012-2022 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,7 @@
#include "../DistrhoPlugin.hpp"
#ifdef DISTRHO_PLUGIN_TARGET_VST3
-# include "DistrhoPluginVST3.hpp"
+# include "DistrhoPluginVST.hpp"
#endif
#include <set>
diff --git a/distrho/src/DistrhoPluginVST.hpp b/distrho/src/DistrhoPluginVST.hpp
@@ -0,0 +1,421 @@
+/*
+ * DISTRHO Plugin Framework (DPF)
+ * Copyright (C) 2012-2022 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_PLUGIN_VST_HPP_INCLUDED
+#define DISTRHO_PLUGIN_VST_HPP_INCLUDED
+
+#include "DistrhoPluginChecks.h"
+#include "../DistrhoUtils.hpp"
+
+#include <algorithm>
+#include <cmath>
+
+#if DISTRHO_PLUGIN_HAS_UI && ! DISTRHO_PLUGIN_HAS_EMBED_UI
+# undef DISTRHO_PLUGIN_HAS_UI
+# define DISTRHO_PLUGIN_HAS_UI 0
+#endif
+
+#if DISTRHO_PLUGIN_HAS_UI && ! defined(HAVE_DGL) && ! DISTRHO_PLUGIN_HAS_EXTERNAL_UI
+# undef DISTRHO_PLUGIN_HAS_UI
+# define DISTRHO_PLUGIN_HAS_UI 0
+#endif
+
+#if DISTRHO_PLUGIN_HAS_UI && ! DISTRHO_PLUGIN_HAS_EXTERNAL_UI
+# include "Base.hpp"
+#endif
+
+#if DISTRHO_PLUGIN_HAS_UI == 1 && DISTRHO_PLUGIN_WANT_DIRECT_ACCESS == 0
+# define DPF_VST3_USES_SEPARATE_CONTROLLER 1
+#else
+# define DPF_VST3_USES_SEPARATE_CONTROLLER 0
+#endif
+
+// --------------------------------------------------------------------------------------------------------------------
+
+#ifdef DISTRHO_PROPER_CPP11_SUPPORT
+# include <atomic>
+#else
+// quick and dirty std::atomic replacement for the things we need
+namespace std {
+ struct atomic_int {
+ volatile int value;
+ explicit atomic_int(volatile int v) noexcept : value(v) {}
+ int operator++() volatile noexcept { return __atomic_add_fetch(&value, 1, __ATOMIC_RELAXED); }
+ int operator--() volatile noexcept { return __atomic_sub_fetch(&value, 1, __ATOMIC_RELAXED); }
+ operator int() volatile noexcept { return __atomic_load_n(&value, __ATOMIC_RELAXED); }
+ };
+};
+#endif
+
+// --------------------------------------------------------------------------------------------------------------------
+
+START_NAMESPACE_DISTRHO
+
+// --------------------------------------------------------------------------------------------------------------------
+
+enum Vst3InternalParameters {
+#if DPF_VST3_USES_SEPARATE_CONTROLLER
+ kVst3InternalParameterBufferSize,
+ kVst3InternalParameterSampleRate,
+#endif
+#if DISTRHO_PLUGIN_WANT_LATENCY
+ kVst3InternalParameterLatency,
+#endif
+#if DISTRHO_PLUGIN_WANT_PROGRAMS
+ kVst3InternalParameterProgram,
+#endif
+ kVst3InternalParameterBaseCount,
+#if DISTRHO_PLUGIN_WANT_MIDI_INPUT
+ kVst3InternalParameterMidiCC_start = kVst3InternalParameterBaseCount,
+ kVst3InternalParameterMidiCC_end = kVst3InternalParameterMidiCC_start + 130*16,
+ kVst3InternalParameterCount = kVst3InternalParameterMidiCC_end
+#else
+ kVst3InternalParameterCount = kVst3InternalParameterBaseCount
+#endif
+};
+
+#if DPF_VST3_USES_SEPARATE_CONTROLLER || DISTRHO_PLUGIN_WANT_LATENCY || DISTRHO_PLUGIN_WANT_PROGRAMS || DISTRHO_PLUGIN_WANT_MIDI_INPUT
+# define DPF_VST3_HAS_INTERNAL_PARAMETERS 1
+#else
+# define DPF_VST3_HAS_INTERNAL_PARAMETERS 0
+#endif
+
+#if DPF_VST3_HAS_INTERNAL_PARAMETERS && DISTRHO_PLUGIN_WANT_MIDI_INPUT && \
+ !(DPF_VST3_USES_SEPARATE_CONTROLLER || DISTRHO_PLUGIN_WANT_LATENCY || DISTRHO_PLUGIN_WANT_PROGRAMS)
+# define DPF_VST3_PURE_MIDI_INTERNAL_PARAMETERS 1
+#else
+# define DPF_VST3_PURE_MIDI_INTERNAL_PARAMETERS 0
+#endif
+
+// --------------------------------------------------------------------------------------------------------------------
+
+static inline
+bool strcmp_utf16(const int16_t* const str16, const char* const str8)
+{
+ size_t i = 0;
+ for (; str8[i] != '\0'; ++i)
+ {
+ const uint8_t char8 = static_cast<uint8_t>(str8[i]);
+
+ // skip non-ascii chars, unsupported
+ if (char8 >= 0x80)
+ return false;
+
+ if (str16[i] != char8)
+ return false;
+ }
+
+ return str16[i] == str8[i];
+}
+
+// --------------------------------------------------------------------------------------------------------------------
+
+static inline
+size_t strlen_utf16(const int16_t* const str)
+{
+ size_t i = 0;
+
+ while (str[i] != 0)
+ ++i;
+
+ return i;
+}
+
+// --------------------------------------------------------------------------------------------------------------------
+
+static inline
+void strncpy(char* const dst, const char* const src, const size_t length)
+{
+ DISTRHO_SAFE_ASSERT_RETURN(length > 0,);
+
+ if (const size_t len = std::min(std::strlen(src), length-1U))
+ {
+ std::memcpy(dst, src, len);
+ dst[len] = '\0';
+ }
+ else
+ {
+ dst[0] = '\0';
+ }
+}
+
+static inline
+void strncpy_utf8(char* const dst, const int16_t* const src, const size_t length)
+{
+ DISTRHO_SAFE_ASSERT_RETURN(length > 0,);
+
+ if (const size_t len = std::min(strlen_utf16(src), length-1U))
+ {
+ for (size_t i=0; i<len; ++i)
+ {
+ // skip non-ascii chars, unsupported
+ if (src[i] >= 0x80)
+ continue;
+
+ dst[i] = src[i];
+ }
+ dst[len] = 0;
+ }
+ else
+ {
+ dst[0] = 0;
+ }
+}
+
+static inline
+void strncpy_utf16(int16_t* const dst, const char* const src, const size_t length)
+{
+ DISTRHO_SAFE_ASSERT_RETURN(length > 0,);
+
+ if (const size_t len = std::min(std::strlen(src), length-1U))
+ {
+ for (size_t i=0; i<len; ++i)
+ {
+ // skip non-ascii chars, unsupported
+ if ((uint8_t)src[i] >= 0x80)
+ continue;
+
+ dst[i] = src[i];
+ }
+ dst[len] = 0;
+ }
+ else
+ {
+ dst[0] = 0;
+ }
+}
+
+// --------------------------------------------------------------------------------------------------------------------
+
+template<typename T>
+static void snprintf_t(char* const dst, const T value, const char* const format, const size_t size)
+{
+ DISTRHO_SAFE_ASSERT_RETURN(size > 0,);
+ std::snprintf(dst, size-1, format, value);
+ dst[size-1] = '\0';
+}
+
+template<typename T>
+static void snprintf_utf16_t(int16_t* const dst, const T value, const char* const format, const size_t size)
+{
+ DISTRHO_SAFE_ASSERT_RETURN(size > 0,);
+
+ char* const tmpbuf = (char*)std::malloc(size);
+ DISTRHO_SAFE_ASSERT_RETURN(tmpbuf != nullptr,);
+
+ std::snprintf(tmpbuf, size-1, format, value);
+ tmpbuf[size-1] = '\0';
+
+ strncpy_utf16(dst, tmpbuf, size);
+ std::free(tmpbuf);
+}
+
+static inline
+void snprintf_f32(char* const dst, const float value, const size_t size)
+{
+ return snprintf_t<float>(dst, value, "%f", size);
+}
+
+static inline
+void snprintf_i32(char* const dst, const int32_t value, const size_t size)
+{
+ return snprintf_t<int32_t>(dst, value, "%d", size);
+}
+
+static inline
+void snprintf_u32(char* const dst, const uint32_t value, const size_t size)
+{
+ return snprintf_t<uint32_t>(dst, value, "%u", size);
+}
+
+static inline
+void snprintf_f32_utf16(int16_t* const dst, const float value, const size_t size)
+{
+ return snprintf_utf16_t<float>(dst, value, "%f", size);
+}
+
+static inline
+void snprintf_i32_utf16(int16_t* const dst, const int32_t value, const size_t size)
+{
+ return snprintf_utf16_t<int32_t>(dst, value, "%d", size);
+}
+
+static inline
+void snprintf_u32_utf16(int16_t* const dst, const uint32_t value, const size_t size)
+{
+ return snprintf_utf16_t<uint32_t>(dst, value, "%u", size);
+}
+
+#if DISTRHO_PLUGIN_HAS_UI && ! DISTRHO_PLUGIN_HAS_EXTERNAL_UI
+// --------------------------------------------------------------------------------------------------------------------
+// translate a vstgui-based key character and code to matching values used by DPF
+
+static inline
+uint translateVstKeyCode(bool& special, const int16_t keychar, const int16_t keycode) noexcept
+{
+ using namespace DGL_NAMESPACE;
+
+ // special stuff first
+ special = true;
+ switch (keycode)
+ {
+ case 1: return kKeyBackspace;
+ // 2 \t (handled below)
+ // 3 clear
+ // 4 \r (handled below)
+ case 6: return kKeyEscape;
+ // 7 space (handled below)
+ // 8 next
+ // 17 select
+ // 18 print
+ // 19 \n (handled below)
+ // 20 snapshot
+ case 22: return kKeyDelete;
+ // 23 help
+ // 57 = (handled below)
+ // numpad stuff follows
+ // 24 0 (handled below)
+ // 25 1 (handled below)
+ // 26 2 (handled below)
+ // 27 3 (handled below)
+ // 28 4 (handled below)
+ // 29 5 (handled below)
+ // 30 6 (handled below)
+ // 31 7 (handled below)
+ // 32 8 (handled below)
+ // 33 9 (handled below)
+ // 34 * (handled below)
+ // 35 + (handled below)
+ // 36 separator
+ // 37 - (handled below)
+ // 38 . (handled below)
+ // 39 / (handled below)
+ // handle rest of special keys
+ /* these special keys are missing:
+ - kKeySuper
+ - kKeyCapsLock
+ - kKeyPrintScreen
+ */
+ case 40: return kKeyF1;
+ case 41: return kKeyF2;
+ case 42: return kKeyF3;
+ case 43: return kKeyF4;
+ case 44: return kKeyF5;
+ case 45: return kKeyF6;
+ case 46: return kKeyF7;
+ case 47: return kKeyF8;
+ case 48: return kKeyF9;
+ case 49: return kKeyF10;
+ case 50: return kKeyF11;
+ case 51: return kKeyF12;
+ case 11: return kKeyLeft;
+ case 12: return kKeyUp;
+ case 13: return kKeyRight;
+ case 14: return kKeyDown;
+ case 15: return kKeyPageUp;
+ case 16: return kKeyPageDown;
+ case 10: return kKeyHome;
+ case 9: return kKeyEnd;
+ case 21: return kKeyInsert;
+ case 54: return kKeyShift;
+ case 55: return kKeyControl;
+ case 56: return kKeyAlt;
+ case 58: return kKeyMenu;
+ case 52: return kKeyNumLock;
+ case 53: return kKeyScrollLock;
+ case 5: return kKeyPause;
+ }
+
+ // regular keys next
+ special = false;
+ switch (keycode)
+ {
+ case 2: return '\t';
+ case 4: return '\r';
+ case 7: return ' ';
+ case 19: return '\n';
+ case 57: return '=';
+ case 24: return '0';
+ case 25: return '1';
+ case 26: return '2';
+ case 27: return '3';
+ case 28: return '4';
+ case 29: return '5';
+ case 30: return '6';
+ case 31: return '7';
+ case 32: return '8';
+ case 33: return '9';
+ case 34: return '*';
+ case 35: return '+';
+ case 37: return '-';
+ case 38: return '.';
+ case 39: return '/';
+ }
+
+ // fallback
+ return keychar;
+}
+#endif
+
+// --------------------------------------------------------------------------------------------------------------------
+// handy way to create a utf16 string from a utf8 one on the current function scope, used for message strings
+
+struct ScopedUTF16String {
+ int16_t* str;
+ ScopedUTF16String(const char* const s) noexcept
+ : str(nullptr)
+ {
+ const size_t len = std::strlen(s);
+ str = static_cast<int16_t*>(std::malloc(sizeof(int16_t) * (len + 1)));
+ DISTRHO_SAFE_ASSERT_RETURN(str != nullptr,);
+ strncpy_utf16(str, s, len + 1);
+ }
+
+ ~ScopedUTF16String() noexcept
+ {
+ std::free(str);
+ }
+
+ operator const int16_t*() const noexcept
+ {
+ return str;
+ }
+};
+
+// --------------------------------------------------------------------------------------------------------------------
+// handy way to create a utf8 string from a utf16 one on the current function scope (limited to 128 chars)
+
+struct ScopedUTF8String {
+ char str[128];
+
+ ScopedUTF8String(const int16_t* const s) noexcept
+ {
+ strncpy_utf8(str, s, 128);
+ }
+
+ operator const char*() const noexcept
+ {
+ return str;
+ }
+};
+
+// --------------------------------------------------------------------------------------------------------------------
+
+END_NAMESPACE_DISTRHO
+
+// --------------------------------------------------------------------------------------------------------------------
+
+#endif // DISTRHO_PLUGIN_VST_HPP_INCLUDED
diff --git a/distrho/src/DistrhoPluginVST2.cpp b/distrho/src/DistrhoPluginVST2.cpp
@@ -15,20 +15,11 @@
*/
#include "DistrhoPluginInternal.hpp"
+#include "DistrhoPluginVST.hpp"
#include "../DistrhoPluginUtils.hpp"
#include "../extra/ScopedSafeLocale.hpp"
#include "../extra/ScopedPointer.hpp"
-#if DISTRHO_PLUGIN_HAS_UI && ! DISTRHO_PLUGIN_HAS_EMBED_UI
-# undef DISTRHO_PLUGIN_HAS_UI
-# define DISTRHO_PLUGIN_HAS_UI 0
-#endif
-
-#if DISTRHO_PLUGIN_HAS_UI && ! defined(HAVE_DGL) && ! DISTRHO_PLUGIN_HAS_EXTERNAL_UI
-# undef DISTRHO_PLUGIN_HAS_UI
-# define DISTRHO_PLUGIN_HAS_UI 0
-#endif
-
#if DISTRHO_PLUGIN_HAS_UI
# include "DistrhoUIInternal.hpp"
# include "../extra/RingBuffer.hpp"
@@ -85,37 +76,6 @@ static const requestParameterValueChangeFunc requestParameterValueChangeCallback
// -----------------------------------------------------------------------
-void strncpy(char* const dst, const char* const src, const size_t size)
-{
- DISTRHO_SAFE_ASSERT_RETURN(size > 0,);
-
- if (const size_t len = std::min(std::strlen(src), size-1U))
- {
- std::memcpy(dst, src, len);
- dst[len] = '\0';
- }
- else
- {
- dst[0] = '\0';
- }
-}
-
-void snprintf_param(char* const dst, const float value, const size_t size)
-{
- DISTRHO_SAFE_ASSERT_RETURN(size > 0,);
- std::snprintf(dst, size-1, "%f", value);
- dst[size-1] = '\0';
-}
-
-void snprintf_iparam(char* const dst, const int32_t value, const size_t size)
-{
- DISTRHO_SAFE_ASSERT_RETURN(size > 0,);
- std::snprintf(dst, size-1, "%d", value);
- dst[size-1] = '\0';
-}
-
-// -----------------------------------------------------------------------
-
struct ParameterAndNotesHelper
{
float* parameterValues;
@@ -257,85 +217,16 @@ public:
# endif
# if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI
- int handlePluginKeyEvent(const bool down, int32_t index, const intptr_t value)
+ int handlePluginKeyEvent(const bool down, const int32_t index, const intptr_t value)
{
d_stdout("handlePluginKeyEvent %i %i %li\n", down, index, (long int)value);
using namespace DGL_NAMESPACE;
- switch (value)
- {
- // convert some VST2 special values to normal keys
- case 1: index = kKeyBackspace; break;
- case 2: index = '\t'; break;
- // 3 clear
- case 4: index = '\r'; break;
- case 6: index = kKeyEscape; break;
- case 7: index = ' '; break;
- // 8 next
- // 17 select
- // 18 print
- case 19: index = '\n'; break;
- // 20 snapshot
- case 22: index = kKeyDelete; break;
- // 23 help
- case 57: index = '='; break;
-
- // numpad stuff follows
- case 24: index = '0'; break;
- case 25: index = '1'; break;
- case 26: index = '2'; break;
- case 27: index = '3'; break;
- case 28: index = '4'; break;
- case 29: index = '5'; break;
- case 30: index = '6'; break;
- case 31: index = '7'; break;
- case 32: index = '8'; break;
- case 33: index = '9'; break;
- case 34: index = '*'; break;
- case 35: index = '+'; break;
- // 36 separator
- case 37: index = '-'; break;
- case 38: index = '.'; break;
- case 39: index = '/'; break;
-
- // handle rest of special keys
- /* these special keys are missing:
- - kKeySuper
- - kKeyCapsLock
- - kKeyPrintScreen
- */
- case 40: index = kKeyF1; break;
- case 41: index = kKeyF2; break;
- case 42: index = kKeyF3; break;
- case 43: index = kKeyF4; break;
- case 44: index = kKeyF5; break;
- case 45: index = kKeyF6; break;
- case 46: index = kKeyF7; break;
- case 47: index = kKeyF8; break;
- case 48: index = kKeyF9; break;
- case 49: index = kKeyF10; break;
- case 50: index = kKeyF11; break;
- case 51: index = kKeyF12; break;
- case 11: index = kKeyLeft; break;
- case 12: index = kKeyUp; break;
- case 13: index = kKeyRight; break;
- case 14: index = kKeyDown; break;
- case 15: index = kKeyPageUp; break;
- case 16: index = kKeyPageDown; break;
- case 10: index = kKeyHome; break;
- case 9: index = kKeyEnd; break;
- case 21: index = kKeyInsert; break;
- case 54: index = kKeyShift; break;
- case 55: index = kKeyControl; break;
- case 56: index = kKeyAlt; break;
- case 58: index = kKeyMenu; break;
- case 52: index = kKeyNumLock; break;
- case 53: index = kKeyScrollLock; break;
- case 5: index = kKeyPause; break;
- }
+ bool special;
+ const uint key = translateVstKeyCode(special, index, static_cast<int32_t>(value));
- switch (index)
+ switch (key)
{
case kKeyShift:
if (down)
@@ -357,17 +248,9 @@ public:
break;
}
- if (index > 0)
- {
- // keyboard events must always be lowercase
- if (index >= 'A' && index <= 'Z')
- index += 'a' - 'A'; // A-Z -> a-z
-
- fUI.handlePluginKeyboardVST2(down, static_cast<uint>(index), fKeyboardModifiers);
- return 1;
- }
-
- return 0;
+ return fUI.handlePluginKeyboardVST(down, special, key,
+ value >= 0 ? static_cast<uint>(value) : 0,
+ fKeyboardModifiers) ? 1 : 0;
}
# endif // !DISTRHO_PLUGIN_HAS_EXTERNAL_UI
@@ -490,7 +373,7 @@ public:
fAudioMaster(audioMaster),
fEffect(effect)
{
- std::memset(fProgramName, 0, sizeof(char)*(32+1));
+ std::memset(fProgramName, 0, sizeof(fProgramName));
std::strcpy(fProgramName, "Default");
const uint32_t parameterCount = fPlugin.getParameterCount();
@@ -575,7 +458,7 @@ public:
case effSetProgramName:
if (char* const programName = (char*)ptr)
{
- DISTRHO_NAMESPACE::strncpy(fProgramName, programName, 32);
+ strncpy(fProgramName, programName, 32);
return 1;
}
break;
@@ -583,7 +466,7 @@ public:
case effGetProgramName:
if (char* const programName = (char*)ptr)
{
- DISTRHO_NAMESPACE::strncpy(programName, fProgramName, 24);
+ strncpy(programName, fProgramName, 24);
return 1;
}
break;
@@ -591,7 +474,7 @@ public:
case effGetProgramNameIndexed:
if (char* const programName = (char*)ptr)
{
- DISTRHO_NAMESPACE::strncpy(programName, fProgramName, 24);
+ strncpy(programName, fProgramName, 24);
return 1;
}
break;
@@ -621,14 +504,14 @@ public:
if (d_isNotEqual(value, enumValues.values[i].value))
continue;
- DISTRHO_NAMESPACE::strncpy((char*)ptr, enumValues.values[i].label.buffer(), 24);
+ strncpy((char*)ptr, enumValues.values[i].label.buffer(), 24);
return 1;
}
if (hints & kParameterIsInteger)
- DISTRHO_NAMESPACE::snprintf_iparam((char*)ptr, (int32_t)value, 24);
+ snprintf_i32((char*)ptr, (int32_t)value, 24);
else
- DISTRHO_NAMESPACE::snprintf_param((char*)ptr, value, 24);
+ snprintf_f32((char*)ptr, value, 24);
return 1;
}
@@ -1196,7 +1079,7 @@ private:
AEffect* const fEffect;
// Temporary data
- char fProgramName[32+1];
+ char fProgramName[32];
#if DISTRHO_PLUGIN_WANT_MIDI_INPUT
uint32_t fMidiEventCount;
@@ -1477,7 +1360,7 @@ static intptr_t vst_dispatcherCallback(AEffect* effect, int32_t opcode, int32_t
case effGetParamLabel:
if (ptr != nullptr && index < static_cast<int32_t>(sPlugin->getParameterCount()))
{
- DISTRHO_NAMESPACE::strncpy((char*)ptr, sPlugin->getParameterUnit(index), 8);
+ strncpy((char*)ptr, sPlugin->getParameterUnit(index), 8);
return 1;
}
return 0;
@@ -1487,9 +1370,9 @@ static intptr_t vst_dispatcherCallback(AEffect* effect, int32_t opcode, int32_t
{
const String& shortName(sPlugin->getParameterShortName(index));
if (shortName.isNotEmpty())
- DISTRHO_NAMESPACE::strncpy((char*)ptr, shortName, 16);
+ strncpy((char*)ptr, shortName, 16);
else
- DISTRHO_NAMESPACE::strncpy((char*)ptr, sPlugin->getParameterName(index), 16);
+ strncpy((char*)ptr, sPlugin->getParameterName(index), 16);
return 1;
}
return 0;
@@ -1502,17 +1385,17 @@ static intptr_t vst_dispatcherCallback(AEffect* effect, int32_t opcode, int32_t
memset(properties, 0, sizeof(VstParameterProperties));
// full name
- DISTRHO_NAMESPACE::strncpy(properties->label,
- sPlugin->getParameterName(index),
- sizeof(properties->label));
+ strncpy(properties->label,
+ sPlugin->getParameterName(index),
+ sizeof(properties->label));
// short name
const String& shortName(sPlugin->getParameterShortName(index));
if (shortName.isNotEmpty())
- DISTRHO_NAMESPACE::strncpy(properties->shortLabel,
- sPlugin->getParameterShortName(index),
- sizeof(properties->shortLabel));
+ strncpy(properties->shortLabel,
+ sPlugin->getParameterShortName(index),
+ sizeof(properties->shortLabel));
// parameter hints
const uint32_t hints = sPlugin->getParameterHints(index);
@@ -1551,9 +1434,9 @@ static intptr_t vst_dispatcherCallback(AEffect* effect, int32_t opcode, int32_t
if (portGroup.groupId == groupId)
{
properties->category = i + 1;
- DISTRHO_NAMESPACE::strncpy(properties->categoryLabel,
- portGroup.name.buffer(),
- sizeof(properties->categoryLabel));
+ strncpy(properties->categoryLabel,
+ portGroup.name.buffer(),
+ sizeof(properties->categoryLabel));
break;
}
}
@@ -1581,7 +1464,7 @@ static intptr_t vst_dispatcherCallback(AEffect* effect, int32_t opcode, int32_t
case effGetEffectName:
if (char* const cptr = (char*)ptr)
{
- DISTRHO_NAMESPACE::strncpy(cptr, sPlugin->getName(), 32);
+ strncpy(cptr, sPlugin->getName(), 32);
return 1;
}
return 0;
@@ -1589,7 +1472,7 @@ static intptr_t vst_dispatcherCallback(AEffect* effect, int32_t opcode, int32_t
case effGetVendorString:
if (char* const cptr = (char*)ptr)
{
- DISTRHO_NAMESPACE::strncpy(cptr, sPlugin->getMaker(), 32);
+ strncpy(cptr, sPlugin->getMaker(), 32);
return 1;
}
return 0;
@@ -1597,7 +1480,7 @@ static intptr_t vst_dispatcherCallback(AEffect* effect, int32_t opcode, int32_t
case effGetProductString:
if (char* const cptr = (char*)ptr)
{
- DISTRHO_NAMESPACE::strncpy(cptr, sPlugin->getLabel(), 32);
+ strncpy(cptr, sPlugin->getLabel(), 32);
return 1;
}
return 0;
diff --git a/distrho/src/DistrhoPluginVST3.cpp b/distrho/src/DistrhoPluginVST3.cpp
@@ -1019,22 +1019,22 @@ public:
buffer[sizeof(buffer)-1] = '\xff';
v3_result res;
- for (int32_t pos = 0, term = 0, read; term == 0; pos += read)
+ for (int32_t terminated = 0, read; terminated == 0;)
{
+ read = -1;
res = v3_cpp_obj(stream)->read(stream, buffer, sizeof(buffer)-1, &read);
DISTRHO_SAFE_ASSERT_INT_RETURN(res == V3_OK, res, res);
+ DISTRHO_SAFE_ASSERT_INT_RETURN(read > 0, read, V3_INTERNAL_ERR);
if (read == 0)
return V3_OK;
- DISTRHO_SAFE_ASSERT_INT_RETURN(read > 0, read, V3_INTERNAL_ERR);
-
for (int32_t i = 0; i < read; ++i)
{
// found terminator, stop here
if (buffer[i] == '\xfe')
{
- term = 1;
+ terminated = 1;
break;
}
@@ -1808,9 +1808,9 @@ public:
info->flags = V3_PARAM_CAN_AUTOMATE | V3_PARAM_IS_HIDDEN;
info->step_count = 127;
char ccstr[24];
- snprintf(ccstr, sizeof(ccstr)-1, "MIDI Ch. %d CC %d", static_cast<uint8_t>(index / 130) + 1, index % 130);
+ snprintf(ccstr, sizeof(ccstr), "MIDI Ch. %d CC %d", static_cast<uint8_t>(index / 130) + 1, index % 130);
strncpy_utf16(info->title, ccstr, 128);
- snprintf(ccstr, sizeof(ccstr)-1, "Ch.%d CC%d", index / 130 + 1, index % 130);
+ snprintf(ccstr, sizeof(ccstr), "Ch.%d CC%d", index / 130 + 1, index % 130);
strncpy_utf16(info->short_title, ccstr+5, 128);
return V3_OK;
}
@@ -4300,10 +4300,10 @@ static const char* getPluginVersion()
const uint32_t versionNum = getPluginInfo().getVersion();
char versionBuf[64];
- snprintf(versionBuf, sizeof(versionBuf)-1, "%d.%d.%d",
- (versionNum >> 16) & 0xff,
- (versionNum >> 8) & 0xff,
- (versionNum >> 0) & 0xff);
+ std::snprintf(versionBuf, sizeof(versionBuf)-1, "%d.%d.%d",
+ (versionNum >> 16) & 0xff,
+ (versionNum >> 8) & 0xff,
+ (versionNum >> 0) & 0xff);
versionBuf[sizeof(versionBuf)-1] = '\0';
version = versionBuf;
}
diff --git a/distrho/src/DistrhoPluginVST3.hpp b/distrho/src/DistrhoPluginVST3.hpp
@@ -1,288 +0,0 @@
-/*
- * DISTRHO Plugin Framework (DPF)
- * Copyright (C) 2012-2021 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_PLUGIN_VST3_HPP_INCLUDED
-#define DISTRHO_PLUGIN_VST3_HPP_INCLUDED
-
-#include "DistrhoPluginChecks.h"
-#include "../DistrhoUtils.hpp"
-
-#include <algorithm>
-#include <cmath>
-
-#if DISTRHO_PLUGIN_HAS_UI && ! DISTRHO_PLUGIN_HAS_EMBED_UI
-# undef DISTRHO_PLUGIN_HAS_UI
-# define DISTRHO_PLUGIN_HAS_UI 0
-#endif
-
-#if DISTRHO_PLUGIN_HAS_UI && ! defined(HAVE_DGL) && ! DISTRHO_PLUGIN_HAS_EXTERNAL_UI
-# undef DISTRHO_PLUGIN_HAS_UI
-# define DISTRHO_PLUGIN_HAS_UI 0
-#endif
-
-#if DISTRHO_PLUGIN_HAS_UI == 1 && DISTRHO_PLUGIN_WANT_DIRECT_ACCESS == 0
-# define DPF_VST3_USES_SEPARATE_CONTROLLER 1
-#else
-# define DPF_VST3_USES_SEPARATE_CONTROLLER 0
-#endif
-
-// --------------------------------------------------------------------------------------------------------------------
-
-#ifdef DISTRHO_PROPER_CPP11_SUPPORT
-# include <atomic>
-#else
-// quick and dirty std::atomic replacement for the things we need
-namespace std {
- struct atomic_int {
- volatile int value;
- explicit atomic_int(volatile int v) noexcept : value(v) {}
- int operator++() volatile noexcept { return __atomic_add_fetch(&value, 1, __ATOMIC_RELAXED); }
- int operator--() volatile noexcept { return __atomic_sub_fetch(&value, 1, __ATOMIC_RELAXED); }
- operator int() volatile noexcept { return __atomic_load_n(&value, __ATOMIC_RELAXED); }
- };
-};
-#endif
-
-// --------------------------------------------------------------------------------------------------------------------
-
-START_NAMESPACE_DISTRHO
-
-// --------------------------------------------------------------------------------------------------------------------
-
-enum Vst3InternalParameters {
-#if DPF_VST3_USES_SEPARATE_CONTROLLER
- kVst3InternalParameterBufferSize,
- kVst3InternalParameterSampleRate,
-#endif
-#if DISTRHO_PLUGIN_WANT_LATENCY
- kVst3InternalParameterLatency,
-#endif
-#if DISTRHO_PLUGIN_WANT_PROGRAMS
- kVst3InternalParameterProgram,
-#endif
- kVst3InternalParameterBaseCount,
-#if DISTRHO_PLUGIN_WANT_MIDI_INPUT
- kVst3InternalParameterMidiCC_start = kVst3InternalParameterBaseCount,
- kVst3InternalParameterMidiCC_end = kVst3InternalParameterMidiCC_start + 130*16,
- kVst3InternalParameterCount = kVst3InternalParameterMidiCC_end
-#else
- kVst3InternalParameterCount = kVst3InternalParameterBaseCount
-#endif
-};
-
-#if DPF_VST3_USES_SEPARATE_CONTROLLER || DISTRHO_PLUGIN_WANT_LATENCY || DISTRHO_PLUGIN_WANT_PROGRAMS || DISTRHO_PLUGIN_WANT_MIDI_INPUT
-# define DPF_VST3_HAS_INTERNAL_PARAMETERS 1
-#else
-# define DPF_VST3_HAS_INTERNAL_PARAMETERS 0
-#endif
-
-#if DPF_VST3_HAS_INTERNAL_PARAMETERS && DISTRHO_PLUGIN_WANT_MIDI_INPUT && \
- !(DPF_VST3_USES_SEPARATE_CONTROLLER || DISTRHO_PLUGIN_WANT_LATENCY || DISTRHO_PLUGIN_WANT_PROGRAMS)
-# define DPF_VST3_PURE_MIDI_INTERNAL_PARAMETERS 1
-#else
-# define DPF_VST3_PURE_MIDI_INTERNAL_PARAMETERS 0
-#endif
-
-// --------------------------------------------------------------------------------------------------------------------
-
-static inline
-bool strcmp_utf16(const int16_t* const str16, const char* const str8)
-{
- size_t i = 0;
- for (; str8[i] != '\0'; ++i)
- {
- const uint8_t char8 = static_cast<uint8_t>(str8[i]);
-
- // skip non-ascii chars, unsupported
- if (char8 >= 0x80)
- return false;
-
- if (str16[i] != char8)
- return false;
- }
-
- return str16[i] == str8[i];
-}
-
-// --------------------------------------------------------------------------------------------------------------------
-
-static inline
-size_t strlen_utf16(const int16_t* const str)
-{
- size_t i = 0;
-
- while (str[i] != 0)
- ++i;
-
- return i;
-}
-
-// --------------------------------------------------------------------------------------------------------------------
-
-static inline
-void strncpy(char* const dst, const char* const src, const size_t length)
-{
- DISTRHO_SAFE_ASSERT_RETURN(length > 0,);
-
- if (const size_t len = std::min(std::strlen(src), length-1U))
- {
- std::memcpy(dst, src, len);
- dst[len] = '\0';
- }
- else
- {
- dst[0] = '\0';
- }
-}
-
-static inline
-void strncpy_utf8(char* const dst, const int16_t* const src, const size_t length)
-{
- DISTRHO_SAFE_ASSERT_RETURN(length > 0,);
-
- if (const size_t len = std::min(strlen_utf16(src), length-1U))
- {
- for (size_t i=0; i<len; ++i)
- {
- // skip non-ascii chars, unsupported
- if (src[i] >= 0x80)
- continue;
-
- dst[i] = src[i];
- }
- dst[len] = 0;
- }
- else
- {
- dst[0] = 0;
- }
-}
-
-static inline
-void strncpy_utf16(int16_t* const dst, const char* const src, const size_t length)
-{
- DISTRHO_SAFE_ASSERT_RETURN(length > 0,);
-
- if (const size_t len = std::min(std::strlen(src), length-1U))
- {
- for (size_t i=0; i<len; ++i)
- {
- // skip non-ascii chars, unsupported
- if ((uint8_t)src[i] >= 0x80)
- continue;
-
- dst[i] = src[i];
- }
- dst[len] = 0;
- }
- else
- {
- dst[0] = 0;
- }
-}
-
-// --------------------------------------------------------------------------------------------------------------------
-
-template<typename T>
-static void snprintf_t(char* const dst, const T value, const char* const format, const size_t size)
-{
- DISTRHO_SAFE_ASSERT_RETURN(size > 0,);
- std::snprintf(dst, size-1, format, value);
- dst[size-1] = '\0';
-}
-
-template<typename T>
-static void snprintf_utf16_t(int16_t* const dst, const T value, const char* const format, const size_t size)
-{
- DISTRHO_SAFE_ASSERT_RETURN(size > 0,);
-
- char* const tmpbuf = (char*)std::malloc(size);
- DISTRHO_SAFE_ASSERT_RETURN(tmpbuf != nullptr,);
-
- std::snprintf(tmpbuf, size-1, format, value);
- tmpbuf[size-1] = '\0';
-
- strncpy_utf16(dst, tmpbuf, size);
- std::free(tmpbuf);
-}
-
-static inline
-void snprintf_u32(char* const dst, const uint32_t value, const size_t size)
-{
- return snprintf_t<uint32_t>(dst, value, "%u", size);
-}
-
-static inline
-void snprintf_f32_utf16(int16_t* const dst, const float value, const size_t size)
-{
- return snprintf_utf16_t<float>(dst, value, "%f", size);
-}
-
-static inline
-void snprintf_i32_utf16(int16_t* const dst, const int value, const size_t size)
-{
- return snprintf_utf16_t<int>(dst, value, "%d", size);
-}
-
-// --------------------------------------------------------------------------------------------------------------------
-// handy way to create a utf16 string from a utf8 one on the current function scope, used for message strings
-
-struct ScopedUTF16String {
- int16_t* str;
- ScopedUTF16String(const char* const s) noexcept
- : str(nullptr)
- {
- const size_t len = std::strlen(s);
- str = static_cast<int16_t*>(std::malloc(sizeof(int16_t) * (len + 1)));
- DISTRHO_SAFE_ASSERT_RETURN(str != nullptr,);
- strncpy_utf16(str, s, len + 1);
- }
-
- ~ScopedUTF16String() noexcept
- {
- std::free(str);
- }
-
- operator const int16_t*() const noexcept
- {
- return str;
- }
-};
-
-// --------------------------------------------------------------------------------------------------------------------
-// handy way to create a utf8 string from a utf16 one on the current function scope (limited to 128 chars)
-
-struct ScopedUTF8String {
- char str[128];
-
- ScopedUTF8String(const int16_t* const s) noexcept
- {
- strncpy_utf8(str, s, 128);
- }
-
- operator const char*() const noexcept
- {
- return str;
- }
-};
-
-// --------------------------------------------------------------------------------------------------------------------
-
-END_NAMESPACE_DISTRHO
-
-// --------------------------------------------------------------------------------------------------------------------
-
-#endif // DISTRHO_PLUGIN_VST3_HPP_INCLUDED
diff --git a/distrho/src/DistrhoUIInternal.hpp b/distrho/src/DistrhoUIInternal.hpp
@@ -329,31 +329,7 @@ public:
}
#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI
- bool handlePluginKeyboardVST2(const bool press, const uint key, const uint16_t mods)
- {
- DGL_NAMESPACE::Widget::KeyboardEvent ev;
- ev.mod = mods;
- ev.press = press;
- ev.key = key;
-
- const bool ret = ui->onKeyboard(ev);
-
- if (! press)
- return ret;
-
- DGL_NAMESPACE::Widget::CharacterInputEvent cev;
- cev.mod = mods;
- cev.character = key;
-
- // if shift modifier is on, convert a-z -> A-Z for character input
- if (key >= 'a' && key <= 'z' && (mods & DGL_NAMESPACE::kModifierShift) != 0)
- cev.character -= 'a' - 'A';
-
- ui->onCharacterInput(cev);
- return ret;
- }
-
- bool handlePluginKeyboardVST3(const bool press, const uint keychar, const uint keycode, const uint16_t mods)
+ bool handlePluginKeyboardVST(const bool press, const bool special, const uint keychar, const uint keycode, const uint16_t mods)
{
DGL_NAMESPACE::Widget::KeyboardEvent ev;
ev.mod = mods;
@@ -361,21 +337,26 @@ public:
ev.key = keychar;
ev.keycode = keycode;
+ // keyboard events must always be lowercase
+ if (ev.key >= 'A' && ev.key <= 'Z')
+ ev.key += 'a' - 'A'; // A-Z -> a-z
+
const bool ret = ui->onKeyboard(ev);
- if (! press)
- return ret;
+ if (press && !special && (mods & (kModifierControl|kModifierAlt|kModifierSuper)) == 0x0)
+ {
+ DGL_NAMESPACE::Widget::CharacterInputEvent cev;
+ cev.mod = mods;
+ cev.character = keychar;
+ cev.keycode = keycode;
- DGL_NAMESPACE::Widget::CharacterInputEvent cev;
- cev.mod = mods;
- cev.keycode = keycode;
- cev.character = keychar;
+ // if shift modifier is on, convert a-z -> A-Z for character input
+ if (cev.character >= 'a' && cev.character <= 'z' && (mods & DGL_NAMESPACE::kModifierShift) != 0)
+ cev.character -= 'a' - 'A';
- // if shift modifier is on, convert a-z -> A-Z for character input
- if (keychar >= 'a' && keychar <= 'z' && (mods & DGL_NAMESPACE::kModifierShift) != 0)
- cev.character -= 'a' - 'A';
+ ui->onCharacterInput(cev);
+ }
- ui->onCharacterInput(cev);
return ret;
}
#endif
diff --git a/distrho/src/DistrhoUIPrivateData.hpp b/distrho/src/DistrhoUIPrivateData.hpp
@@ -20,7 +20,7 @@
#include "../DistrhoUI.hpp"
#ifdef DISTRHO_PLUGIN_TARGET_VST3
-# include "DistrhoPluginVST3.hpp"
+# include "DistrhoPluginVST.hpp"
#endif
#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI
diff --git a/distrho/src/DistrhoUIVST3.cpp b/distrho/src/DistrhoUIVST3.cpp
@@ -32,7 +32,6 @@
/* TODO items:
* - mousewheel event
- * - key down/up events
* - file request?
*/
@@ -106,6 +105,31 @@ static void applyGeometryConstraints(const uint minimumWidth,
// --------------------------------------------------------------------------------------------------------------------
+#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI
+static uint translateVST3Modifiers(const int64_t modifiers) noexcept
+{
+ uint dglmods = 0;
+ if (modifiers & (1 << 0))
+ dglmods |= kModifierShift;
+ if (modifiers & (1 << 1))
+ dglmods |= kModifierAlt;
+ #ifdef DISTRHO_OS_MAC
+ if (modifiers & (1 << 2))
+ dglmods |= kModifierSuper;
+ if (modifiers & (1 << 3))
+ dglmods |= kModifierControl;
+ #else
+ if (modifiers & (1 << 2))
+ dglmods |= kModifierControl;
+ if (modifiers & (1 << 3))
+ dglmods |= kModifierSuper;
+ #endif
+ return dglmods;
+}
+#endif
+
+// --------------------------------------------------------------------------------------------------------------------
+
/**
* Helper class for getting a native idle timer, either through pugl or via native APIs.
*/
@@ -330,64 +354,28 @@ public:
v3_result onKeyDown(const int16_t keychar, const int16_t keycode, const int16_t modifiers)
{
- d_stdout("onKeyDown %i %i %x\n", keychar, keycode, modifiers);
DISTRHO_SAFE_ASSERT_INT_RETURN(keychar >= 0 && keychar < 0x7f, keychar, V3_FALSE);
- using namespace DGL_NAMESPACE;
+ bool special;
+ const uint key = translateVstKeyCode(special, keychar, keycode);
+ d_debug("onKeyDown %d %d %x -> %d %d", keychar, keycode, modifiers, special, key);
- // TODO
- uint dglcode = 0;
-
- // TODO verify these
- uint dglmods = 0;
- if (modifiers & (1 << 0))
- dglmods |= kModifierShift;
- if (modifiers & (1 << 1))
- dglmods |= kModifierAlt;
- #ifdef DISTRHO_OS_MAC
- if (modifiers & (1 << 2))
- dglmods |= kModifierSuper;
- if (modifiers & (1 << 3))
- dglmods |= kModifierControl;
- #else
- if (modifiers & (1 << 2))
- dglmods |= kModifierControl;
- if (modifiers & (1 << 3))
- dglmods |= kModifierSuper;
- #endif
-
- return fUI.handlePluginKeyboardVST3(true, static_cast<uint>(keychar), dglcode, dglmods) ? V3_TRUE : V3_FALSE;
+ return fUI.handlePluginKeyboardVST(true, special, key,
+ keycode >= 0 ? static_cast<uint>(keycode) : 0,
+ translateVST3Modifiers(modifiers)) ? V3_TRUE : V3_FALSE;
}
v3_result onKeyUp(const int16_t keychar, const int16_t keycode, const int16_t modifiers)
{
- d_stdout("onKeyDown %i %i %x\n", keychar, keycode, modifiers);
DISTRHO_SAFE_ASSERT_INT_RETURN(keychar >= 0 && keychar < 0x7f, keychar, V3_FALSE);
- using namespace DGL_NAMESPACE;
-
- // TODO
- uint dglcode = 0;
-
- // TODO verify these
- uint dglmods = 0;
- if (modifiers & (1 << 0))
- dglmods |= kModifierShift;
- if (modifiers & (1 << 1))
- dglmods |= kModifierAlt;
- #ifdef DISTRHO_OS_MAC
- if (modifiers & (1 << 2))
- dglmods |= kModifierSuper;
- if (modifiers & (1 << 3))
- dglmods |= kModifierControl;
- #else
- if (modifiers & (1 << 2))
- dglmods |= kModifierControl;
- if (modifiers & (1 << 3))
- dglmods |= kModifierSuper;
- #endif
+ bool special;
+ const uint key = translateVstKeyCode(special, keychar, keycode);
+ d_debug("onKeyUp %d %d %x -> %d %d", keychar, keycode, modifiers, special, key);
- return fUI.handlePluginKeyboardVST3(false, static_cast<uint>(keychar), dglcode, dglmods) ? V3_TRUE : V3_FALSE;
+ return fUI.handlePluginKeyboardVST(false, special, key,
+ keycode >= 0 ? static_cast<uint>(keycode) : 0,
+ translateVST3Modifiers(modifiers)) ? V3_TRUE : V3_FALSE;
}
v3_result onFocus(const bool state)