From 026595d99f7a8a5c213ac3643cc2c369a020e5de Mon Sep 17 00:00:00 2001 From: Robbert van der Helm Date: Tue, 15 Dec 2020 14:01:04 +0100 Subject: [PATCH] Implement IParamValueQueue --- README.md | 1 + meson.build | 2 + src/common/serialization/vst3/README.md | 8 ++ .../serialization/vst3/param-value-queue.cpp | 74 ++++++++++++++++ .../serialization/vst3/param-value-queue.h | 86 +++++++++++++++++++ 5 files changed, 171 insertions(+) create mode 100644 src/common/serialization/vst3/param-value-queue.cpp create mode 100644 src/common/serialization/vst3/param-value-queue.h diff --git a/README.md b/README.md index e5857d99..5f96bbb7 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,7 @@ imcomplete list of things that still have to be done before this can be used: - Fully implemented: - `GetPluginFactory()` and `IPluginFactory{,2,3}` - `IPluginBase` and `IComponent` + - `IParamValueQueue` - Update the GitHub Actions workflows. - Update yabridgectl to handle buth VST2 and VST3 plugins. - Update all documentation to refer to VST2 and VST3 support separately, and diff --git a/meson.build b/meson.build index 17f46217..79972446 100644 --- a/meson.build +++ b/meson.build @@ -80,6 +80,7 @@ vst3_plugin_sources = [ 'src/common/serialization/vst3/base.cpp', 'src/common/serialization/vst3/component.cpp', 'src/common/serialization/vst3/host-application.cpp', + 'src/common/serialization/vst3/param-value-queue.cpp', 'src/common/serialization/vst3/plugin-factory.cpp', 'src/common/configuration.cpp', 'src/common/plugins.cpp', @@ -115,6 +116,7 @@ if with_vst3 'src/common/serialization/vst3/base.cpp', 'src/common/serialization/vst3/component.cpp', 'src/common/serialization/vst3/host-application.cpp', + 'src/common/serialization/vst3/param-value-queue.cpp', 'src/common/serialization/vst3/plugin-factory.cpp', 'src/wine-host/bridges/vst3-impls/host-application.cpp', 'src/wine-host/bridges/vst3.cpp', diff --git a/src/common/serialization/vst3/README.md b/src/common/serialization/vst3/README.md index 12e801bf..5a6b4f8c 100644 --- a/src/common/serialization/vst3/README.md +++ b/src/common/serialization/vst3/README.md @@ -107,6 +107,14 @@ proxying is described in the section above. 8. Finally a pointer to this `YaFooPluginImpl` gets returned as the last step of the initialization process. +## Simple objects + +For serializing objects of interfaces that purely contain getters and setters +(and thus don't need to perform any host callbacks), we'll simply have a +constructor that takes the `IFoo` by `IPtr` or reference (depending on how it's +used in the SDK) and reads the data from it to create a serializable copy of +that object. + ## Safety notes - None of the destructors in the interfaces defined by the SDK are marked as diff --git a/src/common/serialization/vst3/param-value-queue.cpp b/src/common/serialization/vst3/param-value-queue.cpp new file mode 100644 index 00000000..02f1c75f --- /dev/null +++ b/src/common/serialization/vst3/param-value-queue.cpp @@ -0,0 +1,74 @@ +// yabridge: a Wine VST bridge +// Copyright (C) 2020 Robbert van der Helm +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include "param-value-queue.h" + +YaParamValueQueue::YaParamValueQueue(){FUNKNOWN_CTOR} + +YaParamValueQueue::YaParamValueQueue( + Steinberg::Vst::IParamValueQueue& original_queue) + : parameter_id(original_queue.getParameterId()), + queue(original_queue.getPointCount()) { + FUNKNOWN_CTOR + + // Copy over all points to our vector + for (int i = 0; i < original_queue.getPointCount(); i++) { + // We're skipping the assertions here and just assume that the function + // returns `kResultOk` + original_queue.getPoint(i, queue[i].first, queue[i].second); + } +} + +YaParamValueQueue::~YaParamValueQueue() { + FUNKNOWN_DTOR +} + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor" +IMPLEMENT_FUNKNOWN_METHODS(YaParamValueQueue, + Steinberg::Vst::IParamValueQueue, + Steinberg::Vst::IParamValueQueue::iid) +#pragma GCC diagnostic pop + +Steinberg::Vst::ParamID PLUGIN_API YaParamValueQueue::getParameterId() { + return parameter_id; +} + +int32 PLUGIN_API YaParamValueQueue::getPointCount() { + return queue.size(); +} + +tresult PLUGIN_API +YaParamValueQueue::getPoint(int32 index, + int32& sampleOffset /*out*/, + Steinberg::Vst::ParamValue& value /*out*/) { + if (index < static_cast(queue.size())) { + sampleOffset = queue[index].first; + value = queue[index].second; + + return Steinberg::kResultOk; + } else { + return Steinberg::kInvalidArgument; + } +} +tresult PLUGIN_API YaParamValueQueue::addPoint(int32 sampleOffset, + Steinberg::Vst::ParamValue value, + int32& index /*out*/) { + index = queue.size(); + queue.push_back({sampleOffset, value}); + + return Steinberg::kResultOk; +} diff --git a/src/common/serialization/vst3/param-value-queue.h b/src/common/serialization/vst3/param-value-queue.h new file mode 100644 index 00000000..49e0c1de --- /dev/null +++ b/src/common/serialization/vst3/param-value-queue.h @@ -0,0 +1,86 @@ +// yabridge: a Wine VST bridge +// Copyright (C) 2020 Robbert van der Helm +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#pragma once + +#include +#include + +#include "base.h" + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wnon-virtual-dtor" + +/** + * Wraps around `IParamValueQueue` for serializing a queue containing changes to + * a single parameter during the current processing cycle. Used in + * `YaParameterChanges`. + */ +class YaParamValueQueue : public Steinberg::Vst::IParamValueQueue { + public: + /** + * Default constructor with an empty queue. + */ + YaParamValueQueue(); + + /** + * Read data from an existing `IParamValueQueue` object. + */ + YaParamValueQueue(Steinberg::Vst::IParamValueQueue&); + + ~YaParamValueQueue(); + + DECLARE_FUNKNOWN_METHODS + + // From `IParamValueQueue` + Steinberg::Vst::ParamID PLUGIN_API getParameterId() override; + int32 PLUGIN_API getPointCount() override; + tresult PLUGIN_API + getPoint(int32 index, + int32& sampleOffset /*out*/, + Steinberg::Vst::ParamValue& value /*out*/) override; + tresult PLUGIN_API addPoint(int32 sampleOffset, + Steinberg::Vst::ParamValue value, + int32& index /*out*/) override; + + template + void serialize(S& s) { + s.value4b(parameter_id); + // TODO: Does bitsery have a built in way to serialize pairs? + s.container(queue, 1 << 16, [](S& s, std::pair& pair) { + s.value4b(pair.first); + s.value8b(pair.second); + }); + } + + private: + /** + * For `IParamValueQueue::getParameterId`. + */ + Steinberg::Vst::ParamID parameter_id; + + /** + * The actual parameter changes queue. The specification doesn't mention + * that this should be a priority queue or something, but I'd assume both + * the plugin and the host will insert the values in chronological order + * (because, why would they not?). + * + * This contains pairs of `(sample_offset, value)`. + */ + std::vector> queue; +}; + +#pragma GCC diagnostic pop