1 /* 2 * Copyright (C) 2020 Linux Studio Plugins Project <https://lsp-plug.in/> 3 * (C) 2020 Vladimir Sadovnikov <sadko4u@gmail.com> 4 * 5 * This file is part of lsp-plugins 6 * Created on: 23 окт. 2015 г. 7 * 8 * lsp-plugins is free software: you can redistribute it and/or modify 9 * it under the terms of the GNU Lesser General Public License as published by 10 * the Free Software Foundation, either version 3 of the License, or 11 * any later version. 12 * 13 * lsp-plugins is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public License 19 * along with lsp-plugins. If not, see <https://www.gnu.org/licenses/>. 20 */ 21 22 #ifndef CONTAINER_VST_PORTS_H_ 23 #define CONTAINER_VST_PORTS_H_ 24 25 namespace lsp 26 { 27 // Specify port classes 28 class VSTPort: public IPort 29 { 30 protected: 31 AEffect *pEffect; 32 audioMasterCallback hCallback; 33 ssize_t nID; 34 35 protected: from_vst(float value)36 float from_vst(float value) 37 { 38 // lsp_trace("input = %.3f", value); 39 // Set value as integer or normalized 40 if (pMetadata->unit == U_BOOL) 41 value = (value >= 0.5f) ? 1.0f : 0.0f; 42 // else if (pMetadata->unit == U_ENUM) { /* nothing */ } 43 // else if (pMetadata->unit == U_SAMPLES) 44 // value = truncf(value); 45 else 46 { 47 // if (pMetadata->flags & F_INT) 48 // value = truncf(value); 49 // else 50 // { 51 float min = 0.0f, max = 1.0f; 52 get_port_parameters(pMetadata, &min, &max, NULL); 53 value = min + value * (max - min); 54 // } 55 if ((pMetadata->flags & F_INT) || (pMetadata->unit == U_ENUM) || (pMetadata->unit == U_SAMPLES)) 56 value = truncf(value); 57 } 58 59 // lsp_trace("result = %.3f", value); 60 return value; 61 } 62 to_vst(float value)63 float to_vst(float value) 64 { 65 // lsp_trace("input = %.3f", value); 66 // Set value as integer or normalized 67 if (pMetadata->unit == U_BOOL) // { /* nothing */ } 68 value = (value >= 0.5f) ? 1.0f : 0.0f; 69 // else if (pMetadata->unit == U_ENUM) { /* nothing */ } 70 // else if (pMetadata->unit == U_SAMPLES) { /* nothing */ } 71 else 72 { 73 if ((pMetadata->flags & F_INT) || (pMetadata->unit == U_ENUM) || (pMetadata->unit == U_SAMPLES)) 74 value = truncf(value); 75 76 // if (pMetadata->flags & F_INT) { /* nothing */ } 77 // else 78 // { 79 // Normalize value 80 float min = 0.0f, max = 1.0f; 81 get_port_parameters(pMetadata, &min, &max, NULL); 82 value = (max != min) ? (value - min) / (max - min) : 0.0f; 83 // } 84 } 85 86 // lsp_trace("result = %.3f", value); 87 return value; 88 } 89 90 public: VSTPort(const port_t * meta,AEffect * effect,audioMasterCallback callback)91 explicit VSTPort(const port_t *meta, AEffect *effect, audioMasterCallback callback): IPort(meta) 92 { 93 pEffect = effect; 94 hCallback = callback; 95 nID = -1; 96 } ~VSTPort()97 virtual ~VSTPort() 98 { 99 pEffect = NULL; 100 hCallback = NULL; 101 nID = -1; 102 } 103 104 public: getEffect()105 inline AEffect *getEffect() { return pEffect; }; getCallback()106 inline audioMasterCallback getCallback() { return hCallback; }; getID()107 inline ssize_t getID() const { return nID; }; setID(ssize_t id)108 inline void setID(ssize_t id) { nID = id; }; 109 masterCallback(VstInt32 opcode,VstInt32 index,VstIntPtr value,void * ptr,float opt)110 inline VstIntPtr masterCallback(VstInt32 opcode, VstInt32 index, VstIntPtr value, void* ptr, float opt) 111 { 112 return hCallback(pEffect, opcode, index, value, ptr, opt); 113 } 114 writeValue(float value)115 virtual void writeValue(float value) {}; 116 serializable()117 virtual bool serializable() const { return false; } 118 119 /** Serialize the state of the port to the chunk 120 * 121 * @param chunk chunk to perform serialization 122 */ serialize(vst_chunk_t * chunk)123 virtual void serialize(vst_chunk_t *chunk) {} 124 125 /** Deserialize the state of the port from the chunk (legacy version) 126 * 127 * @param data data buffer 128 * @param length length of the buffer in bytes 129 * @return number of bytes deserialized or error 130 */ deserialize_v1(const void * data,size_t length)131 virtual ssize_t deserialize_v1(const void *data, size_t length) 132 { 133 return -1; 134 } 135 136 /** 137 * Deserialize the state of the port from the chunk data, data pointer should 138 * be updated 139 * @param data chunk data 140 * @param limit the data size 141 * @return true on success 142 */ deserialize_v2(const uint8_t * data,size_t size)143 virtual bool deserialize_v2(const uint8_t *data, size_t size) 144 { 145 return true; 146 } 147 }; 148 149 class VSTPortGroup: public VSTPort 150 { 151 private: 152 float nCurrRow; 153 size_t nCols; 154 size_t nRows; 155 volatile vst_serial_t nSID; // Serial ID of the parameter 156 157 public: VSTPortGroup(const port_t * meta,AEffect * effect,audioMasterCallback callback)158 explicit VSTPortGroup(const port_t *meta, AEffect *effect, audioMasterCallback callback) : VSTPort(meta, effect, callback) 159 { 160 nCurrRow = meta->start; 161 nCols = port_list_size(meta->members); 162 nRows = list_size(meta->items); 163 nSID = 0; 164 } 165 ~VSTPortGroup()166 virtual ~VSTPortGroup() 167 { 168 nCurrRow = 0; 169 nCols = 0; 170 nRows = 0; 171 nSID = 0; 172 } 173 174 public: setValue(float value)175 virtual void setValue(float value) 176 { 177 int32_t v = value; 178 if ((v >= 0) && (v < ssize_t(nRows))) 179 nCurrRow = v; 180 } 181 getValue()182 virtual float getValue() 183 { 184 return nCurrRow; 185 } 186 getSID()187 inline vst_serial_t getSID() 188 { 189 return nSID; 190 } 191 serializable()192 virtual bool serializable() const { return true; } 193 serialize(vst_chunk_t * chunk)194 virtual void serialize(vst_chunk_t *chunk) 195 { 196 int32_t v = CPU_TO_BE(int32_t(nCurrRow)); 197 chunk->write(&v, sizeof(v)); 198 } 199 deserialize_v1(const void * data,size_t length)200 virtual ssize_t deserialize_v1(const void *data, size_t length) 201 { 202 if (length < sizeof(int32_t)) 203 return -1; 204 int32_t value = BE_TO_CPU(*(reinterpret_cast<const int32_t *>(data))); 205 if ((value >= 0) && (value < ssize_t(nRows))) 206 { 207 nCurrRow = value; 208 ++nSID; 209 } 210 return sizeof(int32_t); 211 } 212 deserialize_v2(const uint8_t * data,size_t size)213 virtual bool deserialize_v2(const uint8_t *data, size_t size) 214 { 215 if (size < sizeof(int32_t)) 216 return false; 217 218 int32_t v = BE_TO_CPU(*(reinterpret_cast<const int32_t *>(data))); 219 if ((v >= 0) && (v < ssize_t(nRows))) 220 { 221 nCurrRow = v; 222 ++nSID; 223 } 224 225 return true; 226 } 227 228 public: rows()229 inline size_t rows() const { return nRows; } cols()230 inline size_t cols() const { return nCols; } curr_row()231 inline size_t curr_row() const { return nCurrRow; } 232 }; 233 234 class VSTAudioPort: public VSTPort 235 { 236 private: 237 float *pBuffer; 238 float *pSanitized; 239 size_t nBufSize; 240 241 public: VSTAudioPort(const port_t * meta,AEffect * effect,audioMasterCallback callback)242 explicit VSTAudioPort(const port_t *meta, AEffect *effect, audioMasterCallback callback) : VSTPort(meta, effect, callback) 243 { 244 pBuffer = NULL; 245 pSanitized = NULL; 246 nBufSize = 0; 247 } 248 ~VSTAudioPort()249 virtual ~VSTAudioPort() 250 { 251 pBuffer = NULL; 252 253 if (pSanitized != NULL) 254 { 255 ::free(pSanitized); 256 pSanitized = NULL; 257 nBufSize = 0; 258 } 259 }; 260 261 public: getBuffer()262 virtual void *getBuffer() { return pBuffer; }; 263 bind(float * data,size_t samples)264 void bind(float *data, size_t samples) 265 { 266 pBuffer = data; 267 if (pSanitized == NULL) 268 return; 269 270 // Perform sanitize() if possible 271 if (samples <= nBufSize) 272 { 273 dsp::sanitize2(pSanitized, reinterpret_cast<float *>(pBuffer), samples); 274 pBuffer = pSanitized; 275 } 276 else 277 { 278 lsp_warn("Could not sanitize buffer data for port %s, not enough buffer size (required: %d, actual: %d)", 279 pMetadata->id, int(samples), int(nBufSize)); 280 } 281 }; 282 set_blk_size(size_t size)283 void set_blk_size(size_t size) 284 { 285 if (!IS_IN_PORT(pMetadata)) 286 return; 287 if (nBufSize == size) 288 return; 289 290 float *buf = reinterpret_cast<float *>(::realloc(pSanitized, sizeof(float) * size)); 291 if (buf == NULL) 292 { 293 ::free(pSanitized); 294 pSanitized = NULL; 295 return; 296 } 297 298 nBufSize = size; 299 pSanitized = buf; 300 dsp::fill_zero(pSanitized, nBufSize); 301 } 302 }; 303 304 class VSTParameterPort: public VSTPort 305 { 306 private: 307 float fValue; // The internal value 308 float fVstPrev; // Previous value in VST standard notation 309 float fVstValue; // Current value in VST standard notation 310 volatile vst_serial_t nSID; // Serial ID of the parameter 311 312 public: VSTParameterPort(const port_t * meta,AEffect * effect,audioMasterCallback callback)313 explicit VSTParameterPort(const port_t *meta, AEffect *effect, audioMasterCallback callback) : VSTPort(meta, effect, callback) 314 { 315 fValue = meta->start; 316 fVstPrev = to_vst(meta->start); 317 fVstValue = fVstPrev; 318 nSID = 0; 319 } 320 ~VSTParameterPort()321 virtual ~VSTParameterPort() 322 { 323 fValue = pMetadata->start; 324 fVstPrev = 0.0f; 325 fVstValue = 0.0f; 326 nSID = 0; 327 } 328 329 public: getValue()330 virtual float getValue() 331 { 332 return fValue; 333 } 334 setValue(float value)335 virtual void setValue(float value) 336 { 337 fValue = limit_value(pMetadata, value); 338 fVstValue = to_vst(fValue); 339 } 340 pre_process(size_t samples)341 virtual bool pre_process(size_t samples) 342 { 343 if (fVstValue == fVstPrev) 344 return false; 345 fVstPrev = fVstValue; 346 return true; 347 } 348 writeValue(float value)349 virtual void writeValue(float value) 350 { 351 setValue(value); 352 if ((nID >= 0) && (pEffect != NULL) && (hCallback != NULL)) 353 { 354 lsp_trace("hCallback=%p, pEffect=%p, operation=%d, id=%d, value=%.5f, vst_value=%.5f", 355 hCallback, pEffect, int(audioMasterAutomate), int(nID), value, fVstValue); 356 hCallback(pEffect, audioMasterAutomate, nID, 0, NULL, fVstValue); 357 } 358 } 359 setVstValue(float value)360 void setVstValue(float value) 361 { 362 if (fVstValue == value) 363 return; 364 fValue = limit_value(pMetadata, from_vst(value)); 365 fVstValue = value; 366 nSID ++; 367 } 368 getVstValue()369 inline float getVstValue() 370 { 371 return fVstValue; 372 } 373 getSID()374 inline vst_serial_t getSID() 375 { 376 return nSID; 377 } 378 serializable()379 virtual bool serializable() const { return true; } 380 serialize(vst_chunk_t * chunk)381 virtual void serialize(vst_chunk_t *chunk) 382 { 383 float v = CPU_TO_BE(fValue); 384 chunk->write(&v, sizeof(v)); 385 } 386 deserialize_v1(const void * data,size_t length)387 virtual ssize_t deserialize_v1(const void *data, size_t length) 388 { 389 if (length < sizeof(float)) 390 return -1; 391 float value = BE_TO_CPU(*(reinterpret_cast<const float *>(data))); 392 writeValue(value); 393 ++nSID; 394 return sizeof(float); 395 } 396 deserialize_v2(const uint8_t * data,size_t size)397 virtual bool deserialize_v2(const uint8_t *data, size_t size) 398 { 399 if (size < sizeof(float)) 400 return false; 401 402 float v = BE_TO_CPU(*(reinterpret_cast<const float *>(data))); 403 writeValue(v); 404 ++nSID; 405 return true; 406 } 407 }; 408 409 class VSTMeterPort: public VSTPort 410 { 411 public: 412 float fValue; 413 bool bForce; 414 415 public: VSTMeterPort(const port_t * meta,AEffect * effect,audioMasterCallback callback)416 explicit VSTMeterPort(const port_t *meta, AEffect *effect, audioMasterCallback callback) : VSTPort(meta, effect, callback) 417 { 418 fValue = meta->start; 419 bForce = true; 420 } 421 ~VSTMeterPort()422 virtual ~VSTMeterPort() 423 { 424 fValue = pMetadata->start; 425 } 426 427 public: 428 // Native Interface getValue()429 virtual float getValue() 430 { 431 return fValue; 432 } 433 setValue(float value)434 virtual void setValue(float value) 435 { 436 value = limit_value(pMetadata, value); 437 438 if (pMetadata->flags & F_PEAK) 439 { 440 if ((bForce) || (fabs(fValue) < fabs(value))) 441 { 442 fValue = value; 443 bForce = false; 444 } 445 } 446 else 447 fValue = value; 448 } 449 syncValue()450 float syncValue() 451 { 452 float value = fValue; 453 bForce = true; 454 return value; 455 } 456 }; 457 458 class VSTMeshPort: public VSTPort 459 { 460 private: 461 mesh_t *pMesh; 462 463 public: VSTMeshPort(const port_t * meta,AEffect * effect,audioMasterCallback callback)464 explicit VSTMeshPort(const port_t *meta, AEffect *effect, audioMasterCallback callback) : VSTPort(meta, effect, callback) 465 { 466 pMesh = vst_create_mesh(meta); 467 } 468 ~VSTMeshPort()469 virtual ~VSTMeshPort() 470 { 471 vst_destroy_mesh(pMesh); 472 pMesh = NULL; 473 } 474 475 public: getBuffer()476 virtual void *getBuffer() 477 { 478 return pMesh; 479 } 480 }; 481 482 class VSTStreamPort: public VSTPort 483 { 484 private: 485 stream_t *pStream; 486 487 public: VSTStreamPort(const port_t * meta,AEffect * effect,audioMasterCallback callback)488 explicit VSTStreamPort(const port_t *meta, AEffect *effect, audioMasterCallback callback) : VSTPort(meta, effect, callback) 489 { 490 pStream = stream_t::create(pMetadata->min, pMetadata->max, pMetadata->start); 491 } 492 ~VSTStreamPort()493 virtual ~VSTStreamPort() 494 { 495 if (pStream != NULL) 496 { 497 stream_t::destroy(pStream); 498 pStream = NULL; 499 } 500 } 501 502 public: getBuffer()503 virtual void *getBuffer() 504 { 505 return pStream; 506 } 507 }; 508 509 class VSTFrameBufferPort: public VSTPort 510 { 511 private: 512 frame_buffer_t sFB; 513 514 public: VSTFrameBufferPort(const port_t * meta,AEffect * effect,audioMasterCallback callback)515 explicit VSTFrameBufferPort(const port_t *meta, AEffect *effect, audioMasterCallback callback) : VSTPort(meta, effect, callback) 516 { 517 sFB.init(pMetadata->start, pMetadata->step); 518 } 519 ~VSTFrameBufferPort()520 virtual ~VSTFrameBufferPort() 521 { 522 sFB.destroy(); 523 } 524 525 public: getBuffer()526 virtual void *getBuffer() 527 { 528 return &sFB; 529 } 530 destroy()531 virtual void destroy() 532 { 533 sFB.destroy(); 534 } 535 }; 536 537 class VSTMidiInputPort: public VSTPort 538 { 539 private: 540 midi_t sQueue; // MIDI event buffer 541 542 public: VSTMidiInputPort(const port_t * meta,AEffect * effect,audioMasterCallback callback)543 explicit VSTMidiInputPort(const port_t *meta, AEffect *effect, audioMasterCallback callback) : VSTPort(meta, effect, callback) 544 { 545 sQueue.clear(); 546 } 547 ~VSTMidiInputPort()548 virtual ~VSTMidiInputPort() 549 { 550 } 551 552 public: getBuffer()553 virtual void *getBuffer() 554 { 555 return &sQueue; 556 } 557 post_process(size_t samples)558 virtual void post_process(size_t samples) 559 { 560 sQueue.clear(); 561 } 562 563 public: deserialize(const VstEvents * e)564 void deserialize(const VstEvents *e) 565 { 566 size_t count = e->numEvents; 567 for (size_t i=0; i<count; ++i) 568 { 569 // Get event and check type 570 const VstEvent *ve = e->events[i]; 571 if (ve->type != kVstMidiType) 572 continue; 573 574 // Cast to VST MIDI event 575 const VstMidiEvent *vme = reinterpret_cast<const VstMidiEvent *>(ve); 576 const uint8_t *bytes = reinterpret_cast<const uint8_t *>(vme->midiData); 577 578 // Decode MIDI event 579 midi::event_t me; 580 if (midi::decode(&me, bytes) <= 0) 581 return; 582 583 // Put the event to the queue 584 me.timestamp = vme->deltaFrames; 585 586 // Debug 587 #ifdef LSP_TRACE 588 #define TRACE_KEY(x) case midi::MIDI_MSG_ ## x: evt_type = #x; break; 589 lsp_trace("midi dump: %02x %02x %02x", int(bytes[0]) & 0xff, int(bytes[1]) & 0xff, int(bytes[2]) & 0xff); 590 591 char tmp_evt_type[32]; 592 const char *evt_type = NULL; 593 switch (me.type) 594 { 595 TRACE_KEY(NOTE_OFF) 596 TRACE_KEY(NOTE_ON) 597 TRACE_KEY(NOTE_PRESSURE) 598 TRACE_KEY(NOTE_CONTROLLER) 599 TRACE_KEY(PROGRAM_CHANGE) 600 TRACE_KEY(CHANNEL_PRESSURE) 601 TRACE_KEY(PITCH_BEND) 602 TRACE_KEY(SYSTEM_EXCLUSIVE) 603 TRACE_KEY(MTC_QUARTER) 604 TRACE_KEY(SONG_POS) 605 TRACE_KEY(SONG_SELECT) 606 TRACE_KEY(TUNE_REQUEST) 607 TRACE_KEY(END_EXCLUSIVE) 608 TRACE_KEY(CLOCK) 609 TRACE_KEY(START) 610 TRACE_KEY(CONTINUE) 611 TRACE_KEY(STOP) 612 TRACE_KEY(ACTIVE_SENSING) 613 TRACE_KEY(RESET) 614 default: 615 snprintf(tmp_evt_type, sizeof(tmp_evt_type), "UNKNOWN(0x%02x)", int(me.type)); 616 evt_type = tmp_evt_type; 617 break; 618 } 619 620 lsp_trace("MIDI Event: type=%s, timestamp=%ld", evt_type, (long)(me.timestamp)); 621 622 #undef TRACE_KEY 623 624 #endif /* LSP_TRACE */ 625 626 // Add event to the queue 627 if (!sQueue.push(me)) 628 lsp_error("MIDI event queue overflow"); 629 } 630 631 // We don't know anything about ordering of events, reorder them chronologically 632 sQueue.sort(); 633 } 634 }; 635 636 class VSTMidiOutputPort: public VSTPort 637 { 638 private: 639 midi_t sQueue; // MIDI event buffer 640 VstEvents *pEvents; // Root pointer to VST MIDI events 641 VstMidiEvent vEvents[MIDI_EVENTS_MAX]; // Buffer for VST MIDI events 642 643 public: VSTMidiOutputPort(const port_t * meta,AEffect * effect,audioMasterCallback callback)644 explicit VSTMidiOutputPort(const port_t *meta, AEffect *effect, audioMasterCallback callback) : VSTPort(meta, effect, callback) 645 { 646 sQueue.clear(); 647 648 // Allocate buffer for VST MIDI events 649 size_t evt_size = ALIGN_SIZE(sizeof(VstEvents) + MIDI_EVENTS_MAX * sizeof(VstMidiEvent *), DEFAULT_ALIGN); 650 pEvents = reinterpret_cast<VstEvents *>(new uint8_t[evt_size]); 651 } 652 ~VSTMidiOutputPort()653 virtual ~VSTMidiOutputPort() 654 { 655 } 656 657 public: getBuffer()658 virtual void *getBuffer() 659 { 660 return &sQueue; 661 } 662 post_process(size_t samples)663 virtual void post_process(size_t samples) 664 { 665 // Check that there are pending MIDI events 666 if (sQueue.nEvents <= 0) 667 return; 668 669 // We don't know anything about ordering of events, reorder them chronologically 670 sQueue.sort(); 671 672 // Translate events 673 pEvents->numEvents = 0; 674 675 for (size_t i=0; i<sQueue.nEvents; ++i) 676 { 677 const midi::event_t *me = &sQueue.vEvents[i]; 678 VstMidiEvent *dst = &vEvents[pEvents->numEvents]; 679 680 // Debug 681 #ifdef LSP_TRACE 682 #define TRACE_KEY(x) case midi::MIDI_MSG_ ## x: evt_type = #x; break; 683 684 char tmp_evt_type[32]; 685 const char *evt_type = NULL; 686 switch (me->type) 687 { 688 TRACE_KEY(NOTE_OFF) 689 TRACE_KEY(NOTE_ON) 690 TRACE_KEY(NOTE_PRESSURE) 691 TRACE_KEY(NOTE_CONTROLLER) 692 TRACE_KEY(PROGRAM_CHANGE) 693 TRACE_KEY(CHANNEL_PRESSURE) 694 TRACE_KEY(PITCH_BEND) 695 TRACE_KEY(SYSTEM_EXCLUSIVE) 696 TRACE_KEY(MTC_QUARTER) 697 TRACE_KEY(SONG_POS) 698 TRACE_KEY(SONG_SELECT) 699 TRACE_KEY(TUNE_REQUEST) 700 TRACE_KEY(END_EXCLUSIVE) 701 TRACE_KEY(CLOCK) 702 TRACE_KEY(START) 703 TRACE_KEY(CONTINUE) 704 TRACE_KEY(STOP) 705 TRACE_KEY(ACTIVE_SENSING) 706 TRACE_KEY(RESET) 707 default: 708 snprintf(tmp_evt_type, sizeof(tmp_evt_type), "UNKNOWN(0x%02x)", int(me->type)); 709 evt_type = tmp_evt_type; 710 break; 711 } 712 713 lsp_trace("MIDI Event: type=%s, timestamp=%ld", evt_type, (long)(me->timestamp)); 714 715 #undef TRACE_KEY 716 717 #endif /* LSP_TRACE */ 718 719 ssize_t bytes = midi::encode(reinterpret_cast<uint8_t *>(dst->midiData), me); 720 if (bytes <= 0) 721 { 722 lsp_error("Tried to serialize invalid MIDI event"); 723 continue; 724 } 725 726 dst->type = kVstMidiType; 727 dst->byteSize = sizeof(VstMidiEvent); 728 dst->deltaFrames = me->timestamp; 729 dst->flags = (me->type >= midi::MIDI_MSG_CLOCK) ? kVstMidiEventIsRealtime : 0; 730 dst->noteLength = 0; 731 dst->noteOffset = 0; 732 dst->detune = 0; 733 dst->noteOffVelocity= (me->type == midi::MIDI_MSG_NOTE_OFF) ? me->note.velocity : 0; 734 735 lsp_trace("midi dump: %02x %02x %02x", 736 int(dst->midiData[0]) & 0xff, int(dst->midiData[1]) & 0xff, int(dst->midiData[2]) & 0xff); 737 738 // Add pointer to the VST event to the VST eventn list 739 pEvents->events[pEvents->numEvents++] = reinterpret_cast<VstEvent *>(dst); 740 } 741 742 // Call host to process MIDI events if they are 743 if (pEvents->numEvents > 0) 744 { 745 masterCallback(audioMasterProcessEvents, 0, 0, pEvents, 0.0f); 746 pEvents->numEvents = 0; 747 } 748 749 sQueue.clear(); 750 } 751 }; 752 753 class VSTPathPort: public VSTPort 754 { 755 private: 756 vst_path_t sPath; 757 758 public: VSTPathPort(const port_t * meta,AEffect * effect,audioMasterCallback callback)759 explicit VSTPathPort(const port_t *meta, AEffect *effect, audioMasterCallback callback) : VSTPort(meta, effect, callback) 760 { 761 sPath.init(); 762 } 763 ~VSTPathPort()764 virtual ~VSTPathPort() 765 { 766 } 767 768 public: getBuffer()769 virtual void *getBuffer() 770 { 771 return static_cast<path_t *>(&sPath); 772 } 773 pre_process(size_t samples)774 virtual bool pre_process(size_t samples) 775 { 776 return sPath.pending(); 777 } 778 sizeof_state()779 size_t sizeof_state() 780 { 781 size_t bytes = strlen(sPath.sPath); 782 if (bytes >= 0x7fff) 783 bytes = 0x7fff; 784 if (bytes > 0x7f) 785 bytes += 2; 786 else 787 bytes += 1; 788 789 return bytes; 790 } 791 serialize(vst_chunk_t * chunk)792 virtual void serialize(vst_chunk_t *chunk) 793 { 794 chunk->write_string(sPath.sPath); 795 } 796 deserialize_v1(const void * data,size_t length)797 virtual ssize_t deserialize_v1(const void *data, size_t length) 798 { 799 const uint8_t *ptr = reinterpret_cast<const uint8_t *>(data); 800 const uint8_t *tail = ptr + length; 801 if (ptr >= tail) 802 return -1; 803 804 // Read length of string 805 size_t bytes = *(ptr++); 806 if (bytes & 0x80) 807 { 808 if (ptr >= tail) 809 return -1; 810 811 bytes = ((bytes << 8) | (*(ptr++))) & 0x7fff; 812 } 813 814 // Read string 815 tail -= bytes; 816 if (ptr > tail) 817 return -1; 818 819 // Submit data 820 sPath.submit(reinterpret_cast<const char *>(ptr), bytes, false, PF_STATE_RESTORE); 821 ptr += bytes; 822 return ptr - reinterpret_cast<const uint8_t *>(data); 823 } 824 deserialize_v2(const uint8_t * data,size_t size)825 virtual bool deserialize_v2(const uint8_t *data, size_t size) 826 { 827 const char *str = reinterpret_cast<const char *>(data); 828 size_t len = ::strnlen(str, size) + 1; 829 if (len > size) 830 return false; 831 832 sPath.submit(str, len, false, PF_STATE_RESTORE); 833 return true; 834 } 835 serializable()836 virtual bool serializable() const { return true; } 837 }; 838 839 class VSTOscPort: public VSTPort 840 { 841 private: 842 osc_buffer_t *pFB; 843 844 public: VSTOscPort(const port_t * meta,AEffect * effect,audioMasterCallback callback)845 explicit VSTOscPort(const port_t *meta, AEffect *effect, audioMasterCallback callback) : VSTPort(meta, effect, callback) 846 { 847 pFB = NULL; 848 } 849 ~VSTOscPort()850 virtual ~VSTOscPort() 851 { 852 } 853 854 public: getBuffer()855 virtual void *getBuffer() 856 { 857 return pFB; 858 } 859 init()860 virtual int init() 861 { 862 pFB = osc_buffer_t::create(OSC_BUFFER_MAX); 863 return (pFB == NULL) ? STATUS_NO_MEM : STATUS_OK; 864 } 865 destroy()866 virtual void destroy() 867 { 868 if (pFB != NULL) 869 { 870 osc_buffer_t::destroy(pFB); 871 pFB = NULL; 872 } 873 } 874 }; 875 } 876 877 878 #endif /* CONTAINER_VST_PORTS_H_ */ 879