diff --git a/meson.build b/meson.build index 1c7b9d38..f722f8ee 100644 --- a/meson.build +++ b/meson.build @@ -87,6 +87,7 @@ vst3_plugin_sources = [ 'src/common/serialization/vst3/plugin/plugin-base.cpp', 'src/common/serialization/vst3/component-handler/component-handler.cpp', 'src/common/serialization/vst3/host-context/host-application.cpp', + 'src/common/serialization/vst3/attribute-list.cpp', 'src/common/serialization/vst3/base.cpp', 'src/common/serialization/vst3/component-handler-proxy.cpp', 'src/common/serialization/vst3/event-list.cpp', @@ -140,6 +141,7 @@ if with_vst3 'src/common/serialization/vst3/plugin/plugin-base.cpp', 'src/common/serialization/vst3/component-handler/component-handler.cpp', 'src/common/serialization/vst3/host-context/host-application.cpp', + 'src/common/serialization/vst3/attribute-list.cpp', 'src/common/serialization/vst3/base.cpp', 'src/common/serialization/vst3/component-handler-proxy.cpp', 'src/common/serialization/vst3/event-list.cpp', diff --git a/src/common/serialization/vst3/README.md b/src/common/serialization/vst3/README.md index bc6837d8..f4aabc68 100644 --- a/src/common/serialization/vst3/README.md +++ b/src/common/serialization/vst3/README.md @@ -36,6 +36,7 @@ implemented for serialization purposes: | yabridge class | Interfaces | Notes | | -------------------- | ------------------- | ---------------------------------------------------------------------- | +| `YaAttributeList` | `IAttributeList` | | | `YaEventList` | `IEventList` | Comes with a lot of serialization wrappers around the related structs. | | `YaParameterChanges` | `IParameterChanges` | | | `YaParamValueQueue` | `IParamValueQueue` | | diff --git a/src/common/serialization/vst3/attribute-list.cpp b/src/common/serialization/vst3/attribute-list.cpp new file mode 100644 index 00000000..33311fe3 --- /dev/null +++ b/src/common/serialization/vst3/attribute-list.cpp @@ -0,0 +1,115 @@ +// 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 "attribute-list.h" + +YaAttributeList::YaAttributeList(){FUNKNOWN_CTOR} + +YaAttributeList::~YaAttributeList() { + FUNKNOWN_DTOR +} + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor" +IMPLEMENT_FUNKNOWN_METHODS(YaAttributeList, + Steinberg::Vst::IAttributeList, + Steinberg::Vst::IAttributeList::iid) +#pragma GCC diagnostic pop + +tresult PLUGIN_API YaAttributeList::setInt(AttrID id, int64 value) { + attrs_int[id] = value; + return Steinberg::kResultOk; +} + +tresult PLUGIN_API YaAttributeList::getInt(AttrID id, int64& value) { + if (const auto it = attrs_int.find(id); it != attrs_int.end()) { + value = it->second; + return Steinberg::kResultOk; + } else { + return Steinberg::kResultFalse; + } +} + +tresult PLUGIN_API YaAttributeList::setFloat(AttrID id, double value) { + attrs_float[id] = value; + return Steinberg::kResultOk; +} + +tresult PLUGIN_API YaAttributeList::getFloat(AttrID id, double& value) { + if (const auto it = attrs_float.find(id); it != attrs_float.end()) { + value = it->second; + return Steinberg::kResultOk; + } else { + return Steinberg::kResultFalse; + } +} + +tresult PLUGIN_API +YaAttributeList::setString(AttrID id, const Steinberg::Vst::TChar* string) { + if (!string) { + return Steinberg::kInvalidArgument; + } + + attrs_string[id] = tchar_pointer_to_u16string(string); + return Steinberg::kResultOk; +} + +tresult PLUGIN_API YaAttributeList::getString(AttrID id, + Steinberg::Vst::TChar* string, + uint32 sizeInBytes) { + if (!string) { + return Steinberg::kInvalidArgument; + } + + if (const auto it = attrs_string.find(id); it != attrs_string.end()) { + // We may only copy `sizeInBytes / 2` UTF-16 characters to `string`, + // We'll also have to make sure it's null terminated, so we'll reserve + // another byte for that. + const size_t copy_characters = std::min( + (static_cast(sizeInBytes) / sizeof(Steinberg::Vst::TChar)) - + 1, + it->second.size()); + std::copy_n(it->second.begin(), copy_characters, string); + string[copy_characters] = 0; + + return Steinberg::kResultOk; + } else { + return Steinberg::kResultFalse; + } +} + +tresult PLUGIN_API YaAttributeList::setBinary(AttrID id, + const void* data, + uint32 sizeInBytes) { + if (!data) { + return Steinberg::kInvalidArgument; + } + + const uint8_t* data_bytes = static_cast(data); + attrs_binary[id].assign(data_bytes, data_bytes + sizeInBytes); + return Steinberg::kResultOk; +} +tresult PLUGIN_API YaAttributeList::getBinary(AttrID id, + const void*& data, + uint32& sizeInBytes) { + if (const auto it = attrs_binary.find(id); it != attrs_binary.end()) { + data = it->second.data(); + sizeInBytes = it->second.size(); + return Steinberg::kResultOk; + } else { + return Steinberg::kResultFalse; + } +} diff --git a/src/common/serialization/vst3/attribute-list.h b/src/common/serialization/vst3/attribute-list.h new file mode 100644 index 00000000..f7cd586c --- /dev/null +++ b/src/common/serialization/vst3/attribute-list.h @@ -0,0 +1,90 @@ +// 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 +#include + +#include "base.h" + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wnon-virtual-dtor" + +/** + * Wraps around `IAttributeList` for storing parameters in `YaMessage`. + */ +class YaAttributeList : public Steinberg::Vst::IAttributeList { + public: + /** + * Default constructor with an empty attributeList. The plugin can use this + * to write a attributeList. + */ + YaAttributeList(); + + ~YaAttributeList(); + + DECLARE_FUNKNOWN_METHODS + + virtual tresult PLUGIN_API setInt(AttrID id, int64 value) override; + virtual tresult PLUGIN_API getInt(AttrID id, int64& value) override; + virtual tresult PLUGIN_API setFloat(AttrID id, double value) override; + virtual tresult PLUGIN_API getFloat(AttrID id, double& value) override; + virtual tresult PLUGIN_API + setString(AttrID id, const Steinberg::Vst::TChar* string) override; + virtual tresult PLUGIN_API getString(AttrID id, + Steinberg::Vst::TChar* string, + uint32 sizeInBytes) override; + virtual tresult PLUGIN_API setBinary(AttrID id, + const void* data, + uint32 sizeInBytes) override; + virtual tresult PLUGIN_API getBinary(AttrID id, + const void*& data, + uint32& sizeInBytes) override; + + template + void serialize(S& s) { + s.ext(attrs_int, bitsery::ext::StdMap{1 << 20}, + [](S& s, AttrID& key, int64& value) { + s.text1b(key, 1024); + s.value8b(value); + }); + s.ext(attrs_float, bitsery::ext::StdMap{1 << 20}, + [](S& s, AttrID& key, double& value) { + s.text1b(key, 1024); + s.value8b(value); + }); + s.ext(attrs_string, bitsery::ext::StdMap{1 << 20}, + [](S& s, AttrID& key, double& value) { + s.text1b(key, 1024); + s.text2b(value, 1 << 20); + }); + s.ext(attrs_binary, bitsery::ext::StdMap{1 << 20}, + [](S& s, AttrID& key, std::vector& value) { + s.text1b(key, 1024); + s.container1b(value, 1 << 20); + }); + } + + private: + std::unordered_map attrs_int; + std::unordered_map attrs_float; + std::unordered_map attrs_string; + std::unordered_map> attrs_binary; +};