Browse Source

Move common vst3 code to new file; Skip params for shared controller

Signed-off-by: falkTX <falktx@falktx.com>
pull/357/head
falkTX 3 years ago
parent
commit
431d330d87
Signed by: falkTX <falktx@falktx.com> GPG Key ID: CDBAA37ABC74FBA0
6 changed files with 340 additions and 349 deletions
  1. +4
    -22
      distrho/src/DistrhoPluginInternal.hpp
  2. +56
    -280
      distrho/src/DistrhoPluginVST3.cpp
  3. +275
    -0
      distrho/src/DistrhoPluginVST3.hpp
  4. +4
    -22
      distrho/src/DistrhoUIPrivateData.hpp
  5. +0
    -23
      distrho/src/DistrhoUIVST3.cpp
  6. +1
    -2
      examples/CVPort/Makefile

+ 4
- 22
distrho/src/DistrhoPluginInternal.hpp View File

@@ -19,6 +19,10 @@


#include "../DistrhoPlugin.hpp" #include "../DistrhoPlugin.hpp"


#ifdef DISTRHO_PLUGIN_TARGET_VST3
# include "DistrhoPluginVST3.hpp"
#endif

#include <set> #include <set>


START_NAMESPACE_DISTRHO START_NAMESPACE_DISTRHO
@@ -81,28 +85,6 @@ static void fillInPredefinedPortGroupData(const uint32_t groupId, PortGroup& por
} }
} }


// #ifdef DISTRHO_PLUGIN_TARGET_VST3
enum Vst3InternalParameters {
kVst3InternalParameterActive = 0,
kVst3InternalParameterBufferSize,
kVst3InternalParameterSampleRate,
# 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
};
// #endif

// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
// Plugin private data // Plugin private data




+ 56
- 280
distrho/src/DistrhoPluginVST3.cpp View File

@@ -18,20 +18,6 @@
#include "../DistrhoPluginUtils.hpp" #include "../DistrhoPluginUtils.hpp"
#include "../extra/ScopedPointer.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 == 1 && DISTRHO_PLUGIN_WANT_DIRECT_ACCESS == 0
# define DPF_VST3_USES_SEPARATE_CONTROLLER
#endif

#define DPF_VST3_MAX_BUFFER_SIZE 32768 #define DPF_VST3_MAX_BUFFER_SIZE 32768
#define DPF_VST3_MAX_SAMPLE_RATE 384000 #define DPF_VST3_MAX_SAMPLE_RATE 384000
#define DPF_VST3_MAX_LATENCY DPF_VST3_MAX_SAMPLE_RATE * 10 #define DPF_VST3_MAX_LATENCY DPF_VST3_MAX_SAMPLE_RATE * 10
@@ -46,21 +32,6 @@
#include "travesty/factory.h" #include "travesty/factory.h"
#include "travesty/host.h" #include "travesty/host.h"


#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

#include <map> #include <map>
#include <string> #include <string>
#include <vector> #include <vector>
@@ -71,8 +42,6 @@ namespace std {
* - have parameter outputs host-provided UI working in at least 1 host * - have parameter outputs host-provided UI working in at least 1 host
* - parameter groups via unit ids * - parameter groups via unit ids
* - test parameter changes from DSP (aka requestParameterValueChange) * - test parameter changes from DSP (aka requestParameterValueChange)
* - how to hide parameter outputs?
* - how to hide program parameter?
* - test receiving midi CC * - test receiving midi CC
* - implement getParameterNormalized/setParameterNormalized for MIDI CC params ? * - implement getParameterNormalized/setParameterNormalized for MIDI CC params ?
* - fully implemented parameter stuff and verify * - fully implemented parameter stuff and verify
@@ -241,190 +210,6 @@ const char* tuid2str(const v3_tuid iid)
return buf; return buf;
} }


// --------------------------------------------------------------------------------------------------------------------

static 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 size_t strlen_utf16(const int16_t* const str)
{
size_t i = 0;

while (str[i] != 0)
++i;

return i;
}

// --------------------------------------------------------------------------------------------------------------------

static 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';
}
}

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

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;
~ScopedUTF16String() noexcept;
operator const int16_t*() const noexcept;
};

// --------------------------------------------------------------------------------------------------------------------

ScopedUTF16String::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::~ScopedUTF16String() noexcept
{
std::free(str);
}

ScopedUTF16String::operator const int16_t*() const noexcept
{
return str;
}

// --------------------------------------------------------------------------------------------------------------------
// handy way to create a utf8 string from a utf16 one on the current function scope

struct ScopedUTF8String {
char str[128];

ScopedUTF8String(const int16_t* const s) noexcept
{
strncpy_utf8(str, s, 128);
}

operator const char*() const noexcept
{
return str;
}
};

// -------------------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------------------
// dpf_plugin_view_create (implemented on UI side) // dpf_plugin_view_create (implemented on UI side)


@@ -469,7 +254,7 @@ public:
: fPlugin(this, writeMidiCallback, requestParameterValueChangeCallback), : fPlugin(this, writeMidiCallback, requestParameterValueChangeCallback),
fComponentHandler(nullptr), fComponentHandler(nullptr),
#if DISTRHO_PLUGIN_HAS_UI #if DISTRHO_PLUGIN_HAS_UI
# ifdef DPF_VST3_USES_SEPARATE_CONTROLLER
# if DPF_VST3_USES_SEPARATE_CONTROLLER
fConnectionFromCompToCtrl(nullptr), fConnectionFromCompToCtrl(nullptr),
# endif # endif
fConnectionFromCtrlToView(nullptr), fConnectionFromCtrlToView(nullptr),
@@ -563,9 +348,10 @@ public:
{ {
fCachedParameterValues = new float[extraParameterCount]; fCachedParameterValues = new float[extraParameterCount];


fCachedParameterValues[kVst3InternalParameterActive] = 0.0f;
#if DPF_VST3_USES_SEPARATE_CONTROLLER
fCachedParameterValues[kVst3InternalParameterBufferSize] = fPlugin.getBufferSize(); fCachedParameterValues[kVst3InternalParameterBufferSize] = fPlugin.getBufferSize();
fCachedParameterValues[kVst3InternalParameterSampleRate] = fPlugin.getSampleRate(); fCachedParameterValues[kVst3InternalParameterSampleRate] = fPlugin.getSampleRate();
#endif
#if DISTRHO_PLUGIN_WANT_LATENCY #if DISTRHO_PLUGIN_WANT_LATENCY
fCachedParameterValues[kVst3InternalParameterLatency] = fLastKnownLatency; fCachedParameterValues[kVst3InternalParameterLatency] = fLastKnownLatency;
#endif #endif
@@ -1243,11 +1029,13 @@ public:
fPlugin.setSampleRate(setup->sample_rate, true); fPlugin.setSampleRate(setup->sample_rate, true);
fPlugin.setBufferSize(setup->max_block_size, true); fPlugin.setBufferSize(setup->max_block_size, true);


#if DPF_VST3_USES_SEPARATE_CONTROLLER
fCachedParameterValues[kVst3InternalParameterBufferSize] = setup->max_block_size; fCachedParameterValues[kVst3InternalParameterBufferSize] = setup->max_block_size;
fParameterValuesChangedDuringProcessing[kVst3InternalParameterBufferSize] = true; fParameterValuesChangedDuringProcessing[kVst3InternalParameterBufferSize] = true;


fCachedParameterValues[kVst3InternalParameterSampleRate] = setup->sample_rate; fCachedParameterValues[kVst3InternalParameterSampleRate] = setup->sample_rate;
fParameterValuesChangedDuringProcessing[kVst3InternalParameterSampleRate] = true; fParameterValuesChangedDuringProcessing[kVst3InternalParameterSampleRate] = true;
#endif
#if DISTRHO_PLUGIN_HAS_UI #if DISTRHO_PLUGIN_HAS_UI
fParameterValueChangesForUI[kVst3InternalParameterSampleRate] = true; fParameterValueChangesForUI[kVst3InternalParameterSampleRate] = true;
#endif #endif
@@ -1272,8 +1060,6 @@ public:
fPlugin.deactivateIfNeeded(); fPlugin.deactivateIfNeeded();
} }


fCachedParameterValues[kVst3InternalParameterActive] = processing ? 1.0f : 0.0f;
fParameterValuesChangedDuringProcessing[kVst3InternalParameterActive] = true;
return V3_OK; return V3_OK;
} }


@@ -1608,12 +1394,7 @@ public:


switch (rindex) switch (rindex)
{ {
case kVst3InternalParameterActive:
info->flags = V3_PARAM_READ_ONLY | V3_PARAM_IS_HIDDEN;
info->step_count = 1;
strncpy_utf16(info->title, "Active", 128);
strncpy_utf16(info->short_title, "Active", 128);
return V3_OK;
#if DPF_VST3_USES_SEPARATE_CONTROLLER
case kVst3InternalParameterBufferSize: case kVst3InternalParameterBufferSize:
info->flags = V3_PARAM_READ_ONLY | V3_PARAM_IS_HIDDEN; info->flags = V3_PARAM_READ_ONLY | V3_PARAM_IS_HIDDEN;
info->step_count = DPF_VST3_MAX_BUFFER_SIZE - 1; info->step_count = DPF_VST3_MAX_BUFFER_SIZE - 1;
@@ -1627,6 +1408,7 @@ public:
strncpy_utf16(info->short_title, "Sample Rate", 128); strncpy_utf16(info->short_title, "Sample Rate", 128);
strncpy_utf16(info->units, "frames", 128); strncpy_utf16(info->units, "frames", 128);
return V3_OK; return V3_OK;
#endif
#if DISTRHO_PLUGIN_WANT_LATENCY #if DISTRHO_PLUGIN_WANT_LATENCY
case kVst3InternalParameterLatency: case kVst3InternalParameterLatency:
info->flags = V3_PARAM_READ_ONLY | V3_PARAM_IS_HIDDEN; info->flags = V3_PARAM_READ_ONLY | V3_PARAM_IS_HIDDEN;
@@ -1714,15 +1496,14 @@ public:


switch (rindex) switch (rindex)
{ {
case kVst3InternalParameterActive:
strncpy_utf16(output, normalized > 0.5 ? "On" : "Off", 128);
return V3_OK;
#if DPF_VST3_USES_SEPARATE_CONTROLLER
case kVst3InternalParameterBufferSize: case kVst3InternalParameterBufferSize:
snprintf_i32_utf16(output, static_cast<int>(normalized * DPF_VST3_MAX_BUFFER_SIZE + 0.5), 128); snprintf_i32_utf16(output, static_cast<int>(normalized * DPF_VST3_MAX_BUFFER_SIZE + 0.5), 128);
return V3_OK; return V3_OK;
case kVst3InternalParameterSampleRate: case kVst3InternalParameterSampleRate:
snprintf_f32_utf16(output, std::round(normalized * DPF_VST3_MAX_SAMPLE_RATE), 128); snprintf_f32_utf16(output, std::round(normalized * DPF_VST3_MAX_SAMPLE_RATE), 128);
return V3_OK; return V3_OK;
#endif
#if DISTRHO_PLUGIN_WANT_LATENCY #if DISTRHO_PLUGIN_WANT_LATENCY
case kVst3InternalParameterLatency: case kVst3InternalParameterLatency:
snprintf_f32_utf16(output, std::round(normalized * DPF_VST3_MAX_LATENCY), 128); snprintf_f32_utf16(output, std::round(normalized * DPF_VST3_MAX_LATENCY), 128);
@@ -1783,15 +1564,14 @@ public:
{ {
switch (rindex) switch (rindex)
{ {
case kVst3InternalParameterActive:
*output = strcmp_utf16(input, "On") ? 1.0 : 0.0;
return V3_OK;
#if DPF_VST3_USES_SEPARATE_CONTROLLER
case kVst3InternalParameterBufferSize: case kVst3InternalParameterBufferSize:
*output = static_cast<double>(std::atoi(ScopedUTF8String(input))) / DPF_VST3_MAX_BUFFER_SIZE; *output = static_cast<double>(std::atoi(ScopedUTF8String(input))) / DPF_VST3_MAX_BUFFER_SIZE;
return V3_OK; return V3_OK;
case kVst3InternalParameterSampleRate: case kVst3InternalParameterSampleRate:
*output = std::atof(ScopedUTF8String(input)) / DPF_VST3_MAX_SAMPLE_RATE; *output = std::atof(ScopedUTF8String(input)) / DPF_VST3_MAX_SAMPLE_RATE;
return V3_OK; return V3_OK;
#endif
#if DISTRHO_PLUGIN_WANT_LATENCY #if DISTRHO_PLUGIN_WANT_LATENCY
case kVst3InternalParameterLatency: case kVst3InternalParameterLatency:
*output = std::atof(ScopedUTF8String(input)) / DPF_VST3_MAX_LATENCY; *output = std::atof(ScopedUTF8String(input)) / DPF_VST3_MAX_LATENCY;
@@ -1852,12 +1632,12 @@ public:


switch (rindex) switch (rindex)
{ {
case kVst3InternalParameterActive:
return normalized > 0.5 ? 1.0 : 0.0;
#if DPF_VST3_USES_SEPARATE_CONTROLLER
case kVst3InternalParameterBufferSize: case kVst3InternalParameterBufferSize:
return std::round(normalized * DPF_VST3_MAX_BUFFER_SIZE); return std::round(normalized * DPF_VST3_MAX_BUFFER_SIZE);
case kVst3InternalParameterSampleRate: case kVst3InternalParameterSampleRate:
return normalized * DPF_VST3_MAX_SAMPLE_RATE; return normalized * DPF_VST3_MAX_SAMPLE_RATE;
#endif
#if DISTRHO_PLUGIN_WANT_LATENCY #if DISTRHO_PLUGIN_WANT_LATENCY
case kVst3InternalParameterLatency: case kVst3InternalParameterLatency:
return normalized * DPF_VST3_MAX_LATENCY; return normalized * DPF_VST3_MAX_LATENCY;
@@ -1897,12 +1677,12 @@ public:
{ {
switch (rindex) switch (rindex)
{ {
case kVst3InternalParameterActive:
return plain;
#if DPF_VST3_USES_SEPARATE_CONTROLLER
case kVst3InternalParameterBufferSize: case kVst3InternalParameterBufferSize:
return std::max(0.0, std::min(1.0, plain / DPF_VST3_MAX_BUFFER_SIZE)); return std::max(0.0, std::min(1.0, plain / DPF_VST3_MAX_BUFFER_SIZE));
case kVst3InternalParameterSampleRate: case kVst3InternalParameterSampleRate:
return std::max(0.0, std::min(1.0, plain / DPF_VST3_MAX_SAMPLE_RATE)); return std::max(0.0, std::min(1.0, plain / DPF_VST3_MAX_SAMPLE_RATE));
#endif
#if DISTRHO_PLUGIN_WANT_LATENCY #if DISTRHO_PLUGIN_WANT_LATENCY
case kVst3InternalParameterLatency: case kVst3InternalParameterLatency:
return std::max(0.0, std::min(1.0, plain / DPF_VST3_MAX_LATENCY)); return std::max(0.0, std::min(1.0, plain / DPF_VST3_MAX_LATENCY));
@@ -1933,11 +1713,13 @@ public:
return 0.0; return 0.0;
#endif #endif


#if DPF_VST3_USES_SEPARATE_CONTROLLER || DISTRHO_PLUGIN_WANT_LATENCY || DISTRHO_PLUGIN_WANT_PROGRAMS
switch (rindex) switch (rindex)
{ {
case kVst3InternalParameterActive:
#if DPF_VST3_USES_SEPARATE_CONTROLLER
case kVst3InternalParameterBufferSize: case kVst3InternalParameterBufferSize:
case kVst3InternalParameterSampleRate: case kVst3InternalParameterSampleRate:
#endif
#if DISTRHO_PLUGIN_WANT_LATENCY #if DISTRHO_PLUGIN_WANT_LATENCY
case kVst3InternalParameterLatency: case kVst3InternalParameterLatency:
#endif #endif
@@ -1946,6 +1728,7 @@ public:
#endif #endif
return plainParameterToNormalized(rindex, fCachedParameterValues[rindex]); return plainParameterToNormalized(rindex, fCachedParameterValues[rindex]);
} }
#endif


const uint32_t index = static_cast<uint32_t>(rindex - kVst3InternalParameterCount); const uint32_t index = static_cast<uint32_t>(rindex - kVst3InternalParameterCount);
DISTRHO_SAFE_ASSERT_UINT2_RETURN(index < fParameterCount, index, fParameterCount, 0.0); DISTRHO_SAFE_ASSERT_UINT2_RETURN(index < fParameterCount, index, fParameterCount, 0.0);
@@ -1971,23 +1754,14 @@ public:


switch (rindex) switch (rindex)
{ {
case kVst3InternalParameterActive:
if (fCachedParameterValues[rindex] > 0.5f)
{
if (! fPlugin.isActive())
fPlugin.activate();
}
else
{
fPlugin.deactivateIfNeeded();
}
break;
#if DPF_VST3_USES_SEPARATE_CONTROLLER
case kVst3InternalParameterBufferSize: case kVst3InternalParameterBufferSize:
fPlugin.setBufferSize(fCachedParameterValues[rindex], true); fPlugin.setBufferSize(fCachedParameterValues[rindex], true);
break; break;
case kVst3InternalParameterSampleRate: case kVst3InternalParameterSampleRate:
fPlugin.setSampleRate(fCachedParameterValues[rindex], true); fPlugin.setSampleRate(fCachedParameterValues[rindex], true);
break; break;
#endif
#if DISTRHO_PLUGIN_WANT_LATENCY #if DISTRHO_PLUGIN_WANT_LATENCY
case kVst3InternalParameterLatency: case kVst3InternalParameterLatency:
flags = V3_RESTART_LATENCY_CHANGED; flags = V3_RESTART_LATENCY_CHANGED;
@@ -2019,10 +1793,12 @@ public:
return V3_OK; return V3_OK;
} }


#if DPF_VST3_USES_SEPARATE_CONTROLLER
const uint32_t index = static_cast<uint32_t>(rindex - kVst3InternalParameterCount); const uint32_t index = static_cast<uint32_t>(rindex - kVst3InternalParameterCount);
DISTRHO_SAFE_ASSERT_UINT2_RETURN(index < fParameterCount, index, fParameterCount, V3_INVALID_ARG); DISTRHO_SAFE_ASSERT_UINT2_RETURN(index < fParameterCount, index, fParameterCount, V3_INVALID_ARG);


setNormalizedPluginParameterValue(index, normalized); setNormalizedPluginParameterValue(index, normalized);
#endif
return V3_OK; return V3_OK;
} }


@@ -2036,7 +1812,7 @@ public:
// ---------------------------------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------------------------------
// v3_connection_point interface calls // v3_connection_point interface calls


#ifdef DPF_VST3_USES_SEPARATE_CONTROLLER
#if DPF_VST3_USES_SEPARATE_CONTROLLER
void comp2ctrl_connect(v3_connection_point** const other) void comp2ctrl_connect(v3_connection_point** const other)
{ {
fConnectionFromCompToCtrl = other; fConnectionFromCompToCtrl = other;
@@ -2230,7 +2006,7 @@ public:
#if DISTRHO_PLUGIN_WANT_MIDI_INPUT #if DISTRHO_PLUGIN_WANT_MIDI_INPUT
if (std::strcmp(msgid, "midi") == 0) if (std::strcmp(msgid, "midi") == 0)
{ {
#ifdef DPF_VST3_USES_SEPARATE_CONTROLLER
#if DPF_VST3_USES_SEPARATE_CONTROLLER
DISTRHO_SAFE_ASSERT_RETURN(fConnectionFromCompToCtrl != nullptr, V3_INTERNAL_ERR); DISTRHO_SAFE_ASSERT_RETURN(fConnectionFromCompToCtrl != nullptr, V3_INTERNAL_ERR);
return v3_cpp_obj(fConnectionFromCompToCtrl)->notify(fConnectionFromCompToCtrl, message); return v3_cpp_obj(fConnectionFromCompToCtrl)->notify(fConnectionFromCompToCtrl, message);
#else #else
@@ -2242,7 +2018,7 @@ public:
#if DISTRHO_PLUGIN_WANT_STATE #if DISTRHO_PLUGIN_WANT_STATE
if (std::strcmp(msgid, "state-set") == 0) if (std::strcmp(msgid, "state-set") == 0)
{ {
#ifdef DPF_VST3_USES_SEPARATE_CONTROLLER
#if DPF_VST3_USES_SEPARATE_CONTROLLER
DISTRHO_SAFE_ASSERT_RETURN(fConnectionFromCompToCtrl != nullptr, V3_INTERNAL_ERR); DISTRHO_SAFE_ASSERT_RETURN(fConnectionFromCompToCtrl != nullptr, V3_INTERNAL_ERR);
return v3_cpp_obj(fConnectionFromCompToCtrl)->notify(fConnectionFromCompToCtrl, message); return v3_cpp_obj(fConnectionFromCompToCtrl)->notify(fConnectionFromCompToCtrl, message);
#else #else
@@ -2352,7 +2128,7 @@ private:
// VST3 stuff // VST3 stuff
v3_component_handler** fComponentHandler; v3_component_handler** fComponentHandler;
#if DISTRHO_PLUGIN_HAS_UI #if DISTRHO_PLUGIN_HAS_UI
#ifdef DPF_VST3_USES_SEPARATE_CONTROLLER
#if DPF_VST3_USES_SEPARATE_CONTROLLER
v3_connection_point** fConnectionFromCompToCtrl; v3_connection_point** fConnectionFromCompToCtrl;
#endif #endif
v3_connection_point** fConnectionFromCtrlToView; v3_connection_point** fConnectionFromCtrlToView;
@@ -2401,7 +2177,8 @@ private:
v3_param_id paramId; v3_param_id paramId;
float curValue; float curValue;


for (v3_param_id i=kVst3InternalParameterActive; i<=kVst3InternalParameterSampleRate; ++i)
#if DPF_VST3_USES_SEPARATE_CONTROLLER
for (v3_param_id i=kVst3InternalParameterBufferSize; i<=kVst3InternalParameterSampleRate; ++i)
{ {
if (! fParameterValuesChangedDuringProcessing[i]) if (! fParameterValuesChangedDuringProcessing[i])
continue; continue;
@@ -2410,6 +2187,7 @@ private:
fParameterValuesChangedDuringProcessing[i] = false; fParameterValuesChangedDuringProcessing[i] = false;
addParameterDataToHostOutputEvents(outparamsptr, i, curValue); addParameterDataToHostOutputEvents(outparamsptr, i, curValue);
} }
#endif


for (uint32_t i=0; i<fParameterCount; ++i) for (uint32_t i=0; i<fParameterCount; ++i)
{ {
@@ -2685,7 +2463,7 @@ static uint32_t handleUncleanComponent(dpf_component** const componentptr)
return 0; return 0;
} }


#ifdef DPF_VST3_USES_SEPARATE_CONTROLLER
#if DPF_VST3_USES_SEPARATE_CONTROLLER
// -------------------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------------------
// Store controllers that we can't delete properly, to be cleaned up on module unload // Store controllers that we can't delete properly, to be cleaned up on module unload


@@ -2951,7 +2729,7 @@ struct dpf_edit_controller : v3_edit_controller_cpp {
#if DISTRHO_PLUGIN_HAS_UI #if DISTRHO_PLUGIN_HAS_UI
ScopedPointer<dpf_ctrl2view_connection_point> connectionCtrl2View; ScopedPointer<dpf_ctrl2view_connection_point> connectionCtrl2View;
#endif #endif
#ifdef DPF_VST3_USES_SEPARATE_CONTROLLER
#if DPF_VST3_USES_SEPARATE_CONTROLLER
ScopedPointer<dpf_comp2ctrl_connection_point> connectionComp2Ctrl; ScopedPointer<dpf_comp2ctrl_connection_point> connectionComp2Ctrl;
ScopedPointer<PluginVst3> vst3; ScopedPointer<PluginVst3> vst3;
#else #else
@@ -2961,12 +2739,12 @@ struct dpf_edit_controller : v3_edit_controller_cpp {
// cached values // cached values
v3_component_handler** handler; v3_component_handler** handler;
v3_host_application** const hostApplicationFromFactory; v3_host_application** const hostApplicationFromFactory;
#ifndef DPF_VST3_USES_SEPARATE_CONTROLLER
#if !DPF_VST3_USES_SEPARATE_CONTROLLER
v3_host_application** const hostApplicationFromComponent; v3_host_application** const hostApplicationFromComponent;
#endif #endif
v3_host_application** hostApplicationFromInitialize; v3_host_application** hostApplicationFromInitialize;


#ifdef DPF_VST3_USES_SEPARATE_CONTROLLER
#if DPF_VST3_USES_SEPARATE_CONTROLLER
dpf_edit_controller(v3_host_application** const hostApp) dpf_edit_controller(v3_host_application** const hostApp)
: refcounter(1), : refcounter(1),
vst3(nullptr), vst3(nullptr),
@@ -2978,7 +2756,7 @@ struct dpf_edit_controller : v3_edit_controller_cpp {
#endif #endif
handler(nullptr), handler(nullptr),
hostApplicationFromFactory(hostApp), hostApplicationFromFactory(hostApp),
#ifndef DPF_VST3_USES_SEPARATE_CONTROLLER
#if !DPF_VST3_USES_SEPARATE_CONTROLLER
hostApplicationFromComponent(hostComp), hostApplicationFromComponent(hostComp),
#endif #endif
hostApplicationFromInitialize(nullptr) hostApplicationFromInitialize(nullptr)
@@ -2988,7 +2766,7 @@ struct dpf_edit_controller : v3_edit_controller_cpp {
// make sure host application is valid through out this controller lifetime // make sure host application is valid through out this controller lifetime
if (hostApplicationFromFactory != nullptr) if (hostApplicationFromFactory != nullptr)
v3_cpp_obj_ref(hostApplicationFromFactory); v3_cpp_obj_ref(hostApplicationFromFactory);
#ifndef DPF_VST3_USES_SEPARATE_CONTROLLER
#if !DPF_VST3_USES_SEPARATE_CONTROLLER
if (hostApplicationFromComponent != nullptr) if (hostApplicationFromComponent != nullptr)
v3_cpp_obj_ref(hostApplicationFromComponent); v3_cpp_obj_ref(hostApplicationFromComponent);
#endif #endif
@@ -3024,12 +2802,12 @@ struct dpf_edit_controller : v3_edit_controller_cpp {
#if DISTRHO_PLUGIN_HAS_UI #if DISTRHO_PLUGIN_HAS_UI
connectionCtrl2View = nullptr; connectionCtrl2View = nullptr;
#endif #endif
#ifdef DPF_VST3_USES_SEPARATE_CONTROLLER
#if DPF_VST3_USES_SEPARATE_CONTROLLER
connectionComp2Ctrl = nullptr; connectionComp2Ctrl = nullptr;
vst3 = nullptr; vst3 = nullptr;
#endif #endif


#ifndef DPF_VST3_USES_SEPARATE_CONTROLLER
#if !DPF_VST3_USES_SEPARATE_CONTROLLER
if (hostApplicationFromComponent != nullptr) if (hostApplicationFromComponent != nullptr)
v3_cpp_obj_unref(hostApplicationFromComponent); v3_cpp_obj_unref(hostApplicationFromComponent);
#endif #endif
@@ -3065,7 +2843,7 @@ struct dpf_edit_controller : v3_edit_controller_cpp {
} }
#endif #endif


#ifdef DPF_VST3_USES_SEPARATE_CONTROLLER
#if DPF_VST3_USES_SEPARATE_CONTROLLER
if (v3_tuid_match(iid, v3_connection_point_iid)) if (v3_tuid_match(iid, v3_connection_point_iid))
{ {
d_stdout("query_interface_edit_controller => %p %s %p | OK convert %p", d_stdout("query_interface_edit_controller => %p %s %p | OK convert %p",
@@ -3105,7 +2883,7 @@ struct dpf_edit_controller : v3_edit_controller_cpp {
return refcount; return refcount;
} }


#ifdef DPF_VST3_USES_SEPARATE_CONTROLLER
#if DPF_VST3_USES_SEPARATE_CONTROLLER
/** /**
* Some hosts will have unclean instances of a few of the controller child classes at this point. * Some hosts will have unclean instances of a few of the controller child classes at this point.
* We check for those here, going through the whole possible chain to see if it is safe to delete. * We check for those here, going through the whole possible chain to see if it is safe to delete.
@@ -3144,7 +2922,7 @@ struct dpf_edit_controller : v3_edit_controller_cpp {
dpf_edit_controller* const controller = *static_cast<dpf_edit_controller**>(self); dpf_edit_controller* const controller = *static_cast<dpf_edit_controller**>(self);


// check if already initialized // check if already initialized
#ifdef DPF_VST3_USES_SEPARATE_CONTROLLER
#if DPF_VST3_USES_SEPARATE_CONTROLLER
DISTRHO_SAFE_ASSERT_RETURN(controller->vst3 == nullptr, V3_INVALID_ARG); DISTRHO_SAFE_ASSERT_RETURN(controller->vst3 == nullptr, V3_INVALID_ARG);
#else #else
DISTRHO_SAFE_ASSERT_RETURN(! controller->initialized, V3_INVALID_ARG); DISTRHO_SAFE_ASSERT_RETURN(! controller->initialized, V3_INVALID_ARG);
@@ -3160,7 +2938,7 @@ struct dpf_edit_controller : v3_edit_controller_cpp {
// save it for later so we can unref it // save it for later so we can unref it
controller->hostApplicationFromInitialize = hostApplication; controller->hostApplicationFromInitialize = hostApplication;


#ifdef DPF_VST3_USES_SEPARATE_CONTROLLER
#if DPF_VST3_USES_SEPARATE_CONTROLLER
// provide the factory application to the plugin if this new one is missing // provide the factory application to the plugin if this new one is missing
if (hostApplication == nullptr) if (hostApplication == nullptr)
hostApplication = controller->hostApplicationFromFactory; hostApplication = controller->hostApplicationFromFactory;
@@ -3195,7 +2973,7 @@ struct dpf_edit_controller : v3_edit_controller_cpp {
d_stdout("dpf_edit_controller::terminate => %p", self); d_stdout("dpf_edit_controller::terminate => %p", self);
dpf_edit_controller* const controller = *static_cast<dpf_edit_controller**>(self); dpf_edit_controller* const controller = *static_cast<dpf_edit_controller**>(self);


#ifdef DPF_VST3_USES_SEPARATE_CONTROLLER
#if DPF_VST3_USES_SEPARATE_CONTROLLER
// check if already terminated // check if already terminated
DISTRHO_SAFE_ASSERT_RETURN(controller->vst3 != nullptr, V3_INVALID_ARG); DISTRHO_SAFE_ASSERT_RETURN(controller->vst3 != nullptr, V3_INVALID_ARG);


@@ -3226,7 +3004,7 @@ struct dpf_edit_controller : v3_edit_controller_cpp {
{ {
d_stdout("dpf_edit_controller::set_component_state => %p %p", self, stream); d_stdout("dpf_edit_controller::set_component_state => %p %p", self, stream);


#ifdef DPF_VST3_USES_SEPARATE_CONTROLLER
#if DPF_VST3_USES_SEPARATE_CONTROLLER
dpf_edit_controller* const controller = *static_cast<dpf_edit_controller**>(self); dpf_edit_controller* const controller = *static_cast<dpf_edit_controller**>(self);


PluginVst3* const vst3 = controller->vst3; PluginVst3* const vst3 = controller->vst3;
@@ -3246,7 +3024,7 @@ struct dpf_edit_controller : v3_edit_controller_cpp {
{ {
d_stdout("dpf_edit_controller::set_state => %p %p", self, stream); d_stdout("dpf_edit_controller::set_state => %p %p", self, stream);


#ifdef DPF_VST3_USES_SEPARATE_CONTROLLER
#if DPF_VST3_USES_SEPARATE_CONTROLLER
dpf_edit_controller* const controller = *static_cast<dpf_edit_controller**>(self); dpf_edit_controller* const controller = *static_cast<dpf_edit_controller**>(self);
DISTRHO_SAFE_ASSERT_RETURN(controller->vst3 != nullptr, V3_NOT_INITIALIZED); DISTRHO_SAFE_ASSERT_RETURN(controller->vst3 != nullptr, V3_NOT_INITIALIZED);
#endif #endif
@@ -3262,7 +3040,7 @@ struct dpf_edit_controller : v3_edit_controller_cpp {
{ {
d_stdout("dpf_edit_controller::get_state => %p %p", self, stream); d_stdout("dpf_edit_controller::get_state => %p %p", self, stream);


#ifdef DPF_VST3_USES_SEPARATE_CONTROLLER
#if DPF_VST3_USES_SEPARATE_CONTROLLER
dpf_edit_controller* const controller = *static_cast<dpf_edit_controller**>(self); dpf_edit_controller* const controller = *static_cast<dpf_edit_controller**>(self);
DISTRHO_SAFE_ASSERT_RETURN(controller->vst3 != nullptr, V3_NOT_INITIALIZED); DISTRHO_SAFE_ASSERT_RETURN(controller->vst3 != nullptr, V3_NOT_INITIALIZED);
#endif #endif
@@ -3396,7 +3174,7 @@ struct dpf_edit_controller : v3_edit_controller_cpp {
// we require a host application for message creation // we require a host application for message creation
v3_host_application** const host = controller->hostApplicationFromInitialize != nullptr v3_host_application** const host = controller->hostApplicationFromInitialize != nullptr
? controller->hostApplicationFromInitialize ? controller->hostApplicationFromInitialize
#ifndef DPF_VST3_USES_SEPARATE_CONTROLLER
#if !DPF_VST3_USES_SEPARATE_CONTROLLER
: controller->hostApplicationFromComponent != nullptr : controller->hostApplicationFromComponent != nullptr
? controller->hostApplicationFromComponent ? controller->hostApplicationFromComponent
#endif #endif
@@ -3646,7 +3424,7 @@ struct dpf_audio_processor : v3_audio_processor_cpp {
struct dpf_component : v3_component_cpp { struct dpf_component : v3_component_cpp {
std::atomic_int refcounter; std::atomic_int refcounter;
ScopedPointer<dpf_audio_processor> processor; ScopedPointer<dpf_audio_processor> processor;
#ifdef DPF_VST3_USES_SEPARATE_CONTROLLER
#if DPF_VST3_USES_SEPARATE_CONTROLLER
ScopedPointer<dpf_comp2ctrl_connection_point> connectionComp2Ctrl; ScopedPointer<dpf_comp2ctrl_connection_point> connectionComp2Ctrl;
#else #else
ScopedPointer<dpf_edit_controller> controller; ScopedPointer<dpf_edit_controller> controller;
@@ -3691,7 +3469,7 @@ struct dpf_component : v3_component_cpp {
{ {
d_stdout("~dpf_component()"); d_stdout("~dpf_component()");
processor = nullptr; processor = nullptr;
#ifdef DPF_VST3_USES_SEPARATE_CONTROLLER
#if DPF_VST3_USES_SEPARATE_CONTROLLER
connectionComp2Ctrl = nullptr; connectionComp2Ctrl = nullptr;
#else #else
controller = nullptr; controller = nullptr;
@@ -3743,7 +3521,7 @@ struct dpf_component : v3_component_cpp {
return V3_OK; return V3_OK;
} }


#ifdef DPF_VST3_USES_SEPARATE_CONTROLLER
#if DPF_VST3_USES_SEPARATE_CONTROLLER
if (v3_tuid_match(iid, v3_connection_point_iid)) if (v3_tuid_match(iid, v3_connection_point_iid))
{ {
d_stdout("query_interface_component => %p %s %p | OK convert %p", d_stdout("query_interface_component => %p %s %p | OK convert %p",
@@ -3815,7 +3593,7 @@ struct dpf_component : v3_component_cpp {
} }
} }


#ifdef DPF_VST3_USES_SEPARATE_CONTROLLER
#if DPF_VST3_USES_SEPARATE_CONTROLLER
if (dpf_comp2ctrl_connection_point* const point = component->connectionComp2Ctrl) if (dpf_comp2ctrl_connection_point* const point = component->connectionComp2Ctrl)
{ {
if (const int refcount = point->refcounter) if (const int refcount = point->refcounter)
@@ -3880,7 +3658,7 @@ struct dpf_component : v3_component_cpp {
// create the actual plugin // create the actual plugin
component->vst3 = new PluginVst3(hostApplication); component->vst3 = new PluginVst3(hostApplication);


#ifdef DPF_VST3_USES_SEPARATE_CONTROLLER
#if DPF_VST3_USES_SEPARATE_CONTROLLER
// set connection point if needed // set connection point if needed
if (dpf_comp2ctrl_connection_point* const point = component->connectionComp2Ctrl) if (dpf_comp2ctrl_connection_point* const point = component->connectionComp2Ctrl)
{ {
@@ -4133,7 +3911,7 @@ struct dpf_factory : v3_plugin_factory_cpp {
if (hostContext != nullptr) if (hostContext != nullptr)
v3_cpp_obj_unref(hostContext); v3_cpp_obj_unref(hostContext);


#ifdef DPF_VST3_USES_SEPARATE_CONTROLLER
#if DPF_VST3_USES_SEPARATE_CONTROLLER
if (gControllerGarbage.size() != 0) if (gControllerGarbage.size() != 0)
{ {
d_stdout("DPF notice: cleaning up previously undeleted controllers now"); d_stdout("DPF notice: cleaning up previously undeleted controllers now");
@@ -4271,7 +4049,7 @@ struct dpf_factory : v3_plugin_factory_cpp {
return V3_OK; return V3_OK;
} }


#ifdef DPF_VST3_USES_SEPARATE_CONTROLLER
#if DPF_VST3_USES_SEPARATE_CONTROLLER
// create edit controller // create edit controller
if (v3_tuid_match(class_id, *(const v3_tuid*)&dpf_tuid_controller) && v3_tuid_match(iid, v3_edit_controller_iid)) if (v3_tuid_match(class_id, *(const v3_tuid*)&dpf_tuid_controller) && v3_tuid_match(iid, v3_edit_controller_iid))
{ {
@@ -4299,8 +4077,7 @@ struct dpf_factory : v3_plugin_factory_cpp {
DISTRHO_SAFE_ASSERT_RETURN(idx == 0, V3_INVALID_ARG); DISTRHO_SAFE_ASSERT_RETURN(idx == 0, V3_INVALID_ARG);


info->cardinality = 0x7FFFFFFF; info->cardinality = 0x7FFFFFFF;
// TODO FIXME
#ifdef DPF_VST3_USES_SEPARATE_CONTROLLER
#if DPF_VST3_USES_SEPARATE_CONTROLLER || !DISTRHO_PLUGIN_HAS_UI
info->class_flags = V3_DISTRIBUTABLE; info->class_flags = V3_DISTRIBUTABLE;
#endif #endif
std::memcpy(info->class_id, dpf_tuid_class, sizeof(v3_tuid)); std::memcpy(info->class_id, dpf_tuid_class, sizeof(v3_tuid));
@@ -4323,8 +4100,7 @@ struct dpf_factory : v3_plugin_factory_cpp {
DISTRHO_SAFE_ASSERT_RETURN(idx == 0, V3_INVALID_ARG); DISTRHO_SAFE_ASSERT_RETURN(idx == 0, V3_INVALID_ARG);


info->cardinality = 0x7FFFFFFF; info->cardinality = 0x7FFFFFFF;
// TODO FIXME
#ifdef DPF_VST3_USES_SEPARATE_CONTROLLER
#if DPF_VST3_USES_SEPARATE_CONTROLLER || !DISTRHO_PLUGIN_HAS_UI
info->class_flags = V3_DISTRIBUTABLE; info->class_flags = V3_DISTRIBUTABLE;
#endif #endif
std::memcpy(info->class_id, dpf_tuid_class, sizeof(v3_tuid)); std::memcpy(info->class_id, dpf_tuid_class, sizeof(v3_tuid));


+ 275
- 0
distrho/src/DistrhoPluginVST3.hpp View File

@@ -0,0 +1,275 @@
/*
* 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
};

// --------------------------------------------------------------------------------------------------------------------

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

+ 4
- 22
distrho/src/DistrhoUIPrivateData.hpp View File

@@ -19,6 +19,10 @@


#include "../DistrhoUI.hpp" #include "../DistrhoUI.hpp"


#ifdef DISTRHO_PLUGIN_TARGET_VST3
# include "DistrhoPluginVST3.hpp"
#endif

#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI #if DISTRHO_PLUGIN_HAS_EXTERNAL_UI
# include "../extra/Sleep.hpp" # include "../extra/Sleep.hpp"
#else #else
@@ -294,28 +298,6 @@ typedef void (*sendNoteFunc) (void* ptr, uint8_t channel, uint8_t note, uint8
typedef void (*setSizeFunc) (void* ptr, uint width, uint height); typedef void (*setSizeFunc) (void* ptr, uint width, uint height);
typedef bool (*fileRequestFunc) (void* ptr, const char* key); typedef bool (*fileRequestFunc) (void* ptr, const char* key);


#if defined(DISTRHO_PLUGIN_TARGET_VST3) && !defined(DISTRHO_PLUGIN_INTERNAL_HPP_INCLUDED)
enum Vst3InternalParameters {
kVst3InternalParameterActive = 0,
kVst3InternalParameterBufferSize,
kVst3InternalParameterSampleRate,
# 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
};
#endif

// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
// UI private data // UI private data




+ 0
- 23
distrho/src/DistrhoUIVST3.cpp View File

@@ -21,21 +21,6 @@
#include "travesty/host.h" #include "travesty/host.h"
#include "travesty/view.h" #include "travesty/view.h"


#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

/* TODO items: /* TODO items:
* - mousewheel event * - mousewheel event
* - key down/up events * - key down/up events
@@ -66,14 +51,6 @@ static constexpr const setStateFunc setStateCallback = nullptr;
// Utility functions (defined on plugin side) // Utility functions (defined on plugin side)


const char* tuid2str(const v3_tuid iid); const char* tuid2str(const v3_tuid iid);
void strncpy_utf16(int16_t* dst, const char* src, size_t length);

struct ScopedUTF16String {
int16_t* str;
ScopedUTF16String(const char* const s) noexcept;
~ScopedUTF16String() noexcept;
operator const int16_t*() const noexcept;
};


// -------------------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------------------




+ 1
- 2
examples/CVPort/Makefile View File

@@ -23,8 +23,7 @@ include ../../Makefile.plugins.mk
# -------------------------------------------------------------- # --------------------------------------------------------------
# Enable all possible plugin types # Enable all possible plugin types


TARGETS += jack
TARGETS += lv2_dsp
TARGETS = jack lv2_dsp vst3


all: $(TARGETS) all: $(TARGETS)




Loading…
Cancel
Save