mirror of
https://github.com/robbert-vdh/yabridge.git
synced 2026-05-10 04:30:12 +02:00
Write back preset meta data set by the plugin
The docs don't mention that this is a thing you should support, but `IStreamAttributes` doesn't make much sense without this.
This commit is contained in:
@@ -29,6 +29,28 @@ IMPLEMENT_FUNKNOWN_METHODS(YaAttributeList,
|
|||||||
Steinberg::Vst::IAttributeList::iid)
|
Steinberg::Vst::IAttributeList::iid)
|
||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
|
|
||||||
|
tresult YaAttributeList::write_back(
|
||||||
|
Steinberg::Vst::IAttributeList* stream) const {
|
||||||
|
if (!stream) {
|
||||||
|
return Steinberg::kInvalidArgument;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& [key, value] : attrs_int) {
|
||||||
|
stream->setInt(key.c_str(), value);
|
||||||
|
}
|
||||||
|
for (const auto& [key, value] : attrs_float) {
|
||||||
|
stream->setFloat(key.c_str(), value);
|
||||||
|
}
|
||||||
|
for (const auto& [key, value] : attrs_string) {
|
||||||
|
stream->setString(key.c_str(), u16string_to_tchar_pointer(value));
|
||||||
|
}
|
||||||
|
for (const auto& [key, value] : attrs_binary) {
|
||||||
|
stream->setBinary(key.c_str(), value.data(), value.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
return Steinberg::kResultOk;
|
||||||
|
}
|
||||||
|
|
||||||
tresult PLUGIN_API YaAttributeList::setInt(AttrID id, int64 value) {
|
tresult PLUGIN_API YaAttributeList::setInt(AttrID id, int64 value) {
|
||||||
attrs_int[id] = value;
|
attrs_int[id] = value;
|
||||||
return Steinberg::kResultOk;
|
return Steinberg::kResultOk;
|
||||||
|
|||||||
@@ -42,6 +42,13 @@ class YaAttributeList : public Steinberg::Vst::IAttributeList {
|
|||||||
|
|
||||||
DECLARE_FUNKNOWN_METHODS
|
DECLARE_FUNKNOWN_METHODS
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write the attribute list a host provided `IAttributeList`. This is used
|
||||||
|
* in `YaBStream::write_back` to write any preset meta data back to the host
|
||||||
|
* for hosts that support it.
|
||||||
|
*/
|
||||||
|
tresult write_back(Steinberg::Vst::IAttributeList* stream) const;
|
||||||
|
|
||||||
virtual tresult PLUGIN_API setInt(AttrID id, int64 value) override;
|
virtual tresult PLUGIN_API setInt(AttrID id, int64 value) override;
|
||||||
virtual tresult PLUGIN_API getInt(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 setFloat(AttrID id, double value) override;
|
||||||
|
|||||||
@@ -21,6 +21,31 @@
|
|||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* These are the meta data keys used for `IStreamAttributes`. We need to keep
|
||||||
|
* track of this because `IAttributeList` has no way to just iterate over the
|
||||||
|
* stored keys. We'll read these from the host if the host supports this
|
||||||
|
* interface, and if the plugin writes an attribute with one of these keys we'll
|
||||||
|
* write the value back to the host.
|
||||||
|
*
|
||||||
|
* TODO: There's also `Steinberg::Vst::PresetAttributes::kFilePathStringType`
|
||||||
|
* This would require translating between Windows and Unix style paths,
|
||||||
|
* which we can't easily do outside of Wine. If this ends up being
|
||||||
|
* important, then we'll have to shell out to `winepath` which is not
|
||||||
|
* ideal. On the Wine side we can just use the `wine_get_dos_file_name`
|
||||||
|
* and `wine_get_unix_file_name` functions instead. Requesting this should
|
||||||
|
* also use a 1024 character buffer.
|
||||||
|
*/
|
||||||
|
const static char* stream_meta_data_keys[] = {
|
||||||
|
Steinberg::Vst::PresetAttributes::kPlugInName,
|
||||||
|
Steinberg::Vst::PresetAttributes::kPlugInCategory,
|
||||||
|
Steinberg::Vst::PresetAttributes::kInstrument,
|
||||||
|
Steinberg::Vst::PresetAttributes::kStyle,
|
||||||
|
Steinberg::Vst::PresetAttributes::kCharacter,
|
||||||
|
Steinberg::Vst::PresetAttributes::kStateType,
|
||||||
|
Steinberg::Vst::PresetAttributes::kName,
|
||||||
|
Steinberg::Vst::PresetAttributes::kFileName};
|
||||||
|
|
||||||
YaBStream::YaBStream(){FUNKNOWN_CTOR}
|
YaBStream::YaBStream(){FUNKNOWN_CTOR}
|
||||||
|
|
||||||
YaBStream::YaBStream(Steinberg::IBStream* stream) {
|
YaBStream::YaBStream(Steinberg::IBStream* stream) {
|
||||||
@@ -61,29 +86,12 @@ YaBStream::YaBStream(Steinberg::IBStream* stream) {
|
|||||||
file_name.emplace(tchar_pointer_to_u16string(vst_string));
|
file_name.emplace(tchar_pointer_to_u16string(vst_string));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy over all predefined meta data keys. `IAttributeList` does not
|
|
||||||
// offer any interface to enumerate over the stored keys.
|
|
||||||
// TODO: There's also
|
|
||||||
// `Steinberg::Vst::PresetAttributes::kFilePathStringType`
|
|
||||||
// This would require translating between Windows and Unix style
|
|
||||||
// paths, which we can't easily do outside of Wine. If this ends
|
|
||||||
// up being important, then we'll have to shell out to `winepath`
|
|
||||||
// which is not ideal. On the Wine side we can just use the
|
|
||||||
// `wine_get_dos_file_name` and `wine_get_unix_file_name`
|
|
||||||
// functions instead. Requesting this should also use a 1024
|
|
||||||
// character buffer.
|
|
||||||
attributes.emplace();
|
attributes.emplace();
|
||||||
Steinberg::IPtr<Steinberg::Vst::IAttributeList> stream_attributes_list =
|
if (Steinberg::IPtr<Steinberg::Vst::IAttributeList>
|
||||||
stream_attributes->getAttributes();
|
stream_attributes_list = stream_attributes->getAttributes()) {
|
||||||
for (const auto& key :
|
// Copy over all predefined meta data keys. `IAttributeList` does
|
||||||
{Steinberg::Vst::PresetAttributes::kPlugInName,
|
// not offer any interface to enumerate the stored keys.
|
||||||
Steinberg::Vst::PresetAttributes::kPlugInCategory,
|
for (const auto& key : stream_meta_data_keys) {
|
||||||
Steinberg::Vst::PresetAttributes::kInstrument,
|
|
||||||
Steinberg::Vst::PresetAttributes::kStyle,
|
|
||||||
Steinberg::Vst::PresetAttributes::kCharacter,
|
|
||||||
Steinberg::Vst::PresetAttributes::kStateType,
|
|
||||||
Steinberg::Vst::PresetAttributes::kName,
|
|
||||||
Steinberg::Vst::PresetAttributes::kFileName}) {
|
|
||||||
vst_string[0] = 0;
|
vst_string[0] = 0;
|
||||||
if (stream_attributes_list->getString(key, vst_string,
|
if (stream_attributes_list->getString(key, vst_string,
|
||||||
sizeof(vst_string)) ==
|
sizeof(vst_string)) ==
|
||||||
@@ -92,6 +100,7 @@ YaBStream::YaBStream(Steinberg::IBStream* stream) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
YaBStream::~YaBStream() {
|
YaBStream::~YaBStream() {
|
||||||
@@ -139,6 +148,18 @@ tresult YaBStream::write_back(Steinberg::IBStream* stream) const {
|
|||||||
// back after `*::getState()`? I'd assume so, but the docs don't
|
// back after `*::getState()`? I'd assume so, but the docs don't
|
||||||
// mention this. If so then we need to always store whether the host
|
// mention this. If so then we need to always store whether the host
|
||||||
// supports `IStreamAttributes`.
|
// supports `IStreamAttributes`.
|
||||||
|
// Write back any attributes written by the plugin if the host supports
|
||||||
|
// preset meta data
|
||||||
|
if (Steinberg::FUnknownPtr<Steinberg::Vst::IStreamAttributes>
|
||||||
|
stream_attributes = stream;
|
||||||
|
stream_attributes && attributes) {
|
||||||
|
if (Steinberg::IPtr<Steinberg::Vst::IAttributeList>
|
||||||
|
stream_attributes_list = stream_attributes->getAttributes()) {
|
||||||
|
// XXX: If the host somehow preset some attributes, then we're also
|
||||||
|
// writing those back. This should not cause any issues though.
|
||||||
|
attributes->write_back(stream_attributes_list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return Steinberg::kResultOk;
|
return Steinberg::kResultOk;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,8 +58,8 @@ class YaBStream : public Steinberg::IBStream,
|
|||||||
DECLARE_FUNKNOWN_METHODS
|
DECLARE_FUNKNOWN_METHODS
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write the vector buffer back to an IBStream. After writing the seek
|
* Write the vector buffer back to a host provided `IBStream`. After writing
|
||||||
* position will be left at the end of the stream.
|
* the seek position will be left at the end of the stream.
|
||||||
*/
|
*/
|
||||||
tresult write_back(Steinberg::IBStream* stream) const;
|
tresult write_back(Steinberg::IBStream* stream) const;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user