1 //------------------------------------------------------------------------
2 // Project : VST SDK
3 //
4 // Category : Helpers
5 // Filename : public.sdk/source/vst/vst2wrapper/vst2wrapper.cpp
6 // Created by : Steinberg, 01/2009
7 // Description : VST 3 -> VST 2 Wrapper
8 //
9 //-----------------------------------------------------------------------------
10 // LICENSE
11 // (c) 2020, Steinberg Media Technologies GmbH, All Rights Reserved
12 //-----------------------------------------------------------------------------
13 // Redistribution and use in source and binary forms, with or without modification,
14 // are permitted provided that the following conditions are met:
15 //
16 // * Redistributions of source code must retain the above copyright notice,
17 // this list of conditions and the following disclaimer.
18 // * Redistributions in binary form must reproduce the above copyright notice,
19 // this list of conditions and the following disclaimer in the documentation
20 // and/or other materials provided with the distribution.
21 // * Neither the name of the Steinberg Media Technologies nor the names of its
22 // contributors may be used to endorse or promote products derived from this
23 // software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
26 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
27 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28 // IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
29 // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30 // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
33 // OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
34 // OF THE POSSIBILITY OF SUCH DAMAGE.
35 //-----------------------------------------------------------------------------
36
37 /// \cond ignore
38
39 #include "public.sdk/source/vst/vst2wrapper/vst2wrapper.h"
40
41 #include "public.sdk/source/vst/hosting/hostclasses.h"
42 #include "public.sdk/source/vst2.x/aeffeditor.h"
43
44 #include "pluginterfaces/base/futils.h"
45 #include "pluginterfaces/base/keycodes.h"
46 #include "pluginterfaces/gui/iplugview.h"
47 #include "pluginterfaces/vst/ivstmessage.h"
48 #include "pluginterfaces/vst/ivstmidicontrollers.h"
49 #include "pluginterfaces/vst/vstpresetkeys.h"
50
51 #include "base/source/fstreamer.h"
52
53 #include <cstdio>
54 #include <cstdlib>
55 #include <limits>
56
57 extern bool DeinitModule (); //! Called in Vst2Wrapper destructor
58
59 //------------------------------------------------------------------------
60 // some Defines
61 //------------------------------------------------------------------------
62 // should be kVstMaxParamStrLen if we want to respect the VST 2 specification!!!
63 #define kVstExtMaxParamStrLen 32
64
65 //------------------------------------------------------------------------
66 namespace Steinberg {
67 namespace Vst {
68
69 //! The parameter's name contains the unit path (e.g. "Modulators.LFO 1.frequency")
70 bool vst2WrapperFullParameterPath = true;
71
72 //------------------------------------------------------------------------
73 // Vst2EditorWrapper Declaration
74 //------------------------------------------------------------------------
75 class Vst2EditorWrapper : public BaseEditorWrapper, public AEffEditor
76 {
77 public:
78 //------------------------------------------------------------------------
79 Vst2EditorWrapper (AudioEffect* effect, IEditController* controller);
80
81 //--- from BaseEditorWrapper ---------------------
82 void _close () SMTG_OVERRIDE;
83
84 //--- from AEffEditor-------------------
85 bool getRect (ERect** rect) SMTG_OVERRIDE;
86 bool open (void* ptr) SMTG_OVERRIDE;
close()87 void close () SMTG_OVERRIDE { _close (); }
setKnobMode(VstInt32 val)88 bool setKnobMode (VstInt32 val) SMTG_OVERRIDE
89 {
90 return BaseEditorWrapper::_setKnobMode (static_cast<Vst::KnobMode> (val));
91 }
92
93 ///< Receives key down event. Return true only if key was really used!
94 bool onKeyDown (VstKeyCode& keyCode) SMTG_OVERRIDE;
95 ///< Receives key up event. Return true only if key was really used!
96 bool onKeyUp (VstKeyCode& keyCode) SMTG_OVERRIDE;
97 ///< Handles mouse wheel event, distance is positive or negative to indicate wheel direction.
98 bool onWheel (float distance) SMTG_OVERRIDE;
99
100 //--- IPlugFrame ----------------------------
101 tresult PLUGIN_API resizeView (IPlugView* view, ViewRect* newSize) SMTG_OVERRIDE;
102
103 //------------------------------------------------------------------------
104 protected:
105 ERect mERect;
106 };
107
108 //------------------------------------------------------------------------
areSizeEquals(const ViewRect & r1,const ViewRect & r2)109 bool areSizeEquals (const ViewRect &r1, const ViewRect& r2)
110 {
111 if (r1.getHeight() != r2.getHeight ())
112 return false;
113 if (r1.getWidth() != r2.getWidth ())
114 return false;
115 return true;
116 }
117
118 //------------------------------------------------------------------------
119 // Vst2EditorWrapper Implementation
120 //------------------------------------------------------------------------
Vst2EditorWrapper(AudioEffect * effect,IEditController * controller)121 Vst2EditorWrapper::Vst2EditorWrapper (AudioEffect* effect, IEditController* controller)
122 : BaseEditorWrapper (controller), AEffEditor (effect)
123 {
124 }
125
126 //------------------------------------------------------------------------
resizeView(IPlugView * view,ViewRect * newSize)127 tresult PLUGIN_API Vst2EditorWrapper::resizeView (IPlugView* view, ViewRect* newSize)
128 {
129 tresult result = kResultFalse;
130 if (view && newSize && effect)
131 {
132 if (areSizeEquals (*newSize, mViewRect))
133 return kResultTrue;
134
135 auto* effectx = dynamic_cast<AudioEffectX*> (effect);
136 if (effectx && effectx->sizeWindow (newSize->getWidth (), newSize->getHeight ()))
137 {
138 result = view->onSize (newSize);
139 }
140 }
141
142 return result;
143 }
144
145 //------------------------------------------------------------------------
getRect(ERect ** rect)146 bool Vst2EditorWrapper::getRect (ERect** rect)
147 {
148 ViewRect size;
149 if (BaseEditorWrapper::getRect (size))
150 {
151 mERect.left = (VstInt16)size.left;
152 mERect.top = (VstInt16)size.top;
153 mERect.right = (VstInt16)size.right;
154 mERect.bottom = (VstInt16)size.bottom;
155
156 *rect = &mERect;
157 return true;
158 }
159
160 *rect = nullptr;
161 return false;
162 }
163
164 //------------------------------------------------------------------------
open(void * ptr)165 bool Vst2EditorWrapper::open (void* ptr)
166 {
167 AEffEditor::open (ptr);
168 return BaseEditorWrapper::_open (ptr);
169 }
170
171 //------------------------------------------------------------------------
_close()172 void Vst2EditorWrapper::_close ()
173 {
174 BaseEditorWrapper::_close ();
175 AEffEditor::close ();
176 }
177
178 //------------------------------------------------------------------------
onKeyDown(VstKeyCode & keyCode)179 bool Vst2EditorWrapper::onKeyDown (VstKeyCode& keyCode)
180 {
181 if (!mView)
182 return false;
183
184 return mView->onKeyDown (VirtualKeyCodeToChar (keyCode.virt), keyCode.virt, keyCode.modifier) ==
185 kResultTrue;
186 }
187
188 //------------------------------------------------------------------------
onKeyUp(VstKeyCode & keyCode)189 bool Vst2EditorWrapper::onKeyUp (VstKeyCode& keyCode)
190 {
191 if (!mView)
192 return false;
193
194 return mView->onKeyUp (VirtualKeyCodeToChar (keyCode.virt), keyCode.virt, keyCode.modifier) ==
195 kResultTrue;
196 }
197
198 //------------------------------------------------------------------------
onWheel(float distance)199 bool Vst2EditorWrapper::onWheel (float distance)
200 {
201 if (!mView)
202 return false;
203
204 return mView->onWheel (distance) == kResultTrue;
205 }
206
207 //------------------------------------------------------------------------
208 // Vst2MidiEventQueue Declaration
209 //------------------------------------------------------------------------
210 class Vst2MidiEventQueue
211 {
212 public:
213 //------------------------------------------------------------------------
214 Vst2MidiEventQueue (int32 maxEventCount);
215 ~Vst2MidiEventQueue ();
216
isEmpty() const217 bool isEmpty () const { return eventList->numEvents == 0; }
218 bool add (const VstMidiEvent& e);
219 bool add (const VstMidiSysexEvent& e);
220 void flush ();
221
operator VstEvents*()222 operator VstEvents* () { return eventList; }
223 //------------------------------------------------------------------------
224 protected:
225 VstEvents* eventList;
226 int32 maxEventCount;
227 };
228
229 //------------------------------------------------------------------------
230 // Vst2MidiEventQueue Implementation
231 //------------------------------------------------------------------------
Vst2MidiEventQueue(int32 _maxEventCount)232 Vst2MidiEventQueue::Vst2MidiEventQueue (int32 _maxEventCount) : maxEventCount (_maxEventCount)
233 {
234 eventList = (VstEvents*)new char[sizeof (VstEvents) + (maxEventCount - 2) * sizeof (VstEvent*)];
235 eventList->numEvents = 0;
236 eventList->reserved = 0;
237
238 auto eventSize = sizeof (VstMidiSysexEvent) > sizeof (VstMidiEvent) ?
239 sizeof (VstMidiSysexEvent) :
240 sizeof (VstMidiEvent);
241
242 for (int32 i = 0; i < maxEventCount; i++)
243 {
244 char* eventBuffer = new char[eventSize];
245 memset (eventBuffer, 0, eventSize);
246 eventList->events[i] = (VstEvent*)eventBuffer;
247 }
248 }
249
250 //------------------------------------------------------------------------
~Vst2MidiEventQueue()251 Vst2MidiEventQueue::~Vst2MidiEventQueue ()
252 {
253 for (int32 i = 0; i < maxEventCount; i++)
254 delete[] (char*) eventList->events[i];
255
256 delete[] (char*) eventList;
257 }
258
259 //------------------------------------------------------------------------
add(const VstMidiEvent & e)260 bool Vst2MidiEventQueue::add (const VstMidiEvent& e)
261 {
262 if (eventList->numEvents >= maxEventCount)
263 return false;
264
265 auto* dst = (VstMidiEvent*)eventList->events[eventList->numEvents++];
266 memcpy (dst, &e, sizeof (VstMidiEvent));
267 dst->type = kVstMidiType;
268 dst->byteSize = sizeof (VstMidiEvent);
269 return true;
270 }
271
272 //------------------------------------------------------------------------
add(const VstMidiSysexEvent & e)273 bool Vst2MidiEventQueue::add (const VstMidiSysexEvent& e)
274 {
275 if (eventList->numEvents >= maxEventCount)
276 return false;
277
278 auto* dst = (VstMidiSysexEvent*)eventList->events[eventList->numEvents++];
279 memcpy (dst, &e, sizeof (VstMidiSysexEvent));
280 dst->type = kVstSysExType;
281 dst->byteSize = sizeof (VstMidiSysexEvent);
282 return true;
283 }
284
285 //------------------------------------------------------------------------
flush()286 void Vst2MidiEventQueue::flush ()
287 {
288 eventList->numEvents = 0;
289 }
290
291 //------------------------------------------------------------------------
292 // Vst2Wrapper
293 //------------------------------------------------------------------------
Vst2Wrapper(BaseWrapper::SVST3Config & config,audioMasterCallback audioMaster,VstInt32 vst2ID)294 Vst2Wrapper::Vst2Wrapper (BaseWrapper::SVST3Config& config, audioMasterCallback audioMaster,
295 VstInt32 vst2ID)
296 : BaseWrapper (config), AudioEffectX (audioMaster, 0, 0)
297 {
298 mUseExportedBypass = false;
299 mUseIncIndex = true;
300
301 setUniqueID (vst2ID);
302 canProcessReplacing (true); // supports replacing output
303 programsAreChunks (true);
304 }
305
306 //------------------------------------------------------------------------
~Vst2Wrapper()307 Vst2Wrapper::~Vst2Wrapper ()
308 {
309 //! editor needs to be destroyed BEFORE DeinitModule. Therefore destroy it here already
310 // instead of AudioEffect destructor
311 if (mEditor)
312 {
313 setEditor (nullptr);
314 mEditor = nullptr;
315 }
316
317 if (mVst2InputArrangement)
318 free (mVst2InputArrangement);
319 if (mVst2OutputArrangement)
320 free (mVst2OutputArrangement);
321
322 delete mVst2OutputEvents;
323 mVst2OutputEvents = nullptr;
324 }
325
326 //------------------------------------------------------------------------
init()327 bool Vst2Wrapper::init ()
328 {
329 if (strstr (mSubCategories, "Instrument"))
330 isSynth (true);
331
332 bool res = BaseWrapper::init ();
333
334 numPrograms = cEffect.numPrograms = mNumPrograms;
335
336 if (mController)
337 {
338 if (BaseEditorWrapper::hasEditor (mController))
339 {
340 auto* _editor = new Vst2EditorWrapper (this, mController);
341 _setEditor (_editor);
342 setEditor (_editor);
343 }
344 }
345 return res;
346 }
347
348 //------------------------------------------------------------------------
_canDoubleReplacing(bool val)349 void Vst2Wrapper::_canDoubleReplacing (bool val)
350 {
351 canDoubleReplacing (val);
352 }
353
354 //------------------------------------------------------------------------
_setInitialDelay(uint32 delay)355 void Vst2Wrapper::_setInitialDelay (uint32 delay)
356 {
357 setInitialDelay (static_cast<VstInt32> (delay));
358 }
359
360 //------------------------------------------------------------------------
_noTail(bool val)361 void Vst2Wrapper::_noTail (bool val)
362 {
363 noTail (val);
364 }
365
366 //------------------------------------------------------------------------
setupBuses()367 void Vst2Wrapper::setupBuses ()
368 {
369 BaseWrapper::setupBuses ();
370
371 if (mHasEventOutputBuses)
372 {
373 if (mVst2OutputEvents == nullptr)
374 mVst2OutputEvents = new Vst2MidiEventQueue (kMaxEvents);
375 }
376 else
377 {
378 if (mVst2OutputEvents)
379 {
380 delete mVst2OutputEvents;
381 mVst2OutputEvents = nullptr;
382 }
383 }
384 }
385 //------------------------------------------------------------------------
setupProcessTimeInfo()386 void Vst2Wrapper::setupProcessTimeInfo ()
387 {
388 VstTimeInfo* vst2timeInfo = AudioEffectX::getTimeInfo (0xffffffff);
389 if (vst2timeInfo)
390 {
391 const uint32 portableFlags =
392 ProcessContext::kPlaying | ProcessContext::kCycleActive | ProcessContext::kRecording |
393 ProcessContext::kSystemTimeValid | ProcessContext::kProjectTimeMusicValid |
394 ProcessContext::kBarPositionValid | ProcessContext::kCycleValid |
395 ProcessContext::kTempoValid | ProcessContext::kTimeSigValid |
396 ProcessContext::kSmpteValid | ProcessContext::kClockValid;
397
398 mProcessContext.state = ((uint32)vst2timeInfo->flags) & portableFlags;
399 mProcessContext.sampleRate = vst2timeInfo->sampleRate;
400 mProcessContext.projectTimeSamples = (TSamples)vst2timeInfo->samplePos;
401
402 if (mProcessContext.state & ProcessContext::kSystemTimeValid)
403 mProcessContext.systemTime = (TSamples)vst2timeInfo->nanoSeconds;
404 else
405 mProcessContext.systemTime = 0;
406
407 if (mProcessContext.state & ProcessContext::kProjectTimeMusicValid)
408 mProcessContext.projectTimeMusic = vst2timeInfo->ppqPos;
409 else
410 mProcessContext.projectTimeMusic = 0;
411
412 if (mProcessContext.state & ProcessContext::kBarPositionValid)
413 mProcessContext.barPositionMusic = vst2timeInfo->barStartPos;
414 else
415 mProcessContext.barPositionMusic = 0;
416
417 if (mProcessContext.state & ProcessContext::kCycleValid)
418 {
419 mProcessContext.cycleStartMusic = vst2timeInfo->cycleStartPos;
420 mProcessContext.cycleEndMusic = vst2timeInfo->cycleEndPos;
421 }
422 else
423 mProcessContext.cycleStartMusic = mProcessContext.cycleEndMusic = 0.0;
424
425 if (mProcessContext.state & ProcessContext::kTempoValid)
426 mProcessContext.tempo = vst2timeInfo->tempo;
427 else
428 mProcessContext.tempo = 120.0;
429
430 if (mProcessContext.state & ProcessContext::kTimeSigValid)
431 {
432 mProcessContext.timeSigNumerator = vst2timeInfo->timeSigNumerator;
433 mProcessContext.timeSigDenominator = vst2timeInfo->timeSigDenominator;
434 }
435 else
436 mProcessContext.timeSigNumerator = mProcessContext.timeSigDenominator = 4;
437
438 mProcessContext.frameRate.flags = 0;
439 if (mProcessContext.state & ProcessContext::kSmpteValid)
440 {
441 mProcessContext.smpteOffsetSubframes = vst2timeInfo->smpteOffset;
442 switch (vst2timeInfo->smpteFrameRate)
443 {
444 case kVstSmpte24fps: ///< 24 fps
445 mProcessContext.frameRate.framesPerSecond = 24;
446 break;
447 case kVstSmpte25fps: ///< 25 fps
448 mProcessContext.frameRate.framesPerSecond = 25;
449 break;
450 case kVstSmpte2997fps: ///< 29.97 fps
451 mProcessContext.frameRate.framesPerSecond = 30;
452 mProcessContext.frameRate.flags = FrameRate::kPullDownRate;
453 break;
454 case kVstSmpte30fps: ///< 30 fps
455 mProcessContext.frameRate.framesPerSecond = 30;
456 break;
457 case kVstSmpte2997dfps: ///< 29.97 drop
458 mProcessContext.frameRate.framesPerSecond = 30;
459 mProcessContext.frameRate.flags =
460 FrameRate::kPullDownRate | FrameRate::kDropRate;
461 break;
462 case kVstSmpte30dfps: ///< 30 drop
463 mProcessContext.frameRate.framesPerSecond = 30;
464 mProcessContext.frameRate.flags = FrameRate::kDropRate;
465 break;
466 case kVstSmpteFilm16mm: // not a smpte rate
467 case kVstSmpteFilm35mm:
468 mProcessContext.state &= ~ProcessContext::kSmpteValid;
469 break;
470 case kVstSmpte239fps: ///< 23.9 fps
471 mProcessContext.frameRate.framesPerSecond = 24;
472 mProcessContext.frameRate.flags = FrameRate::kPullDownRate;
473 break;
474 case kVstSmpte249fps: ///< 24.9 fps
475 mProcessContext.frameRate.framesPerSecond = 25;
476 mProcessContext.frameRate.flags = FrameRate::kPullDownRate;
477 break;
478 case kVstSmpte599fps: ///< 59.9 fps
479 mProcessContext.frameRate.framesPerSecond = 60;
480 mProcessContext.frameRate.flags = FrameRate::kPullDownRate;
481 break;
482 case kVstSmpte60fps: ///< 60 fps
483 mProcessContext.frameRate.framesPerSecond = 60;
484 break;
485 default: mProcessContext.state &= ~ProcessContext::kSmpteValid; break;
486 }
487 }
488 else
489 {
490 mProcessContext.smpteOffsetSubframes = 0;
491 mProcessContext.frameRate.framesPerSecond = 0;
492 }
493
494 ///< MIDI Clock Resolution (24 Per Quarter Note), can be negative (nearest)
495 if (mProcessContext.state & ProcessContext::kClockValid)
496 mProcessContext.samplesToNextClock = vst2timeInfo->samplesToNextClock;
497 else
498 mProcessContext.samplesToNextClock = 0;
499
500 mProcessData.processContext = &mProcessContext;
501 }
502 else
503 mProcessData.processContext = nullptr;
504 }
505
506 //------------------------------------------------------------------------
suspend()507 void Vst2Wrapper::suspend ()
508 {
509 BaseWrapper::_suspend ();
510 }
511
512 //------------------------------------------------------------------------
resume()513 void Vst2Wrapper::resume ()
514 {
515 AudioEffectX::resume ();
516 BaseWrapper::_resume ();
517
518 mChunk.setSize (0);
519 }
520
521 //------------------------------------------------------------------------
startProcess()522 VstInt32 Vst2Wrapper::startProcess ()
523 {
524 BaseWrapper::_startProcess ();
525 return 0;
526 }
527
528 //------------------------------------------------------------------------
stopProcess()529 VstInt32 Vst2Wrapper::stopProcess ()
530 {
531 BaseWrapper::_stopProcess ();
532 return 0;
533 }
534
535 //------------------------------------------------------------------------
setSampleRate(float newSamplerate)536 void Vst2Wrapper::setSampleRate (float newSamplerate)
537 {
538 BaseWrapper::_setSampleRate (newSamplerate);
539 AudioEffectX::setSampleRate (mSampleRate);
540 }
541
542 //------------------------------------------------------------------------
setBlockSize(VstInt32 newBlockSize)543 void Vst2Wrapper::setBlockSize (VstInt32 newBlockSize)
544 {
545 if (BaseWrapper::_setBlockSize (newBlockSize))
546 AudioEffectX::setBlockSize (newBlockSize);
547 }
548
549 //------------------------------------------------------------------------
getParameter(VstInt32 index)550 float Vst2Wrapper::getParameter (VstInt32 index)
551 {
552 return BaseWrapper::_getParameter (index);
553 }
554
555 //------------------------------------------------------------------------
setParameter(VstInt32 index,float value)556 void Vst2Wrapper::setParameter (VstInt32 index, float value)
557 {
558 if (!mController)
559 return;
560
561 if (index < (int32)mParameterMap.size ())
562 {
563 ParamID id = mParameterMap.at (index).vst3ID;
564 addParameterChange (id, (ParamValue)value, 0);
565 }
566 }
567
568 //------------------------------------------------------------------------
setProgram(VstInt32 program)569 void Vst2Wrapper::setProgram (VstInt32 program)
570 {
571 if (mProgramParameterID != kNoParamId && mController != nullptr && mProgramParameterIdx != -1)
572 {
573 AudioEffectX::setProgram (program);
574
575 ParameterInfo paramInfo = {0};
576 if (mController->getParameterInfo (mProgramParameterIdx, paramInfo) == kResultTrue)
577 {
578 if (paramInfo.stepCount > 0 && program <= paramInfo.stepCount)
579 {
580 ParamValue normalized = (ParamValue)program / (ParamValue)paramInfo.stepCount;
581 addParameterChange (mProgramParameterID, normalized, 0);
582 }
583 }
584 }
585 }
586
587 //------------------------------------------------------------------------
setProgramName(char *)588 void Vst2Wrapper::setProgramName (char* /*name*/)
589 {
590 // not supported in VST 3
591 }
592
593 //------------------------------------------------------------------------
getProgramName(char * name)594 void Vst2Wrapper::getProgramName (char* name)
595 {
596 // name of the current program. Limited to #kVstMaxProgNameLen.
597 *name = 0;
598 if (mUnitInfo)
599 {
600 ProgramListInfo listInfo = {0};
601 if (mUnitInfo->getProgramListInfo (0, listInfo) == kResultTrue)
602 {
603 String128 tmp = {0};
604 if (mUnitInfo->getProgramName (listInfo.id, curProgram, tmp) == kResultTrue)
605 {
606 String str (tmp);
607 str.copyTo8 (name, 0, kVstMaxProgNameLen);
608 }
609 }
610 }
611 }
612
613 //------------------------------------------------------------------------
getProgramNameIndexed(VstInt32,VstInt32 index,char * name)614 bool Vst2Wrapper::getProgramNameIndexed (VstInt32, VstInt32 index, char* name)
615 {
616 *name = 0;
617 if (mUnitInfo)
618 {
619 ProgramListInfo listInfo = {0};
620 if (mUnitInfo->getProgramListInfo (0, listInfo) == kResultTrue)
621 {
622 String128 tmp = {0};
623 if (mUnitInfo->getProgramName (listInfo.id, index, tmp) == kResultTrue)
624 {
625 String str (tmp);
626 str.copyTo8 (name, 0, kVstMaxProgNameLen);
627 return true;
628 }
629 }
630 }
631
632 return false;
633 }
634
635 //------------------------------------------------------------------------
getParameterLabel(VstInt32 index,char * label)636 void Vst2Wrapper::getParameterLabel (VstInt32 index, char* label)
637 {
638 // units in which parameter \e index is displayed (i.e. "sec", "dB", "type", etc...). Limited to
639 // #kVstMaxParamStrLen.
640 *label = 0;
641 if (mController)
642 {
643 int32 vst3Index = mParameterMap.at (index).vst3Index;
644
645 ParameterInfo paramInfo = {0};
646 if (mController->getParameterInfo (vst3Index, paramInfo) == kResultTrue)
647 {
648 String str (paramInfo.units);
649 str.copyTo8 (label, 0, kVstMaxParamStrLen);
650 }
651 }
652 }
653
654 //------------------------------------------------------------------------
getParameterDisplay(VstInt32 index,char * text)655 void Vst2Wrapper::getParameterDisplay (VstInt32 index, char* text)
656 {
657 // string representation ("0.5", "-3", "PLATE", etc...) of the value of parameter \e index.
658 // Limited to #kVstMaxParamStrLen.
659 *text = 0;
660 if (mController)
661 {
662 int32 vst3Index = mParameterMap.at (index).vst3Index;
663
664 ParameterInfo paramInfo = {0};
665 if (mController->getParameterInfo (vst3Index, paramInfo) == kResultTrue)
666 {
667 String128 tmp = {0};
668 ParamValue value = 0;
669 if (!getLastParamChange (paramInfo.id, value))
670 value = mController->getParamNormalized (paramInfo.id);
671
672 if (mController->getParamStringByValue (paramInfo.id, value, tmp) == kResultTrue)
673 {
674 String str (tmp);
675 str.copyTo8 (text, 0, kVstMaxParamStrLen);
676 }
677 }
678 }
679 }
680
681 //------------------------------------------------------------------------
getParameterName(VstInt32 index,char * text)682 void Vst2Wrapper::getParameterName (VstInt32 index, char* text)
683 {
684 // name ("Time", "Gain", "RoomType", etc...) of parameter \e index. Limited to
685 // #kVstExtMaxParamStrLen.
686 *text = 0;
687 if (mController && index < (int32)mParameterMap.size ())
688 {
689 int32 vst3Index = mParameterMap.at (index).vst3Index;
690
691 ParameterInfo paramInfo = {0};
692 if (mController->getParameterInfo (vst3Index, paramInfo) == kResultTrue)
693 {
694 String str;
695 if (vst2WrapperFullParameterPath)
696 {
697 //! The parameter's name contains the unit path (e.g. "LFO 1.freq") as well
698 if (mUnitInfo)
699 {
700 getUnitPath (paramInfo.unitId, str);
701 }
702 }
703 str.append (paramInfo.title);
704
705 if (str.length () > kVstExtMaxParamStrLen)
706 {
707 //! In case the string's length exceeds the limit, try parameter's title without
708 // unit path.
709 str = paramInfo.title;
710 }
711 if (str.length () > kVstExtMaxParamStrLen)
712 {
713 str = paramInfo.shortTitle;
714 }
715 str.copyTo8 (text, 0, kVstExtMaxParamStrLen);
716 }
717 }
718 }
719
720 //------------------------------------------------------------------------
canParameterBeAutomated(VstInt32 index)721 bool Vst2Wrapper::canParameterBeAutomated (VstInt32 index)
722 {
723 if (mController && index < (int32)mParameterMap.size ())
724 {
725 int32 vst3Index = mParameterMap.at (index).vst3Index;
726
727 ParameterInfo paramInfo = {0};
728 if (mController->getParameterInfo (vst3Index, paramInfo) == kResultTrue)
729 return (paramInfo.flags & ParameterInfo::kCanAutomate) != 0;
730 }
731 return false;
732 }
733
734 //------------------------------------------------------------------------
string2parameter(VstInt32 index,char * text)735 bool Vst2Wrapper::string2parameter (VstInt32 index, char* text)
736 {
737 if (mController && index < (int32)mParameterMap.size ())
738 {
739 int32 vst3Index = mParameterMap.at (index).vst3Index;
740
741 ParameterInfo paramInfo = {0};
742 if (mController->getParameterInfo (vst3Index, paramInfo) == kResultTrue)
743 {
744 TChar tString[1024] = {0};
745 String tmp (text);
746 tmp.copyTo16 (tString, 0, 1023);
747
748 ParamValue valueNormalized = 0.0;
749
750 if (mController->getParamValueByString (paramInfo.id, tString, valueNormalized))
751 {
752 setParameterAutomated (index, (float)valueNormalized);
753 // TODO: check if setParameterAutomated is correct
754 }
755 }
756 }
757 return false;
758 }
759
760 //------------------------------------------------------------------------
getParameterProperties(VstInt32 index,VstParameterProperties * p)761 bool Vst2Wrapper::getParameterProperties (VstInt32 index, VstParameterProperties* p)
762 {
763 if (mController && index < (int32)mParameterMap.size ())
764 {
765 p->label[0] = 0;
766 p->shortLabel[0] = 0;
767
768 int32 vst3Index = mParameterMap.at (index).vst3Index;
769
770 ParameterInfo paramInfo = {0};
771 if (mController->getParameterInfo (vst3Index, paramInfo) == kResultTrue)
772 {
773 String str (paramInfo.title);
774 str.copyTo8 (p->label, 0, kVstMaxLabelLen);
775
776 String str2 (paramInfo.shortTitle);
777 str.copyTo8 (p->shortLabel, 0, kVstMaxShortLabelLen);
778
779 if (paramInfo.stepCount == 0) // continuous
780 {
781 p->flags |= kVstParameterCanRamp;
782 }
783 else if (paramInfo.stepCount == 1) // on / off
784 {
785 p->flags |= kVstParameterIsSwitch;
786 }
787 else
788 {
789 p->minInteger = 0;
790 p->maxInteger = paramInfo.stepCount;
791 p->flags |= kVstParameterUsesIntegerMinMax;
792 }
793
794 return true;
795 }
796 }
797 return false;
798 }
799
800 //------------------------------------------------------------------------
getChunk(void ** data,bool isPreset)801 VstInt32 Vst2Wrapper::getChunk (void** data, bool isPreset)
802 {
803 return BaseWrapper::_getChunk (data, isPreset);
804 }
805
806 //------------------------------------------------------------------------
setChunk(void * data,VstInt32 byteSize,bool isPreset)807 VstInt32 Vst2Wrapper::setChunk (void* data, VstInt32 byteSize, bool isPreset)
808 {
809 return BaseWrapper::_setChunk (data, byteSize, isPreset);
810 }
811
812 //------------------------------------------------------------------------
vst3ToVst2SpeakerArr(SpeakerArrangement vst3Arr)813 VstInt32 Vst2Wrapper::vst3ToVst2SpeakerArr (SpeakerArrangement vst3Arr)
814 {
815 switch (vst3Arr)
816 {
817 case SpeakerArr::kMono: return kSpeakerArrMono;
818 case SpeakerArr::kStereo: return kSpeakerArrStereo;
819 case SpeakerArr::kStereoSurround: return kSpeakerArrStereoSurround;
820 case SpeakerArr::kStereoCenter: return kSpeakerArrStereoCenter;
821 case SpeakerArr::kStereoSide: return kSpeakerArrStereoSide;
822 case SpeakerArr::kStereoCLfe: return kSpeakerArrStereoCLfe;
823 case SpeakerArr::k30Cine: return kSpeakerArr30Cine;
824 case SpeakerArr::k30Music: return kSpeakerArr30Music;
825 case SpeakerArr::k31Cine: return kSpeakerArr31Cine;
826 case SpeakerArr::k31Music: return kSpeakerArr31Music;
827 case SpeakerArr::k40Cine: return kSpeakerArr40Cine;
828 case SpeakerArr::k40Music: return kSpeakerArr40Music;
829 case SpeakerArr::k41Cine: return kSpeakerArr41Cine;
830 case SpeakerArr::k41Music: return kSpeakerArr41Music;
831 case SpeakerArr::k50: return kSpeakerArr50;
832 case SpeakerArr::k51: return kSpeakerArr51;
833 case SpeakerArr::k60Cine: return kSpeakerArr60Cine;
834 case SpeakerArr::k60Music: return kSpeakerArr60Music;
835 case SpeakerArr::k61Cine: return kSpeakerArr61Cine;
836 case SpeakerArr::k61Music: return kSpeakerArr61Music;
837 case SpeakerArr::k70Cine: return kSpeakerArr70Cine;
838 case SpeakerArr::k70Music: return kSpeakerArr70Music;
839 case SpeakerArr::k71Cine: return kSpeakerArr71Cine;
840 case SpeakerArr::k71Music: return kSpeakerArr71Music;
841 case SpeakerArr::k80Cine: return kSpeakerArr80Cine;
842 case SpeakerArr::k80Music: return kSpeakerArr80Music;
843 case SpeakerArr::k81Cine: return kSpeakerArr81Cine;
844 case SpeakerArr::k81Music: return kSpeakerArr81Music;
845 case SpeakerArr::k102: return kSpeakerArr102;
846 }
847
848 return kSpeakerArrUserDefined;
849 }
850
851 //------------------------------------------------------------------------
vst2ToVst3SpeakerArr(VstInt32 vst2Arr)852 SpeakerArrangement Vst2Wrapper::vst2ToVst3SpeakerArr (VstInt32 vst2Arr)
853 {
854 switch (vst2Arr)
855 {
856 case kSpeakerArrMono: return SpeakerArr::kMono;
857 case kSpeakerArrStereo: return SpeakerArr::kStereo;
858 case kSpeakerArrStereoSurround: return SpeakerArr::kStereoSurround;
859 case kSpeakerArrStereoCenter: return SpeakerArr::kStereoCenter;
860 case kSpeakerArrStereoSide: return SpeakerArr::kStereoSide;
861 case kSpeakerArrStereoCLfe: return SpeakerArr::kStereoCLfe;
862 case kSpeakerArr30Cine: return SpeakerArr::k30Cine;
863 case kSpeakerArr30Music: return SpeakerArr::k30Music;
864 case kSpeakerArr31Cine: return SpeakerArr::k31Cine;
865 case kSpeakerArr31Music: return SpeakerArr::k31Music;
866 case kSpeakerArr40Cine: return SpeakerArr::k40Cine;
867 case kSpeakerArr40Music: return SpeakerArr::k40Music;
868 case kSpeakerArr41Cine: return SpeakerArr::k41Cine;
869 case kSpeakerArr41Music: return SpeakerArr::k41Music;
870 case kSpeakerArr50: return SpeakerArr::k50;
871 case kSpeakerArr51: return SpeakerArr::k51;
872 case kSpeakerArr60Cine: return SpeakerArr::k60Cine;
873 case kSpeakerArr60Music: return SpeakerArr::k60Music;
874 case kSpeakerArr61Cine: return SpeakerArr::k61Cine;
875 case kSpeakerArr61Music: return SpeakerArr::k61Music;
876 case kSpeakerArr70Cine: return SpeakerArr::k70Cine;
877 case kSpeakerArr70Music: return SpeakerArr::k70Music;
878 case kSpeakerArr71Cine: return SpeakerArr::k71Cine;
879 case kSpeakerArr71Music: return SpeakerArr::k71Music;
880 case kSpeakerArr80Cine: return SpeakerArr::k80Cine;
881 case kSpeakerArr80Music: return SpeakerArr::k80Music;
882 case kSpeakerArr81Cine: return SpeakerArr::k81Cine;
883 case kSpeakerArr81Music: return SpeakerArr::k81Music;
884 case kSpeakerArr102: return SpeakerArr::k102;
885 }
886
887 return 0;
888 }
889
890 //------------------------------------------------------------------------
vst3ToVst2Speaker(Vst::Speaker vst3Speaker)891 VstInt32 Vst2Wrapper::vst3ToVst2Speaker (Vst::Speaker vst3Speaker)
892 {
893 switch (vst3Speaker)
894 {
895 case Vst::kSpeakerM: return ::kSpeakerM;
896 case Vst::kSpeakerL: return ::kSpeakerL;
897 case Vst::kSpeakerR: return ::kSpeakerR;
898 case Vst::kSpeakerC: return ::kSpeakerC;
899 case Vst::kSpeakerLfe: return ::kSpeakerLfe;
900 case Vst::kSpeakerLs: return ::kSpeakerLs;
901 case Vst::kSpeakerRs: return ::kSpeakerRs;
902 case Vst::kSpeakerLc: return ::kSpeakerLc;
903 case Vst::kSpeakerRc: return ::kSpeakerRc;
904 case Vst::kSpeakerS: return ::kSpeakerS;
905 case Vst::kSpeakerSl: return ::kSpeakerSl;
906 case Vst::kSpeakerSr: return ::kSpeakerSr;
907 case Vst::kSpeakerTc: return ::kSpeakerTm;
908 case Vst::kSpeakerTfl: return ::kSpeakerTfl;
909 case Vst::kSpeakerTfc: return ::kSpeakerTfc;
910 case Vst::kSpeakerTfr: return ::kSpeakerTfr;
911 case Vst::kSpeakerTrl: return ::kSpeakerTrl;
912 case Vst::kSpeakerTrc: return ::kSpeakerTrc;
913 case Vst::kSpeakerTrr: return ::kSpeakerTrr;
914 case Vst::kSpeakerLfe2: return ::kSpeakerLfe2;
915 }
916 return ::kSpeakerUndefined;
917 }
918
919 //------------------------------------------------------------------------
920 static const char* gSpeakerNames[] = {
921 "M", ///< Mono (M)
922 "L", ///< Left (L)
923 "R", ///< Right (R)
924 "C", ///< Center (C)
925 "Lfe", ///< Subbass (Lfe)
926 "Ls", ///< Left Surround (Ls)
927 "Rs", ///< Right Surround (Rs)
928 "Lc", ///< Left of Center (Lc)
929 "Rc", ///< Right of Center (Rc)
930 "Cs", ///< Center of Surround (Cs) = Surround (S)
931 "Sl", ///< Side Left (Sl)
932 "Sr", ///< Side Right (Sr)
933 "Tm", ///< Top Middle (Tm)
934 "Tfl", ///< Top Front Left (Tfl)
935 "Tfc", ///< Top Front Center (Tfc)
936 "Tfr", ///< Top Front Right (Tfr)
937 "Trl", ///< Top Rear Left (Trl)
938 "Trc", ///< Top Rear Center (Trc)
939 "Trr", ///< Top Rear Right (Trr)
940 "Lfe2" ///< Subbass 2 (Lfe2)
941 };
942 static const int32 kNumSpeakerNames = sizeof (gSpeakerNames) / sizeof (char*);
943
944 //------------------------------------------------------------------------
pinIndexToBusChannel(BusDirection dir,VstInt32 pinIndex,int32 & busIndex,int32 & busChannel)945 bool Vst2Wrapper::pinIndexToBusChannel (BusDirection dir, VstInt32 pinIndex, int32& busIndex,
946 int32& busChannel)
947 {
948 AudioBusBuffers* busBuffers = dir == kInput ? mProcessData.inputs : mProcessData.outputs;
949 int32 busCount = dir == kInput ? mProcessData.numInputs : mProcessData.numOutputs;
950 uint64 mainBusFlags = dir == kInput ? mMainAudioInputBuses : mMainAudioOutputBuses;
951
952 int32 sourceIndex = 0;
953 for (busIndex = 0; busIndex < busCount; busIndex++)
954 {
955 AudioBusBuffers& buffers = busBuffers[busIndex];
956 if (mainBusFlags & (uint64 (1) << busIndex))
957 {
958 for (busChannel = 0; busChannel < buffers.numChannels; busChannel++)
959 {
960 if (pinIndex == sourceIndex)
961 {
962 return true;
963 }
964 sourceIndex++;
965 }
966 }
967 }
968 return false;
969 }
970
971 //------------------------------------------------------------------------
getPinProperties(BusDirection dir,VstInt32 pinIndex,VstPinProperties * properties)972 bool Vst2Wrapper::getPinProperties (BusDirection dir, VstInt32 pinIndex,
973 VstPinProperties* properties)
974 {
975 int32 busIndex = -1;
976 int32 busChannelIndex = -1;
977
978 if (pinIndexToBusChannel (dir, pinIndex, busIndex, busChannelIndex))
979 {
980 BusInfo busInfo = {0};
981 if (mComponent && mComponent->getBusInfo (kAudio, dir, busIndex, busInfo) == kResultTrue)
982 {
983 properties->flags = kVstPinIsActive; // ????
984
985 String name (busInfo.name);
986 name.copyTo8 (properties->label, 0, kVstMaxLabelLen);
987
988 if (busInfo.channelCount == 1)
989 {
990 properties->flags |= kVstPinUseSpeaker;
991 properties->arrangementType = kSpeakerArrMono;
992 }
993 if (busInfo.channelCount == 2)
994 {
995 properties->flags |= kVstPinUseSpeaker;
996 properties->flags |= kVstPinIsStereo;
997 properties->arrangementType = kSpeakerArrStereo;
998 }
999 else if (busInfo.channelCount > 2)
1000 {
1001 Vst::SpeakerArrangement arr = 0;
1002 if (mProcessor && mProcessor->getBusArrangement (dir, busIndex, arr) == kResultTrue)
1003 {
1004 properties->flags |= kVstPinUseSpeaker;
1005 properties->arrangementType = vst3ToVst2SpeakerArr (arr);
1006 }
1007 else
1008 {
1009 return false;
1010 }
1011 }
1012
1013 return true;
1014 }
1015 }
1016
1017 return false;
1018 }
1019
1020 //------------------------------------------------------------------------
getInputProperties(VstInt32 index,VstPinProperties * properties)1021 bool Vst2Wrapper::getInputProperties (VstInt32 index, VstPinProperties* properties)
1022 {
1023 return getPinProperties (kInput, index, properties);
1024 }
1025
1026 //------------------------------------------------------------------------
getOutputProperties(VstInt32 index,VstPinProperties * properties)1027 bool Vst2Wrapper::getOutputProperties (VstInt32 index, VstPinProperties* properties)
1028 {
1029 return getPinProperties (kOutput, index, properties);
1030 }
1031
1032 //------------------------------------------------------------------------
setSpeakerArrangement(VstSpeakerArrangement * pluginInput,VstSpeakerArrangement * pluginOutput)1033 bool Vst2Wrapper::setSpeakerArrangement (VstSpeakerArrangement* pluginInput,
1034 VstSpeakerArrangement* pluginOutput)
1035 {
1036 if (!mProcessor || !mComponent)
1037 return false;
1038
1039 Vst::SpeakerArrangement newInputArr = 0;
1040 Vst::SpeakerArrangement newOutputArr = 0;
1041 Vst::SpeakerArrangement outputArr = 0;
1042 Vst::SpeakerArrangement inputArr = 0;
1043
1044 int32 inputBusCount = mComponent->getBusCount (kAudio, kInput);
1045 int32 outputBusCount = mComponent->getBusCount (kAudio, kOutput);
1046
1047 if (inputBusCount > 0)
1048 if (mProcessor->getBusArrangement (kInput, 0, inputArr) != kResultTrue)
1049 return false;
1050 if (outputBusCount > 0)
1051 if (mProcessor->getBusArrangement (kOutput, 0, outputArr) != kResultTrue)
1052 return false;
1053
1054 if (pluginInput)
1055 {
1056 newInputArr = vst2ToVst3SpeakerArr (pluginInput->type);
1057 if (newInputArr == 0)
1058 return false;
1059 }
1060 if (pluginOutput)
1061 {
1062 newOutputArr = vst2ToVst3SpeakerArr (pluginOutput->type);
1063 if (newOutputArr == 0)
1064 return false;
1065 }
1066
1067 if (newInputArr == 0)
1068 newInputArr = inputArr;
1069 if (newOutputArr == 0)
1070 newOutputArr = outputArr;
1071
1072 if (newInputArr != inputArr || newOutputArr != outputArr)
1073 {
1074 if (mProcessor->setBusArrangements (
1075 &newInputArr, (newInputArr > 0 && inputBusCount > 0) ? 1 : 0, &newOutputArr,
1076 (newOutputArr > 0 && outputBusCount > 0) ? 1 : 0) != kResultTrue)
1077 return false;
1078
1079 restartComponent (kIoChanged);
1080 }
1081
1082 return true;
1083 }
1084
1085 //------------------------------------------------------------------------
setupVst2Arrangement(VstSpeakerArrangement * & vst2arr,Vst::SpeakerArrangement vst3Arrangement)1086 void Vst2Wrapper::setupVst2Arrangement (VstSpeakerArrangement*& vst2arr,
1087 Vst::SpeakerArrangement vst3Arrangement)
1088 {
1089 int32 numChannels = Vst::SpeakerArr::getChannelCount (vst3Arrangement);
1090
1091 if (vst2arr && (numChannels == 0 || (numChannels > vst2arr->numChannels && numChannels > 8)))
1092 {
1093 free (vst2arr);
1094 vst2arr = nullptr;
1095 if (numChannels == 0)
1096 return;
1097 }
1098
1099 if (vst2arr == nullptr)
1100 {
1101 int32 channelOverhead = numChannels > 8 ? numChannels - 8 : 0;
1102 uint32 structSize =
1103 sizeof (VstSpeakerArrangement) + channelOverhead * sizeof (VstSpeakerProperties);
1104 vst2arr = (VstSpeakerArrangement*)malloc (structSize);
1105 memset (vst2arr, 0, structSize);
1106 }
1107
1108 if (vst2arr)
1109 {
1110 vst2arr->type = vst3ToVst2SpeakerArr (vst3Arrangement);
1111 vst2arr->numChannels = numChannels;
1112
1113 Speaker vst3TestSpeaker = 1;
1114
1115 for (int32 i = 0; i < numChannels; i++)
1116 {
1117 VstSpeakerProperties& props = vst2arr->speakers[i];
1118
1119 // find nextSpeaker in vst3 arrangement
1120 Speaker vst3Speaker = 0;
1121 while (vst3Speaker == 0 && vst3TestSpeaker != 0)
1122 {
1123 if (vst3Arrangement & vst3TestSpeaker)
1124 vst3Speaker = vst3TestSpeaker;
1125
1126 vst3TestSpeaker <<= 1;
1127 }
1128
1129 if (vst3Speaker)
1130 {
1131 props.type = vst3ToVst2Speaker (vst3Speaker);
1132 if (props.type >= 0 && props.type < kNumSpeakerNames)
1133 strncpy (props.name, gSpeakerNames[props.type], kVstMaxNameLen);
1134 else
1135 sprintf (props.name, "%ld", i + 1);
1136 }
1137 }
1138 }
1139 }
1140
1141 //------------------------------------------------------------------------
getSpeakerArrangement(VstSpeakerArrangement ** pluginInput,VstSpeakerArrangement ** pluginOutput)1142 bool Vst2Wrapper::getSpeakerArrangement (VstSpeakerArrangement** pluginInput,
1143 VstSpeakerArrangement** pluginOutput)
1144 {
1145 if (!mProcessor)
1146 return false;
1147
1148 Vst::SpeakerArrangement inputArr = 0;
1149 Vst::SpeakerArrangement outputArr = 0;
1150
1151 if (mProcessor->getBusArrangement (kInput, 0, inputArr) != kResultTrue)
1152 inputArr = 0;
1153
1154 if (mProcessor->getBusArrangement (kOutput, 0, outputArr) != kResultTrue)
1155 outputArr = 0;
1156
1157 setupVst2Arrangement (mVst2InputArrangement, inputArr);
1158 setupVst2Arrangement (mVst2OutputArrangement, outputArr);
1159
1160 *pluginInput = mVst2InputArrangement;
1161 *pluginOutput = mVst2OutputArrangement;
1162
1163 return mVst2InputArrangement != nullptr && mVst2OutputArrangement != nullptr;
1164 }
1165
1166 //------------------------------------------------------------------------
setBypass(bool onOff)1167 bool Vst2Wrapper::setBypass (bool onOff)
1168 {
1169 return BaseWrapper::_setBypass (onOff);
1170 }
1171
1172 //-----------------------------------------------------------------------------
setProcessPrecision(VstInt32 precision)1173 bool Vst2Wrapper::setProcessPrecision (VstInt32 precision)
1174 {
1175 int32 newVst3SampleSize = -1;
1176
1177 if (precision == kVstProcessPrecision32)
1178 newVst3SampleSize = kSample32;
1179 else if (precision == kVstProcessPrecision64)
1180 newVst3SampleSize = kSample64;
1181
1182 if (newVst3SampleSize != mVst3SampleSize)
1183 {
1184 if (mProcessor && mProcessor->canProcessSampleSize (newVst3SampleSize) == kResultTrue)
1185 {
1186 mVst3SampleSize = newVst3SampleSize;
1187 setupProcessing ();
1188
1189 setupBuses ();
1190
1191 return true;
1192 }
1193 return false;
1194 }
1195 return true;
1196 }
1197
1198 //-----------------------------------------------------------------------------
getNumMidiInputChannels()1199 VstInt32 Vst2Wrapper::getNumMidiInputChannels ()
1200 {
1201 if (!mComponent)
1202 return 0;
1203
1204 int32 busCount = mComponent->getBusCount (kEvent, kInput);
1205 if (busCount > 0)
1206 {
1207 BusInfo busInfo = {0};
1208 if (mComponent->getBusInfo (kEvent, kInput, 0, busInfo) == kResultTrue)
1209 {
1210 return busInfo.channelCount;
1211 }
1212 }
1213 return 0;
1214 }
1215
1216 //-----------------------------------------------------------------------------
getNumMidiOutputChannels()1217 VstInt32 Vst2Wrapper::getNumMidiOutputChannels ()
1218 {
1219 if (!mComponent)
1220 return 0;
1221
1222 int32 busCount = mComponent->getBusCount (kEvent, kOutput);
1223 if (busCount > 0)
1224 {
1225 BusInfo busInfo = {0};
1226 if (mComponent->getBusInfo (kEvent, kOutput, 0, busInfo) == kResultTrue)
1227 {
1228 return busInfo.channelCount;
1229 }
1230 }
1231 return 0;
1232 }
1233
1234 //-----------------------------------------------------------------------------
getGetTailSize()1235 VstInt32 Vst2Wrapper::getGetTailSize ()
1236 {
1237 if (mProcessor)
1238 return static_cast<VstInt32> (mProcessor->getTailSamples ());
1239
1240 return 0;
1241 }
1242
1243 //-----------------------------------------------------------------------------
getEffectName(char * effectName)1244 bool Vst2Wrapper::getEffectName (char* effectName)
1245 {
1246 if (mName[0])
1247 {
1248 strncpy (effectName, mName, kVstMaxEffectNameLen);
1249 return true;
1250 }
1251 return false;
1252 }
1253
1254 //-----------------------------------------------------------------------------
getVendorString(char * text)1255 bool Vst2Wrapper::getVendorString (char* text)
1256 {
1257 if (mVendor[0])
1258 {
1259 strncpy (text, mVendor, kVstMaxVendorStrLen);
1260 return true;
1261 }
1262 return false;
1263 }
1264
1265 //-----------------------------------------------------------------------------
getVendorVersion()1266 VstInt32 Vst2Wrapper::getVendorVersion ()
1267 {
1268 return mVersion;
1269 }
1270
1271 //-----------------------------------------------------------------------------
vendorSpecific(VstInt32 lArg,VstIntPtr lArg2,void * ptrArg,float floatArg)1272 VstIntPtr Vst2Wrapper::vendorSpecific (VstInt32 lArg, VstIntPtr lArg2, void* ptrArg, float floatArg)
1273 {
1274 switch (lArg)
1275 {
1276 case 'stCA':
1277 case 'stCa':
1278 switch (lArg2)
1279 {
1280 //--- -------
1281 case 'FUID':
1282 if (ptrArg && mVst3EffectClassID.isValid ())
1283 {
1284 memcpy ((char*)ptrArg, mVst3EffectClassID, 16);
1285 return 1;
1286 }
1287 break;
1288 //--- -------
1289 case 'Whee':
1290 if (editor)
1291 editor->onWheel (floatArg);
1292 return 1;
1293 break;
1294 }
1295 }
1296
1297 return AudioEffectX::vendorSpecific (lArg, lArg2, ptrArg, floatArg);
1298 }
1299
1300 //-----------------------------------------------------------------------------
getPlugCategory()1301 VstPlugCategory Vst2Wrapper::getPlugCategory ()
1302 {
1303 if (mSubCategories[0])
1304 {
1305 if (strstr (mSubCategories, "Analyzer"))
1306 return kPlugCategAnalysis;
1307
1308 else if (strstr (mSubCategories, "Delay") || strstr (mSubCategories, "Reverb"))
1309 return kPlugCategRoomFx;
1310
1311 else if (strstr (mSubCategories, "Dynamics") || strstr (mSubCategories, "Mastering"))
1312 return kPlugCategMastering;
1313
1314 else if (strstr (mSubCategories, "Restoration"))
1315 return kPlugCategRestoration;
1316
1317 else if (strstr (mSubCategories, "Generator"))
1318 return kPlugCategGenerator;
1319
1320 else if (strstr (mSubCategories, "Spatial"))
1321 return kPlugCategSpacializer;
1322
1323 else if (strstr (mSubCategories, "Fx"))
1324 return kPlugCategEffect;
1325
1326 else if (strstr (mSubCategories, "Instrument"))
1327 return kPlugCategSynth;
1328 }
1329 return kPlugCategUnknown;
1330 }
1331
1332 //-----------------------------------------------------------------------------
canDo(char * text)1333 VstInt32 Vst2Wrapper::canDo (char* text)
1334 {
1335 if (stricmp (text, "sendVstEvents") == 0)
1336 {
1337 return -1;
1338 }
1339 else if (stricmp (text, "sendVstMidiEvent") == 0)
1340 {
1341 return mHasEventOutputBuses ? 1 : -1;
1342 }
1343 else if (stricmp (text, "receiveVstEvents") == 0)
1344 {
1345 return -1;
1346 }
1347 else if (stricmp (text, "receiveVstMidiEvent") == 0)
1348 {
1349 return mHasEventInputBuses ? 1 : -1;
1350 }
1351 else if (stricmp (text, "receiveVstTimeInfo") == 0)
1352 {
1353 return 1;
1354 }
1355 else if (stricmp (text, "offline") == 0)
1356 {
1357 if (mProcessing)
1358 return 0;
1359 if (mVst3processMode == kOffline)
1360 return 1;
1361
1362 bool canOffline = setupProcessing (kOffline);
1363 setupProcessing ();
1364 return canOffline ? 1 : -1;
1365 }
1366 else if (stricmp (text, "midiProgramNames") == 0)
1367 {
1368 if (mUnitInfo)
1369 {
1370 UnitID unitId = -1;
1371 if (mUnitInfo->getUnitByBus (kEvent, kInput, 0, 0, unitId) == kResultTrue &&
1372 unitId >= 0)
1373 return 1;
1374 }
1375 return -1;
1376 }
1377 else if (stricmp (text, "bypass") == 0)
1378 {
1379 return mBypassParameterID != kNoParamId ? 1 : -1;
1380 }
1381 return 0; // do not know
1382 }
1383
1384 //-----------------------------------------------------------------------------
getMidiProgramName(VstInt32 channel,MidiProgramName * midiProgramName)1385 VstInt32 Vst2Wrapper::getMidiProgramName (VstInt32 channel, MidiProgramName* midiProgramName)
1386 {
1387 UnitID unitId;
1388 ProgramListID programListId;
1389 if (mUnitInfo && getProgramListAndUnit (channel, unitId, programListId))
1390 {
1391 if (midiProgramName)
1392 setupMidiProgram (channel, programListId, *midiProgramName);
1393
1394 ProgramListInfo programListInfo;
1395 if (getProgramListInfoByProgramListID (programListId, programListInfo))
1396 return programListInfo.programCount;
1397 }
1398 return 0;
1399 }
1400
1401 //-----------------------------------------------------------------------------
getCurrentMidiProgram(VstInt32 channel,MidiProgramName * currentProgram)1402 VstInt32 Vst2Wrapper::getCurrentMidiProgram (VstInt32 channel, MidiProgramName* currentProgram)
1403 {
1404 if (mUnitInfo && mController)
1405 {
1406 UnitID unitId;
1407 ProgramListID programListId;
1408 if (getProgramListAndUnit (channel, unitId, programListId))
1409 {
1410 // find program selector parameter
1411 int32 parameterCount = mController->getParameterCount ();
1412 for (int32 i = 0; i < parameterCount; i++)
1413 {
1414 ParameterInfo parameterInfo = {0};
1415 if (mController->getParameterInfo (i, parameterInfo) == kResultTrue)
1416 {
1417 if ((parameterInfo.flags & ParameterInfo::kIsProgramChange) != 0 &&
1418 parameterInfo.unitId == unitId)
1419 {
1420 ParamValue normalized = mController->getParamNormalized (parameterInfo.id);
1421 int32 discreteValue =
1422 Min<int32> ((int32) (normalized * (parameterInfo.stepCount + 1)),
1423 parameterInfo.stepCount);
1424
1425 if (currentProgram)
1426 {
1427 currentProgram->thisProgramIndex = discreteValue;
1428 setupMidiProgram (channel, programListId, *currentProgram);
1429 }
1430
1431 return discreteValue;
1432 }
1433 }
1434 }
1435 }
1436 }
1437
1438 return 0;
1439 }
1440
1441 //-----------------------------------------------------------------------------
setupMidiProgram(int32 midiChannel,ProgramListID programListId,MidiProgramName & midiProgramName)1442 bool Vst2Wrapper::setupMidiProgram (int32 midiChannel, ProgramListID programListId,
1443 MidiProgramName& midiProgramName)
1444 {
1445 if (mUnitInfo)
1446 {
1447 String128 string128 = {0};
1448
1449 if (mUnitInfo->getProgramName (programListId, midiProgramName.thisProgramIndex,
1450 string128) == kResultTrue)
1451 {
1452 String str (string128);
1453 str.copyTo8 (midiProgramName.name, 0, 64);
1454
1455 midiProgramName.midiProgram = static_cast<char8> (midiProgramName.thisProgramIndex);
1456 midiProgramName.midiBankMsb = -1;
1457 midiProgramName.midiBankLsb = -1;
1458 midiProgramName.parentCategoryIndex = -1;
1459 midiProgramName.flags = 0;
1460
1461 if (mUnitInfo->getProgramInfo (programListId, midiProgramName.thisProgramIndex,
1462 PresetAttributes::kInstrument, string128) == kResultTrue)
1463 {
1464 midiProgramName.parentCategoryIndex =
1465 lookupProgramCategory (midiChannel, string128);
1466 }
1467 return true;
1468 }
1469 }
1470 return false;
1471 }
1472
1473 //-----------------------------------------------------------------------------
lookupProgramCategory(int32 midiChannel,String128 instrumentAttribute)1474 int32 Vst2Wrapper::lookupProgramCategory (int32 midiChannel, String128 instrumentAttribute)
1475 {
1476 std::vector<ProgramCategory>& channelCategories = mProgramCategories[midiChannel];
1477
1478 for (uint32 categoryIndex = 0; categoryIndex < channelCategories.size (); categoryIndex++)
1479 {
1480 ProgramCategory& cat = channelCategories[categoryIndex];
1481 if (memcmp (instrumentAttribute, cat.vst3InstrumentAttribute, sizeof (String128)) == 0)
1482 return static_cast<int32> (categoryIndex);
1483 }
1484
1485 return -1;
1486 }
1487
1488 //-----------------------------------------------------------------------------
makeCategoriesRecursive(std::vector<ProgramCategory> & channelCategories,String128 vst3Category)1489 uint32 Vst2Wrapper::makeCategoriesRecursive (std::vector<ProgramCategory>& channelCategories,
1490 String128 vst3Category)
1491 {
1492 for (uint32 categoryIndex = 0; categoryIndex < channelCategories.size (); categoryIndex++)
1493 {
1494 ProgramCategory& cat = channelCategories[categoryIndex];
1495 if (memcmp (vst3Category, cat.vst3InstrumentAttribute, sizeof (String128)) == 0)
1496 {
1497 return categoryIndex;
1498 }
1499 }
1500
1501 int32 parentCategorIndex = -1;
1502
1503 String128 str;
1504 String strAcc (str);
1505 strAcc.copyTo16 (vst3Category, 0, 127);
1506 int32 len = strAcc.length ();
1507 String singleName;
1508
1509 char16 divider = '|';
1510 for (int32 strIndex = len - 1; strIndex >= 0; strIndex--)
1511 {
1512 bool isDivider = str[strIndex] == divider;
1513 str[strIndex] = 0; // zero out rest
1514 if (isDivider)
1515 {
1516 singleName.assign (vst3Category + strIndex + 1);
1517 parentCategorIndex = static_cast<int32> (makeCategoriesRecursive (channelCategories, str));
1518 break;
1519 }
1520 }
1521
1522 // make new
1523 ProgramCategory cat = {};
1524 memcpy (cat.vst3InstrumentAttribute, vst3Category, sizeof (String128));
1525 singleName.copyTo8 (cat.vst2Category.name, 0, kVstMaxNameLen);
1526 cat.vst2Category.parentCategoryIndex = parentCategorIndex;
1527 cat.vst2Category.thisCategoryIndex = (int32)channelCategories.size ();
1528
1529 channelCategories.push_back (cat);
1530
1531 return cat.vst2Category.thisCategoryIndex;
1532 }
1533
1534 //-----------------------------------------------------------------------------
setupProgramCategories()1535 void Vst2Wrapper::setupProgramCategories ()
1536 {
1537 mProgramCategories.clear ();
1538 if (mUnitInfo && mComponent)
1539 {
1540 if (mComponent->getBusCount (kEvent, kInput) > 0)
1541 {
1542 for (int32 channel = 0; channel < 16; channel++) // the 16 channels
1543 {
1544 // make vector for channel
1545 mProgramCategories.push_back (std::vector<ProgramCategory> ());
1546 std::vector<ProgramCategory>& channelCategories = mProgramCategories[channel];
1547
1548 // scan program list of channel and find categories
1549 UnitID unitId;
1550 ProgramListID programListId;
1551 if (getProgramListAndUnit (channel, unitId, programListId))
1552 {
1553 ProgramListInfo programListInfo;
1554 if (getProgramListInfoByProgramListID (programListId, programListInfo))
1555 {
1556 for (int32 programIndex = 0; programIndex < programListInfo.programCount;
1557 programIndex++)
1558 {
1559 String128 string128 = {0};
1560 if (mUnitInfo->getProgramInfo (programListId, programIndex,
1561 PresetAttributes::kInstrument,
1562 string128) == kResultTrue)
1563 {
1564 makeCategoriesRecursive (channelCategories, string128);
1565 }
1566 }
1567 }
1568 }
1569 }
1570 }
1571 }
1572 }
1573
1574 //-----------------------------------------------------------------------------
getMidiProgramCategory(VstInt32 channel,MidiProgramCategory * category)1575 VstInt32 Vst2Wrapper::getMidiProgramCategory (VstInt32 channel, MidiProgramCategory* category)
1576 {
1577 // try to rebuild it each time
1578 setupProgramCategories ();
1579
1580 if (channel >= (VstInt32)mProgramCategories.size ())
1581 return 0;
1582
1583 std::vector<ProgramCategory>& channelCategories = mProgramCategories[channel];
1584 if (category && category->thisCategoryIndex < (VstInt32)channelCategories.size ())
1585 {
1586 ProgramCategory& cat = channelCategories[category->thisCategoryIndex];
1587 if (cat.vst2Category.thisCategoryIndex == category->thisCategoryIndex)
1588 memcpy (category, &cat.vst2Category, sizeof (MidiProgramCategory));
1589 }
1590 return (VstInt32)channelCategories.size ();
1591 }
1592
1593 //-----------------------------------------------------------------------------
hasMidiProgramsChanged(VstInt32)1594 bool Vst2Wrapper::hasMidiProgramsChanged (VstInt32 /*channel*/)
1595 {
1596 // names of programs or program categories have changed
1597 return false;
1598 }
1599
1600 //-----------------------------------------------------------------------------
getMidiKeyName(VstInt32 channel,MidiKeyName * keyName)1601 bool Vst2Wrapper::getMidiKeyName (VstInt32 channel, MidiKeyName* keyName)
1602 {
1603 UnitID unitId;
1604 ProgramListID programListId;
1605 if (mUnitInfo && getProgramListAndUnit (channel, unitId, programListId))
1606 {
1607 String128 string128 = {0};
1608 if (mUnitInfo->getProgramPitchName (programListId, keyName->thisProgramIndex,
1609 keyName->thisKeyNumber, string128))
1610 {
1611 String str (string128);
1612 str.copyTo8 (keyName->keyName, 0, kVstMaxNameLen);
1613 return true;
1614 }
1615 }
1616 return false;
1617 }
1618
1619 //-----------------------------------------------------------------------------
setupParameters()1620 void Vst2Wrapper::setupParameters ()
1621 {
1622 BaseWrapper::setupParameters ();
1623 cEffect.numParams = mNumParams;
1624 }
1625
1626 //-----------------------------------------------------------------------------
processEvents(VstEvents * events)1627 VstInt32 Vst2Wrapper::processEvents (VstEvents* events)
1628 {
1629 if (mInputEvents == nullptr)
1630 return 0;
1631 mInputEvents->clear ();
1632
1633 for (int32 i = 0; i < events->numEvents; i++)
1634 {
1635 VstEvent* e = events->events[i];
1636 if (e->type == kVstMidiType)
1637 {
1638 auto* midiEvent = (VstMidiEvent*)e;
1639 Event toAdd = {0, midiEvent->deltaFrames, 0};
1640 processMidiEvent (toAdd, &midiEvent->midiData[0],
1641 midiEvent->flags & kVstMidiEventIsRealtime, midiEvent->noteLength,
1642 midiEvent->noteOffVelocity * kMidiScaler, midiEvent->detune);
1643 }
1644 //--- -----------------------------
1645 else if (e->type == kVstSysExType)
1646 {
1647 Event toAdd = {0, e->deltaFrames};
1648 VstMidiSysexEvent& src = *(VstMidiSysexEvent*)e;
1649 toAdd.type = Event::kDataEvent;
1650 toAdd.data.type = DataEvent::kMidiSysEx;
1651 toAdd.data.size = src.dumpBytes;
1652 toAdd.data.bytes = (uint8*)src.sysexDump;
1653 mInputEvents->addEvent (toAdd);
1654 }
1655 }
1656
1657 return 0;
1658 }
1659
1660 //-----------------------------------------------------------------------------
processOutputEvents()1661 inline void Vst2Wrapper::processOutputEvents ()
1662 {
1663 if (mVst2OutputEvents && mOutputEvents && mOutputEvents->getEventCount () > 0)
1664 {
1665 mVst2OutputEvents->flush ();
1666
1667 Event e = {0};
1668 for (int32 i = 0, total = mOutputEvents->getEventCount (); i < total; i++)
1669 {
1670 if (mOutputEvents->getEvent (i, e) != kResultOk)
1671 break;
1672
1673 //---SysExclusif----------------
1674 if (e.type == Event::kDataEvent && e.data.type == DataEvent::kMidiSysEx)
1675 {
1676 VstMidiSysexEvent sysexEvent = {0};
1677 sysexEvent.deltaFrames = e.sampleOffset;
1678 sysexEvent.dumpBytes = e.data.size;
1679 sysexEvent.sysexDump = (char*)e.data.bytes;
1680
1681 if (!mVst2OutputEvents->add (sysexEvent))
1682 break;
1683 }
1684 else
1685 {
1686 VstMidiEvent midiEvent = {0};
1687 midiEvent.deltaFrames = e.sampleOffset;
1688 if (e.flags & Event::kIsLive)
1689 midiEvent.flags = kVstMidiEventIsRealtime;
1690 char* midiData = midiEvent.midiData;
1691
1692 switch (e.type)
1693 {
1694 //--- ---------------------
1695 case Event::kNoteOnEvent:
1696 midiData[0] = (char)(kNoteOn | (e.noteOn.channel & kChannelMask));
1697 midiData[1] = (char)(e.noteOn.pitch & kDataMask);
1698 midiData[2] =
1699 (char)((int32) (e.noteOn.velocity * 127.f + 0.4999999f) & kDataMask);
1700 if (midiData[2] == 0) // zero velocity => note off
1701 midiData[0] = (char)(kNoteOff | (e.noteOn.channel & kChannelMask));
1702 midiEvent.detune = (char)e.noteOn.tuning;
1703 midiEvent.noteLength = e.noteOn.length;
1704 break;
1705
1706 //--- ---------------------
1707 case Event::kNoteOffEvent:
1708 midiData[0] = (char)(kNoteOff | (e.noteOff.channel & kChannelMask));
1709 midiData[1] = (char)(e.noteOff.pitch & kDataMask);
1710 midiData[2] = midiEvent.noteOffVelocity =
1711 (char)((int32) (e.noteOff.velocity * 127.f + 0.4999999f) & kDataMask);
1712 break;
1713
1714 break;
1715 }
1716
1717 if (!mVst2OutputEvents->add (midiEvent))
1718 break;
1719 }
1720 }
1721
1722 mOutputEvents->clear ();
1723
1724 sendVstEventsToHost (*mVst2OutputEvents);
1725 }
1726 }
1727
1728 //-----------------------------------------------------------------------------
updateProcessLevel()1729 void Vst2Wrapper::updateProcessLevel ()
1730 {
1731 auto currentLevel = getCurrentProcessLevel ();
1732 if (mCurrentProcessLevel != currentLevel)
1733 {
1734 mCurrentProcessLevel = currentLevel;
1735 if (mCurrentProcessLevel == kVstProcessLevelOffline)
1736 mVst3processMode = kOffline;
1737 else
1738 mVst3processMode = kRealtime;
1739
1740 bool callStartStop = mProcessing;
1741
1742 if (callStartStop)
1743 stopProcess ();
1744
1745 setupProcessing ();
1746
1747 if (callStartStop)
1748 startProcess ();
1749 }
1750 }
1751
1752 //-----------------------------------------------------------------------------
processReplacing(float ** inputs,float ** outputs,VstInt32 sampleFrames)1753 void Vst2Wrapper::processReplacing (float** inputs, float** outputs, VstInt32 sampleFrames)
1754 {
1755 updateProcessLevel ();
1756
1757 _processReplacing (inputs, outputs, sampleFrames);
1758 }
1759
1760 //-----------------------------------------------------------------------------
processDoubleReplacing(double ** inputs,double ** outputs,VstInt32 sampleFrames)1761 void Vst2Wrapper::processDoubleReplacing (double** inputs, double** outputs, VstInt32 sampleFrames)
1762 {
1763 updateProcessLevel ();
1764
1765 _processDoubleReplacing (inputs, outputs, sampleFrames);
1766 }
1767
1768 //-----------------------------------------------------------------------------
1769 // static
1770 //-----------------------------------------------------------------------------
create(IPluginFactory * factory,const TUID vst3ComponentID,VstInt32 vst2ID,audioMasterCallback audioMaster)1771 AudioEffect* Vst2Wrapper::create (IPluginFactory* factory, const TUID vst3ComponentID,
1772 VstInt32 vst2ID, audioMasterCallback audioMaster)
1773 {
1774 if (!factory)
1775 return nullptr;
1776
1777 BaseWrapper::SVST3Config config;
1778 config.factory = factory;
1779 config.processor = nullptr;
1780
1781 FReleaser factoryReleaser (factory);
1782
1783 factory->createInstance (vst3ComponentID, IAudioProcessor::iid, (void**)&config.processor);
1784 if (config.processor)
1785 {
1786 config.controller = nullptr;
1787 if (config.processor->queryInterface (IEditController::iid, (void**)&config.controller) !=
1788 kResultTrue)
1789 {
1790 FUnknownPtr<IComponent> component (config.processor);
1791 if (component)
1792 {
1793 TUID editorCID;
1794 if (component->getControllerClassId (editorCID) == kResultTrue)
1795 {
1796 factory->createInstance (editorCID, IEditController::iid,
1797 (void**)&config.controller);
1798 }
1799 }
1800 }
1801
1802 config.vst3ComponentID = FUID::fromTUID (vst3ComponentID);
1803
1804 auto* wrapper = new Vst2Wrapper (config, audioMaster, vst2ID);
1805 FUnknownPtr<IPluginFactory2> factory2 (factory);
1806 if (factory2)
1807 {
1808 PFactoryInfo factoryInfo;
1809 if (factory2->getFactoryInfo (&factoryInfo) == kResultTrue)
1810 wrapper->setVendorName (factoryInfo.vendor);
1811
1812 for (int32 i = 0; i < factory2->countClasses (); i++)
1813 {
1814 Steinberg::PClassInfo2 classInfo2;
1815 if (factory2->getClassInfo2 (i, &classInfo2) == Steinberg::kResultTrue)
1816 {
1817 if (memcmp (classInfo2.cid, vst3ComponentID, sizeof (TUID)) == 0)
1818 {
1819 wrapper->setSubCategories (classInfo2.subCategories);
1820 wrapper->setEffectName (classInfo2.name);
1821 wrapper->setEffectVersion (classInfo2.version);
1822
1823 if (classInfo2.vendor[0] != 0)
1824 wrapper->setVendorName (classInfo2.vendor);
1825
1826 break;
1827 }
1828 }
1829 }
1830 }
1831
1832 if (wrapper->init () == false)
1833 {
1834 wrapper->release ();
1835 return nullptr;
1836 }
1837
1838 return wrapper;
1839 }
1840
1841 return nullptr;
1842 }
1843
1844 //-----------------------------------------------------------------------------
getName(String128 name)1845 tresult PLUGIN_API Vst2Wrapper::getName (String128 name)
1846 {
1847 char8 productString[128];
1848 if (getHostProductString (productString))
1849 {
1850 String str (productString);
1851 str.copyTo16 (name, 0, 127);
1852
1853 return kResultTrue;
1854 }
1855 return kResultFalse;
1856 }
1857
1858 //-----------------------------------------------------------------------------
1859 // IComponentHandler
1860 //-----------------------------------------------------------------------------
beginEdit(ParamID tag)1861 tresult PLUGIN_API Vst2Wrapper::beginEdit (ParamID tag)
1862 {
1863 std::map<ParamID, int32>::const_iterator iter = mParamIndexMap.find (tag);
1864 if (iter != mParamIndexMap.end ())
1865 AudioEffectX::beginEdit ((*iter).second);
1866 return kResultTrue;
1867 }
1868
1869 //-----------------------------------------------------------------------------
performEdit(ParamID tag,ParamValue valueNormalized)1870 tresult PLUGIN_API Vst2Wrapper::performEdit (ParamID tag, ParamValue valueNormalized)
1871 {
1872 std::map<ParamID, int32>::const_iterator iter = mParamIndexMap.find (tag);
1873 if (iter != mParamIndexMap.end () && audioMaster)
1874 audioMaster (&cEffect, audioMasterAutomate, (*iter).second, 0, nullptr,
1875 (float)valueNormalized); // value is in opt
1876
1877 mInputTransfer.addChange (tag, valueNormalized, 0);
1878
1879 return kResultTrue;
1880 }
1881
1882 //-----------------------------------------------------------------------------
endEdit(ParamID tag)1883 tresult PLUGIN_API Vst2Wrapper::endEdit (ParamID tag)
1884 {
1885 std::map<ParamID, int32>::const_iterator iter = mParamIndexMap.find (tag);
1886 if (iter != mParamIndexMap.end ())
1887 AudioEffectX::endEdit ((*iter).second);
1888 return kResultTrue;
1889 }
1890
1891 //-----------------------------------------------------------------------------
_ioChanged()1892 void Vst2Wrapper::_ioChanged ()
1893 {
1894 BaseWrapper::_ioChanged ();
1895 ioChanged ();
1896 }
1897
1898 //-----------------------------------------------------------------------------
_updateDisplay()1899 void Vst2Wrapper::_updateDisplay ()
1900 {
1901 BaseWrapper::_updateDisplay ();
1902 updateDisplay ();
1903 }
1904
1905 //-----------------------------------------------------------------------------
_setNumInputs(uint32 inputs)1906 void Vst2Wrapper::_setNumInputs (uint32 inputs)
1907 {
1908 BaseWrapper::_setNumInputs (inputs);
1909 setNumInputs (static_cast<VstInt32> (inputs));
1910 }
1911
1912 //-----------------------------------------------------------------------------
_setNumOutputs(uint32 outputs)1913 void Vst2Wrapper::_setNumOutputs (uint32 outputs)
1914 {
1915 BaseWrapper::_setNumOutputs (outputs);
1916 setNumOutputs (static_cast<VstInt32> (outputs));
1917 }
1918
1919 //-----------------------------------------------------------------------------
_sizeWindow(int32 width,int32 height)1920 bool Vst2Wrapper::_sizeWindow (int32 width, int32 height)
1921 {
1922 return sizeWindow (width, height);
1923 }
1924
1925 //-----------------------------------------------------------------------------
1926 } // namespace Vst
1927 } // namespace Steinberg
1928
1929 extern bool InitModule ();
1930
1931 //-----------------------------------------------------------------------------
1932 extern "C" {
1933
1934 //-----------------------------------------------------------------------------
1935 /** Prototype of the export function main */
1936 //-----------------------------------------------------------------------------
VSTPluginMain(audioMasterCallback audioMaster)1937 SMTG_EXPORT_SYMBOL AEffect* VSTPluginMain (audioMasterCallback audioMaster)
1938 {
1939 // Get VST Version of the host
1940 if (!audioMaster (nullptr, audioMasterVersion, 0, 0, nullptr, 0))
1941 return nullptr; // old version
1942
1943 if (InitModule () == false)
1944 return nullptr;
1945
1946 // Create the AudioEffect
1947 AudioEffect* effect = createEffectInstance (audioMaster);
1948 if (!effect)
1949 return nullptr;
1950
1951 // Return the VST AEffect structure
1952 return effect->getAeffect ();
1953 }
1954
1955 //-----------------------------------------------------------------------------
1956 // support for old hosts not looking for VSTPluginMain
1957 #if (TARGET_API_MAC_CARBON && __ppc__)
main_macho(audioMasterCallback audioMaster)1958 SMTG_EXPORT_SYMBOL AEffect* main_macho (audioMasterCallback audioMaster)
1959 {
1960 return VSTPluginMain (audioMaster);
1961 }
1962 #elif WIN32
MAIN(audioMasterCallback audioMaster)1963 SMTG_EXPORT_SYMBOL AEffect* MAIN (audioMasterCallback audioMaster)
1964 {
1965 return VSTPluginMain (audioMaster);
1966 }
1967 #elif BEOS
main_plugin(audioMasterCallback audioMaster)1968 SMTG_EXPORT_SYMBOL AEffect* main_plugin (audioMasterCallback audioMaster)
1969 {
1970 return VSTPluginMain (audioMaster);
1971 }
1972 #endif
1973
1974 } // extern "C"
1975 //-----------------------------------------------------------------------------
1976
1977 /// \endcond
1978