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:
Robbert van der Helm
2021-01-10 17:24:38 +01:00
parent 8971a65825
commit c514233922
4 changed files with 79 additions and 29 deletions
+48 -27
View File
@@ -21,6 +21,31 @@
#include <cassert>
#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(Steinberg::IBStream* stream) {
@@ -61,34 +86,18 @@ YaBStream::YaBStream(Steinberg::IBStream* stream) {
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();
Steinberg::IPtr<Steinberg::Vst::IAttributeList> stream_attributes_list =
stream_attributes->getAttributes();
for (const auto& key :
{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}) {
vst_string[0] = 0;
if (stream_attributes_list->getString(key, vst_string,
sizeof(vst_string)) ==
Steinberg::kResultOk) {
attributes->setString(key, vst_string);
if (Steinberg::IPtr<Steinberg::Vst::IAttributeList>
stream_attributes_list = stream_attributes->getAttributes()) {
// Copy over all predefined meta data keys. `IAttributeList` does
// not offer any interface to enumerate the stored keys.
for (const auto& key : stream_meta_data_keys) {
vst_string[0] = 0;
if (stream_attributes_list->getString(key, vst_string,
sizeof(vst_string)) ==
Steinberg::kResultOk) {
attributes->setString(key, vst_string);
}
}
}
}
@@ -139,6 +148,18 @@ tresult YaBStream::write_back(Steinberg::IBStream* stream) const {
// 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
// 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;
}