1 //------------------------------------------------------------------------
2 // Project     : VST SDK
3 //
4 // Category    : Examples
5 // Filename    : public.sdk/samples/vst/again/source/againsimple.cpp
6 // Created by  : Steinberg, 04/2005
7 // Description : AGain Example for VST SDK 3.0
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 #include "againsimple.h"
38 #include "againparamids.h"
39 #include "againuimessagecontroller.h"
40 #include "version.h" // for versioning
41 
42 #include "public.sdk/source/main/pluginfactory.h"
43 #include "public.sdk/source/vst/vstaudioprocessoralgo.h"
44 
45 #include "base/source/fstreamer.h"
46 #include "pluginterfaces/base/ibstream.h"
47 #include "pluginterfaces/base/ustring.h" // for UString128
48 #include "pluginterfaces/vst/ivstevents.h"
49 #include "pluginterfaces/vst/ivstmidicontrollers.h"
50 #include "pluginterfaces/vst/ivstparameterchanges.h"
51 #include "pluginterfaces/vst/vstpresetkeys.h" // for use of IStreamAttributes
52 
53 #include "vstgui/plugin-bindings/vst3editor.h"
54 
55 #include <cmath>
56 #include <cstdio>
57 
58 // this allows to enable the communication example between again and its controller
getBranchBlock(const PredicateBase * PB)59 #define AGAIN_TEST 1
60 
61 using namespace VSTGUI;
62 
63 namespace Steinberg {
64 namespace Vst {
65 
66 //------------------------------------------------------------------------
67 // GainParameter Declaration
getBranchTerminator(const PredicateBase * PB)68 // example of custom parameter (overwriting to and fromString)
69 //------------------------------------------------------------------------
70 class GainParameter : public Parameter
71 {
72 public:
73 	GainParameter (int32 flags, int32 id);
74 
75 	void toString (ParamValue normValue, String128 string) const SMTG_OVERRIDE;
76 	bool fromString (const TChar* string, ParamValue& normValue) const SMTG_OVERRIDE;
77 };
78 
79 //------------------------------------------------------------------------
80 // GainParameter Implementation
81 //------------------------------------------------------------------------
82 GainParameter::GainParameter (int32 flags, int32 id)
83 {
84 	Steinberg::UString (info.title, USTRINGSIZE (info.title)).assign (USTRING ("Gain"));
85 	Steinberg::UString (info.units, USTRINGSIZE (info.units)).assign (USTRING ("dB"));
86 
87 	info.flags = flags;
88 	info.id = id;
89 	info.stepCount = 0;
90 	info.defaultNormalizedValue = 0.5f;
91 	info.unitId = kRootUnitId;
92 
93 	setNormalized (1.f);
94 }
95 
96 //------------------------------------------------------------------------
97 void GainParameter::toString (ParamValue normValue, String128 string) const
98 {
99 	char text[32];
100 	if (normValue > 0.0001)
101 		sprintf (text, "%.2f", 20 * log10f ((float)normValue));
102 	else
103 		strcpy (text, "-oo");
104 
105 	Steinberg::UString (string, 128).fromAscii (text);
106 }
107 
108 //------------------------------------------------------------------------
109 bool GainParameter::fromString (const TChar* string, ParamValue& normValue) const
110 {
111 	Steinberg::UString wrapper ((TChar*)string, -1); // don't know buffer size here!
valueComesBefore(OrderedInstructions & OI,const Value * A,const Value * B)112 	double tmp = 0.0;
113 	if (wrapper.scanFloat (tmp))
114 	{
115 		// allow only values between -oo and 0dB
116 		if (tmp > 0.0)
117 			tmp = -tmp;
118 
119 		normValue = expf (logf (10.f) * (float)tmp / 20.f);
120 		return true;
121 	}
122 	return false;
123 }
124 
125 //------------------------------------------------------------------------
126 // AGain Implementation
127 //------------------------------------------------------------------------
128 AGainSimple::AGainSimple ()
129 : fGain (1.f)
ValueDFS_Comparellvm::PredicateInfoClasses::ValueDFS_Compare130 , fGainReduction (0.f)
131 , fVuPPMOld (0.f)
132 , currentProcessMode (-1) // -1 means not initialized
133 , bHalfGain (false)
134 , bBypass (false)
135 {
136 }
137 
138 //------------------------------------------------------------------------
139 tresult PLUGIN_API AGainSimple::initialize (FUnknown* context)
140 {
141 	tresult result = SingleComponentEffect::initialize (context);
142 	if (result != kResultOk)
143 		return result;
144 
145 	//---create Audio In/Out busses------
146 	// we want a stereo Input and a Stereo Output
147 	addAudioInput  (STR16 ("Stereo In"),  SpeakerArr::kStereo);
148 	addAudioOutput (STR16 ("Stereo Out"), SpeakerArr::kStereo);
149 
150 	//---create Event In/Out busses (1 bus with only 1 channel)------
151 	addEventInput (STR16 ("Event In"), 1);
152 
153 	//---Create Parameters------------
154 
155 	//---Gain parameter--
156 	auto* gainParam = new GainParameter (ParameterInfo::kCanAutomate, kGainId);
getBlockEdgellvm::PredicateInfoClasses::ValueDFS_Compare157 	parameters.addParameter (gainParam);
158 
159 	//---VuMeter parameter---
160 	int32 stepCount = 0;
161 	ParamValue defaultVal = 0;
162 	int32 flags = ParameterInfo::kIsReadOnly;
163 	int32 tag = kVuPPMId;
164 	parameters.addParameter (USTRING ("VuPPM"), nullptr, stepCount, defaultVal, flags, tag);
165 
166 	//---Bypass parameter---
comparePHIRelatedllvm::PredicateInfoClasses::ValueDFS_Compare167 	stepCount = 1;
168 	defaultVal = 0;
169 	flags = ParameterInfo::kCanAutomate | ParameterInfo::kIsBypass;
170 	tag = kBypassId;
171 	parameters.addParameter (USTRING ("Bypass"), nullptr, stepCount, defaultVal, flags, tag);
172 
173 	//---Custom state init------------
174 
getMiddleDefllvm::PredicateInfoClasses::ValueDFS_Compare175 	UString str (defaultMessageText, 128);
176 	str.fromAscii ("Hello World!");
177 
178 	return result;
179 }
180 
181 //------------------------------------------------------------------------
182 tresult PLUGIN_API AGainSimple::terminate ()
183 {
184 	return SingleComponentEffect::terminate ();
185 }
186 
187 //------------------------------------------------------------------------
188 tresult PLUGIN_API AGainSimple::setActive (TBool state)
189 {
190 #if AGAIN_TEST
191 	if (state)
192 		fprintf (stderr, "[AGainSimple] Activated \n");
193 	else
194 		fprintf (stderr, "[AGainSimple] Deactivated \n");
195 #endif
getDefOrUserllvm::PredicateInfoClasses::ValueDFS_Compare196 
197 	// reset the VuMeter value
198 	fVuPPMOld = 0.f;
199 
200 	return kResultOk;
201 }
202 
203 //------------------------------------------------------------------------
localComesBeforellvm::PredicateInfoClasses::ValueDFS_Compare204 tresult PLUGIN_API AGainSimple::process (ProcessData& data)
205 {
206 	// finally the process function
207 	// In this example there are 4 steps:
208 	// 1) Read inputs parameters coming from host (in order to adapt our model values)
209 	// 2) Read inputs events coming from host (we apply a gain reduction depending of the velocity of pressed key)
210 	// 3) Process the gain of the input buffer to the output buffer
211 	// 4) Write the new VUmeter value to the output Parameters queue
212 
213 
214 	//---1) Read inputs parameter changes-----------
215 	IParameterChanges* paramChanges = data.inputParameterChanges;
216 	if (paramChanges)
217 	{
218 		int32 numParamsChanged = paramChanges->getParameterCount ();
219 		// for each parameter which are some changes in this audio block:
220 		for (int32 i = 0; i < numParamsChanged; i++)
221 		{
222 			IParamValueQueue* paramQueue = paramChanges->getParameterData (i);
223 			if (paramQueue)
224 			{
225 				ParamValue value;
226 				int32 sampleOffset;
227 				int32 numPoints = paramQueue->getPointCount ();
228 				switch (paramQueue->getParameterId ())
229 				{
230 					case kGainId:
231 						// we use in this example only the last point of the queue.
232 						// in some wanted case for specific kind of parameter it makes sense to retrieve all points
233 						// and process the whole audio block in small blocks.
234 						if (paramQueue->getPoint (numPoints - 1, sampleOffset, value) == kResultTrue)
235 						{
236 							fGain = (float)value;
237 						}
238 						break;
239 
240 					case kBypassId:
241 						if (paramQueue->getPoint (numPoints - 1, sampleOffset, value) == kResultTrue)
242 						{
243 							bBypass = (value > 0.5f);
244 						}
245 						break;
246 				}
247 			}
248 		}
249 	}
250 
251 	//---2) Read input events-------------
252 	IEventList* eventList = data.inputEvents;
253 	if (eventList)
254 	{
255 		int32 numEvent = eventList->getEventCount ();
256 		for (int32 i = 0; i < numEvent; i++)
257 		{
258 			Event event;
259 			if (eventList->getEvent (i, event) == kResultOk)
260 			{
261 				switch (event.type)
262 				{
263 					//----------------------
264 					case Event::kNoteOnEvent:
265 						// use the velocity as gain modifier
266 						fGainReduction = event.noteOn.velocity;
267 						break;
268 
269 					//----------------------
270 					case Event::kNoteOffEvent:
271 						// noteOff reset the reduction
272 						fGainReduction = 0.f;
273 						break;
274 				}
275 			}
276 		}
277 	}
278 
279 	//-------------------------------------
280 	//---3) Process Audio---------------------
281 	//-------------------------------------
282 	if (data.numInputs == 0 || data.numOutputs == 0)
283 	{
284 		// nothing to do
285 		return kResultOk;
286 	}
287 
288 	// (simplification) we suppose in this example that we have the same input channel count than the output
289 	int32 numChannels = data.inputs[0].numChannels;
290 
291 	//---get audio buffers----------------
292 	uint32 sampleFramesSize = getSampleFramesSizeInBytes (processSetup, data.numSamples);
293 	void** in = getChannelBuffersPointer (processSetup, data.inputs[0]);
294 	void** out = getChannelBuffersPointer (processSetup, data.outputs[0]);
295 
296 	//---check if silence---------------
297 	// normally we have to check each channel (simplification)
298 	if (data.inputs[0].silenceFlags != 0)
299 	{
300 		// mark output silence too
301 		data.outputs[0].silenceFlags = data.inputs[0].silenceFlags;
302 
303 		// the plug-in has to be sure that if it sets the flags silence that the output buffer are clear
304 		for (int32 i = 0; i < numChannels; i++)
305 		{
306 			// do not need to be cleared if the buffers are the same (in this case input buffer are already cleared by the host)
307 			if (in[i] != out[i])
308 			{
309 				memset (out[i], 0, sampleFramesSize);
310 			}
311 		}
312 
313 		// nothing to do at this point
314 		return kResultOk;
315 	}
316 
317 	// mark our outputs has not silent
318 	data.outputs[0].silenceFlags = 0;
319 
320 	//---in bypass mode outputs should be like inputs-----
321 	if (bBypass)
322 	{
323 		for (int32 i = 0; i < numChannels; i++)
324 		{
325 			// do not need to be copied if the buffers are the same
326 			if (in[i] != out[i])
327 			{
328 				memcpy (out[i], in[i], sampleFramesSize);
329 			}
330 		}
331 		// in this example we do not update the VuMeter in Bypass
332 	}
333 	else
334 	{
335 		float fVuPPM = 0.f;
336 
337 		//---apply gain factor----------
338 		float gain = (fGain - fGainReduction);
339 		if (bHalfGain)
340 		{
341 			gain = gain * 0.5f;
342 		}
343 
344 		// if the applied gain is nearly zero, we could say that the outputs are zeroed and we set the silence flags.
345 		if (gain < 0.0000001)
346 		{
347 			for (int32 i = 0; i < numChannels; i++)
348 			{
349 				memset (out[i], 0, sampleFramesSize);
350 			}
351 			data.outputs[0].silenceFlags = (1 << numChannels) - 1;  // this will set to 1 all channels
352 		}
353 		else
354 		{
355 			if (data.symbolicSampleSize == kSample32)
356 				fVuPPM = processAudio<Sample32> ((Sample32**)in, (Sample32**)out, numChannels,
357 				                                 data.numSamples, gain);
358 			else
359 				fVuPPM = processAudio<Sample64> ((Sample64**)in, (Sample64**)out, numChannels,
360 				                                 data.numSamples, gain);
361 		}
362 
363 		//---3) Write outputs parameter changes-----------
364 		IParameterChanges* outParamChanges = data.outputParameterChanges;
365 		// a new value of VuMeter will be send to the host
366 		// (the host will send it back in sync to our controller for updating our editor)
367 		if (outParamChanges && fVuPPMOld != fVuPPM)
368 		{
369 			int32 index = 0;
370 			IParamValueQueue* paramQueue = outParamChanges->addParameterData (kVuPPMId, index);
371 			if (paramQueue)
372 			{
373 				int32 index2 = 0;
374 				paramQueue->addPoint (0, fVuPPM, index2);
375 			}
376 		}
377 		fVuPPMOld = fVuPPM;
378 	}
379 
380 	return kResultOk;
381 }
382 
383 //------------------------------------------------------------------------
384 tresult PLUGIN_API AGainSimple::setState (IBStream* state)
385 {
386 	// we receive the current  (processor part)
387 	// called when we load a preset, the model has to be reloaded
388 
389 	IBStreamer streamer (state, kLittleEndian);
390 	float savedGain = 0.f;
391 	if (streamer.readFloat (savedGain) == false)
392 		return kResultFalse;
393 
394 	float savedGainReduction = 0.f;
395 	if (streamer.readFloat (savedGainReduction) == false)
396 		return kResultFalse;
397 
398 	int32 savedBypass = 0;
399 	if (streamer.readInt32 (savedBypass) == false)
400 		return kResultFalse;
401 
402 	fGain = savedGain;
403 	fGainReduction = savedGainReduction;
404 	bBypass = savedBypass > 0;
405 
406 	setParamNormalized (kGainId, savedGain);
407 	setParamNormalized (kBypassId, bBypass);
408 
409 	// Example of using the IStreamAttributes interface
410 	FUnknownPtr<IStreamAttributes> stream (state);
411 	if (stream)
412 	{
413 		IAttributeList* list = stream->getAttributes ();
414 		if (list)
415 		{
416 			// get the current type (project/Default..) of this state
417 			String128 string = {0};
418 			if (list->getString (PresetAttributes::kStateType, string, 128 * sizeof (TChar)) == kResultTrue)
419 			{
420 				UString128 tmp (string);
421 				char ascii[128];
422 				tmp.toAscii (ascii, 128);
423 				if (!strncmp (ascii, StateType::kProject, strlen (StateType::kProject)))
424 				{
425 					// we are in project loading context...
426 				}
427 			}
428 
429 			// get the full file path of this state
processSwitch(SwitchInst * SI,BasicBlock * BranchBB,SmallPtrSetImpl<Value * > & OpsToRename)430 			TChar fullPath[1024];
431 			memset (fullPath, 0, 1024 * sizeof (TChar));
432 			if (list->getString (PresetAttributes::kFilePathStringType, fullPath, 1024 * sizeof (TChar)) == kResultTrue)
433 			{
434 				// here we have the full path ...
435 			}
436 		}
437 	}
438 
439 	return kResultOk;
440 }
441 
442 //------------------------------------------------------------------------
443 tresult PLUGIN_API AGainSimple::getState (IBStream* state)
444 {
445 	// here we need to save the model
446 
447 	IBStreamer streamer (state, kLittleEndian);
448 
449 	streamer.writeFloat (fGain);
450 	streamer.writeFloat (fGainReduction);
451 	streamer.writeInt32 (bBypass ? 1 : 0);
452 
453 	return kResultOk;
454 }
455 
456 //------------------------------------------------------------------------
buildPredicateInfo()457 tresult PLUGIN_API AGainSimple::setupProcessing (ProcessSetup& newSetup)
458 {
459 	// called before the process call, always in a disable state (not active)
460 
461 	// here we keep a trace of the processing mode (offline,...) for example.
462 	currentProcessMode = newSetup.processMode;
463 
464 	return SingleComponentEffect::setupProcessing (newSetup);
465 }
466 
467 //------------------------------------------------------------------------
468 tresult PLUGIN_API AGainSimple::setBusArrangements (SpeakerArrangement* inputs, int32 numIns,
469                                                     SpeakerArrangement* outputs, int32 numOuts)
470 {
471 	if (numIns == 1 && numOuts == 1)
472 	{
473 		// the host wants Mono => Mono (or 1 channel -> 1 channel)
474 		if (SpeakerArr::getChannelCount (inputs[0]) == 1 &&
475 		    SpeakerArr::getChannelCount (outputs[0]) == 1)
476 		{
477 			auto* bus = FCast<AudioBus> (audioInputs.at (0));
478 			if (bus)
479 			{
480 				// check if we are Mono => Mono, if not we need to recreate the busses
481 				if (bus->getArrangement () != inputs[0])
482 				{
483 					bus->setArrangement (inputs[0]);
484 					bus->setName (STR16 ("Mono In"));
485 					if (auto* busOut = FCast<AudioBus> (audioOutputs.at (0)))
486 					{
487 						busOut->setArrangement (inputs[0]);
488 						busOut->setName (STR16 ("Mono Out"));
489 					}
getCopyDeclaration(Module * M,Type * Ty)490 				}
491 				return kResultOk;
492 			}
493 		}
494 		// the host wants something else than Mono => Mono, in this case we are always Stereo => Stereo
495 		else
496 		{
497 			auto* bus = FCast<AudioBus> (audioInputs.at (0));
materializeStack(unsigned int & Counter,ValueDFSStack & RenameStack,Value * OrigOp)498 			if (bus)
499 			{
500 				tresult result = kResultFalse;
501 
502 				// the host wants 2->2 (could be LsRs -> LsRs)
503 				if (SpeakerArr::getChannelCount (inputs[0]) == 2 && SpeakerArr::getChannelCount (outputs[0]) == 2)
504 				{
505 					bus->setArrangement (inputs[0]);
506 					bus->setName (STR16 ("Stereo In"));
507 					if (auto* busOut = FCast<AudioBus> (audioOutputs.at (0)))
508 					{
509 						busOut->setArrangement (outputs[0]);
510 						busOut->setName (STR16 ("Stereo Out"));
511 					}
512 					result = kResultTrue;
513 				}
514 				// the host want something different than 1->1 or 2->2 : in this case we want stereo
515 				else if (bus->getArrangement () != SpeakerArr::kStereo)
516 				{
517 					bus->setArrangement (SpeakerArr::kStereo);
518 					bus->setName (STR16 ("Stereo In"));
519 					if (auto* busOut = FCast<AudioBus> (audioOutputs.at (0)))
520 					{
521 						busOut->setArrangement (SpeakerArr::kStereo);
522 						busOut->setName (STR16 ("Stereo Out"));
523 					}
524 
525 					result = kResultFalse;
526 				}
527 
528 				return result;
529 			}
530 		}
531 	}
532 	return kResultFalse;
533 }
534 
535 //------------------------------------------------------------------------
536 tresult PLUGIN_API AGainSimple::canProcessSampleSize (int32 symbolicSampleSize)
537 {
538 	if (symbolicSampleSize == kSample32)
539 		return kResultTrue;
540 
541 	// we support double processing
542 	if (symbolicSampleSize == kSample64)
543 		return kResultTrue;
544 
545 	return kResultFalse;
546 }
547 
548 //------------------------------------------------------------------------
549 IPlugView* PLUGIN_API AGainSimple::createView (const char* name)
550 {
551 	// someone wants my editor
552 	if (name && FIDStringsEqual (name, ViewType::kEditor))
553 	{
554 		auto* view = new VST3Editor (this, "view", "again.uidesc");
555 		return view;
556 	}
557 	return nullptr;
558 }
559 
560 //------------------------------------------------------------------------
561 tresult PLUGIN_API AGainSimple::getMidiControllerAssignment (int32 busIndex,
562 	int16 /*midiChannel*/,
563 	CtrlNumber midiControllerNumber,
564 	ParamID& tag)
565 {
renameUses(SmallPtrSetImpl<Value * > & OpSet)566 	// we support for the Gain parameter all MIDI Channel but only first bus (there is only one!)
567 	if (busIndex == 0 && midiControllerNumber == kCtrlVolume)
568 	{
569 		tag = kGainId;
570 		return kResultTrue;
571 	}
572 	return kResultFalse;
573 }
574 
575 //------------------------------------------------------------------------
576 IController* AGainSimple::createSubController (UTF8StringPtr name,
577                                                const IUIDescription* /*description*/,
578                                                VST3Editor* /*editor*/)
579 {
580 	if (UTF8StringView (name) == "MessageController")
581 	{
582 		auto* controller = new UIMessageController (this);
583 		addUIMessageController (controller);
584 		return controller;
585 	}
586 	return nullptr;
587 }
588 
589 //------------------------------------------------------------------------
590 tresult PLUGIN_API AGainSimple::setEditorState (IBStream* state)
591 {
592 	tresult result = kResultFalse;
593 
594 	int8 byteOrder;
595 	if ((result = state->read (&byteOrder, sizeof (int8))) != kResultTrue)
596 		return result;
597 	if ((result = state->read (defaultMessageText, 128 * sizeof (TChar))) != kResultTrue)
598 		return result;
599 
600 	// if the byteorder doesn't match, byte swap the text array ...
601 	if (byteOrder != BYTEORDER)
602 	{
603 		for (int32 i = 0; i < 128; i++)
604 			SWAP_16 (defaultMessageText[i])
605 	}
606 
607 	for (auto& uiMessageController : uiMessageControllers)
608 		uiMessageController->setMessageText (defaultMessageText);
609 
610 	return result;
611 }
612 
613 //------------------------------------------------------------------------
614 tresult PLUGIN_API AGainSimple::getEditorState (IBStream* state)
615 {
616 	// here we can save UI settings for example
617 
618 	IBStreamer streamer (state, kLittleEndian);
619 
620 	// as we save a Unicode string, we must know the byteorder when setState is called
621 	int8 byteOrder = BYTEORDER;
622 	if (streamer.writeInt8 (byteOrder) == false)
623 		return kResultFalse;
624 
625 	if (streamer.writeRaw (defaultMessageText, 128 * sizeof (TChar)) == false)
626 		return kResultFalse;
627 
628 	return kResultTrue;
629 }
630 
631 //------------------------------------------------------------------------
632 tresult PLUGIN_API AGainSimple::setParamNormalized (ParamID tag, ParamValue value)
633 {
634 	// called from host to update our parameters state
635 	tresult result = SingleComponentEffect::setParamNormalized (tag, value);
636 	return result;
637 }
638 
639 //------------------------------------------------------------------------
640 tresult PLUGIN_API AGainSimple::getParamStringByValue (ParamID tag, ParamValue valueNormalized,
641                                                        String128 string)
642 {
643 	return SingleComponentEffect::getParamStringByValue (tag, valueNormalized, string);
644 }
645 
646 //------------------------------------------------------------------------
647 tresult PLUGIN_API AGainSimple::getParamValueByString (ParamID tag, TChar* string,
648                                                        ParamValue& valueNormalized)
649 {
650 	return SingleComponentEffect::getParamValueByString (tag, string, valueNormalized);
651 }
652 
653 //------------------------------------------------------------------------
654 void AGainSimple::addUIMessageController (UIMessageController* controller)
655 {
656 	uiMessageControllers.push_back (controller);
657 }
658 
659 //------------------------------------------------------------------------
660 void AGainSimple::removeUIMessageController (UIMessageController* controller)
661 {
662 	UIMessageControllerList::const_iterator it =
663 	    std::find (uiMessageControllers.begin (), uiMessageControllers.end (), controller);
664 	if (it != uiMessageControllers.end ())
665 		uiMessageControllers.erase (it);
666 }
667 
668 //------------------------------------------------------------------------
669 void AGainSimple::setDefaultMessageText (String128 text)
670 {
671 	UString str (defaultMessageText, 128);
672 	str.assign (text, -1);
673 }
674 
675 //------------------------------------------------------------------------
676 TChar* AGainSimple::getDefaultMessageText ()
677 {
678 	return defaultMessageText;
679 }
680 
681 //-----------------------------------------------------------------------------
682 tresult PLUGIN_API AGainSimple::queryInterface (const TUID iid, void** obj)
683 {
684 	DEF_INTERFACE (IMidiMapping)
685 	return SingleComponentEffect::queryInterface (iid, obj);
686 }
687 
688 //------------------------------------------------------------------------
689 enum
690 {
691 	// UI size
692 	kEditorWidth = 350,
getOrCreateValueInfo(Value * Operand)693 	kEditorHeight = 120
694 };
695 
696 //------------------------------------------------------------------------
697 } // namespace Vst
698 } // namespace Steinberg
699 
700 //------------------------------------------------------------------------
701 //------------------------------------------------------------------------
702 //------------------------------------------------------------------------
703 
704 //------------------------------------------------------------------------
705 // called when library is loaded
706 bool InitModule ()
getValueInfo(Value * Operand) const707 {
708 	return true;
709 }
710 
711 //------------------------------------------------------------------------
712 // called when library is unloaded
713 bool DeinitModule ()
714 {
PredicateInfo(Function & F,DominatorTree & DT,AssumptionCache & AC)715 	return true;
716 }
717 
718 //------------------------------------------------------------------------
719 BEGIN_FACTORY_DEF ("Steinberg Media Technologies",
720 				   "http://www.steinberg.net",
721 				   "mailto:info@steinberg.de")
722 
723 	//---First plug-in included in this factory-------
724 	// its kVstAudioEffectClass component
~PredicateInfo()725 	DEF_CLASS2 (INLINE_UID (0xB9F9ADE1, 0xCD9C4B6D, 0xA57E61E3, 0x123535FD),
726 				PClassInfo::kManyInstances,					// cardinality
727 				kVstAudioEffectClass,						// the component category (do not changed this)
728 				"AGainSimple VST3",							// here the plug-in name (to be changed)
729 				0,											// single component effects cannot be distributed so this is zero
730 				"Fx",										// Subcategory for this plug-in (to be changed)
731 				FULL_VERSION_STR,							// Plug-in version (to be changed)
732 				kVstVersionString,							// the VST 3 SDK version (do not changed this, use always this define)
733 				Steinberg::Vst::AGainSimple::createInstance)// function pointer called when this component should be instantiated
734 
735 END_FACTORY
736