text:
//------------------------------------------------------------------------
// Project     : VST SDK
//
// Category    : Common Base Classes
// Filename    : public.sdk/source/main/pluginfactoryvst3.h
// Created by  : Steinberg, 01/2004
// Description : Standard Plug-in Factory
//
//-----------------------------------------------------------------------------
// LICENSE
// (c) 2017, Steinberg Media Technologies GmbH, All Rights Reserved
//-----------------------------------------------------------------------------
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistributions of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//   * Redistributions in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//   * Neither the name of the Steinberg Media Technologies nor the names of its
//     contributors may be used to endorse or promote products derived from this
//     software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE  OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//-----------------------------------------------------------------------------

#pragma once

#include "pluginterfaces/base/ipluginbase.h"

namespace Steinberg {

//------------------------------------------------------------------------
/** Default Class Factory implementation.
\ingroup sdkBase
\see \ref classFactoryMacros */
//------------------------------------------------------------------------
class CPluginFactory : public IPluginFactory3
{
public:
//------------------------------------------------------------------------
	CPluginFactory (const PFactoryInfo& info);
	virtual ~CPluginFactory ();

//------------------------------------------------------------------------
	/** Registers a Plug-in class with classInfo version 1, returns true for success. */
	bool registerClass (const PClassInfo* info,
						FUnknown* (*createFunc)(void*),
						void* context = 0);

	/** Registers a Plug-in class with classInfo version 2, returns true for success. */
	bool registerClass (const PClassInfo2* info,
						FUnknown* (*createFunc)(void*),
						void* context = 0);

	/** Registers a Plug-in class with classInfo Unicode version, returns true for success. */
	bool registerClass (const PClassInfoW* info,
						FUnknown* (*createFunc)(void*),
						void* context = 0);

	/** Check if a class for a given classId is already registered. */
	bool isClassRegistered (const FUID& cid);

//------------------------------------------------------------------------
	DECLARE_FUNKNOWN_METHODS

	//---from IPluginFactory------
	tresult PLUGIN_API getFactoryInfo (PFactoryInfo* info) SMTG_OVERRIDE;
	int32 PLUGIN_API countClasses () SMTG_OVERRIDE;
	tresult PLUGIN_API getClassInfo (int32 index, PClassInfo* info) SMTG_OVERRIDE;
	tresult PLUGIN_API createInstance (FIDString cid, FIDString _iid, void** obj) SMTG_OVERRIDE;

	//---from IPluginFactory2-----
	tresult PLUGIN_API getClassInfo2 (int32 index, PClassInfo2* info) SMTG_OVERRIDE;

	//---from IPluginFactory3-----
	tresult PLUGIN_API getClassInfoUnicode (int32 index, PClassInfoW* info) SMTG_OVERRIDE;
	tresult PLUGIN_API setHostContext (FUnknown* context) SMTG_OVERRIDE;

//------------------------------------------------------------------------
protected:
	/// @cond
	struct PClassEntry
	{
	//-----------------------------------
		PClassInfo2 info8;
		PClassInfoW info16;

		FUnknown* (*createFunc)(void*);
		void* context;
		bool isUnicode;
	//-----------------------------------
	};
	/// @endcond

	PFactoryInfo factoryInfo;
	PClassEntry* classes;
	int32 classCount;
	int32 maxClassCount;

	bool growClasses ();
};

extern CPluginFactory* gPluginFactory;
//------------------------------------------------------------------------
} // namespace Steinberg

//------------------------------------------------------------------------
#if defined(__GNUC__) && ((__GNUC__ >= 4) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1)))
	#define EXPORT_FACTORY	__attribute__ ((visibility ("default")))
#else
	#define EXPORT_FACTORY
#endif

//------------------------------------------------------------------------
/** \defgroup classFactoryMacros Macros for defining the class factory
\ingroup sdkBase

\b Example - How to use the class factory macros:
\code
BEGIN_FACTORY ("Steinberg Technologies",
			   "http://www.steinberg.de",
			   "mailto:info@steinberg.de",
			   PFactoryInfo::kNoFlags)

DEF_CLASS (INLINE_UID (0x00000000, 0x00000000, 0x00000000, 0x00000000),
			PClassInfo::kManyInstances,
			"Service",
			"Test Service",
			TestService::newInstance)

END_FACTORY
\endcode

@{*/

#define BEGIN_FACTORY(vendor,url,email,flags) using namespace Steinberg; \
	EXPORT_FACTORY IPluginFactory* PLUGIN_API GetPluginFactory () { \
	if (!gPluginFactory) \
	{	static PFactoryInfo factoryInfo (vendor,url,email,flags); \
		gPluginFactory = new CPluginFactory (factoryInfo); \

#define DEF_CLASS(cid,cardinality,category,name,createMethod) \
	{ TUID lcid = cid; static PClassInfo componentClass (lcid,cardinality,category,name); \
	gPluginFactory->registerClass (&componentClass,createMethod); }

#define DEF_CLASS1(cid,cardinality,category,name,createMethod) \
	{ static PClassInfo componentClass (cid,cardinality,category,name); \
	gPluginFactory->registerClass (&componentClass,createMethod); }

#define DEF_CLASS2(cid,cardinality,category,name,classFlags,subCategories,version,sdkVersion,createMethod) \
	{ TUID lcid = cid; static PClassInfo2 componentClass (lcid,cardinality,category,name,classFlags,subCategories, 0 ,version,sdkVersion);\
	gPluginFactory->registerClass (&componentClass,createMethod); }

#define DEF_CLASS_W(cid,cardinality,category,name,classFlags,subCategories,version,sdkVersion,createMethod) \
	{ TUID lcid = cid; static PClassInfoUnicode componentClass (lcid,cardinality,category,name,classFlags,subCategories, 0,version,sdkVersion);\
	gPluginFactory->registerClass (&componentClass,createMethod); }

#define END_FACTORY	} else gPluginFactory->addRef (); \
	return gPluginFactory; }

/** @} */


text:
//-----------------------------------------------------------------------------
// Project     : VST SDK
//
// Category    : Helpers
// Filename    : public.sdk/source/vst/vstparameters.cpp
// Created by  : Steinberg, 03/2008
// Description : VST Parameter Implementation
//
//-----------------------------------------------------------------------------
// LICENSE
// (c) 2017, Steinberg Media Technologies GmbH, All Rights Reserved
//-----------------------------------------------------------------------------
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistributions of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//   * Redistributions in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//   * Neither the name of the Steinberg Media Technologies nor the names of its
//     contributors may be used to endorse or promote products derived from this
//     software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE  OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//-----------------------------------------------------------------------------

#include "vstparameters.h"
#include "pluginterfaces/base/futils.h"
#include "pluginterfaces/base/ustring.h"
#include <cstdlib>

namespace Steinberg {
namespace Vst {

//------------------------------------------------------------------------
// Parameter Implementation
//------------------------------------------------------------------------
Parameter::Parameter ()
: valueNormalized (0.)
, precision (4)
{
	memset (&info, 0, sizeof (ParameterInfo));
}

//------------------------------------------------------------------------
Parameter::Parameter (const ParameterInfo& info)
: info (info)
, valueNormalized (info.defaultNormalizedValue)
, precision (4)
{}

//------------------------------------------------------------------------
Parameter::Parameter (const TChar* title, ParamID tag, const TChar* units, ParamValue defaultValueNormalized, int32 stepCount, int32 flags, UnitID unitID)
: precision (4)
{
	memset (&info, 0, sizeof (ParameterInfo));

	UString (info.title, str16BufferSize (String128)).assign (title);
	if (units)
		UString (info.units, str16BufferSize (String128)).assign (units);

	info.stepCount = stepCount;
	info.defaultNormalizedValue = valueNormalized = defaultValueNormalized;
	info.flags = flags;
	info.id = tag;
	info.unitId = unitID;
}

//------------------------------------------------------------------------
Parameter::~Parameter ()
{}

//------------------------------------------------------------------------
bool Parameter::setNormalized (ParamValue normValue)
{
	if (normValue > 1.0)
	{
		normValue = 1.0;
	}
	else if (normValue < 0.)
	{
		normValue = 0.;
	}

	if (normValue != valueNormalized)
	{
		valueNormalized = normValue;
		changed ();
		return true;
	}
	return false;
}

//------------------------------------------------------------------------
void Parameter::toString (ParamValue normValue, String128 string) const
{
	UString wrapper (string, str16BufferSize (String128));
	if (info.stepCount == 1)
	{
		if (normValue > 0.5)
		{
			wrapper.assign (STR16 ("On"));
		}
		else
		{
			wrapper.assign (STR16 ("Off"));
		}
	}
	else
	{
		if (!wrapper.printFloat (normValue, precision))
			string[0] = 0;
	}
}

//------------------------------------------------------------------------
bool Parameter::fromString (const TChar* string, ParamValue& normValue) const
{
	UString wrapper (const_cast<TChar*> (string), tstrlen (string));
	return wrapper.scanFloat (normValue);
}

//------------------------------------------------------------------------
ParamValue Parameter::toPlain (ParamValue normValue) const
{
	return normValue;
}

//------------------------------------------------------------------------
ParamValue Parameter::toNormalized (ParamValue plainValue) const
{
	return plainValue;
}

//------------------------------------------------------------------------
// RangeParameter Implementation
//------------------------------------------------------------------------
RangeParameter::RangeParameter ()
: minPlain (0)
, maxPlain (1)
{
}

//------------------------------------------------------------------------
RangeParameter::RangeParameter (const ParameterInfo& paramInfo, ParamValue min, ParamValue max)
: Parameter (paramInfo)
, minPlain (min)
, maxPlain (max)
{
}

//------------------------------------------------------------------------
RangeParameter::RangeParameter (const TChar* title, ParamID tag, const TChar* units,
								ParamValue minPlain, ParamValue maxPlain, ParamValue defaultValuePlain,
								int32 stepCount, int32 flags, UnitID unitID)
: minPlain (minPlain)
, maxPlain (maxPlain)
{
	UString (info.title, str16BufferSize (String128)).assign (title);

	UString uUnits (info.units, str16BufferSize (String128));
	if (units)
	{
		uUnits.assign (units);
	}

	info.stepCount = stepCount;
	info.defaultNormalizedValue = valueNormalized = toNormalized (defaultValuePlain);
	info.flags = flags;
	info.id = tag;
	info.unitId = unitID;
}

//------------------------------------------------------------------------
void RangeParameter::toString (ParamValue _valueNormalized, String128 string) const
{
	if (info.stepCount > 1)
	{
		UString wrapper (string, str16BufferSize (String128));
		int64 plain = static_cast<int64> (toPlain (_valueNormalized));
		if (!wrapper.printInt (plain))
			string[0] = 0;
	}
	else
	{
		Parameter::toString (toPlain (_valueNormalized), string);
	}
}

//------------------------------------------------------------------------
bool RangeParameter::fromString (const TChar* string, ParamValue& _valueNormalized) const
{
	UString wrapper (const_cast<TChar*> (string), tstrlen (string));
	if (info.stepCount > 1)
	{
		int64 plainValue;
		if (wrapper.scanInt (plainValue))
		{
			_valueNormalized = toNormalized ((ParamValue)plainValue);
			return true;
		}
		return false;
	}
	if (wrapper.scanFloat (_valueNormalized))
	{
		if (_valueNormalized < getMin ())
			_valueNormalized = getMin ();
		else if (_valueNormalized > getMax ())
			_valueNormalized = getMax ();
		_valueNormalized = toNormalized (_valueNormalized);
		return true;
	}
	return false;
}

//------------------------------------------------------------------------
ParamValue RangeParameter::toPlain (ParamValue _valueNormalized) const
{
	if (info.stepCount > 1)
		return Min<int32> (info.stepCount, (int32)(_valueNormalized * (info.stepCount + 1))) + getMin ();
	return _valueNormalized * (getMax () - getMin ()) + getMin ();
}

//------------------------------------------------------------------------
ParamValue RangeParameter::toNormalized (ParamValue plainValue) const
{
	if (info.stepCount > 1)
		return (plainValue - getMin ()) / info.stepCount;
	return (plainValue - getMin ()) / (getMax () - getMin ());
}

//------------------------------------------------------------------------
// StringListParameter Implementation
//------------------------------------------------------------------------
StringListParameter::StringListParameter (const ParameterInfo& paramInfo)
: Parameter (paramInfo)
{
}

//------------------------------------------------------------------------
StringListParameter::StringListParameter (const TChar* title, ParamID tag, const TChar* units,
										  int32 flags, UnitID unitID)
{
	UString (info.title, str16BufferSize (String128)).assign (title);

	UString uUnits (info.units, str16BufferSize (String128));
	if (units)
	{
		uUnits.assign (units);
	}

	info.stepCount = -1;
	info.defaultNormalizedValue = 0;
	info.flags = flags;
	info.id = tag;
	info.unitId = unitID;
}

//------------------------------------------------------------------------
StringListParameter::~StringListParameter ()
{
	for (StringVector::iterator it = strings.begin (), end = strings.end (); it != end; ++it)
		std::free (*it);
}

//------------------------------------------------------------------------
void StringListParameter::appendString (const String128 string)
{
	int32 length = strlen16 (string);
	TChar* buffer = (TChar*)std::malloc ((length + 1) * sizeof (TChar));
	if (!buffer)
		return;
	memcpy (buffer, string, length * sizeof (TChar));
	buffer[length] = 0;
	strings.push_back (buffer);
	info.stepCount++;
}

//------------------------------------------------------------------------
bool StringListParameter::replaceString (int32 index, const String128 string)
{
	TChar* str = strings.at (index);
	if (!str)
		return false;

	int32 length = strlen16 (string);
	TChar* buffer = (TChar*)malloc ((length + 1) * sizeof (TChar));
	if (!buffer)
		return false;

	memcpy (buffer, string, length * sizeof (TChar));
	buffer[length] = 0;
	strings[index] = buffer;
	std::free (str);
	return true;
}

//------------------------------------------------------------------------
void StringListParameter::toString (ParamValue _valueNormalized, String128 string) const
{
	int32 index = (int32)toPlain (_valueNormalized);
	const TChar* valueString = strings.at (index);
	if (valueString)
	{
		UString (string, str16BufferSize (String128)).assign (valueString);
	}
	else
		string[0] = 0;
}

//------------------------------------------------------------------------
bool StringListParameter::fromString (const TChar* string, ParamValue& _valueNormalized) const
{
	int32 index = 0;
	for (StringVector::const_iterator it = strings.begin (), end = strings.end (); it != end; ++it, ++index)
	{
		if (strcmp16 (*it, string) == 0)
		{
			_valueNormalized = toNormalized ((ParamValue)index);
			return true;
		}
	}
	return false;
}

//------------------------------------------------------------------------
ParamValue StringListParameter::toPlain (ParamValue _valueNormalized) const
{
	if (info.stepCount <= 0)
		return 0;
	return Min<int32> (info.stepCount, (int32)(_valueNormalized * (info.stepCount + 1)));
}

//------------------------------------------------------------------------
ParamValue StringListParameter::toNormalized (ParamValue plainValue) const
{
	if (info.stepCount <= 0)
		return 0;
	return plainValue / (ParamValue)info.stepCount;
}

//------------------------------------------------------------------------
// ParameterContainer Implementation
//------------------------------------------------------------------------
ParameterContainer::ParameterContainer ()
: params (0)
{
}

//------------------------------------------------------------------------
ParameterContainer::~ParameterContainer ()
{
	if (params)
		delete params;
}

//------------------------------------------------------------------------
void ParameterContainer::init (int32 initialSize, int32 resizeDelta)
{
	if (!params)
	{
		params = new ParameterPtrVector;
		if (initialSize > 0)
			params->reserve (initialSize);
	}
}

//------------------------------------------------------------------------
Parameter* ParameterContainer::addParameter (Parameter* p)
{
	if (!params)
		init ();
	id2index[p->getInfo ().id] = params->size ();
	params->push_back (IPtr<Parameter> (p, false));
	return p;
}

//------------------------------------------------------------------------
Parameter* ParameterContainer::addParameter (const ParameterInfo& info)
{
	if (!params)
		init ();
	Parameter* p = new Parameter (info);
	if (addParameter (p))
		return p;
	p->release ();
	return 0;
}

//------------------------------------------------------------------------
Parameter* ParameterContainer::getParameter (ParamID tag)
{
	if (params)
	{
		IndexMap::const_iterator it = id2index.find (tag);
		if (it != id2index.end ())
			return params->at (it->second);
	}
	return 0;
}

//------------------------------------------------------------------------
Parameter* ParameterContainer::addParameter (const TChar* title, const TChar* units,
											 int32 stepCount, ParamValue defaultNormalizedValue,
											 int32 flags, int32 tag, UnitID unitID)
{
	if (!title)
	{
		return 0;
	}

	ParameterInfo info = {0};

	UString (info.title, str16BufferSize (String128)).assign (title);

	UString uUnits (info.units, str16BufferSize (String128));
	if (units)
	{
		uUnits.assign (units);
	}

	info.stepCount = stepCount;
	info.defaultNormalizedValue = defaultNormalizedValue;
	info.flags = flags;
	info.id = (tag >= 0) ? tag : getParameterCount ();
	info.unitId = unitID;

	return addParameter (info);
}

//------------------------------------------------------------------------
} // namespace Vst
} // namespace Steinberg

repo_name: fedden/RenderMan

mime_type: text/x-c++


text:
//-----------------------------------------------------------------------------
// Project     : VST SDK
//
// Category    : Helpers
// Filename    : public.sdk/source/vst/vstbus.cpp
// Created by  : Steinberg, 03/2008
// Description : VST Bus Implementation
//
//-----------------------------------------------------------------------------
// LICENSE
// (c) 2017, Steinberg Media Technologies GmbH, All Rights Reserved
//-----------------------------------------------------------------------------
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistributions of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//   * Redistributions in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//   * Neither the name of the Steinberg Media Technologies nor the names of its
//     contributors may be used to endorse or promote products derived from this
//     software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE  OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//-----------------------------------------------------------------------------

#include "vstbus.h"

namespace Steinberg {
namespace Vst {

//------------------------------------------------------------------------
// Bus Implementation
//------------------------------------------------------------------------
Bus::Bus (const TChar* _name, BusType _busType, int32 _flags)
: name (_name)
, busType (_busType)
, flags (_flags)
, active (false)
{}

//------------------------------------------------------------------------
bool Bus::getInfo (BusInfo& info)
{
	name.copyTo16 (info.name, 0, str16BufferSize (info.name) - 1);
	info.busType = busType;
	info.flags = flags;
	return true;
}

//------------------------------------------------------------------------
// EventBus Implementation
//------------------------------------------------------------------------
EventBus::EventBus (const TChar* name, BusType busType, int32 flags, int32 channelCount)
: Bus (name, busType, flags)
, channelCount (channelCount)
{}

//------------------------------------------------------------------------
bool EventBus::getInfo (BusInfo& info)
{
	info.channelCount = channelCount;
	return Bus::getInfo (info);
}

//------------------------------------------------------------------------
// AudioBus Implementation
//------------------------------------------------------------------------
AudioBus::AudioBus (const TChar* name, BusType busType, int32 flags, SpeakerArrangement arr)
: Bus (name, busType, flags)
, speakerArr (arr)
{}

//------------------------------------------------------------------------
bool AudioBus::getInfo (BusInfo& info)
{
	info.channelCount = SpeakerArr::getChannelCount (speakerArr);
	return Bus::getInfo (info);
}

//------------------------------------------------------------------------
// BusList Implementation
//------------------------------------------------------------------------
BusList::BusList (MediaType type, BusDirection dir)
: type (type)
, direction (dir)
{}

//------------------------------------------------------------------------
} // namespace Vst
} // namespace Steinberg


text:
//------------------------------------------------------------------------
// Project     : VST SDK
//
// Category    : Helpers
// Filename    : public.sdk/source/vst/vstnoteexpressiontypes.cpp
// Created by  : Steinberg, 12/2010
// Description : VST Note Expression Type Info Implementation
//
//-----------------------------------------------------------------------------
// LICENSE
// (c) 2017, Steinberg Media Technologies GmbH, All Rights Reserved
//-----------------------------------------------------------------------------
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistributions of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//   * Redistributions in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//   * Neither the name of the Steinberg Media Technologies nor the names of its
//     contributors may be used to endorse or promote products derived from this
//     software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE  OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//-----------------------------------------------------------------------------

#include "vstnoteexpressiontypes.h"
#include "vstparameters.h"
#include "pluginterfaces/base/ustring.h"
#include "pluginterfaces/base/futils.h"
#include "base/source/fstring.h"

#include <cstring>

namespace Steinberg {
namespace Vst {

//-----------------------------------------------------------------------------
NoteExpressionType::NoteExpressionType ()
: precision (4)
{
	memset (&info, 0, sizeof (info));
}

//-----------------------------------------------------------------------------
NoteExpressionType::NoteExpressionType (const NoteExpressionTypeInfo& _info)
: precision (4)
{
	memcpy (&info, &_info, sizeof (info));
}

//-----------------------------------------------------------------------------
NoteExpressionType::NoteExpressionType (NoteExpressionTypeID _typeId, const TChar* _title, const TChar* _shortTitle, const TChar* _units,
										int32 _unitId, NoteExpressionValue _defaultValue, NoteExpressionValue _minimum, NoteExpressionValue _maximum,
										int32 _stepCount, int32 _flags, int32 _precision)
: precision (_precision)
{
	memset (&info, 0, sizeof (info));
	info.typeId = _typeId;
	if (_title)
		UString (info.title, str16BufferSize (String128)).assign (_title);
	if (_shortTitle)
		UString (info.shortTitle, str16BufferSize (String128)).assign (_shortTitle);
	if (_units)
		UString (info.shortTitle, str16BufferSize (String128)).assign (_units);
	info.unitId = _unitId;
	info.valueDesc.defaultValue = _defaultValue;
	info.valueDesc.minimum = _minimum;
	info.valueDesc.maximum = _maximum;
	info.valueDesc.stepCount = _stepCount;
	info.flags = _flags;
}

//-----------------------------------------------------------------------------
NoteExpressionType::NoteExpressionType (NoteExpressionTypeID _typeId, const TChar* _title, const TChar* _shortTitle, const TChar* _units,
										int32 _unitId, Parameter* _associatedParameter, int32 _flags)
: associatedParameter (_associatedParameter)
, precision (4)
{
	memset (&info, 0, sizeof (info));
	info.typeId = _typeId;
	if (_title)
		UString (info.title, str16BufferSize (String128)).assign (_title);
	if (_shortTitle)
		UString (info.shortTitle, str16BufferSize (String128)).assign (_shortTitle);
	if (_units)
		UString (info.shortTitle, str16BufferSize (String128)).assign (_units);
	info.unitId = _unitId;
	info.valueDesc.defaultValue = 0.5;
	info.valueDesc.minimum = 0.;
	info.valueDesc.maximum = 1.;
	info.flags = _flags;
	if (_associatedParameter)
	{
		info.valueDesc.stepCount = _associatedParameter->getInfo ().stepCount;
		info.valueDesc.defaultValue = _associatedParameter->getInfo ().defaultNormalizedValue;
		info.associatedParameterId = associatedParameter->getInfo ().id;
		info.flags |= NoteExpressionTypeInfo::kAssociatedParameterIDValid;
	}
}

//-----------------------------------------------------------------------------
tresult NoteExpressionType::getStringByValue (NoteExpressionValue valueNormalized /*in*/, String128 string /*out*/)
{
	if (associatedParameter)
	{
		associatedParameter->toString (valueNormalized, string);
		return kResultTrue;
	}
	UString128 wrapper;
	if (info.valueDesc.stepCount > 0)
	{
		int32 value = Min<int32> (info.valueDesc.stepCount, (int32)(valueNormalized * (info.valueDesc.stepCount + 1)));
		wrapper.printInt (value);
	}
	else
	{
		wrapper.printFloat (valueNormalized, precision);
	}
	wrapper.copyTo (string, 128);
	return kResultTrue;
}

//-----------------------------------------------------------------------------
tresult NoteExpressionType::getValueByString (const TChar* string /*in*/, NoteExpressionValue& valueNormalized /*out*/)
{
	if (associatedParameter)
	{
		return associatedParameter->fromString (string, valueNormalized) ? kResultTrue : kResultFalse;
	}
	String wrapper (string);
	if (info.valueDesc.stepCount > 0)
	{
		int32 value;
		if (wrapper.scanInt32 (value) && value <= info.valueDesc.stepCount)
		{
			valueNormalized = (NoteExpressionValue)value / (NoteExpressionValue)info.valueDesc.stepCount;
			return kResultTrue;
		}
		return kResultFalse;
	}
	double value;
	wrapper.scanFloat (value);
	if (value < info.valueDesc.minimum)
		return kResultFalse;
	if (value > info.valueDesc.maximum)
		return kResultFalse;
	valueNormalized = value;
	return kResultTrue;
}

//-----------------------------------------------------------------------------
RangeNoteExpressionType::RangeNoteExpressionType (NoteExpressionTypeID _typeId, const TChar* _title, const TChar* _shortTitle, const TChar* _units,
						 int32 _unitId, NoteExpressionValue _defaultPlainValue, NoteExpressionValue _plainMin, NoteExpressionValue _plainMax,
						 int32 _flags, int32 _precision)
: NoteExpressionType (_typeId, _title, _shortTitle, _units, _unitId, 0, 0, 1, 0, _flags, _precision)
, plainMin (_plainMin)
, plainMax (_plainMax)
{
	info.valueDesc.defaultValue = (_defaultPlainValue - getMin ()) / (getMax () - getMin ());
}

//-----------------------------------------------------------------------------
tresult RangeNoteExpressionType::getStringByValue (NoteExpressionValue valueNormalized /*in*/, String128 string /*out*/)
{
	NoteExpressionValue plain = valueNormalized * (getMax () - getMin ()) + getMin ();
	UString128 wrapper;
	wrapper.printFloat (plain, precision);
	wrapper.copyTo (string, 128);
	return kResultTrue;
}

//-----------------------------------------------------------------------------
tresult RangeNoteExpressionType::getValueByString (const TChar* string /*in*/, NoteExpressionValue& valueNormalized /*out*/)
{
	String wrapper (string);
	double value = 0;
	if (wrapper.scanFloat (value))
	{
		value = (value - getMin ()) / (getMax () - getMin ());
		if (value >= 0. && value <= 1.)
		{
			valueNormalized = value;
			return kResultTrue;
		}
	}
	return kResultFalse;
}

//-----------------------------------------------------------------------------
NoteExpressionTypeContainer::NoteExpressionTypeContainer ()
{
}

//-----------------------------------------------------------------------------
NoteExpressionTypeContainer::NoteExprTypeVector::const_iterator NoteExpressionTypeContainer::find (
    NoteExpressionTypeID typeId) const
{
	for (NoteExprTypeVector::const_iterator it = noteExps.begin (), end = noteExps.end ();
	     it != end; ++it)
	{
		if ((*it)->getInfo ().typeId == typeId)
		{
			return it;
		}
	}
	return noteExps.end ();
}

//-----------------------------------------------------------------------------
bool NoteExpressionTypeContainer::addNoteExpressionType (NoteExpressionType* noteExpType)
{
	noteExps.push_back(IPtr<NoteExpressionType> (noteExpType, false));
	return true;
}

//-----------------------------------------------------------------------------
bool NoteExpressionTypeContainer::removeNoteExpressionType (NoteExpressionTypeID typeId)
{
	NoteExprTypeVector::const_iterator it = find (typeId);
	if (it != noteExps.end ())
	{
		noteExps.erase (it);
		return true;
	}
	return false;
}

//-----------------------------------------------------------------------------
void NoteExpressionTypeContainer::removeAll ()
{
	noteExps.clear ();
}

//-----------------------------------------------------------------------------
NoteExpressionType* NoteExpressionTypeContainer::getNoteExpressionType (NoteExpressionTypeID typeId)
{
	NoteExprTypeVector::const_iterator it = find (typeId);
	if (it != noteExps.end ())
		return (*it);
	return 0;
}

//-----------------------------------------------------------------------------
int32 NoteExpressionTypeContainer::getNoteExpressionCount ()
{
	return static_cast<int32> (noteExps.size ());
}

//-----------------------------------------------------------------------------
tresult NoteExpressionTypeContainer::getNoteExpressionInfo (int32 noteExpressionIndex, NoteExpressionTypeInfo& info /*out*/)
{
	if (noteExpressionIndex < 0 || noteExpressionIndex >= static_cast<int32> (noteExps.size ()))
		return kInvalidArgument;
	std::memcpy (&info, &noteExps[noteExpressionIndex]->getInfo (), sizeof (info));
	return kResultTrue;
}

//-----------------------------------------------------------------------------
tresult NoteExpressionTypeContainer::getNoteExpressionStringByValue (NoteExpressionTypeID id, NoteExpressionValue valueNormalized /*in*/, String128 string /*out*/)
{
	NoteExpressionType* noteExpType = getNoteExpressionType (id);
	if (noteExpType)
	{
		return noteExpType->getStringByValue (valueNormalized, string);
	}
	return kResultFalse;
}

//-----------------------------------------------------------------------------
tresult NoteExpressionTypeContainer::getNoteExpressionValueByString (NoteExpressionTypeID id, const TChar* string /*in*/, NoteExpressionValue& valueNormalized /*out*/)
{
	NoteExpressionType* noteExpType = getNoteExpressionType (id);
	if (noteExpType)
	{
		return noteExpType->getValueByString (string, valueNormalized);
	}
	return kResultFalse;
}

//------------------------------------------------------------------------
} // namespace Vst
} // namespace Steinberg


text:
//-----------------------------------------------------------------------------
// Project     : VST SDK
//
// Category    : Helpers
// Filename    : public.sdk/source/vst/vstcomponent.cpp
// Created by  : Steinberg, 04/2005
// Description : Basic VST Plug-in Implementation
//
//-----------------------------------------------------------------------------
// LICENSE
// (c) 2017, Steinberg Media Technologies GmbH, All Rights Reserved
//-----------------------------------------------------------------------------
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistributions of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//   * Redistributions in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//   * Neither the name of the Steinberg Media Technologies nor the names of its
//     contributors may be used to endorse or promote products derived from this
//     software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE  OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//-----------------------------------------------------------------------------

#include "vstcomponent.h"

namespace Steinberg {
namespace Vst {

//------------------------------------------------------------------------
// Component Implementation
//------------------------------------------------------------------------
Component::Component ()
: audioInputs (kAudio, kInput)
, audioOutputs (kAudio, kOutput)
, eventInputs (kEvent, kInput)
, eventOutputs (kEvent, kOutput)
{}

//------------------------------------------------------------------------
tresult PLUGIN_API Component::initialize (FUnknown* context)
{
	return ComponentBase::initialize (context);
}

//------------------------------------------------------------------------
tresult PLUGIN_API Component::terminate ()
{
	// remove all buses
	removeAllBusses ();

	return ComponentBase::terminate ();
}

//------------------------------------------------------------------------
BusList* Component::getBusList (MediaType type, BusDirection dir)
{
	if (type == kAudio)
		return dir == kInput ? &audioInputs : &audioOutputs;
	else if (type == kEvent)
		return dir == kInput ? &eventInputs : &eventOutputs;
	return 0;
}

//------------------------------------------------------------------------
tresult Component::removeAudioBusses ()
{
	audioInputs.clear ();
	audioOutputs.clear ();

	return kResultOk;
}

//------------------------------------------------------------------------
tresult Component::removeEventBusses ()
{
	eventInputs.clear ();
	eventOutputs.clear ();

	return kResultOk;
}

//------------------------------------------------------------------------
tresult Component::removeAllBusses ()
{
	removeAudioBusses ();
	removeEventBusses ();

	return kResultOk;
}

//------------------------------------------------------------------------
tresult PLUGIN_API Component::getControllerClassId (TUID classID)
{
	if (controllerClass.isValid ())
	{
		controllerClass.toTUID (classID);
		return kResultTrue;
	}
	return kResultFalse;
}

//------------------------------------------------------------------------
tresult PLUGIN_API Component::setIoMode (IoMode /*mode*/)
{
	return kNotImplemented;
}

//------------------------------------------------------------------------
int32 PLUGIN_API Component::getBusCount (MediaType type, BusDirection dir)
{
	BusList* busList = getBusList (type, dir);
	return busList ? static_cast<int32> (busList->size ()) : 0;
}

//------------------------------------------------------------------------
tresult PLUGIN_API Component::getBusInfo (MediaType type, BusDirection dir, int32 index, BusInfo& info)
{
	if (index < 0)
		return kInvalidArgument;
	BusList* busList = getBusList (type, dir);
	if (busList == 0)
		return kInvalidArgument;
	if (index >= static_cast<int32> (busList->size ()))
		return kInvalidArgument;

	Bus* bus = busList->at (index);
	info.mediaType = type;
	info.direction = dir;
	if (bus->getInfo (info))
		return kResultTrue;
	return kResultFalse;
}

//------------------------------------------------------------------------
tresult PLUGIN_API Component::getRoutingInfo (RoutingInfo& /*inInfo*/, RoutingInfo& /*outInfo*/)
{
	return kNotImplemented;
}

//------------------------------------------------------------------------
tresult PLUGIN_API Component::activateBus (MediaType type, BusDirection dir, int32 index, TBool state)
{
	if (index < 0)
		return kInvalidArgument;
	BusList* busList = getBusList (type, dir);
	if (busList == 0)
		return kInvalidArgument;
	if (index >= static_cast<int32> (busList->size ()))
		return kInvalidArgument;

	Bus* bus = busList->at (index);
	bus->setActive (state);
	return kResultTrue;
}

//------------------------------------------------------------------------
tresult PLUGIN_API Component::setActive (TBool /*state*/)
{
	return kResultOk;
}

//------------------------------------------------------------------------
tresult PLUGIN_API Component::setState (IBStream* /*state*/)
{
	return kNotImplemented;
}

//------------------------------------------------------------------------
tresult PLUGIN_API Component::getState (IBStream* /*state*/)
{
	return kNotImplemented;
}

//------------------------------------------------------------------------
tresult Component::renameBus (MediaType type, BusDirection dir, int32 index, const String128 newName)
{
	if (index < 0)
		return kInvalidArgument;
	BusList* busList = getBusList (type, dir);
	if (busList == 0)
		return kInvalidArgument;
	if (index >= static_cast<int32> (busList->size ()))
		return kInvalidArgument;

	Bus* bus = busList->at (index);
	bus->setName (newName);
	return kResultTrue;
}

//------------------------------------------------------------------------
// Helpers Implementation
//------------------------------------------------------------------------
tresult getSpeakerChannelIndex (SpeakerArrangement arrangement, uint64 speaker, int32& channel)
{
	channel = SpeakerArr::getSpeakerIndex (speaker, arrangement);
	return channel < 0  ? kResultFalse : kResultTrue;
}
} // namespace Vst
} // namespace Steinberg


text:
//-----------------------------------------------------------------------------
// Project     : VST SDK
//
// Category    : Helpers
// Filename    : public.sdk/source/vst/vstsinglecomponenteffect.cpp
// Created by  : Steinberg, 03/2008
// Description : Basic Audio Effect Implementation in one component
//
//-----------------------------------------------------------------------------
// LICENSE
// (c) 2017, Steinberg Media Technologies GmbH, All Rights Reserved
//-----------------------------------------------------------------------------
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistributions of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//   * Redistributions in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//   * Neither the name of the Steinberg Media Technologies nor the names of its
//     contributors may be used to endorse or promote products derived from this
//     software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE  OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//-----------------------------------------------------------------------------

#include "vstsinglecomponenteffect.h"

//-----------------------------------------------------------------------------
namespace Steinberg {
namespace Vst {

//-----------------------------------------------------------------------------
// SingleComponentEffect Implementation
//-----------------------------------------------------------------------------
SingleComponentEffect::SingleComponentEffect ()
: audioInputs (kAudio, kInput)
, audioOutputs (kAudio, kOutput)
, eventInputs (kEvent, kInput)
, eventOutputs (kEvent, kOutput)
{
	processSetup.maxSamplesPerBlock = 1024;
	processSetup.processMode = Vst::kRealtime;
	processSetup.sampleRate = 44100.0;
	processSetup.symbolicSampleSize = Vst::kSample32;
}

//-----------------------------------------------------------------------------
SingleComponentEffect::~SingleComponentEffect ()
{
}

//-----------------------------------------------------------------------------
tresult PLUGIN_API SingleComponentEffect::initialize (FUnknown* context)
{
	return EditController::initialize (context);
}

//-----------------------------------------------------------------------------
tresult PLUGIN_API SingleComponentEffect::terminate ()
{
	parameters.removeAll ();
	removeAllBusses ();

	return EditController::terminate ();
}

//-----------------------------------------------------------------------------
int32 PLUGIN_API SingleComponentEffect::getBusCount (MediaType type, BusDirection dir)
{
	BusList* busList = getBusList (type, dir);
	return busList ? static_cast<int32>(busList->size ()) : 0;
}

//-----------------------------------------------------------------------------
tresult PLUGIN_API SingleComponentEffect::getBusInfo (MediaType type, BusDirection dir, int32 index,
                                                      BusInfo& info)
{
	BusList* busList = getBusList (type, dir);
	if (busList == 0)
		return kInvalidArgument;
	if (index >= static_cast<int32> (busList->size ()))
		return kInvalidArgument;

	Bus* bus = busList->at (index);
	info.mediaType = type;
	info.direction = dir;
	if (bus->getInfo (info))
		return kResultTrue;
	return kResultFalse;
}

//-----------------------------------------------------------------------------
tresult PLUGIN_API SingleComponentEffect::activateBus (MediaType type, BusDirection dir,
                                                       int32 index, TBool state)
{
	BusList* busList = getBusList (type, dir);
	Bus* bus = busList ? (Bus*)busList->at (index) : 0;
	if (bus)
	{
		bus->setActive (state);
		return kResultTrue;
	}
	return kResultFalse;
}

//-----------------------------------------------------------------------------
AudioBus* SingleComponentEffect::addAudioInput (const TChar* name, SpeakerArrangement arr,
                                                BusType busType, int32 flags)
{
	AudioBus* newBus = new AudioBus (name, busType, flags, arr);
	audioInputs.push_back (IPtr<Vst::Bus> (newBus, false));
	return newBus;
}

//-----------------------------------------------------------------------------
AudioBus* SingleComponentEffect::addAudioOutput (const TChar* name, SpeakerArrangement arr,
                                                 BusType busType, int32 flags)
{
	AudioBus* newBus = new AudioBus (name, busType, flags, arr);
	audioOutputs.push_back (IPtr<Vst::Bus> (newBus, false));
	return newBus;
}

//-----------------------------------------------------------------------------
EventBus* SingleComponentEffect::addEventInput (const TChar* name, int32 channels, BusType busType,
                                                int32 flags)
{
	EventBus* newBus = new EventBus (name, busType, flags, channels);
	eventInputs.push_back (IPtr<Vst::Bus> (newBus, false));
	return newBus;
}

//-----------------------------------------------------------------------------
EventBus* SingleComponentEffect::addEventOutput (const TChar* name, int32 channels, BusType busType,
                                                 int32 flags)
{
	EventBus* newBus = new EventBus (name, busType, flags, channels);
	eventOutputs.push_back (IPtr<Vst::Bus> (newBus, false));
	return newBus;
}

//-----------------------------------------------------------------------------
tresult SingleComponentEffect::removeAudioBusses ()
{
	audioInputs.clear ();
	audioOutputs.clear ();

	return kResultOk;
}

//-----------------------------------------------------------------------------
tresult SingleComponentEffect::removeEventBusses ()
{
	eventInputs.clear ();
	eventOutputs.clear ();

	return kResultOk;
}

//-----------------------------------------------------------------------------
tresult SingleComponentEffect::removeAllBusses ()
{
	removeAudioBusses ();
	removeEventBusses ();

	return kResultOk;
}

//-----------------------------------------------------------------------------
// IAudioProcessor
//-----------------------------------------------------------------------------
tresult PLUGIN_API SingleComponentEffect::setBusArrangements (SpeakerArrangement* inputs,
                                                              int32 numIns,
                                                              SpeakerArrangement* outputs,
                                                              int32 numOuts)
{
	if (numIns < 0 || numOuts < 0)
		return kInvalidArgument;

	if (numIns > static_cast<int32> (audioInputs.size ()) ||
	    numOuts > static_cast<int32> (audioOutputs.size ()))
		return kResultFalse;

	for (int32 index = 0; index < static_cast<int32>(audioInputs.size ()); ++index)
	{
		if (index >= numIns)
			break;
		FCast<Vst::AudioBus> (audioInputs[index].get ())->setArrangement (inputs[index]);
	}

	for (int32 index = 0; index < static_cast<int32>(audioOutputs.size ()); ++index)
	{
		if (index >= numOuts)
			break;
		FCast<Vst::AudioBus> (audioOutputs[index].get ())->setArrangement (outputs[index]);
	}

	return kResultTrue;
}

//-----------------------------------------------------------------------------
tresult PLUGIN_API SingleComponentEffect::getBusArrangement (BusDirection dir, int32 busIndex,
                                                             SpeakerArrangement& arr)
{
	BusList* busList = getBusList (kAudio, dir);
	AudioBus* audioBus = busList ? FCast<Vst::AudioBus> (busList->at (busIndex)) : 0;
	if (audioBus)
	{
		arr = audioBus->getArrangement ();
		return kResultTrue;
	}
	return kResultFalse;
}

//-----------------------------------------------------------------------------
tresult PLUGIN_API SingleComponentEffect::setupProcessing (ProcessSetup& newSetup)
{
	if (canProcessSampleSize (newSetup.symbolicSampleSize) != kResultTrue)
		return kResultFalse;

	processSetup = newSetup;
	return kResultOk;
}

//-----------------------------------------------------------------------------
tresult PLUGIN_API SingleComponentEffect::canProcessSampleSize (int32 symbolicSampleSize)
{
	return symbolicSampleSize == kSample32 ? kResultTrue : kResultFalse;
}

//-----------------------------------------------------------------------------
BusList* SingleComponentEffect::getBusList (MediaType type, BusDirection dir)
{
	if (type == kAudio)
		return dir == kInput ? &audioInputs : &audioOutputs;
	else if (type == kEvent)
		return dir == kInput ? &eventInputs : &eventOutputs;
	return 0;
}

//-----------------------------------------------------------------------------
tresult PLUGIN_API SingleComponentEffect::queryInterface (const TUID iid, void** obj)
{
	if (memcmp (iid, IConnectionPoint::iid, sizeof (::Steinberg::TUID)) == 0)
	{
		// no need to expose IConnectionPoint to the host
		return kNoInterface;
	}
	DEF_INTERFACE (IComponent)
	DEF_INTERFACE (IAudioProcessor)
	return EditController::queryInterface (iid, obj);
}

//------------------------------------------------------------------------
} // namespace Vst
} // namespace Steinberg

// work around for the name clash of IComponent::setState and IEditController::setState
// make sure that vsteditcontroller.cpp is otherwise excluded from your project
#define setState setEditorState
#define getState getEditorState
#include "public.sdk/source/vst/vsteditcontroller.cpp"
#undef setState
#undef getState


text:
//-----------------------------------------------------------------------------
// Project     : VST SDK
//
// Category    : Helpers
// Filename    : public.sdk/source/vst/vstcomponentbase.h
// Created by  : Steinberg, 05/2005
// Description : Base class for Component and Edit Controller
//
//-----------------------------------------------------------------------------
// LICENSE
// (c) 2017, Steinberg Media Technologies GmbH, All Rights Reserved
//-----------------------------------------------------------------------------
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistributions of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//   * Redistributions in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//   * Neither the name of the Steinberg Media Technologies nor the names of its
//     contributors may be used to endorse or promote products derived from this
//     software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE  OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//-----------------------------------------------------------------------------

#pragma once

#include "pluginterfaces/base/ipluginbase.h"
#include "pluginterfaces/vst/ivstmessage.h"
#include "pluginterfaces/vst/ivsthostapplication.h"
#include "base/source/fobject.h"

//------------------------------------------------------------------------
namespace Steinberg {
namespace Vst {

//------------------------------------------------------------------------
/** Base class for VST 3 Component and Edit Controller.
\ingroup vstClasses */
//------------------------------------------------------------------------
class ComponentBase: public FObject,
					 public IPluginBase,
	                 public IConnectionPoint
{
public:
//------------------------------------------------------------------------
	ComponentBase ();
	virtual ~ComponentBase ();

	//--- Internal Methods------
	/** Returns the hostContext (set by the host during initialize call). */
	FUnknown* getHostContext () { return hostContext; }

	/** Returns the peer for the messaging communication (you can only use IConnectionPoint::notify for communicate between peers, do not try to cast peerConnection. */
	IConnectionPoint* getPeer () { return peerConnection; }

	/** Allocates a message instance (don't forget to release it). */
	IMessage* allocateMessage ();

	/** Sends the given message to the peer. */
	tresult sendMessage (IMessage* message);

	/** Sends a simple text message to the peer (max 255 characters). Text is interpreted as UTF-8. */
	tresult sendTextMessage (const char8* text);

	/** Receives a simple text message from the peer (max 255 characters). Text is UTF-8 encoded. */
	virtual tresult receiveText (const char8* text);

	//---from IPluginBase------
	virtual tresult PLUGIN_API initialize (FUnknown* context) SMTG_OVERRIDE;
	virtual tresult PLUGIN_API terminate () SMTG_OVERRIDE;

	//---from IConnectionPoint-----------
	tresult PLUGIN_API connect (IConnectionPoint* other) SMTG_OVERRIDE;
	tresult PLUGIN_API disconnect (IConnectionPoint* other) SMTG_OVERRIDE;
	tresult PLUGIN_API notify (IMessage* message) SMTG_OVERRIDE;

	//---Interface------
	OBJ_METHODS (ComponentBase, FObject)
	DEFINE_INTERFACES
		DEF_INTERFACE (IPluginBase)
		DEF_INTERFACE (IConnectionPoint)
	END_DEFINE_INTERFACES (FObject)
	REFCOUNT_METHODS(FObject)

//------------------------------------------------------------------------
protected:
	FUnknown* hostContext;
	IConnectionPoint* peerConnection;
};

//------------------------------------------------------------------------
} // namespace Vst
} // namespace Steinberg


text:
//------------------------------------------------------------------------
// Project     : VST SDK
//
// Category    : Helpers
// Filename    : public.sdk/source/vst/vstguieditor.cpp
// Created by  : Steinberg, 04/2005
// Description : VSTGUI Editor
//
//-----------------------------------------------------------------------------
// LICENSE
// (c) 2017, Steinberg Media Technologies GmbH, All Rights Reserved
//-----------------------------------------------------------------------------
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistributions of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//   * Redistributions in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//   * Neither the name of the Steinberg Media Technologies nor the names of its
//     contributors may be used to endorse or promote products derived from this
//     software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE  OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//-----------------------------------------------------------------------------

#include "vstguieditor.h"
#include "pluginterfaces/base/keycodes.h"

#if VSTGUI_VERSION_MAJOR < 4
#include "vstgui/vstkeycode.h"
#endif

#include "base/source/fstring.h"

#if MAC
#include <CoreFoundation/CoreFoundation.h>
#include <dlfcn.h>
namespace VSTGUI {
	static void CreateVSTGUIBundleRef ();
	static void ReleaseVSTGUIBundleRef ();
}
#elif WINDOWS
void* hInstance = 0; // VSTGUI hInstance
extern void* moduleHandle;
#elif LINUX
extern void* moduleHandle;
namespace VSTGUI {
	void* soHandle = nullptr;
} // VSTGUI
#endif // MAC

namespace Steinberg {
namespace Vst {

//------------------------------------------------------------------------
VSTGUIEditor::VSTGUIEditor (void* controller, ViewRect* size)
: EditorView (static_cast<EditController*>(controller), size)
{
	#if MAC
	CreateVSTGUIBundleRef ();
	#elif WINDOWS
	hInstance = moduleHandle;
	#elif LINUX
	VSTGUI::soHandle = moduleHandle;
	#endif
	// create a timer used for idle update: will call notify method
	timer = new CVSTGUITimer (dynamic_cast<CBaseObject*>(this));
}

//------------------------------------------------------------------------
VSTGUIEditor::~VSTGUIEditor ()
{
	if (timer)
		timer->forget ();
	#if MAC
	ReleaseVSTGUIBundleRef ();
	#endif
}

//------------------------------------------------------------------------
void VSTGUIEditor::setIdleRate (int32 millisec)
{
	if (timer)
		timer->setFireTime (millisec);
}

//------------------------------------------------------------------------
tresult PLUGIN_API VSTGUIEditor::isPlatformTypeSupported (FIDString type)
{
#if WINDOWS
	if (strcmp (type, kPlatformTypeHWND) == 0)
		return kResultTrue;

#elif MAC
	#if TARGET_OS_IPHONE
	if (strcmp (type, kPlatformTypeUIView) == 0)
		return kResultTrue;
	#else
	#if MAC_CARBON
	if (strcmp (type, kPlatformTypeHIView) == 0)
		return kResultTrue;
	#endif

	#if MAC_COCOA
	if (strcmp (type, kPlatformTypeNSView) == 0)
		return kResultTrue;
	#endif
	#endif
#elif LINUX
	if (strcmp (type, kPlatformTypeX11EmbedWindowID) == 0)
		return kResultTrue;
#endif

	return kInvalidArgument;
}

//------------------------------------------------------------------------
tresult PLUGIN_API VSTGUIEditor::attached (void* parent, FIDString type)
{
#if MAC
	if (isPlatformTypeSupported (type) != kResultTrue)
		return kResultFalse;

	#if MAC_COCOA && MAC_CARBON && !(VSTGUI_VERSION_MAJOR >= 4 && VSTGUI_VERSION_MINOR >= 1)
	CFrame::setCocoaMode (strcmp (type, kPlatformTypeNSView) == 0);
	#endif
#endif

	if (timer)
		timer->start ();

#if VSTGUI_VERSION_MAJOR >= 4 && VSTGUI_VERSION_MINOR >= 1
	PlatformType platformType = kDefaultNative;
#if MAC
	#if TARGET_OS_IPHONE
	if (strcmp (type, kPlatformTypeUIView) == 0)
		platformType = kUIView;
	#else
	#if MAC_CARBON
	if (strcmp (type, kPlatformTypeHIView) == 0)
		platformType = kWindowRef;
	#endif

	#if MAC_COCOA
	if (strcmp (type, kPlatformTypeNSView) == 0)
		platformType = kNSView;
	#endif
	#endif
#endif // MAC
	if (open (parent, platformType) == true)
#else
	if (open (parent) == true)
#endif
	{
		ViewRect vr (0, 0, (int32)frame->getWidth (), (int32)frame->getHeight ());
		setRect (vr);
		if (plugFrame)
			plugFrame->resizeView (this, &vr);
	}
	return EditorView::attached (parent, type);
}

//------------------------------------------------------------------------
tresult PLUGIN_API VSTGUIEditor::removed ()
{
	if (timer)
		timer->stop ();

	close ();
	return EditorView::removed ();
}

//------------------------------------------------------------------------
tresult PLUGIN_API VSTGUIEditor::onSize (ViewRect* newSize)
{
	if (frame)
		frame->setSize (newSize->right - newSize->left, newSize->bottom - newSize->top);

	return EditorView::onSize (newSize);
}

//------------------------------------------------------------------------
void VSTGUIEditor::beginEdit (VSTGUI_INT32 index)
{
	if (controller)
		controller->beginEdit (index);
}

//------------------------------------------------------------------------
void VSTGUIEditor::endEdit (VSTGUI_INT32 index)
{
	if (controller)
		controller->endEdit (index);
}

//------------------------------------------------------------------------
VSTGUI_INT32 VSTGUIEditor::getKnobMode () const
{
	switch (EditController::getHostKnobMode ())
	{
		case kRelativCircularMode: return VSTGUI::kRelativCircularMode;
		case kLinearMode: return VSTGUI::kLinearMode;
	}
	return VSTGUI::kCircularMode;
}

//------------------------------------------------------------------------
CMessageResult VSTGUIEditor::notify (CBaseObject* /*sender*/, const char* message)
{
	if (message == CVSTGUITimer::kMsgTimer)
	{
		if (frame)
 			frame->idle ();

 		return kMessageNotified;
 	}

 	return kMessageUnknown;
}

//------------------------------------------------------------------------
static bool translateKeyMessage (VstKeyCode& keyCode, char16 key, int16 keyMsg, int16 modifiers)
{
	keyCode.character = 0;
	keyCode.virt = (unsigned char)keyMsg;
	keyCode.modifier = 0;
	if (key == 0)
		key = VirtualKeyCodeToChar ((uint8)keyMsg);
	if (key)
	{
		String keyStr (STR(" "));
		keyStr.setChar16 (0, key);
		keyStr.toMultiByte (kCP_Utf8);
		if (keyStr.length () == 1)
			keyCode.character = keyStr.getChar8 (0);
	}
	if (modifiers)
	{
		if (modifiers & kShiftKey)
			keyCode.modifier |= MODIFIER_SHIFT;
		if (modifiers & kAlternateKey)
			keyCode.modifier |= MODIFIER_ALTERNATE;
		if (modifiers & kCommandKey)
			keyCode.modifier |= MODIFIER_CONTROL;
		if (modifiers & kControlKey)
			keyCode.modifier |= MODIFIER_COMMAND;
	}
	return true;
}

//------------------------------------------------------------------------
tresult PLUGIN_API VSTGUIEditor::onKeyDown (char16 key, int16 keyMsg, int16 modifiers)
{
	if (frame)
	{
		VstKeyCode keyCode = {0};
		if (translateKeyMessage (keyCode, key, keyMsg, modifiers))
		{
			VSTGUI_INT32 result = frame->onKeyDown (keyCode);
			if (result == 1)
				return kResultTrue;
		}
	}
	return kResultFalse;
}

//------------------------------------------------------------------------
tresult PLUGIN_API VSTGUIEditor::onKeyUp (char16 key, int16 keyMsg, int16 modifiers)
{
	if (frame)
	{
		VstKeyCode keyCode = {0};
		if (translateKeyMessage (keyCode, key, keyMsg, modifiers))
		{
			VSTGUI_INT32 result = frame->onKeyUp (keyCode);
			if (result == 1)
				return kResultTrue;
		}
	}
	return kResultFalse;
}

//------------------------------------------------------------------------
tresult PLUGIN_API VSTGUIEditor::onWheel (float distance)
{
	if (frame)
	{
		CPoint where;
		frame->getCurrentMouseLocation (where);
		if (frame->onWheel (where, distance, frame->getCurrentMouseButtons ()))
			return kResultTrue;
	}
	return kResultFalse;
}

//------------------------------------------------------------------------
tresult PLUGIN_API VSTGUIEditor::setFrame (IPlugFrame* frame)
{
	if (frame)
	{
		FUnknownPtr<IPlugFrameIdle> frameIdle (frame);
		if (frameIdle)
			frameIdle->addIdleHandler (this);

	}
	else if (plugFrame)
	{
		FUnknownPtr<IPlugFrameIdle> frameIdle (plugFrame);
		if (frameIdle)
			frameIdle->removeIdleHandler (this);
	}
	return EditorView::setFrame (frame);
}

//------------------------------------------------------------------------
void PLUGIN_API VSTGUIEditor::onPlugViewIdle ()
{
	frame->handleNextSystemEvents ();
}

//------------------------------------------------------------------------
} // namespace Vst
} // namespace Steinberg

#if MAC
namespace VSTGUI {
void* gBundleRef = 0;
static int openCount = 0;
//------------------------------------------------------------------------
void CreateVSTGUIBundleRef ()
{
	openCount++;
	if (gBundleRef)
	{
		CFRetain (gBundleRef);
		return;
	}
#if TARGET_OS_IPHONE
	gBundleRef = CFBundleGetMainBundle ();
	CFRetain (gBundleRef);
#else
	Dl_info info;
	if (dladdr ((const void*)CreateVSTGUIBundleRef, &info))
	{
		if (info.dli_fname)
		{
			Steinberg::String name;
			name.assign (info.dli_fname);
			for (int i = 0; i < 3; i++)
			{
				int delPos = name.findLast ('/');
				if (delPos == -1)
				{
					fprintf (stdout, "Could not determine bundle location.\n");
					return; // unexpected
				}
				name.remove (delPos, name.length () - delPos);
			}
			CFURLRef bundleUrl = CFURLCreateFromFileSystemRepresentation (0, (const UInt8*)name.text8 (), name.length (), true);
			if (bundleUrl)
			{
				gBundleRef = CFBundleCreate (0, bundleUrl);
				CFRelease (bundleUrl);
			}
		}
	}
#endif
}

//------------------------------------------------------------------------
void ReleaseVSTGUIBundleRef ()
{
	openCount--;
	if (gBundleRef)
		CFRelease (gBundleRef);
	if (openCount == 0)
		gBundleRef = 0;
}

//------------------------------------------------------------------------
} // namespace VSTGUI

#endif // MAC


text:
//-----------------------------------------------------------------------------
// Project     : VST SDK
//
// Category    : Helpers
// Filename    : public.sdk/source/vst/vstcomponent.h
// Created by  : Steinberg, 04/2005
// Description : Basic VST Plug-in Implementation
//
//-----------------------------------------------------------------------------
// LICENSE
// (c) 2017, Steinberg Media Technologies GmbH, All Rights Reserved
//-----------------------------------------------------------------------------
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistributions of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//   * Redistributions in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//   * Neither the name of the Steinberg Media Technologies nor the names of its
//     contributors may be used to endorse or promote products derived from this
//     software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE  OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//-----------------------------------------------------------------------------

#pragma once

#include "public.sdk/source/vst/vstcomponentbase.h"
#include "public.sdk/source/vst/vstbus.h"
#include "pluginterfaces/vst/ivstcomponent.h"

//------------------------------------------------------------------------
namespace Steinberg {
namespace Vst {

//------------------------------------------------------------------------
/** Default implementation for a VST 3 Component.
\ingroup vstClasses
Can be used as base class for a VST 3 component implementation. */
//------------------------------------------------------------------------
class Component: public ComponentBase,
				 public IComponent
{
public:
//------------------------------------------------------------------------
	/** Constructor */
	Component ();

	//---Internal Methods-------
	/** Sets the controller Class ID associated to its component. */
	void setControllerClass (const FUID& cid) { controllerClass = cid; }

	/** Removes all Audio Buses. */
	tresult removeAudioBusses ();

	/** Removes all Event Buses. */
	tresult removeEventBusses ();

	/** Renames a specific bus. Do not forget to inform the host about this (see \ref IComponentHandler::restartComponent (kIoTitlesChanged)). */
	tresult renameBus (MediaType type, BusDirection dir, int32 index, const String128 newName);

	//---from IComponent--------
	tresult PLUGIN_API getControllerClassId (TUID classID) SMTG_OVERRIDE;
	tresult PLUGIN_API setIoMode (IoMode mode) SMTG_OVERRIDE;
	int32 PLUGIN_API getBusCount (MediaType type, BusDirection dir) SMTG_OVERRIDE;
	tresult PLUGIN_API getBusInfo (MediaType type, BusDirection dir, int32 index, BusInfo& info) SMTG_OVERRIDE;
	tresult PLUGIN_API getRoutingInfo (RoutingInfo& inInfo, RoutingInfo& outInfo) SMTG_OVERRIDE;
	tresult PLUGIN_API activateBus (MediaType type, BusDirection dir, int32 index, TBool state) SMTG_OVERRIDE;
	tresult PLUGIN_API setActive (TBool state) SMTG_OVERRIDE;
	tresult PLUGIN_API setState (IBStream* state) SMTG_OVERRIDE;
	tresult PLUGIN_API getState (IBStream* state) SMTG_OVERRIDE;

	//---from ComponentBase------
	tresult PLUGIN_API initialize (FUnknown* context) SMTG_OVERRIDE;
	tresult PLUGIN_API terminate () SMTG_OVERRIDE;

	//---Interface---------
	OBJ_METHODS (Component, ComponentBase)
	DEFINE_INTERFACES
		DEF_INTERFACE (IComponent)
	END_DEFINE_INTERFACES (ComponentBase)
	REFCOUNT_METHODS(ComponentBase)

//------------------------------------------------------------------------
protected:
	FUID controllerClass;
	BusList audioInputs;
	BusList audioOutputs;
	BusList eventInputs;
	BusList eventOutputs;

	BusList* getBusList (MediaType type, BusDirection dir);
	tresult removeAllBusses ();
};

//------------------------------------------------------------------------
// some Helper functions....
//------------------------------------------------------------------------

/** Gets the channel index of a given speaker in a arrangement, returns kResultFalse if speaker not part of the arrangement else returns kResultTrue. */
tresult getSpeakerChannelIndex (SpeakerArrangement arrangement, uint64 speaker, int32& channel);

//------------------------------------------------------------------------
} // namespace Vst
} // namespace Steinberg


text:
//------------------------------------------------------------------------
// Project     : VST SDK
//
// Category    : Helpers
// Filename    : public.sdk/source/vst/vstnoteexpressiontypes.h
// Created by  : Steinberg, 12/2010
// Description : VST Note Expression Type Info Implementation
//
//-----------------------------------------------------------------------------
// LICENSE
// (c) 2017, Steinberg Media Technologies GmbH, All Rights Reserved
//-----------------------------------------------------------------------------
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistributions of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//   * Redistributions in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//   * Neither the name of the Steinberg Media Technologies nor the names of its
//     contributors may be used to endorse or promote products derived from this
//     software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE  OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//-----------------------------------------------------------------------------

#pragma once

#include "pluginterfaces/vst/ivstnoteexpression.h"
#include "base/source/fobject.h"

#include <map>
#include <vector>

namespace Steinberg {
namespace Vst {
class Parameter;

//------------------------------------------------------------------------
/** Note expression type object.
\ingroup vstClasses */
//-----------------------------------------------------------------------------
class NoteExpressionType : public FObject
{
public:
	NoteExpressionType ();
	NoteExpressionType (const NoteExpressionTypeInfo& info);
	NoteExpressionType (NoteExpressionTypeID typeId, const TChar* title, const TChar* shortTitle, const TChar* units,
						int32 unitId, NoteExpressionValue defaultValue, NoteExpressionValue minimum, NoteExpressionValue maximum,
						int32 stepCount, int32 flags = 0, int32 precision = 4);
	NoteExpressionType (NoteExpressionTypeID typeId, const TChar* title, const TChar* shortTitle, const TChar* units,
						int32 unitId, Parameter* associatedParameter, int32 flags = 0);

	/** get the underlying NoteExpressionTypeInfo struct */
	NoteExpressionTypeInfo& getInfo () { return info; }

	/** convert a note expression value to a readable string */
	virtual tresult getStringByValue (NoteExpressionValue valueNormalized /*in*/, String128 string /*out*/);
	/** convert a readable string to a note expression value */
	virtual tresult getValueByString (const TChar* string /*in*/, NoteExpressionValue& valueNormalized /*out*/);

	/** gets the current precision (used for string representation of float) */
	int32 getPrecision () const { return precision;}
	/** Sets the precision for string representation of float value (for example 4.34 with 2 as precision) */
	void setPrecision (int32 val) { precision = val;}
//-----------------------------------------------------------------------------
	OBJ_METHODS(NoteExpressionType, FObject)
protected:
	NoteExpressionTypeInfo info;
	IPtr<Parameter> associatedParameter;
	int32 precision;
};

//------------------------------------------------------------------------
/** Note expression type object representing a custom range.
\ingroup vstClasses */
//-----------------------------------------------------------------------------
class RangeNoteExpressionType : public NoteExpressionType
{
public:
	RangeNoteExpressionType (NoteExpressionTypeID typeId, const TChar* title, const TChar* shortTitle, const TChar* units,
							 int32 unitId, NoteExpressionValue defaultPlainValue, NoteExpressionValue plainMin, NoteExpressionValue plainMax,
							 int32 flags = 0, int32 precision = 4);

	/** Gets the minimum plain value */
	virtual ParamValue getMin () const {return plainMin;}
	/** Sets the minimum plain value */
	virtual void setMin (ParamValue value) {plainMin = value;}
	/** Gets the maximum plain value */
	virtual ParamValue getMax () const {return plainMax;}
	/** Sets the maximum plain value */
	virtual void setMax (ParamValue value) {plainMax = value;}

	virtual tresult getStringByValue (NoteExpressionValue valueNormalized /*in*/, String128 string /*out*/) SMTG_OVERRIDE;
	virtual tresult getValueByString (const TChar* string /*in*/, NoteExpressionValue& valueNormalized /*out*/) SMTG_OVERRIDE;
//-----------------------------------------------------------------------------
	OBJ_METHODS(RangeNoteExpressionType, NoteExpressionType)
protected:
	NoteExpressionValue plainMin;
	NoteExpressionValue plainMax;
};

//------------------------------------------------------------------------
/** Collection of note expression types.
\ingroup vstClasses */
//------------------------------------------------------------------------
class NoteExpressionTypeContainer : public FObject
{
public:
	/** default constructor */
	NoteExpressionTypeContainer ();

	/** add a note expression type. The container owns the type. No need to release it afterwards. */
	bool addNoteExpressionType (NoteExpressionType* noteExpType);
	/** remove a note expression type */
	bool removeNoteExpressionType (NoteExpressionTypeID typeId);
	/** remove all note expression types */
	void removeAll ();

	/** get a note expression type object by ID */
	NoteExpressionType* getNoteExpressionType (NoteExpressionTypeID typeId);

	/** get the number of note expression types */
	int32 getNoteExpressionCount ();

	/** get note expression info */
	tresult getNoteExpressionInfo (int32 noteExpressionIndex, NoteExpressionTypeInfo& info /*out*/);
	/** convert a note expression value to a readable string */
	tresult getNoteExpressionStringByValue (NoteExpressionTypeID id, NoteExpressionValue valueNormalized /*in*/, String128 string /*out*/);
	/** convert a string to a note expression value */
	tresult getNoteExpressionValueByString (NoteExpressionTypeID id, const TChar* string /*in*/, NoteExpressionValue& valueNormalized /*out*/);
//-----------------------------------------------------------------------------
	OBJ_METHODS(NoteExpressionTypeContainer, FObject)
protected:
	typedef std::vector<IPtr<NoteExpressionType> > NoteExprTypeVector;
	NoteExprTypeVector::const_iterator find (NoteExpressionTypeID typeId) const;

	NoteExprTypeVector noteExps;
};

//------------------------------------------------------------------------
} // namespace Vst
} // namespace Steinberg


text:
//-----------------------------------------------------------------------------
// Project     : VST SDK
//
// Category    : Helpers
// Filename    : public.sdk/source/vst/vstcomponentbase.cpp
// Created by  : Steinberg, 05/2005
// Description : Base class for VST Component and Edit Controller
//
//-----------------------------------------------------------------------------
// LICENSE
// (c) 2017, Steinberg Media Technologies GmbH, All Rights Reserved
//-----------------------------------------------------------------------------
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistributions of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//   * Redistributions in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//   * Neither the name of the Steinberg Media Technologies nor the names of its
//     contributors may be used to endorse or promote products derived from this
//     software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE  OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//-----------------------------------------------------------------------------

#include "vstcomponentbase.h"
#include "base/source/fstring.h"

namespace Steinberg {
namespace Vst {

//------------------------------------------------------------------------
// ComponentBase Implementation
//------------------------------------------------------------------------
ComponentBase::ComponentBase ()
: hostContext (0)
, peerConnection (0)
{}

//------------------------------------------------------------------------
ComponentBase::~ComponentBase ()
{}

//------------------------------------------------------------------------
tresult PLUGIN_API ComponentBase::initialize (FUnknown* context)
{
	// check if already initialized
	if (hostContext)
		return kResultFalse;

	hostContext = context;
	if (hostContext)
		hostContext->addRef ();

	return kResultOk;
}

//------------------------------------------------------------------------
tresult PLUGIN_API ComponentBase::terminate ()
{
	// release host interfaces
	if (hostContext)
	{
		hostContext->release ();
		hostContext = 0;
	}

	// in case host did not disconnect us,
	// release peer now
	if (peerConnection)
	{
		peerConnection->disconnect (this);
		peerConnection->release ();
		peerConnection = 0;
	}

	return kResultOk;
}

//------------------------------------------------------------------------
tresult PLUGIN_API ComponentBase::connect (IConnectionPoint* other)
{
	if (!other)
		return kInvalidArgument;

	// check if already connected
	if (peerConnection)
		return kResultFalse;

	peerConnection = other;
	peerConnection->addRef ();
	return kResultOk;
}

//------------------------------------------------------------------------
tresult PLUGIN_API ComponentBase::disconnect (IConnectionPoint* other)
{
	if (peerConnection && other == peerConnection)
	{
		peerConnection->release (),
		peerConnection = 0;
		return kResultOk;
	}
	return kResultFalse;
}

//------------------------------------------------------------------------
tresult PLUGIN_API ComponentBase::notify (IMessage* message)
{
	if (!message)
		return kInvalidArgument;

	if (!strcmp (message->getMessageID (), "TextMessage"))
	{
		TChar string[256] = {0};
		if (message->getAttributes ()->getString ("Text", string, sizeof (string) / sizeof (char16)) == kResultOk)
		{
			String tmp (string);
			tmp.toMultiByte (kCP_Utf8);
			return receiveText (tmp.text8 ());
		}
	}

	return kResultFalse;
}

//------------------------------------------------------------------------
IMessage* ComponentBase::allocateMessage ()
{
	FUnknownPtr<IHostApplication> hostApp (hostContext);
	if (hostApp)
		return Vst::allocateMessage (hostApp);
	return 0;
}

//------------------------------------------------------------------------
tresult ComponentBase::sendMessage (IMessage* message)
{
	if (message != 0 && getPeer () != 0)
		return getPeer ()->notify (message);
	return kResultFalse;
}

//------------------------------------------------------------------------
tresult ComponentBase::sendTextMessage (const char8* text)
{
	IMessage* message = allocateMessage ();
	if (!message)
		return kResultFalse;

	FReleaser msgReleaser (message);
	message->setMessageID ("TextMessage");
	String tmp (text, kCP_Utf8);
	if (tmp.length () >= 256)
		tmp.remove (255);
	message->getAttributes ()->setString ("Text", tmp.text16 ());
	return sendMessage (message);
}

//------------------------------------------------------------------------
tresult ComponentBase::receiveText (const char8* /*text*/)
{
	return kResultOk;
}

//------------------------------------------------------------------------
} // namespace Vst
} // namespace Steinberg


text:
//-----------------------------------------------------------------------------
// Project     : VST SDK
//
// Category    : Helpers
// Filename    : public.sdk/source/vst/vstbypassprocessor.cpp
// Created by  : Steinberg, 04/2015
// Description : Example of bypass support Implementation
//
//-----------------------------------------------------------------------------
// LICENSE
// (c) 2017, Steinberg Media Technologies GmbH, All Rights Reserved
//-----------------------------------------------------------------------------
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistributions of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//   * Redistributions in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//   * Neither the name of the Steinberg Media Technologies nor the names of its
//     contributors may be used to endorse or promote products derived from this
//     software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE  OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//-----------------------------------------------------------------------------

#include "vstbypassprocessor.h"
#include "vstspeakerarray.h"

#include <cstdlib>

namespace Steinberg {
namespace Vst {

//------------------------------------------------------------------------
static bool delay (int32 sampleFrames, float* inStream, float* outStream, float* delayBuffer,
                   int32 bufferSize, int32 bufferInPos, int32 bufferOutPos)
{
	// delay inStream
	int32 remain, inFrames, outFrames;
	float* bufIn;
	float* bufOut;

	remain = sampleFrames;
	while (remain > 0)
	{
		bufIn = delayBuffer + bufferInPos;
		bufOut = delayBuffer + bufferOutPos;

		if (bufferInPos > bufferOutPos)
			inFrames = bufferSize - bufferInPos;
		else
			inFrames = bufferOutPos - bufferInPos;

		outFrames = bufferSize - bufferOutPos;

		if (inFrames > remain)
			inFrames = remain;

		if (outFrames > inFrames)
			outFrames = inFrames;

		// order important for in-place processing!
		memcpy (bufIn, inStream, inFrames * sizeof (float)); // copy to buffer
		memcpy (outStream, bufOut, outFrames * sizeof (float)); // copy from buffer

		inStream += inFrames;
		outStream += outFrames;

		bufferInPos += inFrames;
		if (bufferInPos >= bufferSize)
			bufferInPos -= bufferSize;
		bufferOutPos += outFrames;
		if (bufferOutPos >= bufferSize)
			bufferOutPos -= bufferSize;

		if (inFrames > outFrames)
		{
			// still some output to copy
			bufOut = delayBuffer + bufferOutPos;
			outFrames = inFrames - outFrames;

			memcpy (outStream, bufOut, outFrames * sizeof (float)); // copy from buffer

			outStream += outFrames;

			bufferOutPos += outFrames;
			if (bufferOutPos >= bufferSize)
				bufferOutPos -= bufferSize;
		}

		remain -= inFrames;
	}

	return true;
}

//------------------------------------------------------------------------
// AudioBuffer Implementation
//------------------------------------------------------------------------
AudioBuffer::AudioBuffer ()
: mBuffer (nullptr)
, mMaxSamples (0)
{}

//------------------------------------------------------------------------
AudioBuffer::~AudioBuffer ()
{
	resize (0);
}

//------------------------------------------------------------------------
void AudioBuffer::resize (int32 _maxSamples)
{
	if (mMaxSamples != _maxSamples)
	{
		mMaxSamples = _maxSamples;
		if (mMaxSamples <= 0)
		{
			if (mBuffer)
				free (mBuffer),
				mBuffer = nullptr;
		}
		else
		{
			if (mBuffer)
				mBuffer = (float*)realloc (mBuffer, mMaxSamples * sizeof (float));
			else
				mBuffer = (float*)malloc (mMaxSamples * sizeof (float));
		}
	}
}

//------------------------------------------------------------------------
void AudioBuffer::clear (int32 numSamples)
{
	if (mBuffer)
	{
		int32 count = numSamples < mMaxSamples ? numSamples : mMaxSamples;
		memset (mBuffer, 0, count * sizeof (float));
	}
}

//------------------------------------------------------------------------
//------------------------------------------------------------------------
// BypassProcessor Implementation
//------------------------------------------------------------------------
BypassProcessor::BypassProcessor () : mActive (false), mMainIOBypass (false)
{
	for (int32 i = 0; i < kMaxChannelsSupported; i++)
	{
		mInputPinLookup[i] = -1;
		mDelays[i] = nullptr;
	}
}

//------------------------------------------------------------------------
BypassProcessor::~BypassProcessor () { reset (); }

//------------------------------------------------------------------------
void BypassProcessor::setup (IAudioProcessor& audioProcessor, ProcessSetup& processSetup,
                             int32 delaySamples)
{
	reset ();

	SpeakerArrangement inputArr = 0;
	bool hasInput = audioProcessor.getBusArrangement (kInput, 0, inputArr) == kResultOk;

	SpeakerArrangement outputArr = 0;
	bool hasOutput = audioProcessor.getBusArrangement (kOutput, 0, outputArr) == kResultOk;

	mMainIOBypass = hasInput && hasOutput;
	if (!mMainIOBypass)
		return;

	// create lookup table (in <- out) and delays...
	SpeakerArray inArray (inputArr);
	SpeakerArray outArray (outputArr);

	// security check (todo)
	if (outArray.total () >= kMaxChannelsSupported)
		return;

	for (int32 i = 0; i < outArray.total (); i++)
	{
		if (outArray.at (i) == Vst::kSpeakerL)
		{
			if (inArray.total () == 1 && inArray.at (0) == Vst::kSpeakerM)
			{
				mInputPinLookup[i] = 0;
			}
			else
				mInputPinLookup[i] = inArray.getSpeakerIndex (outArray.at (i));
		}
		else
			mInputPinLookup[i] = inArray.getSpeakerIndex (outArray.at (i));

		mDelays[i] = new Delay (processSetup.maxSamplesPerBlock, delaySamples);
		mDelays[i]->flush ();
	}
}

//------------------------------------------------------------------------
void BypassProcessor::reset ()
{
	mMainIOBypass = false;

	for (int32 i = 0; i < kMaxChannelsSupported; i++)
	{
		mInputPinLookup[i] = -1;
		if (mDelays[i])
		{
			delete mDelays[i];
			mDelays[i] = nullptr;
		}
	}
}

//------------------------------------------------------------------------
void BypassProcessor::setActive (bool state)
{
	if (mActive == state)
		return;

	mActive = state;

	// flush delays when turning on
	if (state && mMainIOBypass)
		for (int32 i = 0; i < kMaxChannelsSupported; i++)
		{
			if (!mDelays[i])
				break;
			mDelays[i]->flush ();
		}
}

//------------------------------------------------------------------------
void BypassProcessor::process (ProcessData& data)
{
	if (mMainIOBypass)
	{
		AudioBusBuffers& inBus = data.inputs[0];
		AudioBusBuffers& outBus = data.outputs[0];

		for (int32 channel = 0; channel < outBus.numChannels; channel++)
		{
			float* src = nullptr;
			bool silent = true;
			float* dst = outBus.channelBuffers32[channel];
			if (!dst)
				continue;

			int inputChannel = mInputPinLookup[channel];
			if (inputChannel != -1)
			{
				silent = (inBus.silenceFlags & (1ll << inputChannel)) != 0;
				src = inBus.channelBuffers32[inputChannel];
			}

			if (mDelays[channel]->process (src, dst, data.numSamples, silent))
			{
				outBus.silenceFlags |= (1ll << channel);
			}
			else
			{
				outBus.silenceFlags = 0;
			}
		}
	}

	// clear all other outputs
	for (int32 outBusIndex = mMainIOBypass ? 1 : 0; outBusIndex < data.numOutputs; outBusIndex++)
	{
		AudioBusBuffers& outBus = data.outputs[outBusIndex];
		if (!outBus.channelBuffers32)
			continue;

		for (int32 channel = 0; channel < outBus.numChannels; channel++)
		{
			float* dst = outBus.channelBuffers32[channel];
			if (dst)
			{
				memset (dst, 0, data.numSamples * sizeof (float));
				outBus.silenceFlags |= 1ll << channel;
			}
		}
	}
}

//------------------------------------------------------------------------
void BypassProcessor::Delay::flush ()
{
	mDelayBuffer.clearAll ();

	mInPos = mOutPos = 0;
	if (hasDelay ())
		mOutPos = getBufferSamples () - mDelaySamples; // must be != inPos
}

//------------------------------------------------------------------------
bool BypassProcessor::Delay::process (float* src, float* dst, int32 numSamples, bool silentIn)
{
	bool silentOut = false;

	if (hasDelay () && src)
	{
		int32 bufferSize = getBufferSamples ();
		delay (numSamples, src, dst, mDelayBuffer, bufferSize, mInPos, mOutPos);

		// update inPos, outPos
		mInPos += numSamples;
		if (mInPos >= bufferSize)
			mInPos -= bufferSize;
		mOutPos += numSamples;
		if (mOutPos >= bufferSize)
			mOutPos -= bufferSize;
	}
	else
	{
		if (src != dst)
		{
			if (src && !silentIn)
			{
				memcpy (dst, src, numSamples * sizeof (float));
			}
			else
			{
				memset (dst, 0, numSamples * sizeof (float));
				silentOut = true;
			}
		}
		else
		{
			silentOut = silentIn;
		}
	}
	return silentOut;
}

//------------------------------------------------------------------------
} // namespace Vst
} // namespace Steinberg