sfizz/vst/SfizzVstEditor.cpp

264 lines
7.9 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 "SfizzVstEditor.h"
#include "SfizzVstState.h"
2020-08-29 04:54:18 +02:00
#include "editor/Editor.h"
#include "editor/EditIds.h"
2020-03-05 11:16:47 +01:00
#if !defined(__APPLE__) && !defined(_WIN32)
2020-03-12 00:41:35 +01:00
#include "X11RunLoop.h"
2020-03-05 11:16:47 +01:00
#endif
using namespace VSTGUI;
2020-08-29 04:54:18 +02:00
static ViewRect sfizzUiViewRect { 0, 0, Editor::viewWidth, Editor::viewHeight };
2020-03-05 11:16:47 +01:00
SfizzVstEditor::SfizzVstEditor(void *controller)
2020-08-29 04:54:18 +02:00
: VSTGUIEditor(controller, &sfizzUiViewRect)
2020-03-05 11:16:47 +01:00
{
2020-03-05 18:21:46 +01:00
getController()->addSfizzStateListener(this);
2020-03-05 11:16:47 +01:00
}
SfizzVstEditor::~SfizzVstEditor()
{
2020-03-05 18:21:46 +01:00
getController()->removeSfizzStateListener(this);
2020-03-05 11:16:47 +01:00
}
bool PLUGIN_API SfizzVstEditor::open(void* parent, const VSTGUI::PlatformType& platformType)
{
fprintf(stderr, "[sfizz] about to open view with parent %p\n", parent);
CRect wsize(0, 0, sfizzUiViewRect.getWidth(), sfizzUiViewRect.getHeight());
2020-03-05 11:16:47 +01:00
CFrame *frame = new CFrame(wsize, this);
this->frame = frame;
IPlatformFrameConfig* config = nullptr;
#if !defined(__APPLE__) && !defined(_WIN32)
X11::FrameConfig x11config;
2020-03-12 00:41:35 +01:00
if (!_runLoop)
_runLoop = new RunLoop(plugFrame);
x11config.runLoop = _runLoop;
2020-03-05 11:16:47 +01:00
config = &x11config;
#endif
2020-08-29 04:54:18 +02:00
Editor* editor = editor_.get();
if (!editor) {
editor = new Editor(*this);
editor_.reset(editor);
}
2020-03-05 11:16:47 +01:00
updateStateDisplay();
if (!frame->open(parent, platformType, config)) {
fprintf(stderr, "[sfizz] error opening frame\n");
return false;
}
2020-08-29 04:54:18 +02:00
editor->open(*frame);
2020-03-05 11:16:47 +01:00
return true;
}
void PLUGIN_API SfizzVstEditor::close()
{
CFrame *frame = this->frame;
if (frame) {
2020-08-29 04:54:18 +02:00
if (editor_)
editor_->close();
2020-03-12 00:41:35 +01:00
if (frame->getNbReference() != 1)
2020-08-29 04:54:18 +02:00
frame->forget();
else
2020-03-12 00:41:35 +01:00
frame->close();
2020-03-05 11:16:47 +01:00
}
}
///
2020-03-12 00:41:35 +01:00
CMessageResult SfizzVstEditor::notify(CBaseObject* sender, const char* message)
{
CMessageResult result = VSTGUIEditor::notify(sender, message);
if (result != kMessageNotified)
return result;
#if !defined(__APPLE__) && !defined(_WIN32)
if (message == CVSTGUITimer::kMsgTimer) {
SharedPointer<VSTGUI::RunLoop> runLoop = RunLoop::get();
if (runLoop) {
// note(jpc) I don't find a reliable way to check if the host
// notifier of X11 events is working. If there is, remove this and
// avoid polluting Linux hosts which implement the loop correctly.
runLoop->processSomeEvents();
runLoop->cleanupDeadHandlers();
}
}
#endif
return result;
}
2020-03-05 11:16:47 +01:00
void SfizzVstEditor::onStateChanged()
{
updateStateDisplay();
}
///
2020-08-29 04:54:18 +02:00
void SfizzVstEditor::uiSendValue(EditId id, const EditValue& v)
2020-03-05 11:16:47 +01:00
{
2020-08-29 04:54:18 +02:00
if (id == EditId::SfzFile)
loadSfzFile(absl::get<std::string>(v));
else if (id == EditId::ScalaFile)
loadScalaFile(absl::get<std::string>(v));
else {
SfizzVstController* ctrl = getController();
auto normalizeAndSet = [ctrl](Vst::ParamID pid, const SfizzParameterRange& range, float value) {
float normValue = range.normalize(value);
ctrl->setParamNormalized(pid, normValue);
ctrl->performEdit(pid, normValue);
};
switch (id) {
case EditId::Volume:
normalizeAndSet(kPidVolume, kParamVolumeRange, absl::get<float>(v));
break;
case EditId::Polyphony:
normalizeAndSet(kPidNumVoices, kParamNumVoicesRange, absl::get<float>(v));
break;
case EditId::Oversampling:
{
const int32 value = static_cast<int32>(absl::get<float>(v));
int32 log2Value = 0;
for (int32 f = value; f > 1; f /= 2)
++log2Value;
normalizeAndSet(kPidOversampling, kParamOversamplingRange, log2Value);
}
break;
case EditId::PreloadSize:
normalizeAndSet(kPidPreloadSize, kParamPreloadSizeRange, absl::get<float>(v));
break;
case EditId::ScalaRootKey:
normalizeAndSet(kPidScalaRootKey, kParamScalaRootKeyRange, absl::get<float>(v));
break;
case EditId::TuningFrequency:
normalizeAndSet(kPidTuningFrequency, kParamTuningFrequencyRange, absl::get<float>(v));
break;
case EditId::StretchTuning:
normalizeAndSet(kPidStretchedTuning, kParamStretchedTuningRange, absl::get<float>(v));
break;
2020-03-05 11:16:47 +01:00
2020-08-29 04:54:18 +02:00
case EditId::UIActivePanel:
ctrl->getSfizzUiState().activePanel = static_cast<int32>(absl::get<float>(v));
break;
2020-03-05 11:16:47 +01:00
2020-08-29 04:54:18 +02:00
default:
break;
}
2020-03-05 11:16:47 +01:00
}
}
2020-08-29 04:54:18 +02:00
void SfizzVstEditor::uiBeginSend(EditId id)
{
Vst::ParamID pid = parameterOfEditId(id);
if (pid != -1)
getController()->beginEdit(pid);
}
void SfizzVstEditor::uiEndSend(EditId id)
{
Vst::ParamID pid = parameterOfEditId(id);
if (pid != -1)
getController()->endEdit(pid);
}
void SfizzVstEditor::uiSendMIDI(const uint8_t* msg, uint32_t len)
{
// TODO send MIDI...
}
///
2020-03-05 11:16:47 +01:00
void SfizzVstEditor::loadSfzFile(const std::string& filePath)
{
2020-03-05 18:21:46 +01:00
SfizzVstController* ctl = getController();
2020-03-05 15:53:01 +01:00
2020-06-20 05:49:00 +02:00
Steinberg::OPtr<Vst::IMessage> msg { ctl->allocateMessage() };
2020-03-05 15:53:01 +01:00
if (!msg) {
fprintf(stderr, "[Sfizz] UI could not allocate message\n");
return;
2020-03-05 11:16:47 +01:00
}
2020-03-05 15:53:01 +01:00
msg->setMessageID("LoadSfz");
Vst::IAttributeList* attr = msg->getAttributes();
2020-03-28 17:00:07 +01:00
attr->setBinary("File", filePath.data(), filePath.size());
2020-03-05 15:53:01 +01:00
ctl->sendMessage(msg);
2020-06-20 05:49:00 +02:00
}
void SfizzVstEditor::loadScalaFile(const std::string& filePath)
{
SfizzVstController* ctl = getController();
Steinberg::OPtr<Vst::IMessage> msg { ctl->allocateMessage() };
if (!msg) {
fprintf(stderr, "[Sfizz] UI could not allocate message\n");
return;
}
msg->setMessageID("LoadScala");
Vst::IAttributeList* attr = msg->getAttributes();
attr->setBinary("File", filePath.data(), filePath.size());
ctl->sendMessage(msg);
2020-03-05 11:16:47 +01:00
}
void SfizzVstEditor::updateStateDisplay()
{
if (!frame)
return;
2020-03-05 18:21:46 +01:00
SfizzVstController* controller = getController();
const SfizzVstState& state = controller->getSfizzState();
const SfizzUiState& uiState = controller->getSfizzUiState();
2020-08-12 19:23:50 +02:00
const SfizzPlayState& playState = controller->getSfizzPlayState();
2020-03-05 11:16:47 +01:00
2020-08-12 19:23:50 +02:00
///
2020-08-29 04:54:18 +02:00
uiReceiveValue(EditId::SfzFile, state.sfzFile);
uiReceiveValue(EditId::Volume, state.volume);
uiReceiveValue(EditId::Polyphony, state.numVoices);
uiReceiveValue(EditId::Oversampling, 1u << state.oversamplingLog2);
uiReceiveValue(EditId::PreloadSize, state.preloadSize);
uiReceiveValue(EditId::ScalaFile, state.scalaFile);
uiReceiveValue(EditId::ScalaRootKey, state.scalaRootKey);
uiReceiveValue(EditId::TuningFrequency, state.tuningFrequency);
uiReceiveValue(EditId::StretchTuning, state.stretchedTuning);
2020-03-05 18:21:46 +01:00
2020-08-12 19:23:50 +02:00
///
2020-08-29 04:54:18 +02:00
uiReceiveValue(EditId::UINumCurves, playState.curves);
uiReceiveValue(EditId::UINumMasters, playState.masters);
uiReceiveValue(EditId::UINumGroups, playState.groups);
uiReceiveValue(EditId::UINumRegions, playState.regions);
uiReceiveValue(EditId::UINumPreloadedSamples, playState.preloadedSamples);
uiReceiveValue(EditId::UINumActiveVoices, playState.activeVoices);
2020-08-12 19:23:50 +02:00
///
2020-08-29 04:54:18 +02:00
uiReceiveValue(EditId::UIActivePanel, uiState.activePanel);
2020-06-20 05:49:00 +02:00
}
2020-08-29 04:54:18 +02:00
Vst::ParamID SfizzVstEditor::parameterOfEditId(EditId id)
2020-06-20 05:49:00 +02:00
{
2020-08-29 04:54:18 +02:00
switch (id) {
case EditId::Volume: return kPidVolume;
case EditId::Polyphony: return kPidNumVoices;
case EditId::Oversampling: return kPidOversampling;
case EditId::PreloadSize: return kPidPreloadSize;
case EditId::ScalaRootKey: return kPidScalaRootKey;
case EditId::TuningFrequency: return kPidTuningFrequency;
case EditId::StretchTuning: return kPidStretchedTuning;
default: return -1;
2020-03-05 16:41:59 +01:00
}
}