//-----------------------------------------------------------------------------
// Project     : VST SDK
//
// Category    : Examples
// Filename    : public.sdk/samples/vst/pitchnames/source/pitchnames.cpp
// Created by  : Steinberg, 12/2010
// Description : A VST 3 instrument which shows the usage of pitch names for the most simple
//				case that only the root Unit is defined
//
//-----------------------------------------------------------------------------
// This file is part of a Steinberg SDK. It is subject to the license terms
// in the LICENSE file found in the top-level directory of this distribution
// and at www.steinberg.net/sdklicenses.
// No part of the SDK, including this file, may be copied, modified, propagated,
// or distributed except according to the terms contained in the LICENSE file.
//-----------------------------------------------------------------------------

#include "pitchnames.h"
#include "pitchnamesdatabrowsersource.h"
#include "pluginterfaces/base/ustring.h"

using namespace VSTGUI;

#define MULTI_CHANNEL_SCENARIO 1

namespace Steinberg {
namespace Vst {

//-----------------------------------------------------------------------------
FUID PitchNamesController::cid (0xB9123C35, 0x0FFD404C, 0x826774E0, 0x00819A0C);
FUID PitchNamesProcessor::cid (0x32ECDB17, 0xD0894B22, 0xAF9759F8, 0xF5D58DD4);

#if MULTI_CHANNEL_SCENARIO
static ProgramListID kProgramList0ID = 0;
static ProgramListID kProgramList1ID = 1;
static UnitID kChannel0UnitId = 'ch00';
static UnitID kChannel1UnitId = 'ch01';

#else
static ProgramListID kProgramListID = 0;

#endif

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
tresult PLUGIN_API PitchNamesController::initialize (FUnknown* context)
{
	tresult result = EditControllerEx1::initialize (context);
	if (result == kResultOk)
	{
#if MULTI_CHANNEL_SCENARIO
		addUnit (new Unit (String ("Root"), kRootUnitId, kNoParentUnitId));
		addUnit (new Unit (String ("Channel 0"), kChannel0UnitId, kRootUnitId, kProgramList0ID));
		addUnit (new Unit (String ("Channel 1"), kChannel1UnitId, kRootUnitId, kProgramList1ID));

		auto* list = new ProgramListWithPitchNames (String ("ProgramList 0"), kProgramList0ID,
		                                            kChannel0UnitId);
		list->addProgram (String ("Init 1"));
		list->setPitchName (0, 0, String ("Channel 0 First Item"));
		addProgramList (list);
		parameters.addParameter (list->getParameter ());

		list = new ProgramListWithPitchNames (String ("ProgramList 1"), kProgramList1ID,
		                                      kChannel1UnitId);
		list->addProgram (String ("Init 1"));
		list->setPitchName (0, 0, String ("Channel 1 First Item"));
		addProgramList (list);
		parameters.addParameter (list->getParameter ());

#else
		addUnit (new Unit (String ("Root"), kRootUnitId, kNoParentUnitId, kProgramListID));
		ProgramListWithPitchNames* list =
		    new ProgramListWithPitchNames (String ("ProgramList"), kProgramListID, kRootUnitId);
		list->addProgram (String ("Init 1"));
		list->setPitchName (0, 38, String ("Snare"));
		list->setPitchName (0, 42, String ("Closed Hi-Hat"));
		list->setPitchName (0, 45, String ("Low Tom"));

		addProgramList (list);

		parameters.addParameter (list->getParameter ());

#endif
	}
	return result;
}

//-----------------------------------------------------------------------------
tresult PLUGIN_API PitchNamesController::getUnitByBus (MediaType type, BusDirection dir,
                                                       int32 busIndex, int32 channel,
                                                       UnitID& unitId /*out*/)
{
	if (type == kEvent && dir == kInput)
	{
#if MULTI_CHANNEL_SCENARIO
		if (busIndex == 0)
		{
			if (channel == 0)
			{
				unitId = kChannel0UnitId;
				return kResultTrue;
			}
			else if (channel == 1)
			{
				unitId = kChannel1UnitId;
				return kResultTrue;
			}
		}
#else
		if (busIndex == 0 && channel == 0)
		{
			unitId = kRootUnitId;
			return kResultTrue;
		}
#endif
	}
	return kResultFalse;
}

//-----------------------------------------------------------------------------
IPlugView* PLUGIN_API PitchNamesController::createView (FIDString name)
{
	if (ConstString (name) == ViewType::kEditor)
	{
		return new VST3Editor (this, "PitchNamesEditor", "pitchnames.uidesc");
	}
	return nullptr;
}

//-----------------------------------------------------------------------------
CView* PitchNamesController::createCustomView (UTF8StringPtr name, const UIAttributes& /*attributes*/,
                                               const IUIDescription* /*description*/,
                                               VST3Editor* /*editor*/)
{
#if MULTI_CHANNEL_SCENARIO
	if (ConstString (name) == "PitchNamesDataBrowser")
	{
		IDataBrowserDelegate* dataSource = new PitchNamesDataBrowserSource (this, kChannel0UnitId);

		return new CDataBrowser (CRect (0, 0, 100, 100), dataSource,
		                         CDataBrowser::kDrawRowLines | CDataBrowser::kDrawColumnLines |
		                             CDataBrowser::kDrawHeader | CDataBrowser::kVerticalScrollbar);
	}
#else
	if (ConstString (name) == "PitchNamesDataBrowser")
	{
		IDataBrowser* dataSource = new PitchNamesDataBrowserSource (this, kRootUnitId);
		return new CDataBrowser (CRect (0, 0, 100, 100), 0, dataSource,
		                         CDataBrowser::kDrawRowLines | CDataBrowser::kDrawColumnLines |
		                             CDataBrowser::kDrawHeader | CDataBrowser::kVerticalScrollbar);
	}
#endif
	return nullptr;
}

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
PitchNamesProcessor::PitchNamesProcessor () { setControllerClass (PitchNamesController::cid); }

//-----------------------------------------------------------------------------
tresult PLUGIN_API PitchNamesProcessor::initialize (FUnknown* context)
{
	tresult result = AudioEffect::initialize (context);
	if (result == kResultOk)
	{
		addAudioOutput (USTRING ("Audio Output"), SpeakerArr::kStereo);
#if MULTI_CHANNEL_SCENARIO
		addEventInput (USTRING ("Event Input"), 2);
#else
		addEventInput (USTRING ("Event Input"), 1);
#endif
	}
	return result;
}

//-----------------------------------------------------------------------------
tresult PLUGIN_API PitchNamesProcessor::process (ProcessData& data)
{
	if (data.numSamples && data.numOutputs)
	{
		for (int32 i = 0; i < data.outputs[0].numChannels; i++)
			memset (data.outputs[0].channelBuffers32[i], 0, data.numSamples * sizeof (float));
		data.outputs[0].silenceFlags = 3;
	}
	return kResultOk;
}
}
} // namespaces
