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