DPF

DISTRHO Plugin Framework
Log | Files | Refs | Submodules | README | LICENSE

DistrhoPluginVST.hpp (11242B)


      1 /*
      2  * DISTRHO Plugin Framework (DPF)
      3  * Copyright (C) 2012-2022 Filipe Coelho <falktx@falktx.com>
      4  *
      5  * Permission to use, copy, modify, and/or distribute this software for any purpose with
      6  * or without fee is hereby granted, provided that the above copyright notice and this
      7  * permission notice appear in all copies.
      8  *
      9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
     10  * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
     11  * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
     12  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
     13  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
     14  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     15  */
     16 
     17 #ifndef DISTRHO_PLUGIN_VST_HPP_INCLUDED
     18 #define DISTRHO_PLUGIN_VST_HPP_INCLUDED
     19 
     20 #include "DistrhoPluginChecks.h"
     21 #include "../DistrhoUtils.hpp"
     22 
     23 #include <algorithm>
     24 #include <cmath>
     25 
     26 #if DISTRHO_PLUGIN_HAS_UI && ! DISTRHO_PLUGIN_HAS_EMBED_UI
     27 # undef DISTRHO_PLUGIN_HAS_UI
     28 # define DISTRHO_PLUGIN_HAS_UI 0
     29 #endif
     30 
     31 #if DISTRHO_PLUGIN_HAS_UI && ! defined(HAVE_DGL) && ! DISTRHO_PLUGIN_HAS_EXTERNAL_UI
     32 # undef DISTRHO_PLUGIN_HAS_UI
     33 # define DISTRHO_PLUGIN_HAS_UI 0
     34 #endif
     35 
     36 #if DISTRHO_PLUGIN_HAS_UI && ! DISTRHO_PLUGIN_HAS_EXTERNAL_UI
     37 # include "Base.hpp"
     38 #endif
     39 
     40 #if DISTRHO_PLUGIN_HAS_UI == 1 && DISTRHO_PLUGIN_WANT_DIRECT_ACCESS == 0
     41 # define DPF_VST3_USES_SEPARATE_CONTROLLER 1
     42 #else
     43 # define DPF_VST3_USES_SEPARATE_CONTROLLER 0
     44 #endif
     45 
     46 // --------------------------------------------------------------------------------------------------------------------
     47 
     48 #ifdef DISTRHO_PROPER_CPP11_SUPPORT
     49 # include <atomic>
     50 #else
     51 // quick and dirty std::atomic replacement for the things we need
     52 namespace std {
     53     struct atomic_int {
     54         volatile int value;
     55         explicit atomic_int(volatile int v) noexcept : value(v) {}
     56         int operator++() volatile noexcept { return __atomic_add_fetch(&value, 1, __ATOMIC_RELAXED); }
     57         int operator--() volatile noexcept { return __atomic_sub_fetch(&value, 1, __ATOMIC_RELAXED); }
     58         operator int() volatile noexcept { return __atomic_load_n(&value, __ATOMIC_RELAXED); }
     59     };
     60 };
     61 #endif
     62 
     63 // --------------------------------------------------------------------------------------------------------------------
     64 
     65 START_NAMESPACE_DISTRHO
     66 
     67 // --------------------------------------------------------------------------------------------------------------------
     68 
     69 enum Vst3InternalParameters {
     70    #if DPF_VST3_USES_SEPARATE_CONTROLLER
     71     kVst3InternalParameterBufferSize,
     72     kVst3InternalParameterSampleRate,
     73    #endif
     74    #if DISTRHO_PLUGIN_WANT_LATENCY
     75     kVst3InternalParameterLatency,
     76    #endif
     77    #if DISTRHO_PLUGIN_WANT_PROGRAMS
     78     kVst3InternalParameterProgram,
     79    #endif
     80     kVst3InternalParameterBaseCount,
     81    #if DISTRHO_PLUGIN_WANT_MIDI_INPUT
     82     kVst3InternalParameterMidiCC_start = kVst3InternalParameterBaseCount,
     83     kVst3InternalParameterMidiCC_end = kVst3InternalParameterMidiCC_start + 130*16,
     84     kVst3InternalParameterCount
     85    #else
     86     kVst3InternalParameterCount = kVst3InternalParameterBaseCount
     87    #endif
     88 };
     89 
     90 #if DPF_VST3_USES_SEPARATE_CONTROLLER || DISTRHO_PLUGIN_WANT_LATENCY || DISTRHO_PLUGIN_WANT_PROGRAMS || DISTRHO_PLUGIN_WANT_MIDI_INPUT
     91 # define DPF_VST3_HAS_INTERNAL_PARAMETERS 1
     92 #else
     93 # define DPF_VST3_HAS_INTERNAL_PARAMETERS 0
     94 #endif
     95 
     96 #if DPF_VST3_HAS_INTERNAL_PARAMETERS && DISTRHO_PLUGIN_WANT_MIDI_INPUT && \
     97     !(DPF_VST3_USES_SEPARATE_CONTROLLER || DISTRHO_PLUGIN_WANT_LATENCY || DISTRHO_PLUGIN_WANT_PROGRAMS)
     98 # define DPF_VST3_PURE_MIDI_INTERNAL_PARAMETERS 1
     99 #else
    100 # define DPF_VST3_PURE_MIDI_INTERNAL_PARAMETERS 0
    101 #endif
    102 
    103 // --------------------------------------------------------------------------------------------------------------------
    104 
    105 static inline
    106 bool strcmp_utf16(const int16_t* const str16, const char* const str8)
    107 {
    108     size_t i = 0;
    109     for (; str8[i] != '\0'; ++i)
    110     {
    111         const uint8_t char8 = static_cast<uint8_t>(str8[i]);
    112 
    113         // skip non-ascii chars, unsupported
    114         if (char8 >= 0x80)
    115             return false;
    116 
    117         if (str16[i] != char8)
    118             return false;
    119     }
    120 
    121     return str16[i] == str8[i];
    122 }
    123 
    124 // --------------------------------------------------------------------------------------------------------------------
    125 
    126 static inline
    127 size_t strlen_utf16(const int16_t* const str)
    128 {
    129     size_t i = 0;
    130 
    131     while (str[i] != 0)
    132         ++i;
    133 
    134     return i;
    135 }
    136 
    137 // --------------------------------------------------------------------------------------------------------------------
    138 
    139 static inline
    140 void strncpy_utf8(char* const dst, const int16_t* const src, const size_t length)
    141 {
    142     DISTRHO_SAFE_ASSERT_RETURN(length > 0,);
    143 
    144     if (const size_t len = std::min(strlen_utf16(src), length-1U))
    145     {
    146         for (size_t i=0; i<len; ++i)
    147         {
    148             // skip non-ascii chars, unsupported
    149             if (src[i] >= 0x80)
    150                 continue;
    151 
    152             dst[i] = src[i];
    153         }
    154         dst[len] = 0;
    155     }
    156     else
    157     {
    158         dst[0] = 0;
    159     }
    160 }
    161 
    162 static inline
    163 void strncpy_utf16(int16_t* const dst, const char* const src, const size_t length)
    164 {
    165     DISTRHO_SAFE_ASSERT_RETURN(length > 0,);
    166 
    167     if (const size_t len = std::min(std::strlen(src), length-1U))
    168     {
    169         for (size_t i=0; i<len; ++i)
    170         {
    171             // skip non-ascii chars, unsupported
    172             if ((uint8_t)src[i] >= 0x80)
    173                 continue;
    174 
    175             dst[i] = src[i];
    176         }
    177         dst[len] = 0;
    178     }
    179     else
    180     {
    181         dst[0] = 0;
    182     }
    183 }
    184 
    185 // --------------------------------------------------------------------------------------------------------------------
    186 
    187 template<typename T>
    188 static inline
    189 void snprintf_utf16_t(int16_t* const dst, const T value, const char* const format, const size_t size)
    190 {
    191     DISTRHO_SAFE_ASSERT_RETURN(size > 0,);
    192 
    193     char* const tmpbuf = (char*)std::malloc(size);
    194     DISTRHO_SAFE_ASSERT_RETURN(tmpbuf != nullptr,);
    195 
    196     std::snprintf(tmpbuf, size-1, format, value);
    197     tmpbuf[size-1] = '\0';
    198 
    199     strncpy_utf16(dst, tmpbuf, size);
    200     std::free(tmpbuf);
    201 }
    202 
    203 static inline
    204 void snprintf_f32_utf16(int16_t* const dst, const float value, const size_t size)
    205 {
    206     return snprintf_utf16_t<float>(dst, value, "%f", size);
    207 }
    208 
    209 static inline
    210 void snprintf_f32_utf16(int16_t* const dst, const double value, const size_t size)
    211 {
    212     return snprintf_utf16_t<double>(dst, value, "%f", size);
    213 }
    214 
    215 static inline
    216 void snprintf_i32_utf16(int16_t* const dst, const int32_t value, const size_t size)
    217 {
    218     return snprintf_utf16_t<int32_t>(dst, value, "%d", size);
    219 }
    220 
    221 static inline
    222 void snprintf_u32_utf16(int16_t* const dst, const uint32_t value, const size_t size)
    223 {
    224     return snprintf_utf16_t<uint32_t>(dst, value, "%u", size);
    225 }
    226 
    227 #if DISTRHO_PLUGIN_HAS_UI && ! DISTRHO_PLUGIN_HAS_EXTERNAL_UI
    228 // --------------------------------------------------------------------------------------------------------------------
    229 // translate a vstgui-based key character and code to matching values used by DPF
    230 
    231 static inline
    232 uint translateVstKeyCode(bool& special, const int16_t keychar, const int16_t keycode) noexcept
    233 {
    234     using namespace DGL_NAMESPACE;
    235 
    236     // special stuff first
    237     special = true;
    238     switch (keycode)
    239     {
    240     case 1: return kKeyBackspace;
    241     // 2 \t (handled below)
    242     // 3 clear
    243     // 4 \r (handled below)
    244     case 6: return kKeyEscape;
    245     //  7 space (handled below)
    246     //  8 next
    247     // 17 select
    248     // 18 print
    249     // 19 \n (handled below)
    250     // 20 snapshot
    251     case 22: return kKeyDelete;
    252     // 23 help
    253     // 57 = (handled below)
    254     // numpad stuff follows
    255     // 24 0 (handled below)
    256     // 25 1 (handled below)
    257     // 26 2 (handled below)
    258     // 27 3 (handled below)
    259     // 28 4 (handled below)
    260     // 29 5 (handled below)
    261     // 30 6 (handled below)
    262     // 31 7 (handled below)
    263     // 32 8 (handled below)
    264     // 33 9 (handled below)
    265     // 34 * (handled below)
    266     // 35 + (handled below)
    267     // 36 separator
    268     // 37 - (handled below)
    269     // 38 . (handled below)
    270     // 39 / (handled below)
    271     // handle rest of special keys
    272     /* these special keys are missing:
    273         - kKeySuper
    274         - kKeyCapsLock
    275         - kKeyPrintScreen
    276         */
    277     case 40: return kKeyF1;
    278     case 41: return kKeyF2;
    279     case 42: return kKeyF3;
    280     case 43: return kKeyF4;
    281     case 44: return kKeyF5;
    282     case 45: return kKeyF6;
    283     case 46: return kKeyF7;
    284     case 47: return kKeyF8;
    285     case 48: return kKeyF9;
    286     case 49: return kKeyF10;
    287     case 50: return kKeyF11;
    288     case 51: return kKeyF12;
    289     case 11: return kKeyLeft;
    290     case 12: return kKeyUp;
    291     case 13: return kKeyRight;
    292     case 14: return kKeyDown;
    293     case 15: return kKeyPageUp;
    294     case 16: return kKeyPageDown;
    295     case 10: return kKeyHome;
    296     case  9: return kKeyEnd;
    297     case 21: return kKeyInsert;
    298     case 54: return kKeyShiftL;
    299     case 55: return kKeyControlL;
    300     case 56: return kKeyAltL;
    301     case 58: return kKeyMenu;
    302     case 52: return kKeyNumLock;
    303     case 53: return kKeyScrollLock;
    304     case  5: return kKeyPause;
    305     }
    306 
    307     // regular keys next
    308     special = false;
    309     switch (keycode)
    310     {
    311     case  2: return '\t';
    312     case  4: return '\r';
    313     case  7: return ' ';
    314     case 19: return '\n';
    315     case 57: return '=';
    316     case 24: return '0';
    317     case 25: return '1';
    318     case 26: return '2';
    319     case 27: return '3';
    320     case 28: return '4';
    321     case 29: return '5';
    322     case 30: return '6';
    323     case 31: return '7';
    324     case 32: return '8';
    325     case 33: return '9';
    326     case 34: return '*';
    327     case 35: return '+';
    328     case 37: return '-';
    329     case 38: return '.';
    330     case 39: return '/';
    331     }
    332 
    333     // fallback
    334     return keychar;
    335 }
    336 #endif
    337 
    338 // --------------------------------------------------------------------------------------------------------------------
    339 // handy way to create a utf16 string from a utf8 one on the current function scope, used for message strings
    340 
    341 struct ScopedUTF16String {
    342     int16_t* str;
    343     ScopedUTF16String(const char* const s) noexcept
    344         : str(nullptr)
    345     {
    346         const size_t len = std::strlen(s);
    347         str = static_cast<int16_t*>(std::malloc(sizeof(int16_t) * (len + 1)));
    348         DISTRHO_SAFE_ASSERT_RETURN(str != nullptr,);
    349         strncpy_utf16(str, s, len + 1);
    350     }
    351 
    352     ~ScopedUTF16String() noexcept
    353     {
    354         std::free(str);
    355     }
    356 
    357     operator const int16_t*() const noexcept
    358     {
    359         return str;
    360     }
    361 };
    362 
    363 // --------------------------------------------------------------------------------------------------------------------
    364 // handy way to create a utf8 string from a utf16 one on the current function scope (limited to 128 chars)
    365 
    366 struct ScopedUTF8String {
    367     char str[128];
    368 
    369     ScopedUTF8String(const int16_t* const s) noexcept
    370     {
    371         strncpy_utf8(str, s, 128);
    372     }
    373 
    374     operator const char*() const noexcept
    375     {
    376         return str;
    377     }
    378 };
    379 
    380 // --------------------------------------------------------------------------------------------------------------------
    381 
    382 END_NAMESPACE_DISTRHO
    383 
    384 // --------------------------------------------------------------------------------------------------------------------
    385 
    386 #endif // DISTRHO_PLUGIN_VST_HPP_INCLUDED