text:
//-----------------------------------------------------------------------------
// Project     : VST SDK
//
// Category    : Helpers
// Filename    : plublic.sdk/source/vst/vstsinglecomponenteffect.h
// Created by  : Steinberg, 03/2008
// Description : Recombination class of Audio Effect 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/vst/ivstaudioprocessor.h"

// work around for the name clash of IComponent::setState and IEditController::setState
#define setState setEditorState
#define getState getEditorState
#include "public.sdk/source/vst/vsteditcontroller.h"
#include "pluginterfaces/vst/ivsteditcontroller.h"
#undef setState
#undef getState

#include "public.sdk/source/vst/vstbus.h"
#include "public.sdk/source/vst/vstparameters.h"

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

//------------------------------------------------------------------------
/** Default implementation for a non-distributable Plug-in that combines
processor and edit controller in one component.
\ingroup vstClasses
- [released: 3.0.2]

This can be used as base class for a VST 3 effect implementation in case that the standard way of
defining two separate components would cause too many implementation difficulties:
- Cubase 4.2 is the first host that supports combined VST 3 Plug-ins
- <b> Use this class only after giving the standard way of defining two components
serious considerations! </b>*/
//------------------------------------------------------------------------
class SingleComponentEffect : public EditController, public IComponent, public IAudioProcessor
{
public:
//------------------------------------------------------------------------
	SingleComponentEffect ();
	virtual ~SingleComponentEffect ();

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

	//---from IComponent-----------------------
	virtual tresult PLUGIN_API getControllerClassId (TUID classId) SMTG_OVERRIDE
	{
		return kNotImplemented;
	}
	virtual tresult PLUGIN_API setIoMode (IoMode mode) SMTG_OVERRIDE { return kNotImplemented; }
	virtual int32 PLUGIN_API getBusCount (MediaType type, BusDirection dir) SMTG_OVERRIDE;
	virtual tresult PLUGIN_API getBusInfo (MediaType type, BusDirection dir, int32 index,
	                                       BusInfo& bus /*out*/) SMTG_OVERRIDE;
	virtual tresult PLUGIN_API getRoutingInfo (RoutingInfo& inInfo,
	                                           RoutingInfo& outInfo /*out*/) SMTG_OVERRIDE
	{
		return kNotImplemented;
	}
	virtual tresult PLUGIN_API activateBus (MediaType type, BusDirection dir, int32 index,
	                                        TBool state) SMTG_OVERRIDE;
	virtual tresult PLUGIN_API setActive (TBool state) SMTG_OVERRIDE { return kResultOk; }
	virtual tresult PLUGIN_API setState (IBStream* state) SMTG_OVERRIDE { return kNotImplemented; }
	virtual tresult PLUGIN_API getState (IBStream* state) SMTG_OVERRIDE { return kNotImplemented; }

	// bus setup methods
	AudioBus* addAudioInput (const TChar* name, SpeakerArrangement arr, BusType busType = kMain,
	                         int32 flags = BusInfo::kDefaultActive);

	AudioBus* addAudioOutput (const TChar* name, SpeakerArrangement arr, BusType busType = kMain,
	                          int32 flags = BusInfo::kDefaultActive);

	EventBus* addEventInput (const TChar* name, int32 channels = 16, BusType busType = kMain,
	                         int32 flags = BusInfo::kDefaultActive);

	EventBus* addEventOutput (const TChar* name, int32 channels = 16, BusType busType = kMain,
	                          int32 flags = BusInfo::kDefaultActive);

	tresult removeAudioBusses ();
	tresult removeEventBusses ();
	tresult removeAllBusses ();

	//---from IAudioProcessor -------------------
	virtual tresult PLUGIN_API setBusArrangements (SpeakerArrangement* inputs, int32 numIns,
	                                               SpeakerArrangement* outputs,
	                                               int32 numOuts) SMTG_OVERRIDE;
	virtual tresult PLUGIN_API getBusArrangement (BusDirection dir, int32 index,
	                                              SpeakerArrangement& arr) SMTG_OVERRIDE;
	virtual tresult PLUGIN_API canProcessSampleSize (int32 symbolicSampleSize) SMTG_OVERRIDE;
	virtual uint32 PLUGIN_API getLatencySamples () SMTG_OVERRIDE { return 0; }
	virtual tresult PLUGIN_API setupProcessing (ProcessSetup& setup) SMTG_OVERRIDE;
	virtual tresult PLUGIN_API setProcessing (TBool state) SMTG_OVERRIDE { return kNotImplemented; }
	virtual tresult PLUGIN_API process (ProcessData& data) SMTG_OVERRIDE { return kNotImplemented; }
	virtual uint32 PLUGIN_API getTailSamples () SMTG_OVERRIDE { return kNoTail; }

	//---Interface---------
	OBJ_METHODS (SingleComponentEffect, EditController)
	tresult PLUGIN_API queryInterface (const TUID iid, void** obj) SMTG_OVERRIDE;
	REFCOUNT_METHODS (EditController)

//------------------------------------------------------------------------
protected:
	BusList* getBusList (MediaType type, BusDirection dir);

	ProcessSetup processSetup;

	BusList audioInputs;
	BusList audioOutputs;
	BusList eventInputs;
	BusList eventOutputs;
};

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


text:
//-----------------------------------------------------------------------------
// Project     : VST SDK
//
// Category    : Helpers
// Filename    : public.sdk/source/vst/vstbypassprocessor.h
// 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.
//-----------------------------------------------------------------------------

#pragma once

#include "pluginterfaces/vst/ivstaudioprocessor.h"

namespace Steinberg {
namespace Vst {

#define kMaxChannelsSupported 64

//------------------------------------------------------------------------
// AudioBuffer
//------------------------------------------------------------------------
class AudioBuffer
{
public:
//------------------------------------------------------------------------
	AudioBuffer ();
	~AudioBuffer ();

	int32 getMaxSamples () const { return mMaxSamples; }
	void resize (int32 _maxSamples);
	void release () { resize (0); }
	void clear (int32 numSamples);
	void clearAll () { if (mMaxSamples > 0) clear (mMaxSamples); }

	operator float* () { return mBuffer; }
//------------------------------------------------------------------------
protected:
	float* mBuffer;
	int32 mMaxSamples;
};

//------------------------------------------------------------------------
// BypassProcessor
//------------------------------------------------------------------------
class BypassProcessor
{
public:
//------------------------------------------------------------------------
	BypassProcessor ();
	~BypassProcessor ();

	void setup (IAudioProcessor& audioProcessor, ProcessSetup& processSetup, int32 delaySamples);
	void reset ();

	bool isActive () const { return mActive; }
	void setActive (bool state);

	void process (ProcessData& data);
//------------------------------------------------------------------------
protected:
	bool mActive;
	bool mMainIOBypass;
	int32 mInputPinLookup[kMaxChannelsSupported];

	struct Delay
	{
		AudioBuffer mDelayBuffer;
		int32 mDelaySamples;
		int32 mInPos;
		int32 mOutPos;

		Delay (int32 maxSamplesPerBlock, int32 delaySamples)
		: mDelaySamples (delaySamples), mInPos (-1), mOutPos (-1)
		{
			if (mDelaySamples > 0)
				mDelayBuffer.resize (maxSamplesPerBlock + mDelaySamples);
		}

		bool hasDelay () const { return mDelaySamples > 0; }
		int32 getBufferSamples () const { return mDelayBuffer.getMaxSamples (); }

		bool process (float* src, float* dst, int32 numSamples, bool silentIn);
		void flush ();
	};

	Delay* mDelays[kMaxChannelsSupported];
};

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

repo_name: fedden/RenderMan

mime_type: text/x-c++


text:
//------------------------------------------------------------------------
// Project     : VST SDK
//
// Category    : Helpers
// Filename    : public.sdk/source/vst/vstguieditor.h
// 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.
//-----------------------------------------------------------------------------

#pragma once

#include "vsteditcontroller.h"
#include "vstgui/vstgui.h"

#if VSTGUI_VERSION_MAJOR < 4
#include "vstgui/cvstguitimer.h"
#define VSTGUI_INT32	long
#else
#define VSTGUI_INT32	int32_t
#endif

namespace Steinberg {
namespace Vst {

//------------------------------------------------------------------------
/** Base class for an edit view using VSTGUI.
\ingroup vstClasses  */
//------------------------------------------------------------------------
class VSTGUIEditor : public EditorView, public VSTGUIEditorInterface, public CBaseObject, public IPlugViewIdleHandler
{
public:
	/** Constructor. */
	VSTGUIEditor (void* controller, ViewRect* size = 0);

	/** Destructor. */
	virtual ~VSTGUIEditor ();

	//---Internal function-----
	/** Called when the editor will be opened. */
#if VSTGUI_VERSION_MAJOR >= 4 && VSTGUI_VERSION_MINOR >= 1
	virtual bool PLUGIN_API open (void* parent, const PlatformType& platformType = kDefaultNative) = 0;
#else
	virtual bool PLUGIN_API open (void* parent) = 0;
#endif
	/** Called when the editor will be closed. */
	virtual void PLUGIN_API close () = 0;

	/** Sets the idle rate controlling the parameter update rate. */
	void setIdleRate (int32 millisec);

	//---from CBaseObject---------------
	CMessageResult notify (CBaseObject* sender, const char* message) SMTG_OVERRIDE;
	void forget () SMTG_OVERRIDE { EditorView::release (); }
	void remember () SMTG_OVERRIDE { EditorView::addRef (); }
	VSTGUI_INT32 getNbReference () const SMTG_OVERRIDE { return refCount; }

	//---from IPlugView-------
	tresult PLUGIN_API isPlatformTypeSupported (FIDString type) SMTG_OVERRIDE;
	tresult PLUGIN_API onSize (ViewRect* newSize) SMTG_OVERRIDE;

	//---from VSTGUIEditorInterface-------
	/** Called from VSTGUI when a user begins editing.
		The default implementation calls performEdit of the EditController. */
	void beginEdit (VSTGUI_INT32 index) SMTG_OVERRIDE;
	/** Called from VSTGUI when a user ends editing.
		The default implementation calls endEdit of the EditController. */
	void endEdit (VSTGUI_INT32 index) SMTG_OVERRIDE;

	VSTGUI_INT32 getKnobMode () const SMTG_OVERRIDE;

	OBJ_METHODS (VSTGUIEditor, EditorView)
	DEFINE_INTERFACES
		DEF_INTERFACE (IPlugViewIdleHandler)
	END_DEFINE_INTERFACES (EditorView)
	REFCOUNT_METHODS(EditorView)
private:
	//---from IPlugView-------
	tresult PLUGIN_API attached (void* parent, FIDString type) SMTG_OVERRIDE;
	tresult PLUGIN_API removed () SMTG_OVERRIDE;
	tresult PLUGIN_API onKeyDown (char16 key, int16 keyMsg, int16 modifiers) SMTG_OVERRIDE;
	tresult PLUGIN_API onKeyUp (char16 key, int16 keyMsg, int16 modifiers) SMTG_OVERRIDE;
	tresult PLUGIN_API onWheel (float distance) SMTG_OVERRIDE;
	tresult PLUGIN_API setFrame (IPlugFrame* frame) SMTG_OVERRIDE;

	//---from IPlugViewIdle-------
	void PLUGIN_API onPlugViewIdle () SMTG_OVERRIDE;

	CVSTGUITimer* timer;
};

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


text:
//-----------------------------------------------------------------------------
// Project     : VST SDK
//
// Category    : Helpers
// Filename    : public.sdk/source/vst/vstaudioeffect.h
// Created by  : Steinberg, 04/2005
// Description : Basic Audio Effect 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/vstcomponent.h"
#include "public.sdk/source/vst/vstbus.h"
#include "pluginterfaces/vst/ivstaudioprocessor.h"

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

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

	//---Internal Methods-----------
	/** Creates and adds a new Audio input bus with a given speaker arrangement, busType (kMain or kAux). */
	AudioBus* addAudioInput (const TChar* name, SpeakerArrangement arr,
							 BusType busType = kMain, int32 flags = BusInfo::kDefaultActive);

	/** Creates and adds a new Audio output bus with a given speaker arrangement, busType (kMain or kAux). */
	AudioBus* addAudioOutput (const TChar* name, SpeakerArrangement arr,
							  BusType busType = kMain, int32 flags = BusInfo::kDefaultActive);

	/** Retrieves an Audio Input Bus by index. */
	AudioBus* getAudioInput (int32 index);

	/** Retrieves an Audio Output Bus by index. */
	AudioBus* getAudioOutput (int32 index);

	/** Creates and adds a new Event input bus with a given speaker arrangement, busType (kMain or kAux). */
	EventBus* addEventInput (const TChar* name, int32 channels = 16,
						      BusType busType = kMain, int32 flags = BusInfo::kDefaultActive);

	/** Creates and adds a new Event output bus with a given speaker arrangement, busType (kMain or kAux). */
	EventBus* addEventOutput (const TChar* name, int32 channels = 16,
							  BusType busType = kMain, int32 flags = BusInfo::kDefaultActive);

	/** Retrieves an Event Input Bus by index. */
	EventBus* getEventInput (int32 index);

	/** Retrieves an Event Output Bus by index. */
	EventBus* getEventOutput (int32 index);

	//---from IAudioProcessor-------
	tresult PLUGIN_API setBusArrangements (SpeakerArrangement* inputs, int32 numIns, SpeakerArrangement* outputs, int32 numOuts) SMTG_OVERRIDE;
	tresult PLUGIN_API getBusArrangement (BusDirection dir, int32 busIndex, SpeakerArrangement& arr) SMTG_OVERRIDE;
	tresult PLUGIN_API canProcessSampleSize (int32 symbolicSampleSize) SMTG_OVERRIDE;
	uint32 PLUGIN_API getLatencySamples () SMTG_OVERRIDE { return 0; }
	tresult PLUGIN_API setupProcessing (ProcessSetup& setup) SMTG_OVERRIDE;
	tresult PLUGIN_API setProcessing (TBool state) SMTG_OVERRIDE;
	tresult PLUGIN_API process (ProcessData& data) SMTG_OVERRIDE;
	uint32 PLUGIN_API getTailSamples () SMTG_OVERRIDE { return kNoTail; }

	//---Interface---------
	OBJ_METHODS (AudioEffect, Component)
	DEFINE_INTERFACES
		DEF_INTERFACE (IAudioProcessor)
	END_DEFINE_INTERFACES (Component)
	REFCOUNT_METHODS(Component)

	//---helpers---------
	/** Return the current channelBuffers used (depending of symbolicSampleSize). */
	void** getChannelBuffersPointer (const AudioBusBuffers& bufs) const
	{
		if (processSetup.symbolicSampleSize == kSample32)
			return (void**)bufs.channelBuffers32;
		return (void**)bufs.channelBuffers64;
	}
	/** Return the size in bytes of numSamples for one channel depending of symbolicSampleSize.*/
	uint32 getSampleFramesSizeInBytes (int32 numSamples)
	{
		if (processSetup.symbolicSampleSize == kSample32)
			return numSamples * sizeof (Sample32);
		return numSamples * sizeof (Sample64);
	}

//------------------------------------------------------------------------
protected:
	ProcessSetup processSetup;
};

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


text:
//-----------------------------------------------------------------------------
// Project     : VST SDK
//
// Category    : Helpers
// Filename    : public.sdk/source/vst/vsteditcontroller.cpp
// Created by  : Steinberg, 04/2005
// Description : VST Edit Controller 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 "public.sdk/source/vst/vsteditcontroller.h"
#include "pluginterfaces/base/ustring.h"
#include "base/source/updatehandler.h"

#include <stdio.h>

namespace Steinberg {
namespace Vst {

KnobMode EditController::hostKnobMode = kCircularMode;

//------------------------------------------------------------------------
// EditController Implementation
//------------------------------------------------------------------------
EditController::EditController ()
: componentHandler (0)
, componentHandler2 (0)
{}

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

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

	if (componentHandler)
	{
		componentHandler->release ();
		componentHandler = 0;
	}

	if (componentHandler2)
	{
		componentHandler2->release ();
		componentHandler2 = 0;
	}

	return ComponentBase::terminate ();
}

//------------------------------------------------------------------------
tresult PLUGIN_API EditController::setComponentState (IBStream* /*state*/)
{
	return kNotImplemented;
}

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

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

//------------------------------------------------------------------------
int32 PLUGIN_API EditController::getParameterCount ()
{
	return parameters.getParameterCount ();
}

//------------------------------------------------------------------------
tresult PLUGIN_API EditController::getParameterInfo (int32 paramIndex, ParameterInfo& info)
{
	Parameter* parameter = parameters.getParameterByIndex (paramIndex);
	if (parameter)
	{
		info = parameter->getInfo ();
		return kResultTrue;
	}
	return kResultFalse;
}

//------------------------------------------------------------------------
tresult PLUGIN_API EditController::getParamStringByValue (ParamID tag, ParamValue valueNormalized, String128 string)
{
	Parameter* parameter = getParameterObject (tag);
	if (parameter)
	{
		parameter->toString (valueNormalized, string);
		return kResultTrue;
	}
	return kResultFalse;
}

//------------------------------------------------------------------------
tresult PLUGIN_API EditController::getParamValueByString (ParamID tag, TChar* string, ParamValue& valueNormalized)
{
	Parameter* parameter = getParameterObject (tag);
	if (parameter)
	{
		if (parameter->fromString (string, valueNormalized))
		{
			return kResultTrue;
		}
	}
	return kResultFalse;
}

//------------------------------------------------------------------------
ParamValue PLUGIN_API EditController::normalizedParamToPlain (ParamID tag, ParamValue valueNormalized)
{
	Parameter* parameter = getParameterObject (tag);
	if (parameter)
	{
		return parameter->toPlain (valueNormalized);
	}
	return valueNormalized;
}

//------------------------------------------------------------------------
ParamValue PLUGIN_API EditController::plainParamToNormalized (ParamID tag, ParamValue plainValue)
{
	Parameter* parameter = getParameterObject (tag);
	if (parameter)
	{
		return parameter->toNormalized (plainValue);
	}
	return plainValue;
}

//------------------------------------------------------------------------
ParamValue PLUGIN_API EditController::getParamNormalized (ParamID tag)
{
	Parameter* parameter = getParameterObject (tag);
	if (parameter)
	{
		return parameter->getNormalized ();
	}
	return 0.0;
}

//------------------------------------------------------------------------
tresult PLUGIN_API EditController::setParamNormalized (ParamID tag, ParamValue value)
{
	Parameter* parameter = getParameterObject (tag);
	if (parameter)
	{
		parameter->setNormalized (value);
		return kResultTrue;
	}
	return kResultFalse;
}

//------------------------------------------------------------------------
tresult PLUGIN_API EditController::setComponentHandler (IComponentHandler* newHandler)
{
	if (componentHandler == newHandler)
	{
		return kResultTrue;
	}

	if (componentHandler)
	{
		componentHandler->release ();
	}

	componentHandler = newHandler;
	if (componentHandler)
	{
		componentHandler->addRef ();
	}

	// try to get the extended version
	if (componentHandler2)
	{
		componentHandler2->release ();
		componentHandler2 = 0;
	}

	if (newHandler)
	{
		newHandler->queryInterface (IComponentHandler2::iid, (void**)&componentHandler2);
	}
	return kResultTrue;
}

//------------------------------------------------------------------------
tresult EditController::beginEdit (ParamID tag)
{
	if (componentHandler)
	{
		return componentHandler->beginEdit (tag);
	}
	return kResultFalse;
}

//------------------------------------------------------------------------
tresult EditController::performEdit (ParamID tag, ParamValue valueNormalized)
{
	if (componentHandler)
	{
		return componentHandler->performEdit (tag, valueNormalized);
	}
	return kResultFalse;
}

//------------------------------------------------------------------------
tresult EditController::endEdit (ParamID tag)
{
	if (componentHandler)
	{
		return componentHandler->endEdit (tag);
	}
	return kResultFalse;
}

//------------------------------------------------------------------------
tresult EditController::startGroupEdit ()
{
	if (componentHandler2)
	{
		return componentHandler2->startGroupEdit ();
	}
	return kNotImplemented;
}

//------------------------------------------------------------------------
tresult EditController::finishGroupEdit ()
{
	if (componentHandler2)
	{
		return componentHandler2->finishGroupEdit ();
	}
	return kNotImplemented;
}

//------------------------------------------------------------------------
tresult EditController::getParameterInfoByTag (ParamID tag, ParameterInfo& info)
{
	Parameter* parameter = getParameterObject (tag);
	if (parameter)
	{
		info = parameter->getInfo ();
		return kResultTrue;
	}
	return kResultFalse;
}

//------------------------------------------------------------------------
tresult EditController::setDirty (TBool state)
{
	if (componentHandler2)
	{
		return componentHandler2->setDirty (state);
	}
	return kNotImplemented;
}

//------------------------------------------------------------------------
tresult EditController::requestOpenEditor (FIDString name)
{
	if (componentHandler2)
	{
		return componentHandler2->requestOpenEditor (name);
	}
	return kNotImplemented;
}

//------------------------------------------------------------------------
// EditorView Implementation
//------------------------------------------------------------------------
EditorView::EditorView (EditController* controller, ViewRect* size)
: CPluginView (size)
, controller (controller)
{
	if (controller)
	{
		controller->addRef ();
	}
}

//------------------------------------------------------------------------
EditorView::~EditorView ()
{
	if (controller)
	{
		controller->editorDestroyed (this);
		controller->release ();
	}
}

//------------------------------------------------------------------------
void EditorView::attachedToParent ()
{
	if (controller)
	{
		controller->editorAttached (this);
	}
}

//------------------------------------------------------------------------
void EditorView::removedFromParent ()
{
	if (controller)
	{
		controller->editorRemoved (this);
	}
}

//------------------------------------------------------------------------
// EditControllerEx1 implementation
//------------------------------------------------------------------------
EditControllerEx1::EditControllerEx1 () : selectedUnit (kRootUnitId) { UpdateHandler::instance (); }

//------------------------------------------------------------------------
EditControllerEx1::~EditControllerEx1 ()
{
	for (ProgramListVector::const_iterator it = programLists.begin (), end = programLists.end ();
	     it != end; ++it)
	{
		if (*it)
			(*it)->removeDependent (this);
	}
}

//------------------------------------------------------------------------
bool EditControllerEx1::addUnit (Unit* unit)
{
	units.push_back (IPtr<Unit> (unit, false));
	return true;
}

//------------------------------------------------------------------------
tresult PLUGIN_API EditControllerEx1::getUnitInfo (int32 unitIndex, UnitInfo& info /*out*/)
{
	Unit* unit = units.at (unitIndex);
	if (unit)
	{
		info = unit->getInfo ();
		return kResultTrue;
	}
	return kResultFalse;
}

//------------------------------------------------------------------------
tresult EditControllerEx1::notifyUnitSelection ()
{
	tresult result = kResultFalse;
	FUnknownPtr<IUnitHandler> unitHandler (componentHandler);
	if (unitHandler)
		result = unitHandler->notifyUnitSelection (selectedUnit);
	return result;
}

//------------------------------------------------------------------------
bool EditControllerEx1::addProgramList (ProgramList* list)
{
	programIndexMap[list->getID ()] = programLists.size ();
	programLists.push_back (IPtr<ProgramList> (list, false));
	list->addDependent (this);
	return true;
}

//------------------------------------------------------------------------
ProgramList* EditControllerEx1::getProgramList (ProgramListID listId) const
{
	ProgramIndexMap::const_iterator it = programIndexMap.find (listId);
	return it == programIndexMap.end () ? 0 : programLists[it->second];
}

//------------------------------------------------------------------------
tresult EditControllerEx1::notifyProgramListChange (ProgramListID listId, int32 programIndex)
{
	tresult result = kResultFalse;
	FUnknownPtr<IUnitHandler> unitHandler (componentHandler);
	if (unitHandler)
		result = unitHandler->notifyProgramListChange (listId, programIndex);
	return result;
}

//------------------------------------------------------------------------
int32 PLUGIN_API EditControllerEx1::getProgramListCount ()
{
	return static_cast<int32> (programLists.size ());
}

//------------------------------------------------------------------------
tresult PLUGIN_API EditControllerEx1::getProgramListInfo (int32 listIndex,
                                                          ProgramListInfo& info /*out*/)
{
	if (listIndex < 0 || listIndex >= static_cast<int32> (programLists.size ()))
		return kResultFalse;
	info = programLists[listIndex]->getInfo ();
	return kResultTrue;
}

//------------------------------------------------------------------------
tresult PLUGIN_API EditControllerEx1::getProgramName (ProgramListID listId, int32 programIndex,
                                                      String128 name /*out*/)
{
	ProgramIndexMap::const_iterator it = programIndexMap.find (listId);
	if (it != programIndexMap.end ())
	{
		return programLists[it->second]->getProgramName (programIndex, name);
	}
	return kResultFalse;
}

//------------------------------------------------------------------------
tresult EditControllerEx1::setProgramName (ProgramListID listId, int32 programIndex,
                                           const String128 name /*in*/)
{
	ProgramIndexMap::const_iterator it = programIndexMap.find (listId);
	if (it != programIndexMap.end ())
	{
		return programLists[it->second]->setProgramName (programIndex, name);
	}
	return kResultFalse;
}

//------------------------------------------------------------------------
tresult PLUGIN_API EditControllerEx1::getProgramInfo (ProgramListID listId, int32 programIndex,
                                                      CString attributeId /*in*/,
                                                      String128 attributeValue /*out*/)
{
	ProgramIndexMap::const_iterator it = programIndexMap.find (listId);
	if (it != programIndexMap.end ())
	{
		return programLists[it->second]->getProgramInfo (programIndex, attributeId, attributeValue);
	}
	return kResultFalse;
}

//------------------------------------------------------------------------
tresult PLUGIN_API EditControllerEx1::hasProgramPitchNames (ProgramListID listId,
                                                            int32 programIndex)
{
	ProgramIndexMap::const_iterator it = programIndexMap.find (listId);
	if (it != programIndexMap.end ())
	{
		return programLists[it->second]->hasPitchNames (programIndex);
	}
	return kResultFalse;
}

//------------------------------------------------------------------------
tresult PLUGIN_API EditControllerEx1::getProgramPitchName (ProgramListID listId, int32 programIndex,
                                                           int16 midiPitch, String128 name /*out*/)
{
	ProgramIndexMap::const_iterator it = programIndexMap.find (listId);
	if (it != programIndexMap.end ())
	{
		return programLists[it->second]->getPitchName (programIndex, midiPitch, name);
	}
	return kResultFalse;
}

//------------------------------------------------------------------------
void PLUGIN_API EditControllerEx1::update (FUnknown* changedUnknown, int32 message)
{
	ProgramList* programList = FCast<ProgramList> (changedUnknown);
	if (programList)
	{
		FUnknownPtr<IUnitHandler> unitHandler (componentHandler);
		if (unitHandler)
			unitHandler->notifyProgramListChange (programList->getID (), kAllProgramInvalid);
	}
}

//------------------------------------------------------------------------
// Unit implementation
//------------------------------------------------------------------------
Unit::Unit ()
{
	memset (&info, 0, sizeof (UnitInfo));
}

//------------------------------------------------------------------------
Unit::Unit (const String128 name, UnitID unitId, UnitID parentUnitId, ProgramListID programListId)
{
	setName (name);
	info.id = unitId;
	info.parentUnitId = parentUnitId;
	info.programListId = programListId;
}

//------------------------------------------------------------------------
Unit::Unit (const UnitInfo& info)
: info (info)
{
}

//------------------------------------------------------------------------
void Unit::setName (const String128 newName)
{
	UString128 (newName).copyTo (info.name, 128);
}

//------------------------------------------------------------------------
// ProgramList implementation
//------------------------------------------------------------------------
ProgramList::ProgramList (const String128 name, ProgramListID listId, UnitID unitId)
: unitId (unitId), parameter (0)
{
	UString128 (name).copyTo (info.name, 128);
	info.id = listId;
	info.programCount = 0;
}

//------------------------------------------------------------------------
ProgramList::ProgramList (const ProgramList& programList)
: info (programList.info)
, unitId (programList.unitId)
, programNames (programList.programNames)
, parameter (0)
{
}

//------------------------------------------------------------------------
int32 ProgramList::addProgram (const String128 name)
{
	++info.programCount;
	programNames.push_back (name);
	programInfos.push_back (ProgramInfoVector::value_type ());
	return static_cast<int32> (programNames.size ()) - 1;
}

//------------------------------------------------------------------------
bool ProgramList::setProgramInfo (int32 programIndex, CString attributeId, const String128 value)
{
	if (programIndex >= 0 && programIndex < static_cast<int32>(programNames.size ()))
	{
		programInfos.at (programIndex).insert (std::make_pair (attributeId, value));
		return true;
	}
	return false;
}

//------------------------------------------------------------------------
tresult ProgramList::getProgramInfo (int32 programIndex, CString attributeId,
                                     String128 value /*out*/)
{
	if (programIndex >= 0 && programIndex < static_cast<int32>(programNames.size ()))
	{
		StringMap::const_iterator it = programInfos[programIndex].find (attributeId);
		if (it != programInfos[programIndex].end ())
		{
			if (!it->second.isEmpty ())
			{
				it->second.copyTo16 (value, 0, 128);
				return kResultTrue;
			}
		}
	}
	return kResultFalse;
}

//------------------------------------------------------------------------
tresult ProgramList::getProgramName (int32 programIndex, String128 name /*out*/)
{
	if (programIndex >= 0 && programIndex < static_cast<int32>(programNames.size ()))
	{
		programNames.at (programIndex).copyTo16 (name, 0, 128);
		return kResultTrue;
	}
	return kResultFalse;
}

//------------------------------------------------------------------------
tresult ProgramList::setProgramName (int32 programIndex, const String128 name /*in*/)
{
	if (programIndex >= 0 && programIndex < static_cast<int32>(programNames.size ()))
	{
		programNames.at (programIndex) = name;
		if (parameter)
		{
			static_cast<StringListParameter*> (parameter)->replaceString (programIndex, name);
		}
		return kResultTrue;
	}
	return kResultFalse;
}

//------------------------------------------------------------------------
Parameter* ProgramList::getParameter ()
{
	if (parameter == 0)
	{
		StringListParameter* listParameter = new StringListParameter (
		    info.name, info.id, 0,
		    ParameterInfo::kCanAutomate | ParameterInfo::kIsList | ParameterInfo::kIsProgramChange,
		    unitId);
		for (StringVector::const_iterator it = programNames.begin (), end = programNames.end ();
		     it != end; ++it)
		{
			listParameter->appendString (*it);
		}
		parameter = listParameter;
	}
	return parameter;
}

//------------------------------------------------------------------------
// ProgramListWithPitchNames implementation
//-----------------------------------------------------------------------------
ProgramListWithPitchNames::ProgramListWithPitchNames (const String128 name, ProgramListID listId,
                                                      UnitID unitId)
: ProgramList (name, listId, unitId)
{
}

//-----------------------------------------------------------------------------
int32 ProgramListWithPitchNames::addProgram (const String128 name)
{
	int32 index = ProgramList::addProgram (name);
	if (index >= 0)
		pitchNames.push_back (PitchNamesVector::value_type ());
	return index;
}

//-----------------------------------------------------------------------------
bool ProgramListWithPitchNames::setPitchName (int32 programIndex, int16 pitch,
                                              const String128 pitchName)
{
	if (programIndex < 0 || programIndex >= getCount ())
		return false;

	bool nameChanged = true;
	std::pair<PitchNameMap::iterator, bool> res =
		pitchNames[programIndex].insert (std::make_pair (pitch, pitchName));
	if (!res.second)
	{
		if (res.first->second == pitchName)
			nameChanged = false;
		else
			res.first->second = pitchName;
	}

	if (nameChanged)
		changed ();
	return true;
}

//-----------------------------------------------------------------------------
bool ProgramListWithPitchNames::removePitchName (int32 programIndex, int16 pitch)
{
	bool result = false;
	if (programIndex >= 0 && programIndex < getCount ())
	{
		result = pitchNames.at (programIndex).erase (pitch) != 0;
	}
	if (result)
		changed ();
	return result;
}

//-----------------------------------------------------------------------------
tresult ProgramListWithPitchNames::hasPitchNames (int32 programIndex)
{
	if (programIndex >= 0 && programIndex < getCount ())
		return pitchNames.at (programIndex).empty () ? kResultFalse : kResultTrue;
	return kResultFalse;
}

//-----------------------------------------------------------------------------
tresult ProgramListWithPitchNames::getPitchName (int32 programIndex, int16 midiPitch,
                                                 String128 name /*out*/)
{
	if (programIndex >= 0 && programIndex < getCount ())
	{
		PitchNameMap::const_iterator it = pitchNames[programIndex].find (midiPitch);
		if (it != pitchNames[programIndex].end ())
		{
			it->second.copyTo16 (name, 0, 128);
			return kResultTrue;
		}
	}
	return kResultFalse;
}

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


text:
//------------------------------------------------------------------------
// Project     : VST SDK
//
// Category    : Helpers
// Filename    : public.sdk/source/vst/vstparameters.h
// 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.
//-----------------------------------------------------------------------------

#pragma once

#include "base/source/fobject.h"
#include "pluginterfaces/vst/ivsteditcontroller.h"
#include "pluginterfaces/vst/ivstunits.h"

#include <vector>
#include <map>

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

//------------------------------------------------------------------------
/** Description of a Parameter.
\ingroup vstClasses */
//------------------------------------------------------------------------
class Parameter: public FObject
{
public:
//------------------------------------------------------------------------
	Parameter ();
	Parameter (const ParameterInfo&);
	Parameter (const TChar* title, ParamID tag, const TChar* units = 0,
			   ParamValue defaultValueNormalized = 0., int32 stepCount = 0,
			   int32 flags = ParameterInfo::kCanAutomate, UnitID unitID = kRootUnitId);
	virtual ~Parameter ();

	/** Returns its readonly info. */
	const ParameterInfo& getInfo () const {return info;}

	/** Returns its writeable info. */
	ParameterInfo& getInfo () {return info;}

	/** Sets its associated UnitId. */
	void setUnitID (UnitID id) {info.unitId = id;}
	/** Gets its associated UnitId. */
	UnitID getUnitID () {return info.unitId;}

	/** Gets its normalized value [0.0, 1.0]. */
	ParamValue getNormalized () const { return valueNormalized; }
	/** Sets its normalized value [0.0, 1.0]. */
	virtual bool setNormalized (ParamValue v);

	/** Converts a normalized value to a string. */
	virtual void toString (ParamValue valueNormalized, String128 string) const;
	/** Converts a string to a normalized value. */
	virtual bool fromString (const TChar* string, ParamValue& valueNormalized) const;

	/** Converts a normalized value to plain value (e.g. 0.5 to 10000.0Hz). */
	virtual ParamValue toPlain (ParamValue valueNormalized) const;
	/** Converts a plain value to a normalized value (e.g. 10000 to 0.5). */
	virtual ParamValue toNormalized (ParamValue plainValue) const;

	/** 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 (Parameter, FObject)
//------------------------------------------------------------------------
protected:
	ParameterInfo info;
	ParamValue valueNormalized;
	int32 precision;
};

//------------------------------------------------------------------------
/** Description of a RangeParameter.
\ingroup vstClasses */
//------------------------------------------------------------------------
class RangeParameter : public Parameter
{
public:
//------------------------------------------------------------------------
	RangeParameter (const ParameterInfo& paramInfo, ParamValue min, ParamValue max);
	RangeParameter (const TChar* title, ParamID tag, const TChar* units = 0,
					ParamValue minPlain = 0., ParamValue maxPlain = 1., ParamValue defaultValuePlain = 0.,
					int32 stepCount = 0, int32 flags = ParameterInfo::kCanAutomate, UnitID unitID = kRootUnitId);

	/** Gets the minimum plain value, same as toPlain (0). */
	virtual ParamValue getMin () const {return minPlain;}
	/** Sets the minimum plain value. */
	virtual void setMin (ParamValue value) {minPlain = value;}
	/** Gets the maximum plain value, same as toPlain (1). */
	virtual ParamValue getMax () const {return maxPlain;}
	/** Sets the maximum plain value. */
	virtual void setMax (ParamValue value) {maxPlain = value;}

	/** Converts a normalized value to a string. */
	virtual void toString (ParamValue _valueNormalized, String128 string) const SMTG_OVERRIDE;
	/** Converts a string to a normalized value. */
	virtual bool fromString (const TChar* string, ParamValue& _valueNormalized) const SMTG_OVERRIDE;

	/** Converts a normalized value to plain value (e.g. 0.5 to 10000.0Hz). */
	virtual ParamValue toPlain (ParamValue _valueNormalized) const SMTG_OVERRIDE;
	/** Converts a plain value to a normalized value (e.g. 10000 to 0.5). */
	virtual ParamValue toNormalized (ParamValue plainValue) const SMTG_OVERRIDE;

	OBJ_METHODS (RangeParameter, Parameter)
//------------------------------------------------------------------------
protected:
	RangeParameter ();

	ParamValue minPlain;
	ParamValue maxPlain;
};

//------------------------------------------------------------------------
/** Description of a StringListParameter.
\ingroup vstClasses */
//------------------------------------------------------------------------
class StringListParameter : public Parameter
{
public:
//------------------------------------------------------------------------
	StringListParameter (const ParameterInfo& paramInfo);
	StringListParameter (const TChar* title, ParamID tag, const TChar* units = 0,
						 int32 flags = ParameterInfo::kCanAutomate | ParameterInfo::kIsList, UnitID unitID = kRootUnitId);
	virtual ~StringListParameter ();

	/** Appends a string and increases the stepCount. */
	virtual void appendString (const String128 string);
	/** Replaces the string at index. Index must be between 0 and stepCount+1 */
	virtual bool replaceString (int32 index, const String128 string);

	/** Converts a normalized value to a string. */
	virtual void toString (ParamValue _valueNormalized, String128 string) const SMTG_OVERRIDE;
	/** Converts a string to a normalized value. */
	virtual bool fromString (const TChar* string, ParamValue& _valueNormalized) const SMTG_OVERRIDE;

	/** Converts a normalized value to plain value (e.g. 0.5 to 10000.0Hz). */
	virtual ParamValue toPlain (ParamValue _valueNormalized) const SMTG_OVERRIDE;
	/** Converts a plain value to a normalized value (e.g. 10000 to 0.5). */
	virtual ParamValue toNormalized (ParamValue plainValue) const SMTG_OVERRIDE;

	OBJ_METHODS (StringListParameter, Parameter)
//------------------------------------------------------------------------
protected:
	typedef std::vector<TChar*> StringVector;
	StringVector strings;
};

//------------------------------------------------------------------------
/** Collection of parameters.
\ingroup vstClasses */
//------------------------------------------------------------------------
class ParameterContainer
{
public:
//------------------------------------------------------------------------
	ParameterContainer ();
	~ParameterContainer ();

	/** Init param array. */
	void init (int32 initialSize = 10, int32 resizeDelta = 100);

	/** Creates and adds a new parameter from a ParameterInfo. */
	Parameter* addParameter (const ParameterInfo& info);

	/** Creates and adds a new parameter with given properties. */
	Parameter* addParameter (const TChar* title, const TChar* units = 0,
							 int32 stepCount = 0,
							 ParamValue defaultValueNormalized = 0.,
							 int32 flags = ParameterInfo::kCanAutomate,
							 int32 tag = -1,
							 UnitID unitID = kRootUnitId);

	/** Adds a given parameter. */
	Parameter* addParameter (Parameter* p);

	/** Returns the count of parameters. */
	int32 getParameterCount () const { return params ? static_cast<int32> (params->size ()) : 0; }

	/** Gets parameter by index. */
	Parameter* getParameterByIndex (int32 index) { return params ? params->at (index) : 0; }

	/** Removes all parameters. */
	void removeAll () { if (params) params->clear (); id2index.clear (); }

	/** Gets parameter by ID. */
	Parameter* getParameter (ParamID tag);

//------------------------------------------------------------------------
protected:
	typedef std::vector<IPtr<Parameter> > ParameterPtrVector;
	typedef std::map<ParamID, ParameterPtrVector::size_type> IndexMap;
	ParameterPtrVector* params;
	IndexMap id2index;
};

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


text:
//-----------------------------------------------------------------------------
// Project     : VST SDK
//
// Category    : Helpers
// Filename    : public.sdk/source/vst/vstbus.h
// 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.
//-----------------------------------------------------------------------------

#pragma once

#include "base/source/fobject.h"
#include "base/source/fstring.h"
#include "pluginterfaces/vst/ivstcomponent.h"
#include "pluginterfaces/vst/ivstaudioprocessor.h"

#include <vector>

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

//------------------------------------------------------------------------
/** Basic Bus object.
\ingroup vstClasses */
//------------------------------------------------------------------------
class Bus: public FObject
{
public:
//------------------------------------------------------------------------
	/** Constructor. */
	Bus (const TChar* name, BusType busType, int32 flags);

	/** Returns true if the bus is active. */
	TBool isActive () const { return active; }

	/** Activates the bus. */
	void setActive (TBool state) { active = state; }

	/** Sets a new name for this bus. */
	void setName (String newName) { name = newName; }

	/** Sets a new busType for this bus. */
	void setBusType (BusType newBusType) { busType = newBusType; }

	/** Sets a new flags for this bus. */
	void setFlags (uint32 newFlags) { flags = newFlags; }

	/** Gets the BusInfo of this bus. */
	virtual bool getInfo (BusInfo&);

	OBJ_METHODS (Vst::Bus, FObject)
//------------------------------------------------------------------------
protected:
	String name;				///< name
	BusType busType;			///< kMain or kAux, see \ref BusTypes
	int32 flags;				///< flags, see \ref BusFlags
	TBool active;				///< activation state
};

//------------------------------------------------------------------------
/** Description of an Event Bus.
\ingroup vstClasses */
//------------------------------------------------------------------------
class EventBus: public Bus
{
public:
//------------------------------------------------------------------------
	/** Constructor of an EventBus. */
	EventBus (const TChar* name, BusType busType, int32 flags, int32 channelCount);

	//---from Bus-------
	/** Gets the BusInfo associated to this Event bus. */
	virtual bool getInfo (BusInfo& info) SMTG_OVERRIDE;

	OBJ_METHODS (Vst::EventBus, Vst::Bus);

//------------------------------------------------------------------------
protected:
	int32 channelCount;
};

//------------------------------------------------------------------------
/** Description of an Audio Bus.
\ingroup vstClasses */
//------------------------------------------------------------------------
class AudioBus: public Bus
{
public:
//------------------------------------------------------------------------
	AudioBus (const TChar* name, BusType busType, int32 flags, SpeakerArrangement arr);

	/** Gets the speaker arrangement defining this Audio bus. */
	SpeakerArrangement getArrangement () const { return speakerArr; }

	/** Sets the speaker arrangement defining this Audio bus. */
	void setArrangement (const SpeakerArrangement& arr) { speakerArr = arr; }

	//---from Bus---------------------
	/** Gets the BusInfo associated to this Audio bus. */
	virtual bool getInfo (BusInfo& info) SMTG_OVERRIDE;

	OBJ_METHODS (Vst::AudioBus, Vst::Bus)

//------------------------------------------------------------------------
protected:
	SpeakerArrangement speakerArr;
};

//------------------------------------------------------------------------
/** List of Buses.
\ingroup vstClasses */
//------------------------------------------------------------------------
class BusList: public FObject, public std::vector<IPtr<Vst::Bus> >
{
public:
//------------------------------------------------------------------------
	/** Constructor. */
	BusList (MediaType type, BusDirection dir);

	/** Returns the BusList Type. See \ref MediaType */
	MediaType getType () const { return type; }

	/** Returns the BusList direction. See \ref BusDirection */
	BusDirection getDirection () const { return direction; }

	OBJ_METHODS (Vst::BusList, FObject);

//------------------------------------------------------------------------
protected:
	MediaType type;
	BusDirection direction;
};

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


text:
//-----------------------------------------------------------------------------
// Project     : VST SDK
//
// Category    : Validator
// Filename    : public.sdk/source/vst/vsttestsuite.h
// Created by  : Steinberg, 04/2005
// Description : VST Test Suite
//
//-----------------------------------------------------------------------------
// 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/test/itest.h"
#include "public.sdk/source/vst/hosting/processdata.h"

// VST 3 interfaces
#include "pluginterfaces/base/ipluginbase.h"
#include "pluginterfaces/vst/ivstcomponent.h"
#include "pluginterfaces/vst/ivstaudioprocessor.h"
#include "pluginterfaces/vst/ivsteditcontroller.h"
#include "pluginterfaces/vst/ivstparameterchanges.h"

namespace Steinberg {
namespace Vst {

typedef int32 ProcessSampleSize;

//------------------------------------------------------------------------
#define DECLARE_VSTTEST(name) \
virtual const char* getName () const SMTG_OVERRIDE { return name; }

/** Set from outside the plug-in context (simulating a host context) */
extern void setStandardPluginContext (FUnknown* context);

//------------------------------------------------------------------------
/** Test Helper.
\ingroup TestClass */
//------------------------------------------------------------------------
class IPlugProvider : public FUnknown
{
public:
//------------------------------------------------------------------------
	virtual IComponent* getComponent () = 0;
	virtual IEditController* getController () = 0;
	virtual tresult releasePlugIn (IComponent* component, IEditController* controller) = 0;
	virtual const char8* getSubCategories () const = 0;
	virtual tresult getPluginUID (FUID& uid) const = 0;

//------------------------------------------------------------------------
	static const FUID iid;
};

DECLARE_CLASS_IID (IPlugProvider, 0xDB014121, 0x09144BAA, 0x87627896, 0xBE41AF5D)

//------------------------------------------------------------------------
/** VstAutomationTest helper classes.
\ingroup TestClass */
class ParamPoint
{
public:
	ParamPoint () : offsetSamples (-1), value (0.), read (false) {}
	void set (int32 offsetSamples, double value)
	{
		this->offsetSamples = offsetSamples;
		this->value = value;
	}
	void get (int32& offsetSamples, double& value)
	{
		offsetSamples = this->offsetSamples;
		value = this->value;
		read = true;
	}
	bool wasRead () const { return read; }

private:
	int32 offsetSamples;
	double value;
	bool read;
};

//------------------------------------------------------------------------
/** VstAutomationTest helper classes: implementation of IParamValueQueue.
\ingroup TestClass */
class ParamChanges : public IParamValueQueue
{
public:
	ParamChanges () : id (-1), numPoints (0), numUsedPoints (0), processedFrames (0), points (nullptr)
	{
		FUNKNOWN_CTOR
	}
	virtual ~ParamChanges ()
	{
		if (points)
			delete[] points;
		FUNKNOWN_DTOR
	}

	DECLARE_FUNKNOWN_METHODS

	void init (ParamID id, int32 numPoints)
	{
		this->id = id;
		this->numPoints = numPoints;
		numUsedPoints = 0;
		if (points)
			delete[] points;
		points = new ParamPoint[numPoints];
		processedFrames = 0;
	}
	bool setPoint (int32 index, int32 offsetSamples, double value)
	{
		if (points && (index >= 0) && (index == numUsedPoints) && (index < numPoints))
		{
			points[index].set (offsetSamples, value);
			numUsedPoints++;
			return true;
		}
		if (!points)
			return true;
		return false;
	}
	void resetPoints ()
	{
		numUsedPoints = 0;
		processedFrames = 0;
	}
	int32 getProcessedFrames () const { return processedFrames; }
	void setProcessedFrames (int32 amount) { processedFrames = amount; }
	bool havePointsBeenRead (bool atAll)
	{
		for (int32 i = 0; i < getPointCount (); ++i)
		{
			if (points[i].wasRead ())
			{
				if (atAll)
					return true;
			}
			else if (!atAll)
				return false;
		}
		return !atAll;
	}

	//---for IParamValueQueue-------------------------
	ParamID PLUGIN_API getParameterId () SMTG_OVERRIDE { return id; }
	int32 PLUGIN_API getPointCount () SMTG_OVERRIDE { return numUsedPoints; }
	tresult PLUGIN_API getPoint (int32 index, int32& offsetSamples, double& value) SMTG_OVERRIDE
	{
		if (points && (index < numUsedPoints) && (index >= 0))
		{
			points[index].get (offsetSamples, value);
			return kResultTrue;
		}
		return kResultFalse;
	}
	tresult PLUGIN_API addPoint (int32 offsetSamples, double value, int32& index) SMTG_OVERRIDE
	{
		return kResultFalse;
	}
//---------------------------------------------------------

private:
	ParamID id;
	int32 numPoints;
	int32 numUsedPoints;
	int32 processedFrames;
	ParamPoint* points;
};

//------------------------------------------------------------------------
/** Test Helper.
\ingroup TestClass */
//------------------------------------------------------------------------
class VstTestBase: public ITest
{
public:
//------------------------------------------------------------------------
	VstTestBase (IPlugProvider* plugProvider);
	virtual ~VstTestBase ();

	virtual const char* getName () const = 0;
	DECLARE_FUNKNOWN_METHODS

	bool PLUGIN_API setup () SMTG_OVERRIDE;
	bool PLUGIN_API run (ITestResult* testResult) SMTG_OVERRIDE {return false;}	// implement me
	bool PLUGIN_API teardown () SMTG_OVERRIDE;
//------------------------------------------------------------------------
protected:
	IPlugProvider* plugProvider;
	IComponent* vstPlug;
	IEditController* controller;

private:
	VstTestBase ();
};

//------------------------------------------------------------------------
/** Test Helper.
\ingroup TestClass */
//------------------------------------------------------------------------
class VstTestEnh : public VstTestBase
{
public:
//------------------------------------------------------------------------
	VstTestEnh (IPlugProvider* plugProvider, ProcessSampleSize sampl);
	virtual ~VstTestEnh ();

	enum AudioDefaults
	{
		kBlockSize = 64,
		kMaxSamplesPerBlock = 8192,
		kSampleRate = 44100,
	};

	bool PLUGIN_API setup () SMTG_OVERRIDE;
	bool PLUGIN_API teardown () SMTG_OVERRIDE;
//------------------------------------------------------------------------
protected:
	// interfaces
	IAudioProcessor* audioEffect;

	ProcessSetup processSetup;
};

//------------------------------------------------------------------------
/** Test Suspend/Resume.
\ingroup TestClass */
//------------------------------------------------------------------------
class VstSuspendResumeTest: public VstTestEnh
{
public:
//------------------------------------------------------------------------
	VstSuspendResumeTest (IPlugProvider* plugProvider, ProcessSampleSize sampl);

	DECLARE_VSTTEST ("Suspend/Resume")

	bool PLUGIN_API run (ITestResult* testResult) SMTG_OVERRIDE;
//------------------------------------------------------------------------
};

//------------------------------------------------------------------------
/** Test Terminate/Initialize.
\ingroup TestClass */
//------------------------------------------------------------------------
class VstTerminateInitializeTest: public VstTestBase
{
public:
//------------------------------------------------------------------------
	VstTerminateInitializeTest (IPlugProvider* plugProvider);

	DECLARE_VSTTEST ("Terminate/Initialize")

	bool PLUGIN_API run (ITestResult* testResult) SMTG_OVERRIDE;
//------------------------------------------------------------------------
};

//------------------------------------------------------------------------
/** Test Scan Buses.
\ingroup TestClass */
//------------------------------------------------------------------------
class VstScanBussesTest: public VstTestBase
{
public:
//------------------------------------------------------------------------
	VstScanBussesTest (IPlugProvider* plugProvider);

	DECLARE_VSTTEST ("Scan Buses")

	bool PLUGIN_API run (ITestResult* testResult) SMTG_OVERRIDE;
//------------------------------------------------------------------------
};

//------------------------------------------------------------------------
/** Test Scan Parameters.
\ingroup TestClass */
//------------------------------------------------------------------------
class VstScanParametersTest: public VstTestBase
{
public:
//------------------------------------------------------------------------
	VstScanParametersTest (IPlugProvider* plugProvider);

	DECLARE_VSTTEST ("Scan Parameters")

	bool PLUGIN_API run (ITestResult* testResult) SMTG_OVERRIDE;
//------------------------------------------------------------------------
};

//------------------------------------------------------------------------
/** Test MIDI Mapping.
\ingroup TestClass */
//------------------------------------------------------------------------
class VstMidiMappingTest: public VstTestBase
{
public:
//------------------------------------------------------------------------
	VstMidiMappingTest (IPlugProvider* plugProvider);

	DECLARE_VSTTEST ("MIDI Mapping")

	bool PLUGIN_API run (ITestResult* testResult) SMTG_OVERRIDE;
//------------------------------------------------------------------------
};

//------------------------------------------------------------------------
/** Test Note Expression.
\ingroup TestClass */
//------------------------------------------------------------------------
class VstNoteExpressionTest: public VstTestBase
{
public:
	//------------------------------------------------------------------------
	VstNoteExpressionTest (IPlugProvider* plugProvider);

	DECLARE_VSTTEST ("Note Expression")

	bool PLUGIN_API run (ITestResult* testResult) SMTG_OVERRIDE;
	//------------------------------------------------------------------------
};

//------------------------------------------------------------------------
/** Test Keyswitch.
\ingroup TestClass */
//------------------------------------------------------------------------
class VstKeyswitchTest: public VstTestBase
{
public:
	//------------------------------------------------------------------------
	VstKeyswitchTest (IPlugProvider* plugProvider);

	DECLARE_VSTTEST ("Keyswitch")

	bool PLUGIN_API run (ITestResult* testResult) SMTG_OVERRIDE;
	//------------------------------------------------------------------------
};

//------------------------------------------------------------------------
/** Test Scan Editor Classes.
\ingroup TestClass */
//------------------------------------------------------------------------
class VstEditorClassesTest: public VstTestBase
{
public:
//------------------------------------------------------------------------
	VstEditorClassesTest (IPlugProvider* plugProvider);

	DECLARE_VSTTEST ("Scan Editor Classes")

	bool PLUGIN_API run (ITestResult* testResult) SMTG_OVERRIDE;
//------------------------------------------------------------------------
};

//------------------------------------------------------------------------
/** Test Scan Units.
\ingroup TestClass */
//------------------------------------------------------------------------
class VstUnitInfoTest: public VstTestBase
{
public:
//------------------------------------------------------------------------
	VstUnitInfoTest (IPlugProvider* plugProvider);

	DECLARE_VSTTEST ("Scan Units")

	bool PLUGIN_API run (ITestResult* testResult) SMTG_OVERRIDE;
//------------------------------------------------------------------------
};

//------------------------------------------------------------------------
/** Test Scan Programs.
\ingroup TestClass */
//------------------------------------------------------------------------
class VstProgramInfoTest: public VstTestBase
{
public:
//------------------------------------------------------------------------
	VstProgramInfoTest (IPlugProvider* plugProvider);

	DECLARE_VSTTEST ("Scan Programs")

	bool PLUGIN_API run (ITestResult* testResult) SMTG_OVERRIDE;
//------------------------------------------------------------------------
};

//------------------------------------------------------------------------
/** Test Check Unit Structure.
\ingroup TestClass */
//------------------------------------------------------------------------
class VstUnitStructureTest: public VstTestBase
{
public:
//------------------------------------------------------------------------
	VstUnitStructureTest (IPlugProvider* plugProvider);

	DECLARE_VSTTEST ("Check Unit Structure")

	bool PLUGIN_API run (ITestResult* testResult) SMTG_OVERRIDE;
//------------------------------------------------------------------------
};

//------------------------------------------------------------------------
/** Test Process Test.
\ingroup TestClass */
//------------------------------------------------------------------------
class VstProcessTest : public VstTestEnh
{
public:
//------------------------------------------------------------------------
	VstProcessTest (IPlugProvider* plugProvider, ProcessSampleSize sampl);

	DECLARE_VSTTEST ("Process Test")

	// ITest
	bool PLUGIN_API setup () SMTG_OVERRIDE;
	bool PLUGIN_API run (ITestResult* testResult) SMTG_OVERRIDE;
	bool PLUGIN_API teardown () SMTG_OVERRIDE;

//------------------------------------------------------------------------
protected:
	virtual bool prepareProcessing ();						///< setup ProcessData and allocate buffers
	virtual bool unprepareProcessing ();					///< free dynamic memory of ProcessData
	virtual bool preProcess (ITestResult* testResult);		///< is called just before the process call
	virtual bool postProcess (ITestResult* testResult);		///< is called right after the process call

	bool setupBuffers (int32 numBusses, AudioBusBuffers* audioBuffers, BusDirection dir);
	bool setupBuffers (AudioBusBuffers& audioBuffers);
	bool freeBuffers (int32 numBuses, AudioBusBuffers* buses);
	bool canProcessSampleSize (ITestResult* testResult);	///< audioEffect has to be available

	HostProcessData processData;
};

//------------------------------------------------------------------------
/** Test Speaker Arrangement.
\ingroup TestClass */
//------------------------------------------------------------------------
class VstSpeakerArrangementTest : public VstProcessTest
{
public:
//------------------------------------------------------------------------
	VstSpeakerArrangementTest (IPlugProvider* plugProvider, ProcessSampleSize sampl, SpeakerArrangement inSpArr, SpeakerArrangement outSpArr);

	const char* getName () const SMTG_OVERRIDE;
	static const char* getSpeakerArrangementName (SpeakerArrangement spArr);

	// ITest
	bool PLUGIN_API run (ITestResult* testResult) SMTG_OVERRIDE;

//------------------------------------------------------------------------
protected:
	bool prepareProcessing () SMTG_OVERRIDE;
	bool verifySA (int32 numBusses, AudioBusBuffers* buses, SpeakerArrangement spArr, ITestResult* testResult);
private:
	SpeakerArrangement inSpArr;
	SpeakerArrangement outSpArr;
};

class ParamChanges;
//------------------------------------------------------------------------
/** Test Automation.
\ingroup TestClass */
//------------------------------------------------------------------------
class VstAutomationTest : public VstProcessTest, public IParameterChanges
{
public:
//------------------------------------------------------------------------
	VstAutomationTest (IPlugProvider* plugProvider, ProcessSampleSize sampl, int32 everyNSamples, int32 numParams, bool sampleAccuracy);
	virtual ~VstAutomationTest ();

	DECLARE_FUNKNOWN_METHODS
	const char* getName () const SMTG_OVERRIDE;
	// ITest
	bool PLUGIN_API setup () SMTG_OVERRIDE;
	bool PLUGIN_API run (ITestResult* testResult) SMTG_OVERRIDE;
	bool PLUGIN_API teardown () SMTG_OVERRIDE;

	// IParameterChanges
	int32 PLUGIN_API getParameterCount () SMTG_OVERRIDE;
	IParamValueQueue* PLUGIN_API getParameterData (int32 index) SMTG_OVERRIDE;
	IParamValueQueue* PLUGIN_API addParameterData (const ParamID& id, int32& index) SMTG_OVERRIDE;

//------------------------------------------------------------------------
protected:
	bool preProcess (ITestResult* testResult) SMTG_OVERRIDE;
	bool postProcess (ITestResult* testResult) SMTG_OVERRIDE;
	ParamID bypassId;

	ParamChanges* paramChanges;
	int32 countParamChanges;
	int32 everyNSamples;
	int32 numParams;
	bool sampleAccuracy;
	bool onceExecuted;
};

//------------------------------------------------------------------------
/** Test Valid State Transition.
\ingroup TestClass */
//------------------------------------------------------------------------
class VstValidStateTransitionTest : public VstTestBase
{
public:
	VstValidStateTransitionTest (IPlugProvider* plugProvider);
	bool PLUGIN_API run (ITestResult* testResult) SMTG_OVERRIDE;

	DECLARE_VSTTEST ("Valid State Transition")
};

//------------------------------------------------------------------------
/** Test Invalid State Transition.
\ingroup TestClass */
//------------------------------------------------------------------------
class VstInvalidStateTransitionTest : public VstTestBase
{
public:
	VstInvalidStateTransitionTest (IPlugProvider* plugProvider);
	bool PLUGIN_API run (ITestResult* testResult) SMTG_OVERRIDE;

	DECLARE_VSTTEST ("Invalid State Transition")
};

//------------------------------------------------------------------------
/** Test Repeat Identical State Transition.
\ingroup TestClass */
//------------------------------------------------------------------------
class VstRepeatIdenticalStateTransitionTest : public VstTestBase
{
public:
	VstRepeatIdenticalStateTransitionTest (IPlugProvider* plugProvider);
	bool PLUGIN_API run (ITestResult* testResult) SMTG_OVERRIDE;

	DECLARE_VSTTEST ("Repeat Identical State Transition")
};

//------------------------------------------------------------------------
/** Test Bus Consistency.
\ingroup TestClass */
//------------------------------------------------------------------------
class VstBusConsistencyTest : public VstTestBase
{
public:
	VstBusConsistencyTest (IPlugProvider* plugProvider);
	bool PLUGIN_API run (ITestResult* testResult) SMTG_OVERRIDE;

	DECLARE_VSTTEST ("Bus Consistency")
};

//------------------------------------------------------------------------
/** Test Bus Invalid Index.
\ingroup TestClass */
//------------------------------------------------------------------------
class VstBusInvalidIndexTest : public VstTestBase
{
public:
	VstBusInvalidIndexTest (IPlugProvider* plugProvider);
	bool PLUGIN_API run (ITestResult* testResult) SMTG_OVERRIDE;

	DECLARE_VSTTEST ("Bus Invalid Index")
};

//------------------------------------------------------------------------
/** Test Silence Flags.
\ingroup TestClass */
//------------------------------------------------------------------------
class VstSilenceFlagsTest : public VstProcessTest
{
public:
	VstSilenceFlagsTest (IPlugProvider* plugProvider, ProcessSampleSize sampl);
	bool PLUGIN_API run (ITestResult* testResult) SMTG_OVERRIDE;

	DECLARE_VSTTEST ("Silence Flags")
};

//------------------------------------------------------------------------
/** Test Silence Processing.
\ingroup TestClass */
//------------------------------------------------------------------------
class VstSilenceProcessingTest : public VstProcessTest
{
public:
	VstSilenceProcessingTest (IPlugProvider* plugProvider, ProcessSampleSize sampl);
	bool PLUGIN_API run (ITestResult* testResult) SMTG_OVERRIDE;

	DECLARE_VSTTEST ("Silence Processing")
protected:
	bool isBufferSilent (void* buffer, int32 numSamples, ProcessSampleSize sampl);
};

//------------------------------------------------------------------------
/** Test Parameters Flush (no Buffer).
\ingroup TestClass */
//------------------------------------------------------------------------
class VstFlushParamTest : public VstAutomationTest
{
public:
	VstFlushParamTest (IPlugProvider* plugProvider, ProcessSampleSize sampl);
	bool PLUGIN_API run (ITestResult* testResult) SMTG_OVERRIDE;

	DECLARE_VSTTEST ("Parameters Flush (no Buffer)")
};

//------------------------------------------------------------------------
/** Test Bus Activation.
\ingroup TestClass */
//------------------------------------------------------------------------
class VstBusActivationTest : public VstTestBase
{
public:
	VstBusActivationTest (IPlugProvider* plugProvider);
	bool PLUGIN_API run (ITestResult* testResult) SMTG_OVERRIDE;

	DECLARE_VSTTEST ("Bus Activation")
};

//------------------------------------------------------------------------
/** Test Variable Block Size.
\ingroup TestClass */
//------------------------------------------------------------------------
class VstVariableBlockSizeTest : public VstProcessTest
{
public:
	VstVariableBlockSizeTest (IPlugProvider* plugProvider, ProcessSampleSize sampl);
	bool PLUGIN_API run (ITestResult* testResult) SMTG_OVERRIDE;

	DECLARE_VSTTEST ("Variable Block Size")
};

//------------------------------------------------------------------------
/** Test Process Format.
\ingroup TestClass */
//------------------------------------------------------------------------
class VstProcessFormatTest : public VstProcessTest
{
public:
	VstProcessFormatTest (IPlugProvider* plugProvider, ProcessSampleSize sampl);
	bool PLUGIN_API run (ITestResult* testResult) SMTG_OVERRIDE;

	DECLARE_VSTTEST ("Process Format")
};

//------------------------------------------------------------------------
/** Test Check Audio Bus Arrangement.
\ingroup TestClass */
//------------------------------------------------------------------------
class VstCheckAudioBusArrangementTest : public VstTestBase
{
public:
	VstCheckAudioBusArrangementTest (IPlugProvider* plugProvider);
	bool PLUGIN_API run (ITestResult* testResult) SMTG_OVERRIDE;

	DECLARE_VSTTEST ("Check Audio Bus Arrangement")
};

//------------------------------------------------------------------------
/** Test ProcesTail.
\ingroup TestClass */
//------------------------------------------------------------------------
class VstProcessTailTest : public VstProcessTest
{
public:
	//------------------------------------------------------------------------
	VstProcessTailTest (IPlugProvider* plugProvider, ProcessSampleSize sampl);
	virtual ~VstProcessTailTest ();

	DECLARE_VSTTEST ("Check Tail processing")

	// ITest
	bool PLUGIN_API setup () SMTG_OVERRIDE;
	bool PLUGIN_API run (ITestResult* testResult) SMTG_OVERRIDE;
	bool preProcess (ITestResult* testResult) SMTG_OVERRIDE;
	bool postProcess (ITestResult* testResult) SMTG_OVERRIDE;

	//------------------------------------------------------------------------
protected:

private:
	uint32 mTailSamples;
	uint32 mInTail;

	float* dataPtrFloat;
	double* dataPtrDouble;
	bool mInSilenceInput;
	bool mDontTest;
};

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