From a9f9691b425a8c17da3ca07785a89127f16b2b67 Mon Sep 17 00:00:00 2001 From: Robbert van der Helm Date: Sun, 2 May 2021 21:59:26 +0200 Subject: [PATCH] Don't copy any VST3 state preamble Bitwig prepends some data when passing an `IBStream*` to the plugin, and when we do copy it iZotope Rx7 plugins cannot load their state (even if we also copy over the same seek position). Not copying that preamble fixes the issue, and it seems like it doesn't break anything. --- CHANGELOG.md | 1 + src/common/serialization/vst3/bstream.cpp | 12 +++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fc50c001..8776e888 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -105,6 +105,7 @@ Versioning](https://semver.org/spec/v2.0.0.html). - Fixed another potential freezing issue in **REAPER** that could happen when the when the plugin resizes itself while sending a parameter change to the host, if REAPER's 'disable saving full plug-in state' is not disabled. +- Fixed saving and loading _iZotope Rx7_ plugin state in **Bitwig Studio**. - Fixed a potential assertion failure when setting VST3 preset data. This would depend on the `libstdc++` version used to built yabridge with. - _PSPaudioware InifniStrip_ would fail to initialize because the plugin expects diff --git a/src/common/serialization/vst3/bstream.cpp b/src/common/serialization/vst3/bstream.cpp index 02dcdb3f..293600f7 100644 --- a/src/common/serialization/vst3/bstream.cpp +++ b/src/common/serialization/vst3/bstream.cpp @@ -30,21 +30,31 @@ YaBStream::YaBStream(Steinberg::IBStream* stream) { // Copy any existing contents, used for `IComponent::setState` and similar // methods + // NOTE: Bitwig Studio seems to prepend some default header on new presets + // We _don't_ want to copy that, since some plugins may try to read + // the entire preset and fail to load. Examples of such plugins are + // the iZotope Rx7 plugins. int64 old_position; stream->tell(&old_position); if (stream->seek(0, Steinberg::IBStream::IStreamSeekMode::kIBSeekEnd) == Steinberg::kResultOk) { int64 size = 0; stream->tell(&size); + size -= old_position; + if (size > 0) { int32 num_bytes_read = 0; buffer.resize(size); - stream->seek(0, Steinberg::IBStream::IStreamSeekMode::kIBSeekSet); + stream->seek(old_position, + Steinberg::IBStream::IStreamSeekMode::kIBSeekSet); stream->read(buffer.data(), static_cast(size), &num_bytes_read); assert(num_bytes_read == 0 || num_bytes_read == size); } } + + // If the host did prepend some header, we should leave it in place when + // writing stream->seek(old_position, Steinberg::IBStream::IStreamSeekMode::kIBSeekSet);