sfizz/vst/SfizzVstController.cpp

360 lines
11 KiB
C++
Raw Normal View History

2020-03-05 11:16:47 +01:00
// SPDX-License-Identifier: BSD-2-Clause
// This code is part of the sfizz library and is licensed under a BSD 2-clause
// license. You should have receive a LICENSE.md file along with the code.
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
#include "SfizzVstController.h"
#include "SfizzVstEditor.h"
#include "base/source/fstreamer.h"
#include "pluginterfaces/vst/ivstmidicontrollers.h"
tresult PLUGIN_API SfizzVstControllerNoUi::initialize(FUnknown* context)
{
tresult result = EditController::initialize(context);
if (result != kResultTrue)
return result;
Vst::ParamID pid = 0;
2020-03-05 18:21:46 +01:00
// Ordinary parameters
parameters.addParameter(
kParamVolumeRange.createParameter(
Steinberg::String("Volume"), pid++, Steinberg::String("dB"),
0, Vst::ParameterInfo::kCanAutomate, Vst::kRootUnitId));
2020-03-06 11:46:49 +01:00
parameters.addParameter(
kParamNumVoicesRange.createParameter(
Steinberg::String("Polyphony"), pid++, nullptr,
2020-05-16 21:30:58 +02:00
0, Vst::ParameterInfo::kCanAutomate, Vst::kRootUnitId));
2020-03-06 11:55:52 +01:00
parameters.addParameter(
kParamOversamplingRange.createParameter(
Steinberg::String("Oversampling"), pid++, nullptr,
2020-05-16 21:30:58 +02:00
0, Vst::ParameterInfo::kCanAutomate, Vst::kRootUnitId));
2020-03-06 13:15:32 +01:00
parameters.addParameter(
kParamPreloadSizeRange.createParameter(
Steinberg::String("Preload size"), pid++, nullptr,
2020-05-16 21:30:58 +02:00
0, Vst::ParameterInfo::kCanAutomate, Vst::kRootUnitId));
2020-06-20 05:49:00 +02:00
parameters.addParameter(
2020-08-29 04:54:18 +02:00
kParamScalaRootKeyRange.createParameter(
2020-06-20 05:49:00 +02:00
Steinberg::String("Scala root key"), pid++, nullptr,
0, Vst::ParameterInfo::kCanAutomate, Vst::kRootUnitId));
parameters.addParameter(
2020-08-29 04:54:18 +02:00
kParamTuningFrequencyRange.createParameter(
2020-06-20 05:49:00 +02:00
Steinberg::String("Tuning frequency"), pid++, Steinberg::String("Hz"),
0, Vst::ParameterInfo::kCanAutomate, Vst::kRootUnitId));
parameters.addParameter(
2020-08-29 04:54:18 +02:00
kParamStretchedTuningRange.createParameter(
2020-06-20 05:49:00 +02:00
Steinberg::String("Stretched tuning"), pid++, nullptr,
0, Vst::ParameterInfo::kCanAutomate, Vst::kRootUnitId));
2020-03-05 18:21:46 +01:00
// MIDI special controllers
parameters.addParameter(Steinberg::String("Aftertouch"), nullptr, 0, 0.5, 0, pid++, Vst::kRootUnitId);
2020-06-20 05:49:00 +02:00
parameters.addParameter(Steinberg::String("Pitch bend"), nullptr, 0, 0.5, 0, pid++, Vst::kRootUnitId);
2020-03-05 11:16:47 +01:00
// MIDI controllers
2020-03-05 18:21:46 +01:00
for (unsigned i = 0; i < kNumControllerParams; ++i) {
2020-03-05 11:16:47 +01:00
Steinberg::String title;
Steinberg::String shortTitle;
title.printf("Controller %u", i);
shortTitle.printf("CC%u", i);
parameters.addParameter(
2020-05-16 21:30:58 +02:00
title, nullptr, 0, 0, Vst::ParameterInfo::kNoFlags,
2020-03-05 11:16:47 +01:00
pid++, Vst::kRootUnitId, shortTitle);
}
return kResultTrue;
}
tresult PLUGIN_API SfizzVstControllerNoUi::terminate()
{
return EditController::terminate();
}
tresult PLUGIN_API SfizzVstControllerNoUi::getMidiControllerAssignment(int32 busIndex, int16 channel, Vst::CtrlNumber midiControllerNumber, Vst::ParamID& id)
{
switch (midiControllerNumber) {
case Vst::kAfterTouch:
id = kPidMidiAftertouch;
return kResultTrue;
case Vst::kPitchBend:
id = kPidMidiPitchBend;
return kResultTrue;
default:
2020-03-05 18:21:46 +01:00
if (midiControllerNumber < 0 || midiControllerNumber >= kNumControllerParams)
2020-03-05 11:16:47 +01:00
return kResultFalse;
id = kPidMidiCC0 + midiControllerNumber;
return kResultTrue;
}
}
2020-03-06 11:55:52 +01:00
tresult PLUGIN_API SfizzVstControllerNoUi::getParamStringByValue(Vst::ParamID tag, Vst::ParamValue valueNormalized, Vst::String128 string)
{
switch (tag) {
case kPidOversampling:
{
2020-03-12 23:45:04 +01:00
auto factorLog2 = static_cast<int>(kParamOversamplingRange.denormalize(valueNormalized));
2020-03-06 11:55:52 +01:00
Steinberg::String buf;
2020-03-06 13:15:32 +01:00
buf.printf("%dX", 1 << factorLog2);
2020-03-06 11:55:52 +01:00
buf.copyTo(string);
return kResultTrue;
}
}
return EditController::getParamStringByValue(tag, valueNormalized, string);
}
tresult PLUGIN_API SfizzVstControllerNoUi::getParamValueByString(Vst::ParamID tag, Vst::TChar* string, Vst::ParamValue& valueNormalized)
{
switch (tag) {
case kPidOversampling:
{
int32 factor;
2020-03-06 13:15:32 +01:00
if (!Steinberg::String::scanInt32(string, factor, false) || factor < 1)
2020-03-06 11:55:52 +01:00
factor = 1;
2020-03-06 13:15:32 +01:00
int32 log2Factor = 0;
for (int32 f = factor; f > 1; f /= 2)
2020-03-06 13:15:32 +01:00
++log2Factor;
valueNormalized = kParamOversamplingRange.normalize(log2Factor);
2020-03-06 11:55:52 +01:00
return kResultTrue;
}
}
return EditController::getParamValueByString(tag, string, valueNormalized);
}
2020-03-05 11:16:47 +01:00
// --- Controller with UI --- //
IPlugView* PLUGIN_API SfizzVstController::createView(FIDString _name)
{
ConstString name(_name);
fprintf(stderr, "[sfizz] about to create view: %s\n", _name);
2020-03-05 11:16:47 +01:00
if (name != Vst::ViewType::kEditor)
return nullptr;
if (IPtr<SfizzVstEditor> editor = _editor.lock()) {
withStateLock([this, editor]() {
_uiState = editor->getCurrentUiState();
2020-12-07 09:41:36 +01:00
});
2020-11-24 07:24:24 +01:00
}
IPtr<SfizzVstEditor> editor = Steinberg::owned(new SfizzVstEditor(this));
_editor = editor->getWeakPtr();
2020-11-24 07:24:24 +01:00
2020-12-07 09:41:36 +01:00
withStateLock([this, editor]() {
editor->updateState(_state);
editor->updateUiState(_uiState);
editor->updatePlayState(_playState);
});
2020-11-24 07:24:24 +01:00
editor->remember();
return editor;
2020-03-05 11:16:47 +01:00
}
2020-03-05 18:21:46 +01:00
tresult PLUGIN_API SfizzVstController::setParamNormalized(Vst::ParamID tag, Vst::ParamValue normValue)
2020-03-05 11:16:47 +01:00
{
2020-03-05 18:21:46 +01:00
tresult r = SfizzVstControllerNoUi::setParamNormalized(tag, normValue);
2020-03-05 11:16:47 +01:00
if (r != kResultTrue)
return r;
2020-03-06 11:46:49 +01:00
float *slotF32 = nullptr;
int32 *slotI32 = nullptr;
2020-03-05 18:21:46 +01:00
float value = 0;
switch (tag) {
case kPidVolume: {
2020-03-06 11:46:49 +01:00
slotF32 = &_state.volume;
2020-03-05 18:21:46 +01:00
value = kParamVolumeRange.denormalize(normValue);
break;
}
2020-03-06 11:46:49 +01:00
case kPidNumVoices: {
slotI32 = &_state.numVoices;
value = kParamNumVoicesRange.denormalize(normValue);
break;
}
2020-03-06 11:55:52 +01:00
case kPidOversampling: {
2020-03-06 13:15:32 +01:00
slotI32 = &_state.oversamplingLog2;
2020-03-06 11:55:52 +01:00
value = kParamOversamplingRange.denormalize(normValue);
break;
}
2020-03-06 13:15:32 +01:00
case kPidPreloadSize: {
slotI32 = &_state.preloadSize;
value = kParamPreloadSizeRange.denormalize(normValue);
break;
}
2020-06-20 05:49:00 +02:00
case kPidScalaRootKey: {
slotI32 = &_state.scalaRootKey;
2020-08-29 04:54:18 +02:00
value = kParamScalaRootKeyRange.denormalize(normValue);
2020-06-20 05:49:00 +02:00
break;
}
case kPidTuningFrequency: {
slotF32 = &_state.tuningFrequency;
2020-08-29 04:54:18 +02:00
value = kParamTuningFrequencyRange.denormalize(normValue);
2020-06-20 05:49:00 +02:00
break;
}
case kPidStretchedTuning: {
slotF32 = &_state.stretchedTuning;
2020-08-29 04:54:18 +02:00
value = kParamStretchedTuningRange.denormalize(normValue);
2020-06-20 05:49:00 +02:00
break;
}
2020-03-06 11:46:49 +01:00
}
if (slotF32 && *slotF32 != value) {
2020-12-07 09:41:36 +01:00
withStateLock([this, slotF32, value]() {
*slotF32 = value;
if (IPtr<SfizzVstEditor> editor = _editor.lock())
2020-12-07 09:41:36 +01:00
editor->updateState(_state);
});
2020-03-06 11:46:49 +01:00
}
else if (slotI32 && *slotI32 != (int32)value) {
2020-12-07 09:41:36 +01:00
withStateLock([this, slotI32, value]() {
*slotI32 = (int32)value;
if (IPtr<SfizzVstEditor> editor = _editor.lock())
2020-12-07 09:41:36 +01:00
editor->updateState(_state);
});
2020-03-05 18:21:46 +01:00
}
2020-03-05 11:16:47 +01:00
return kResultTrue;
}
2020-12-07 09:41:36 +01:00
tresult PLUGIN_API SfizzVstController::setState(IBStream* stream)
2020-03-05 18:21:46 +01:00
{
SfizzUiState s;
2020-12-07 09:41:36 +01:00
tresult r = s.load(stream);
2020-03-05 18:21:46 +01:00
if (r != kResultTrue)
return r;
2020-12-07 09:41:36 +01:00
withStateLock([this, &s]() {
_uiState = s;
if (IPtr<SfizzVstEditor> editor = _editor.lock())
2020-12-07 09:41:36 +01:00
editor->updateUiState(_uiState);
});
2020-03-05 18:21:46 +01:00
return kResultTrue;
}
2020-12-07 09:41:36 +01:00
tresult PLUGIN_API SfizzVstController::getState(IBStream* stream)
2020-03-05 18:21:46 +01:00
{
2020-12-07 09:41:36 +01:00
tresult result;
2020-11-24 07:24:24 +01:00
2020-12-07 09:41:36 +01:00
withStateLock([this, stream, &result]() {
if (IPtr<SfizzVstEditor> editor = _editor.lock())
_uiState = editor->getCurrentUiState();
2020-12-07 09:41:36 +01:00
result = _uiState.store(stream);
});
return result;
2020-03-05 18:21:46 +01:00
}
2020-12-07 09:41:36 +01:00
tresult PLUGIN_API SfizzVstController::setComponentState(IBStream* stream)
2020-03-05 11:16:47 +01:00
{
SfizzVstState s;
2020-12-07 09:41:36 +01:00
tresult r = s.load(stream);
2020-03-05 11:16:47 +01:00
if (r != kResultTrue)
return r;
2020-03-05 18:21:46 +01:00
setParamNormalized(kPidVolume, kParamVolumeRange.normalize(s.volume));
2020-03-06 11:46:49 +01:00
setParamNormalized(kPidNumVoices, kParamNumVoicesRange.normalize(s.numVoices));
2020-03-06 13:15:32 +01:00
setParamNormalized(kPidOversampling, kParamOversamplingRange.normalize(s.oversamplingLog2));
setParamNormalized(kPidPreloadSize, kParamPreloadSizeRange.normalize(s.preloadSize));
2020-08-29 04:54:18 +02:00
setParamNormalized(kPidScalaRootKey, kParamScalaRootKeyRange.normalize(s.scalaRootKey));
setParamNormalized(kPidTuningFrequency, kParamTuningFrequencyRange.normalize(s.tuningFrequency));
setParamNormalized(kPidStretchedTuning, kParamStretchedTuningRange.normalize(s.stretchedTuning));
2020-03-05 18:21:46 +01:00
2020-12-07 09:41:36 +01:00
withStateLock([this, &s]() {
_state = s;
if (IPtr<SfizzVstEditor> editor = _editor.lock())
2020-12-07 09:41:36 +01:00
editor->updateState(_state);
});
2020-03-05 11:16:47 +01:00
return kResultTrue;
}
2020-06-20 05:49:00 +02:00
tresult SfizzVstController::notify(Vst::IMessage* message)
{
2020-12-07 09:41:36 +01:00
// Note: may be called from any thread (Reaper)
2020-06-20 05:49:00 +02:00
tresult result = SfizzVstControllerNoUi::notify(message);
if (result != kResultFalse)
return result;
const char* id = message->getMessageID();
Vst::IAttributeList* attr = message->getAttributes();
if (!strcmp(id, "LoadedSfz")) {
const void* data = nullptr;
uint32 size = 0;
result = attr->getBinary("File", data, size);
if (result != kResultTrue)
return result;
2020-12-07 09:41:36 +01:00
withStateLock([this, data, size]() {
_state.sfzFile.assign(static_cast<const char *>(data), size);
if (IPtr<SfizzVstEditor> editor = _editor.lock())
2020-12-07 09:41:36 +01:00
editor->updateState(_state);
});
2020-06-20 05:49:00 +02:00
}
else if (!strcmp(id, "LoadedScala")) {
const void* data = nullptr;
uint32 size = 0;
result = attr->getBinary("File", data, size);
if (result != kResultTrue)
return result;
2020-12-07 09:41:36 +01:00
withStateLock([this, data, size]() {
_state.scalaFile.assign(static_cast<const char *>(data), size);
if (IPtr<SfizzVstEditor> editor = _editor.lock())
2020-12-07 09:41:36 +01:00
editor->updateState(_state);
});
2020-06-20 05:49:00 +02:00
}
2020-08-12 19:23:50 +02:00
else if (!strcmp(id, "NotifiedPlayState")) {
const void* data = nullptr;
uint32 size = 0;
result = attr->getBinary("PlayState", data, size);
if (result != kResultTrue)
return result;
2020-12-07 09:41:36 +01:00
withStateLock([this, data]() {
_playState = *static_cast<const SfizzPlayState*>(data);
if (IPtr<SfizzVstEditor> editor = _editor.lock())
2020-12-07 09:41:36 +01:00
editor->updatePlayState(_playState);
});
2020-08-12 19:23:50 +02:00
}
2020-10-19 02:58:01 +02:00
else if (!strcmp(id, "ReceivedMessage")) {
const void* data = nullptr;
uint32 size = 0;
result = attr->getBinary("Message", data, size);
if (result != kResultTrue)
return result;
if (IPtr<SfizzVstEditor> editor = _editor.lock())
2020-11-24 07:24:24 +01:00
editor->receiveMessage(data, size);
2020-10-19 02:58:01 +02:00
}
2020-06-20 05:49:00 +02:00
return result;
}
2020-03-05 11:16:47 +01:00
FUnknown* SfizzVstController::createInstance(void*)
{
return static_cast<Vst::IEditController*>(new SfizzVstController);
}
/*
Note(jpc) Generated at random with uuidgen.
Can't find docs on it... maybe it's to register somewhere?
*/
FUID SfizzVstController::cid(0x7129736c, 0xbc784134, 0xbb899d56, 0x2ebafe4f);